From 3607be1f7282a7e9fffca721b89ef90650864dfa Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 16 Apr 2018 16:55:28 -0700 Subject: [PATCH 01/47] Update version number to 2.2.0 --- version.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.props b/version.props index 24f2b00a0a..44985cedb3 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ - 2.1.0 - preview3 + 2.2.0 + preview1 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From 83d54b24760de9fa3046235b0f5a1984d4d921a8 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 23 Apr 2018 12:03:13 -0700 Subject: [PATCH 02/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 24 ++++++++++++------------ korebuild-lock.txt | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 7c25bbe83f..ad5f70f367 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,19 +3,19 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-rc1-15774 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 + 2.2.0-preview1-17037 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 2.0.0 - 2.1.0-rc1-26419-02 + 2.1.0-preview3-26413-05 15.6.1 4.7.49 2.0.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index b419d767b9..f27a67b442 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview3-17018 -commithash:af264ca131f212b5ba8aafbc5110fc0fc510a2be +version:2.2.0-preview1-17037 +commithash:557055a86cbdc359c97d4fb1c2d23a3dc7ae731e From 9fd475d8644ba3be29ea7ec929c296b6e80737e5 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 29 Apr 2018 12:10:59 -0700 Subject: [PATCH 03/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 26 +++++++++++++------------- korebuild-lock.txt | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index ad5f70f367..fd12beff87 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,22 +3,22 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17037 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 + 2.2.0-preview1-17042 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 2.0.0 - 2.1.0-preview3-26413-05 + 2.2.0-preview1-26424-04 15.6.1 4.7.49 - 2.0.1 + 2.0.3 0.8.0 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index f27a67b442..335e579e06 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17037 -commithash:557055a86cbdc359c97d4fb1c2d23a3dc7ae731e +version:2.2.0-preview1-17042 +commithash:edf0705d014293c260de763543784330514db9a3 From db5b775de6012b5f45ccaa1050a874e8b9a5eac5 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 6 May 2018 12:10:10 -0700 Subject: [PATCH 04/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 22 +++++++++++----------- korebuild-lock.txt | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index fd12beff87..76e82896c6 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17042 - 2.2.0-preview1-34066 - 2.2.0-preview1-34066 - 2.2.0-preview1-34066 - 2.2.0-preview1-34066 - 2.2.0-preview1-34066 - 2.2.0-preview1-34066 - 2.2.0-preview1-34066 - 2.2.0-preview1-34066 - 2.2.0-preview1-34066 - 2.2.0-preview1-34066 + 2.2.0-preview1-17047 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 2.0.0 2.2.0-preview1-26424-04 15.6.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 335e579e06..a16d4b9ee4 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17042 -commithash:edf0705d014293c260de763543784330514db9a3 +version:2.2.0-preview1-17047 +commithash:e1957b52ddc8b62bd39c5c400322fccb5364624c From 69e5a8c599c344400b3963c665fc99f8bfa170ca Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 7 May 2018 15:09:04 -0700 Subject: [PATCH 05/47] Upgrade to netcoreapp22 --- Directory.Build.targets | 5 +++- build/dependencies.props | 25 ++++++++++--------- build/repo.props | 3 ++- korebuild-lock.txt | 4 +-- .../SampleDestination.csproj | 4 +-- samples/SampleOrigin/SampleOrigin.csproj | 4 +-- test/Directory.Build.props | 4 +-- 7 files changed, 27 insertions(+), 22 deletions(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index 53b3f6e1da..78626b773e 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,7 +1,10 @@ - + $(MicrosoftNETCoreApp20PackageVersion) $(MicrosoftNETCoreApp21PackageVersion) + $(MicrosoftNETCoreApp22PackageVersion) $(NETStandardLibrary20PackageVersion) + + 99.9 diff --git a/build/dependencies.props b/build/dependencies.props index 76e82896c6..62935a26d4 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,21 +1,22 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17047 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 + 2.2.0-preview1-17048 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 2.0.0 2.2.0-preview1-26424-04 + 2.2.0-preview1-26502-01 15.6.1 4.7.49 2.0.3 diff --git a/build/repo.props b/build/repo.props index 78b0ce5879..17a98ac7e7 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,4 +1,4 @@ - + @@ -10,5 +10,6 @@ + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index a16d4b9ee4..2573a03995 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17047 -commithash:e1957b52ddc8b62bd39c5c400322fccb5364624c +version:2.2.0-preview1-17048 +commithash:de14a0ee5fb48508ee8a29c14280a2928f8dabf8 diff --git a/samples/SampleDestination/SampleDestination.csproj b/samples/SampleDestination/SampleDestination.csproj index b8e59ede3a..e357385cc4 100644 --- a/samples/SampleDestination/SampleDestination.csproj +++ b/samples/SampleDestination/SampleDestination.csproj @@ -1,7 +1,7 @@ - + - netcoreapp2.1;net461 + netcoreapp2.2;net461 diff --git a/samples/SampleOrigin/SampleOrigin.csproj b/samples/SampleOrigin/SampleOrigin.csproj index b43f880f9c..054a6eb713 100644 --- a/samples/SampleOrigin/SampleOrigin.csproj +++ b/samples/SampleOrigin/SampleOrigin.csproj @@ -1,7 +1,7 @@ - + - netcoreapp2.1;net461 + netcoreapp2.2;net461 diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 4244624987..6f4e3f63a6 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -2,9 +2,9 @@ - netcoreapp2.1 + netcoreapp2.2 $(DeveloperBuildTestTfms) - $(StandardTestTfms);netcoreapp2.0 + $(StandardTestTfms) $(StandardTestTfms);net461 From 8549416210c26c64c562af8fb3972bb835d0f5c2 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 13 May 2018 14:03:30 -0700 Subject: [PATCH 06/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 28 ++++++++++++++-------------- korebuild-lock.txt | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 62935a26d4..42b8d614d6 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,22 +1,22 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17048 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 + 2.2.0-preview1-17051 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 2.0.0 - 2.2.0-preview1-26424-04 - 2.2.0-preview1-26502-01 + 2.1.0-rc1 + 2.2.0-preview1-26509-06 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 2573a03995..89629b454c 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17048 -commithash:de14a0ee5fb48508ee8a29c14280a2928f8dabf8 +version:2.2.0-preview1-17051 +commithash:253c3a480063bc3abaa5cde42f6e27b58457ef9b From e2fe2182e8ca0d88d7b373605da9e382a020b059 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 20 May 2018 19:26:44 +0000 Subject: [PATCH 07/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 22 +++++++++++----------- korebuild-lock.txt | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 42b8d614d6..39e61b934b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17051 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 + 2.2.0-preview1-17060 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 2.0.0 2.1.0-rc1 2.2.0-preview1-26509-06 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 89629b454c..cf2fff7def 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17051 -commithash:253c3a480063bc3abaa5cde42f6e27b58457ef9b +version:2.2.0-preview1-17060 +commithash:25b4b134d6f8f7b461928f0d495cfc695ccabb5b From cf22c828d073cb1e7e610726c255312adc7705d7 Mon Sep 17 00:00:00 2001 From: "Nate McMaster (automated)" Date: Fri, 25 May 2018 16:12:54 -0700 Subject: [PATCH 08/47] Update bootstrapper scripts (automated commit) [ci skip] --- run.ps1 | 9 +++++---- run.sh | 19 +++++++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/run.ps1 b/run.ps1 index 96c6c54c69..3b27382468 100644 --- a/run.ps1 +++ b/run.ps1 @@ -113,9 +113,9 @@ function Get-KoreBuild { try { $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix - if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) { + if (Get-Command -Name 'Microsoft.PowerShell.Archive\Expand-Archive' -ErrorAction Ignore) { # Use built-in commands where possible as they are cross-plat compatible - Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath + Microsoft.PowerShell.Archive\Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath } else { # Fallback to old approach for old installations of PowerShell @@ -179,8 +179,9 @@ if (Test-Path $ConfigFile) { } } catch { - Write-Warning "$ConfigFile could not be read. Its settings will be ignored." - Write-Warning $Error[0] + Write-Host -ForegroundColor Red $Error[0] + Write-Error "$ConfigFile contains invalid JSON." + exit 1 } } diff --git a/run.sh b/run.sh index 4606a42e78..02aac15874 100755 --- a/run.sh +++ b/run.sh @@ -186,7 +186,7 @@ while [[ $# -gt 0 ]]; do --reinstall|-[Rr]einstall) reinstall=true ;; - --ci) + --ci|-[Cc][Ii]) ci=true ;; --verbose|-Verbose) @@ -220,17 +220,28 @@ if [ -f "$config_file" ]; then config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" else - __warn "$config_file is invalid JSON. Its settings will be ignored." + _error "$config_file contains invalid JSON." + exit 1 fi elif __machine_has python ; then if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" else - __warn "$config_file is invalid JSON. Its settings will be ignored." + _error "$config_file contains invalid JSON." + exit 1 + fi + elif __machine_has python3 ; then + if python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then + config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" + config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" + else + _error "$config_file contains invalid JSON." + exit 1 fi else - __warn 'Missing required command: jq or pyton. Could not parse the JSON file. Its settings will be ignored.' + _error 'Missing required command: jq or python. Could not parse the JSON file.' + exit 1 fi [ ! -z "${config_channel:-}" ] && channel="$config_channel" From 2c0a235eeea931cd89c64fa608bcab141d94be4a Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 27 May 2018 19:09:37 +0000 Subject: [PATCH 09/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 24 ++++++++++++------------ korebuild-lock.txt | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 39e61b934b..34ae3b06f1 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,20 +3,20 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17060 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 + 2.2.0-preview1-17064 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 2.0.0 2.1.0-rc1 - 2.2.0-preview1-26509-06 + 2.2.0-preview1-26526-03 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index cf2fff7def..3028b66761 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17060 -commithash:25b4b134d6f8f7b461928f0d495cfc695ccabb5b +version:2.2.0-preview1-17064 +commithash:5380a2461b135b261646f31d1c919ab0a7b577a8 From b65803a891573f54e74ad7ea7aa608c52cafb390 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 3 Jun 2018 19:09:26 +0000 Subject: [PATCH 10/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 26 +++++++++++++------------- korebuild-lock.txt | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 34ae3b06f1..b77ebe4187 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,20 +3,20 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17064 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 + 2.2.0-preview1-17067 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 2.0.0 - 2.1.0-rc1 - 2.2.0-preview1-26526-03 + 2.1.0 + 2.2.0-preview1-26531-03 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3028b66761..06ba6285b7 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17064 -commithash:5380a2461b135b261646f31d1c919ab0a7b577a8 +version:2.2.0-preview1-17067 +commithash:2af0e2e3d02329b4f0290061ab9bd8c7ca1aa26f From a2f354a436f2172e43e3359bbd542394960d6700 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 5 Jun 2018 22:30:55 -0700 Subject: [PATCH 11/47] Add certificate names for code signing --- Directory.Build.props | 2 ++ korebuild-lock.txt | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index c81115d310..c2c625e9f1 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -14,6 +14,8 @@ $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)build\Key.snk true + Microsoft + MicrosoftNuGet true true diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 06ba6285b7..b679b80427 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17067 -commithash:2af0e2e3d02329b4f0290061ab9bd8c7ca1aa26f +version:2.2.0-preview1-17075 +commithash:d9f07c7f313a0af1d49f003f5424b4dbbdd3e09f From 9d112a897d5f833428345e4fdc93be3e39a13ccc Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 7 Jun 2018 19:30:13 +0000 Subject: [PATCH 12/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 24 ++++++++++++------------ korebuild-lock.txt | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index b77ebe4187..8856271e9b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,20 +3,20 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17067 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 + 2.2.0-preview1-17081 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 2.0.0 2.1.0 - 2.2.0-preview1-26531-03 + 2.2.0-preview1-26606-01 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index b679b80427..deb7e546f0 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17075 -commithash:d9f07c7f313a0af1d49f003f5424b4dbbdd3e09f +version:2.2.0-preview1-17081 +commithash:73f09c256e2a54270951562ecc0ef4a953926c36 From 9100dbaaa60847030ce70fe88272967dfecefd82 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 7 Jun 2018 15:43:22 -0700 Subject: [PATCH 13/47] Adding VSTS file --- .vsts-pipelines/builds/ci-internal.yml | 13 +++++++++++++ .vsts-pipelines/builds/ci-public.yml | 15 +++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 .vsts-pipelines/builds/ci-internal.yml create mode 100644 .vsts-pipelines/builds/ci-public.yml diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml new file mode 100644 index 0000000000..d7ceb76378 --- /dev/null +++ b/.vsts-pipelines/builds/ci-internal.yml @@ -0,0 +1,13 @@ +trigger: +- dev +- release/* + +resources: + repositories: + - repository: buildtools + type: git + name: aspnet-BuildTools + ref: refs/heads/dev + +phases: +- template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml new file mode 100644 index 0000000000..b7f25723f8 --- /dev/null +++ b/.vsts-pipelines/builds/ci-public.yml @@ -0,0 +1,15 @@ +trigger: +- dev +- release/* + +# See https://github.com/aspnet/BuildTools +resources: + repositories: + - repository: buildtools + type: github + endpoint: DotNet-Bot GitHub Connection + name: aspnet/BuildTools + ref: refs/heads/dev + +phases: +- template: .vsts-pipelines/templates/project-ci.yml@buildtools From 01ee9cbc80a21f8751eaf4d2117b8a236a6d80da Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Wed, 13 Jun 2018 10:53:25 -0700 Subject: [PATCH 14/47] Set 2.1 baselines --- .../baseline.netcore.json | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.Cors/baseline.netcore.json b/src/Microsoft.AspNetCore.Cors/baseline.netcore.json index 31d8e0dd50..ef96cf2eed 100644 --- a/src/Microsoft.AspNetCore.Cors/baseline.netcore.json +++ b/src/Microsoft.AspNetCore.Cors/baseline.netcore.json @@ -1,5 +1,5 @@ { - "AssemblyIdentity": "Microsoft.AspNetCore.Cors, Version=2.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "AssemblyIdentity": "Microsoft.AspNetCore.Cors, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "Types": [ { "Name": "Microsoft.AspNetCore.Builder.CorsMiddlewareExtensions", @@ -10,6 +10,21 @@ "Sealed": true, "ImplementedInterfaces": [], "Members": [ + { + "Kind": "Method", + "Name": "UseCors", + "Parameters": [ + { + "Name": "app", + "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder" + } + ], + "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, { "Kind": "Method", "Name": "UseCors", @@ -106,6 +121,13 @@ "Visibility": "Public", "GenericParameter": [] }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, { "Kind": "Constructor", "Name": ".ctor", @@ -262,6 +284,26 @@ "Visibility": "Public", "GenericParameter": [] }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "next", + "Type": "Microsoft.AspNetCore.Http.RequestDelegate" + }, + { + "Name": "corsService", + "Type": "Microsoft.AspNetCore.Cors.Infrastructure.ICorsService" + }, + { + "Name": "policyProvider", + "Type": "Microsoft.AspNetCore.Cors.Infrastructure.ICorsPolicyProvider" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, { "Kind": "Constructor", "Name": ".ctor", @@ -336,6 +378,32 @@ "Visibility": "Public", "GenericParameter": [] }, + { + "Kind": "Method", + "Name": "AddDefaultPolicy", + "Parameters": [ + { + "Name": "policy", + "Type": "Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AddDefaultPolicy", + "Parameters": [ + { + "Name": "configurePolicy", + "Type": "System.Action" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, { "Kind": "Method", "Name": "AddPolicy", From 32ad46006eface3c8091f333d13eb168931705c5 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 25 Jun 2018 11:10:13 -0700 Subject: [PATCH 15/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 24 ++++++++++++------------ korebuild-lock.txt | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 8856271e9b..6bcc177716 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,20 +3,20 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17081 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 + 2.2.0-preview1-17090 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 2.0.0 2.1.0 - 2.2.0-preview1-26606-01 + 2.2.0-preview1-26618-02 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index deb7e546f0..a8109db529 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17081 -commithash:73f09c256e2a54270951562ecc0ef4a953926c36 +version:2.2.0-preview1-17090 +commithash:b19e903e946579cd9482089bce7d917e8bacd765 From 554855cab34961a27a6cf248fbb847b9dd8bd8d4 Mon Sep 17 00:00:00 2001 From: Daniel Little Date: Wed, 13 Jun 2018 08:03:03 +1000 Subject: [PATCH 16/47] No CORS headers sent if Exception is thrown - Normally headers are added however if a controller throws an exception then CORS headers not be present. Addresses aspnet/Home#3220 --- .../Infrastructure/CorsMiddleware.cs | 106 +++++++++++++-- .../Internal/CORSLoggerExtensions.cs | 11 ++ .../CorsMiddlewareTests.cs | 124 +++++++++++++++++- 3 files changed, 232 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs index eb773f5abf..fb3df360e6 100644 --- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs +++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs @@ -3,7 +3,10 @@ using System; using System.Threading.Tasks; +using Microsoft.AspNetCore.Cors.Internal; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Primitives; namespace Microsoft.AspNetCore.Cors.Infrastructure @@ -18,6 +21,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure private readonly ICorsPolicyProvider _corsPolicyProvider; private readonly CorsPolicy _policy; private readonly string _corsPolicyName; + private readonly ILogger _logger; /// /// Instantiates a new . @@ -25,11 +29,12 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure /// The next middleware in the pipeline. /// An instance of . /// A policy provider which can get an . + [Obsolete("This constructor has been replaced with an equivalent constructor which requires an ILoggerFactory")] public CorsMiddleware( RequestDelegate next, ICorsService corsService, ICorsPolicyProvider policyProvider) - : this(next, corsService, policyProvider, policyName: null) + : this(next, corsService, policyProvider, NullLoggerFactory.Instance, policyName: null) { } @@ -40,11 +45,61 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure /// An instance of . /// A policy provider which can get an . /// An optional name of the policy to be fetched. + [Obsolete("This constructor has been replaced with an equivalent constructor which requires an ILoggerFactory")] public CorsMiddleware( RequestDelegate next, ICorsService corsService, ICorsPolicyProvider policyProvider, string policyName) + : this(next, corsService, policyProvider, NullLoggerFactory.Instance, policyName) + { + } + + /// + /// Instantiates a new . + /// + /// The next middleware in the pipeline. + /// An instance of . + /// An instance of the which can be applied. + [Obsolete("This constructor has been replaced with an equivalent constructor which requires an ILoggerFactory")] + public CorsMiddleware( + RequestDelegate next, + ICorsService corsService, + CorsPolicy policy) + : this(next, corsService, policy, NullLoggerFactory.Instance) + { + } + + /// + /// Instantiates a new . + /// + /// The next middleware in the pipeline. + /// An instance of . + /// A policy provider which can get an . + /// An instance of . + public CorsMiddleware( + RequestDelegate next, + ICorsService corsService, + ICorsPolicyProvider policyProvider, + ILoggerFactory loggerFactory) + : this(next, corsService, policyProvider, loggerFactory, policyName: null) + { + } + + /// + /// Instantiates a new . + /// + /// The next middleware in the pipeline. + /// An instance of . + /// A policy provider which can get an . + /// An instance of . + /// An optional name of the policy to be fetched. + public CorsMiddleware( + RequestDelegate next, + ICorsService corsService, + ICorsPolicyProvider policyProvider, + ILoggerFactory loggerFactory, + string policyName) { if (next == null) { @@ -61,10 +116,16 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure throw new ArgumentNullException(nameof(policyProvider)); } + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + _next = next; _corsService = corsService; _corsPolicyProvider = policyProvider; _corsPolicyName = policyName; + _logger = loggerFactory.CreateLogger(); } /// @@ -73,10 +134,12 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure /// The next middleware in the pipeline. /// An instance of . /// An instance of the which can be applied. + /// An instance of . public CorsMiddleware( - RequestDelegate next, - ICorsService corsService, - CorsPolicy policy) + RequestDelegate next, + ICorsService corsService, + CorsPolicy policy, + ILoggerFactory loggerFactory) { if (next == null) { @@ -93,9 +156,15 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure throw new ArgumentNullException(nameof(policy)); } + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + _next = next; _corsService = corsService; _policy = policy; + _logger = loggerFactory.CreateLogger(); } /// @@ -106,9 +175,6 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var corsPolicy = _policy ?? await _corsPolicyProvider?.GetPolicyAsync(context, _corsPolicyName); if (corsPolicy != null) { - var corsResult = _corsService.EvaluatePolicy(context, corsPolicy); - _corsService.ApplyResult(corsResult, context.Response); - var accessControlRequestMethod = context.Request.Headers[CorsConstants.AccessControlRequestMethod]; if (string.Equals( @@ -117,15 +183,39 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure StringComparison.OrdinalIgnoreCase) && !StringValues.IsNullOrEmpty(accessControlRequestMethod)) { + ApplyCorsHeaders(context, corsPolicy); + // Since there is a policy which was identified, // always respond to preflight requests. context.Response.StatusCode = StatusCodes.Status204NoContent; return; } + else + { + context.Response.OnStarting(state => + { + var (httpContext, policy) = (Tuple)state; + try + { + ApplyCorsHeaders(httpContext, policy); + } + catch (Exception exception) + { + _logger.FailedToSetCorsHeaders(exception); + } + return Task.CompletedTask; + }, Tuple.Create(context, corsPolicy)); + } } } await _next(context); } + + private void ApplyCorsHeaders(HttpContext context, CorsPolicy corsPolicy) + { + var corsResult = _corsService.EvaluatePolicy(context, corsPolicy); + _corsService.ApplyResult(corsResult, context.Response); + } } -} \ No newline at end of file +} diff --git a/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs b/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs index 727d19a4ea..2cf30d7525 100644 --- a/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs +++ b/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs @@ -16,6 +16,7 @@ namespace Microsoft.AspNetCore.Cors.Internal private static readonly Action _originNotAllowed; private static readonly Action _accessControlMethodNotAllowed; private static readonly Action _requestHeaderNotAllowed; + private static readonly Action _failedToSetCorsHeaders; static CORSLoggerExtensions() { @@ -58,6 +59,11 @@ namespace Microsoft.AspNetCore.Cors.Internal LogLevel.Information, 8, "Request header '{requestHeader}' not allowed in CORS policy."); + + _failedToSetCorsHeaders = LoggerMessage.Define( + LogLevel.Warning, + 9, + "Failed to apply CORS Response headers."); } public static void IsPreflightRequest(this ILogger logger) @@ -99,5 +105,10 @@ namespace Microsoft.AspNetCore.Cors.Internal { _requestHeaderNotAllowed(logger, requestHeader, null); } + + public static void FailedToSetCorsHeaders(this ILogger logger, Exception exception) + { + _failedToSetCorsHeaders(logger, exception); + } } } diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs index d74c020eae..44c6d5c1be 100644 --- a/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs +++ b/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Linq; using System.Net; using System.Threading.Tasks; @@ -9,6 +10,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Moq; using Xunit; @@ -246,6 +248,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Arrange var corsService = Mock.Of(); var mockProvider = new Mock(); + var loggerFactory = Mock.Of(); mockProvider.Setup(o => o.GetPolicyAsync(It.IsAny(), It.IsAny())) .Returns(Task.FromResult(null)) .Verifiable(); @@ -254,6 +257,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure Mock.Of(), corsService, mockProvider.Object, + loggerFactory, policyName: null); var httpContext = new DefaultHttpContext(); @@ -274,6 +278,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Arrange var corsService = Mock.Of(); var mockProvider = new Mock(); + var loggerFactory = Mock.Of(); mockProvider.Setup(o => o.GetPolicyAsync(It.IsAny(), It.IsAny())) .Returns(Task.FromResult(null)) .Verifiable(); @@ -282,6 +287,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure Mock.Of(), corsService, mockProvider.Object, + loggerFactory, policyName: null); var httpContext = new DefaultHttpContext(); @@ -349,5 +355,121 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure Assert.Equal("PUT", response.Headers.GetValues(CorsConstants.AccessControlAllowMethods).FirstOrDefault()); } } + + [Fact] + public async Task CorsRequest_SetsResponseHeaders() + { + // Arrange + var hostBuilder = new WebHostBuilder() + .Configure(app => + { + app.UseCors(builder => + builder.WithOrigins("http://localhost:5001") + .WithMethods("PUT") + .WithHeaders("Header1") + .WithExposedHeaders("AllowedHeader")); + app.Run(async context => + { + context.Response.Headers.Add("Test", "Should-Appear"); + await context.Response.WriteAsync("Cross origin response"); + }); + }) + .ConfigureServices(services => services.AddCors()); + + using (var server = new TestServer(hostBuilder)) + { + // Act + // Actual request. + var response = await server.CreateRequest("/") + .AddHeader(CorsConstants.Origin, "http://localhost:5001") + .SendAsync("PUT"); + + // Assert + response.EnsureSuccessStatusCode(); + Assert.Collection( + response.Headers.OrderBy(o => o.Key), + kvp => + { + Assert.Equal(CorsConstants.AccessControlAllowOrigin, kvp.Key); + Assert.Equal("http://localhost:5001", Assert.Single(kvp.Value)); + }, + kvp => + { + Assert.Equal(CorsConstants.AccessControlExposeHeaders, kvp.Key); + Assert.Equal("AllowedHeader", Assert.Single(kvp.Value)); + }, + kvp => + { + Assert.Equal("Test", kvp.Key); + Assert.Equal("Should-Appear", Assert.Single(kvp.Value)); + }); + + Assert.Equal("Cross origin response", await response.Content.ReadAsStringAsync()); + } + } + + [Fact] + public async Task CorsRequest_SetsResponseHeader_IfExceptionHandlerClearsResponse() + { + // Arrange + var exceptionSeen = true; + var hostBuilder = new WebHostBuilder() + .Configure(app => + { + // Simulate ExceptionHandler middleware + app.Use(async (context, next) => + { + try + { + await next(); + } + catch (Exception) + { + exceptionSeen = true; + context.Response.Clear(); + context.Response.StatusCode = 500; + } + }); + + app.UseCors(builder => + builder.WithOrigins("http://localhost:5001") + .WithMethods("PUT") + .WithHeaders("Header1") + .WithExposedHeaders("AllowedHeader")); + + app.Run(context => + { + context.Response.Headers.Add("Test", "Should-Not-Exist"); + throw new Exception("Runtime error"); + }); + }) + .ConfigureServices(services => services.AddCors()); + + using (var server = new TestServer(hostBuilder)) + { + // Act + // Actual request. + var response = await server.CreateRequest("/") + .AddHeader(CorsConstants.Origin, "http://localhost:5001") + .SendAsync("PUT"); + + // Assert + Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + Assert.True(exceptionSeen, "We expect exception middleware to have executed"); + + Assert.Collection( + response.Headers.OrderBy(o => o.Key), + kvp => + { + Assert.Equal(CorsConstants.AccessControlAllowOrigin, kvp.Key); + Assert.Equal("http://localhost:5001", Assert.Single(kvp.Value)); + }, + kvp => + { + Assert.Equal(CorsConstants.AccessControlExposeHeaders, kvp.Key); + Assert.Equal("AllowedHeader", Assert.Single(kvp.Value)); + }); + } + } } -} \ No newline at end of file +} From 0c7cf1b06e4d9e299d1624bc20dc03e81d3e268b Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 28 Jun 2018 16:19:11 -0700 Subject: [PATCH 17/47] Update infrastructure for the 2.2 release --- .vsts-pipelines/builds/ci-internal.yml | 4 ++-- .vsts-pipelines/builds/ci-public.yml | 6 +++--- build/repo.props | 1 + korebuild.json | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml index d7ceb76378..dc7b8a3cb9 100644 --- a/.vsts-pipelines/builds/ci-internal.yml +++ b/.vsts-pipelines/builds/ci-internal.yml @@ -1,5 +1,5 @@ trigger: -- dev +- master - release/* resources: @@ -7,7 +7,7 @@ resources: - repository: buildtools type: git name: aspnet-BuildTools - ref: refs/heads/dev + ref: refs/heads/release/2.2 phases: - template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml index b7f25723f8..f5087d9c30 100644 --- a/.vsts-pipelines/builds/ci-public.yml +++ b/.vsts-pipelines/builds/ci-public.yml @@ -1,5 +1,5 @@ trigger: -- dev +- master - release/* # See https://github.com/aspnet/BuildTools @@ -9,7 +9,7 @@ resources: type: github endpoint: DotNet-Bot GitHub Connection name: aspnet/BuildTools - ref: refs/heads/dev - + ref: refs/heads/release/2.2 + phases: - template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/build/repo.props b/build/repo.props index 17a98ac7e7..f1fe24dd27 100644 --- a/build/repo.props +++ b/build/repo.props @@ -4,6 +4,7 @@ Internal.AspNetCore.Universe.Lineup + 2.2.0-* https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json diff --git a/korebuild.json b/korebuild.json index bd5d51a51b..d217d06e3e 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,4 +1,4 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev" + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.2/tools/korebuild.schema.json", + "channel": "release/2.2" } From cbf2f4ca77c7974e84d86fd6af951231ccba0b3a Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 8 Jul 2018 12:09:00 -0700 Subject: [PATCH 18/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 28 ++++++++++++++-------------- korebuild-lock.txt | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 6bcc177716..d055aed05f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,26 +3,26 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17090 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.0.0 - 2.1.0 + 2.2.0-preview1-17099 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.0.7 + 2.1.1 2.2.0-preview1-26618-02 15.6.1 4.7.49 2.0.3 0.8.0 2.3.1 - 2.4.0-beta.1.build3945 + 2.4.0-rc.1.build4038 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index a8109db529..27e2e80f9a 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17090 -commithash:b19e903e946579cd9482089bce7d917e8bacd765 +version:2.2.0-preview1-17099 +commithash:263ed1db9866b6b419b1f5d5189a712aa218acb3 From 0abc83c1727bcce78d758914c9c83748ce39cfae Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 15 Jul 2018 12:08:55 -0700 Subject: [PATCH 19/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index d055aed05f..45f4f81668 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,23 +4,23 @@ 2.2.0-preview1-17099 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.0.7 - 2.1.1 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.0.9 + 2.1.2 2.2.0-preview1-26618-02 15.6.1 4.7.49 2.0.3 - 0.8.0 + 0.9.0 2.3.1 2.4.0-rc.1.build4038 From 665783146383fe0a264ec196b619c5ce85563c35 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 22 Jul 2018 12:08:33 -0700 Subject: [PATCH 20/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 45f4f81668..5a7a0ecdea 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,16 +4,16 @@ 2.2.0-preview1-17099 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 2.0.9 2.1.2 2.2.0-preview1-26618-02 From feceb3ddeaf0a0ca7e895eb83674d78fee53515c Mon Sep 17 00:00:00 2001 From: Sindhudweep Sarkar Date: Thu, 5 Jul 2018 09:57:22 -0400 Subject: [PATCH 21/47] Lowercase scheme and host to better align with RFC 6454. --- .../Infrastructure/CorsPolicyBuilder.cs | 4 ++-- .../CorsPolicyBuilderTests.cs | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyBuilder.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyBuilder.cs index 88e16fa0fa..3953296168 100644 --- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyBuilder.cs +++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyBuilder.cs @@ -38,9 +38,9 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure /// The current policy builder. public CorsPolicyBuilder WithOrigins(params string[] origins) { - foreach (var req in origins) + foreach (var origin in origins) { - _policy.Origins.Add(req); + _policy.Origins.Add(origin.ToLowerInvariant()); } return this; diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs index 8a223ad225..c9b3afca84 100644 --- a/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs +++ b/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs @@ -128,6 +128,17 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure Assert.Equal(new List() { "http://example.com", "http://example2.com" }, corsPolicy.Origins); } + [Fact] + public void WithOrigins_NormalizesOrigins() + { + // Arrange + var builder = new CorsPolicyBuilder("http://www.EXAMPLE.com", "HTTPS://example2.com"); + + // Assert + var corsPolicy = builder.Build(); + Assert.Equal(new List() { "http://www.example.com", "https://example2.com" }, corsPolicy.Origins); + } + [Fact] public void AllowAnyOrigin_AllowsAny() { From cd72cb76b38a0157345d7743905e5a486849a40d Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 29 Jul 2018 12:08:28 -0700 Subject: [PATCH 22/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 27 ++++++++++++++------------- korebuild-lock.txt | 4 ++-- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 5a7a0ecdea..04dc8d2c9d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,26 +3,27 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17099 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 + 2.2.0-preview1-17102 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 2.0.9 2.1.2 2.2.0-preview1-26618-02 15.6.1 4.7.49 2.0.3 - 0.9.0 + 0.10.0 2.3.1 - 2.4.0-rc.1.build4038 + 2.4.0 + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 27e2e80f9a..6b8da29e6b 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17099 -commithash:263ed1db9866b6b419b1f5d5189a712aa218acb3 +version:2.2.0-preview1-17102 +commithash:e7e2b5a97ca92cfc6acc4def534cb0901a6d1eb9 From 2db11051d86cd2b209989e039dc32d4b7976e54c Mon Sep 17 00:00:00 2001 From: Flying Wraptor Date: Mon, 23 Jul 2018 21:28:03 +0200 Subject: [PATCH 23/47] Removed Simple request filtering --- .../Infrastructure/CorsService.cs | 48 ++---- .../CorsServiceTests.cs | 143 ++++-------------- 2 files changed, 37 insertions(+), 154 deletions(-) diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs index 5060ddf205..5be99f4f71 100644 --- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs +++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs @@ -151,8 +151,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure { foreach (var requestHeader in requestHeaders) { - if (!CorsConstants.SimpleRequestHeaders.Contains(requestHeader, StringComparer.OrdinalIgnoreCase) && - !policy.Headers.Contains(requestHeader, StringComparer.OrdinalIgnoreCase)) + if (!policy.Headers.Contains(requestHeader, StringComparer.OrdinalIgnoreCase)) { _logger?.PolicyFailure(); _logger?.RequestHeaderNotAllowed(requestHeader); @@ -201,50 +200,23 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure if (result.AllowedMethods.Count > 0) { - // Filter out simple methods - var nonSimpleAllowMethods = result.AllowedMethods - .Where(m => - !CorsConstants.SimpleMethods.Contains(m, StringComparer.OrdinalIgnoreCase)) - .ToArray(); - - if (nonSimpleAllowMethods.Length > 0) - { - headers.SetCommaSeparatedValues( - CorsConstants.AccessControlAllowMethods, - nonSimpleAllowMethods); - } + headers.SetCommaSeparatedValues( + CorsConstants.AccessControlAllowMethods, + result.AllowedMethods.ToArray()); } if (result.AllowedHeaders.Count > 0) { - // Filter out simple request headers - var nonSimpleAllowRequestHeaders = result.AllowedHeaders - .Where(header => - !CorsConstants.SimpleRequestHeaders.Contains(header, StringComparer.OrdinalIgnoreCase)) - .ToArray(); - - if (nonSimpleAllowRequestHeaders.Length > 0) - { - headers.SetCommaSeparatedValues( - CorsConstants.AccessControlAllowHeaders, - nonSimpleAllowRequestHeaders); - } + headers.SetCommaSeparatedValues( + CorsConstants.AccessControlAllowHeaders, + result.AllowedHeaders.ToArray()); } if (result.AllowedExposedHeaders.Count > 0) { - // Filter out simple response headers - var nonSimpleAllowResponseHeaders = result.AllowedExposedHeaders - .Where(header => - !CorsConstants.SimpleResponseHeaders.Contains(header, StringComparer.OrdinalIgnoreCase)) - .ToArray(); - - if (nonSimpleAllowResponseHeaders.Length > 0) - { - headers.SetCommaSeparatedValues( - CorsConstants.AccessControlExposeHeaders, - nonSimpleAllowResponseHeaders); - } + headers.SetCommaSeparatedValues( + CorsConstants.AccessControlExposeHeaders, + result.AllowedExposedHeaders.ToArray()); } if (result.PreflightMaxAge.HasValue) diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs index 8a71ce7b42..7f7fb2220f 100644 --- a/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs +++ b/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs @@ -598,32 +598,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure Assert.Contains("foo", result.AllowedHeaders); Assert.Contains("bar", result.AllowedHeaders); } - - [Fact] - public void EvaluatePolicy_PreflightRequest_HeadersRequested_AllowSomeHeaders_ReturnsSubsetOfListedHeaders() - { - // Arrange - var corsService = new CorsService(new TestCorsOptions()); - var requestContext = GetHttpContext( - method: "OPTIONS", - origin: "http://example.com", - accessControlRequestMethod: "PUT", - accessControlRequestHeaders: new[] { "content-type", "accept" }); - var policy = new CorsPolicy(); - policy.Origins.Add(CorsConstants.AnyOrigin); - policy.Methods.Add("*"); - policy.Headers.Add("foo"); - policy.Headers.Add("bar"); - policy.Headers.Add("Content-Type"); - - // Act - var result = corsService.EvaluatePolicy(requestContext, policy); - - // Assert - Assert.Equal(2, result.AllowedHeaders.Count); - Assert.Contains("Content-Type", result.AllowedHeaders, StringComparer.OrdinalIgnoreCase); - } - + [Fact] public void EvaluatePolicy_PreflightRequest_HeadersRequested_NotAllHeaderMatches_ReturnsInvalidResult() { @@ -690,6 +665,31 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure Assert.Null(result.AllowedOrigin); } + [Fact] + public void ApplyResult_SimpleRequests_IgnoresFiltering() + { + // Arrange + var result = new CorsResult(); + result.AllowedHeaders.Add("Content-Type"); + result.AllowedHeaders.Add("Date"); + result.AllowedMethods.Add("GET"); + result.AllowedMethods.Add("PUT"); + + var httpContext = new DefaultHttpContext(); + var service = new CorsService(new TestCorsOptions()); + + + // Act + service.ApplyResult(result, httpContext.Response); + + // Assert + string[] arMethods = httpContext.Response.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlAllowMethods); + Assert.Contains("GET", arMethods); + Assert.Contains("PUT", arMethods); + string[] arHeaders = httpContext.Response.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlAllowHeaders); + Assert.Contains("Content-Type", arHeaders); + Assert.Contains("Date", arHeaders); + } [Fact] public void ApplyResult_ReturnsNoHeaders_ByDefault() @@ -836,52 +836,6 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Assert Assert.Equal("PUT", httpContext.Response.Headers["Access-Control-Allow-Methods"]); } - - [Fact] - public void ApplyResult_SomeSimpleAllowMethods_AllowMethodsHeaderAddedForNonSimpleMethods() - { - // Arrange - var result = new CorsResult(); - result.AllowedMethods.Add("PUT"); - result.AllowedMethods.Add("get"); - result.AllowedMethods.Add("DELETE"); - result.AllowedMethods.Add("POST"); - - var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); - - // Act - service.ApplyResult(result, httpContext.Response); - - // Assert - Assert.Contains("Access-Control-Allow-Methods", httpContext.Response.Headers.Keys); - var value = Assert.Single(httpContext.Response.Headers.Values); - Assert.Equal(new[] { "PUT,DELETE" }, value); - string[] methods = httpContext.Response.Headers.GetCommaSeparatedValues("Access-Control-Allow-Methods"); - Assert.Equal(2, methods.Length); - Assert.Contains("PUT", methods); - Assert.Contains("DELETE", methods); - } - - [Fact] - public void ApplyResult_SimpleAllowMethods_AllowMethodsHeaderNotAdded() - { - // Arrange - var result = new CorsResult(); - result.AllowedMethods.Add("GET"); - result.AllowedMethods.Add("HEAD"); - result.AllowedMethods.Add("POST"); - - var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); - - // Act - service.ApplyResult(result, httpContext.Response); - - // Assert - Assert.DoesNotContain("Access-Control-Allow-Methods", httpContext.Response.Headers.Keys); - } - [Fact] public void ApplyResult_NoAllowHeaders_AllowHeadersHeaderNotAdded() { @@ -943,50 +897,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure Assert.Contains("bar", headerValues); Assert.Contains("baz", headerValues); } - - [Fact] - public void ApplyResult_SomeSimpleAllowHeaders_AllowHeadersHeaderAddedForNonSimpleHeaders() - { - // Arrange - var result = new CorsResult(); - result.AllowedHeaders.Add("Content-Language"); - result.AllowedHeaders.Add("foo"); - result.AllowedHeaders.Add("bar"); - result.AllowedHeaders.Add("Accept"); - - var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); - - // Act - service.ApplyResult(result, httpContext.Response); - - // Assert - Assert.Contains("Access-Control-Allow-Headers", httpContext.Response.Headers.Keys); - string[] headerValues = httpContext.Response.Headers.GetCommaSeparatedValues("Access-Control-Allow-Headers"); - Assert.Equal(2, headerValues.Length); - Assert.Contains("foo", headerValues); - Assert.Contains("bar", headerValues); - } - - [Fact] - public void ApplyResult_SimpleAllowHeaders_AllowHeadersHeaderNotAdded() - { - // Arrange - var result = new CorsResult(); - result.AllowedHeaders.Add("Accept"); - result.AllowedHeaders.Add("Accept-Language"); - result.AllowedHeaders.Add("Content-Language"); - - var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); - - // Act - service.ApplyResult(result, httpContext.Response); - - // Assert - Assert.DoesNotContain("Access-Control-Allow-Headers", httpContext.Response.Headers.Keys); - } - + [Fact] public void ApplyResult_NoAllowExposedHeaders_ExposedHeadersHeaderNotAdded() { From a080301b89fb65f82cde7184468c6100c113847d Mon Sep 17 00:00:00 2001 From: Wraptor Date: Mon, 23 Jul 2018 21:33:25 +0200 Subject: [PATCH 24/47] Removed CorsConstats.Simple* variables --- .../Infrastructure/CorsConstants.cs | 28 +------------------ 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsConstants.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsConstants.cs index 22110b2e41..fbc39a8228 100644 --- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsConstants.cs +++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsConstants.cs @@ -65,31 +65,5 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure /// The Access-Control-Max-Age response header. /// public static readonly string AccessControlMaxAge = HeaderNames.AccessControlMaxAge; - - - internal static readonly string[] SimpleRequestHeaders = - { - HeaderNames.Origin, - HeaderNames.Accept, - HeaderNames.AcceptLanguage, - HeaderNames.ContentLanguage, - }; - - internal static readonly string[] SimpleResponseHeaders = - { - HeaderNames.CacheControl, - HeaderNames.ContentLanguage, - HeaderNames.ContentType, - HeaderNames.Expires, - HeaderNames.LastModified, - HeaderNames.Pragma - }; - - internal static readonly string[] SimpleMethods = - { - HttpMethods.Get, - HttpMethods.Head, - HttpMethods.Post - }; } -} \ No newline at end of file +} From 40a79a6ee5bf393c11a0c3607ea59b2fb8090a69 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 5 Aug 2018 19:09:57 +0000 Subject: [PATCH 25/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 22 +++++++++++----------- korebuild-lock.txt | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 04dc8d2c9d..c3de8ebeef 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17102 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 + 2.2.0-preview1-20180731.1 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 6b8da29e6b..c7af2292c7 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17102 -commithash:e7e2b5a97ca92cfc6acc4def534cb0901a6d1eb9 +version:2.2.0-preview1-20180731.1 +commithash:29fde58465439f4bb9df40830635ed758e063daf From c847d7259054516055ca9174eecf26d3a3da3c9f Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 6 Aug 2018 20:32:14 +0000 Subject: [PATCH 26/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index c3de8ebeef..37e24688fd 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,16 +4,16 @@ 2.2.0-preview1-20180731.1 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 2.0.9 2.1.2 2.2.0-preview1-26618-02 From 49a17c072ab6bad36c67280a965a850a70342bd6 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 12 Aug 2018 19:08:57 +0000 Subject: [PATCH 27/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 22 +++++++++++----------- korebuild-lock.txt | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 37e24688fd..e3915630b8 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180731.1 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 + 2.2.0-preview1-20180807.2 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index c7af2292c7..3fbcc80189 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180731.1 -commithash:29fde58465439f4bb9df40830635ed758e063daf +version:2.2.0-preview1-20180807.2 +commithash:11495dbd236104434e08cb1152fcb58cf2a20923 From e85c36fa8cf3bf29dee1be72289031b418b408cd Mon Sep 17 00:00:00 2001 From: Christer van der Meeren Date: Mon, 20 Aug 2018 17:25:45 +0200 Subject: [PATCH 28/47] Clarify CORS policy result log messages (#177) Fixes https://github.com/aspnet/Home/issues/3419 --- .../Internal/CORSLoggerExtensions.cs | 4 ++-- .../CorsServiceTests.cs | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs b/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs index 2cf30d7525..bfcc82a2e6 100644 --- a/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs +++ b/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs @@ -38,12 +38,12 @@ namespace Microsoft.AspNetCore.Cors.Internal _policySuccess = LoggerMessage.Define( LogLevel.Information, 4, - "Policy execution successful."); + "CORS policy execution successful."); _policyFailure = LoggerMessage.Define( LogLevel.Information, 5, - "Policy execution failed."); + "CORS policy execution failed."); _originNotAllowed = LoggerMessage.Define( LogLevel.Information, diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs index 7f7fb2220f..ebef888ad2 100644 --- a/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs +++ b/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs @@ -261,7 +261,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure Method = "PUT", Headers = null, OriginLogMessage = "The request has an origin header: 'http://example.com'.", - PolicyLogMessage = "Policy execution failed.", + PolicyLogMessage = "CORS policy execution failed.", FailureReason = "Request origin http://example.com does not have permission to access the resource." } }, @@ -271,7 +271,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure Method = "DELETE", Headers = null, OriginLogMessage = "The request has an origin header: 'http://allowed.example.com'.", - PolicyLogMessage = "Policy execution failed.", + PolicyLogMessage = "CORS policy execution failed.", FailureReason = "Request method DELETE not allowed in CORS policy." } }, @@ -281,7 +281,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure Method = "PUT", Headers = new[] { "test" }, OriginLogMessage = "The request has an origin header: 'http://allowed.example.com'.", - PolicyLogMessage = "Policy execution failed.", + PolicyLogMessage = "CORS policy execution failed.", FailureReason = "Request header 'test' not allowed in CORS policy." } }, @@ -330,7 +330,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var writeList = sink.Writes.ToList(); Assert.Equal("The request is a preflight request.", writeList[0].State.ToString()); Assert.Equal("The request has an origin header: 'http://allowed.example.com'.", writeList[1].State.ToString()); - Assert.Equal("Policy execution successful.", writeList[2].State.ToString()); + Assert.Equal("CORS policy execution successful.", writeList[2].State.ToString()); } [Fact] @@ -369,7 +369,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var writeList = sink.Writes.ToList(); Assert.Equal("The request has an origin header: 'http://example.com'.", writeList[0].State.ToString()); - Assert.Equal("Policy execution failed.", writeList[1].State.ToString()); + Assert.Equal("CORS policy execution failed.", writeList[1].State.ToString()); Assert.Equal("Request origin http://example.com does not have permission to access the resource.", writeList[2].State.ToString()); } @@ -389,7 +389,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var writeList = sink.Writes.ToList(); Assert.Equal("The request has an origin header: 'http://allowed.example.com'.", writeList[0].State.ToString()); - Assert.Equal("Policy execution successful.", writeList[1].State.ToString()); + Assert.Equal("CORS policy execution successful.", writeList[1].State.ToString()); } [Fact] From e8da00187024f181a9989a544a3f020c368cd43a Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 21 Aug 2018 13:33:49 -0700 Subject: [PATCH 29/47] Update package branding for 2.2.0-preview2 --- build/dependencies.props | 2 +- version.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index e3915630b8..c3e729c4a3 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -24,6 +24,6 @@ 2.3.1 2.4.0 - + diff --git a/version.props b/version.props index 44985cedb3..15637ba785 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.2.0 - preview1 + preview2 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From 6eb5ead0126e4640e551b7cd060967888a13daf1 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 2 Sep 2018 12:08:25 -0700 Subject: [PATCH 30/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 22 +++++++++++----------- korebuild-lock.txt | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index c3e729c4a3..0c258932d6 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180807.2 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 + 2.2.0-preview1-20180821.1 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3fbcc80189..ad704918df 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180807.2 -commithash:11495dbd236104434e08cb1152fcb58cf2a20923 +version:2.2.0-preview1-20180821.1 +commithash:c8d0cc52cd1abb697be24e288ffd54f8fae8bf17 From 46ca34ef525866c1d327ce857910dd670e0f196e Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Wed, 5 Sep 2018 16:33:28 -0700 Subject: [PATCH 31/47] Update branding to 2.2.0-preview3 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 15637ba785..704cac087b 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.2.0 - preview2 + preview3 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From 7df36459c9915d65167bdfc34a25dc7d3e3b9feb Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 9 Sep 2018 12:09:10 -0700 Subject: [PATCH 32/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 26 +++++++++++++------------- korebuild-lock.txt | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 0c258932d6..42fb69d61b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,20 +3,20 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180821.1 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 + 2.2.0-preview1-20180907.8 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 2.0.9 - 2.1.2 - 2.2.0-preview1-26618-02 + 2.1.3 + 2.2.0-preview2-26905-02 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index ad704918df..312f82f9a5 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180821.1 -commithash:c8d0cc52cd1abb697be24e288ffd54f8fae8bf17 +version:2.2.0-preview1-20180907.8 +commithash:078918eb5c1f176ee1da351c584fb4a4d7491aa0 From 9225e5da807e6b1a8a92305d836d3df66b3d2394 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 16 Sep 2018 12:08:01 -0700 Subject: [PATCH 33/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 22 +++++++++++----------- korebuild-lock.txt | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 42fb69d61b..510831dd3e 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180907.8 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 + 2.2.0-preview1-20180911.1 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 2.0.9 2.1.3 2.2.0-preview2-26905-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 312f82f9a5..7124f37441 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180907.8 -commithash:078918eb5c1f176ee1da351c584fb4a4d7491aa0 +version:2.2.0-preview1-20180911.1 +commithash:ddfecdfc6e8e4859db5a0daea578070b862aac65 From 826d86633b7c2411953659034bd65d2bd4ac2f88 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 23 Sep 2018 19:09:42 +0000 Subject: [PATCH 34/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 22 +++++++++++----------- korebuild-lock.txt | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 510831dd3e..54e156c97d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180911.1 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 + 2.2.0-preview1-20180918.1 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 2.0.9 2.1.3 2.2.0-preview2-26905-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 7124f37441..649bf2ba0b 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180911.1 -commithash:ddfecdfc6e8e4859db5a0daea578070b862aac65 +version:2.2.0-preview1-20180918.1 +commithash:ad5e3fc53442741a0dd49bce437d2ac72f4b5800 From 5b19d1d0f7898c72f7d57bc57b68884383011a67 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 28 Sep 2018 17:10:31 -0700 Subject: [PATCH 35/47] automated: bulk infrastructure updates. Update bootstrapper scripts and remove unnecessary signing properties --- Directory.Build.props | 3 --- run.ps1 | 6 +++--- run.sh | 10 +++++----- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index c2c625e9f1..cd8ab6bb87 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -14,9 +14,6 @@ $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)build\Key.snk true - Microsoft - MicrosoftNuGet - true true diff --git a/run.ps1 b/run.ps1 index 3b27382468..34604c7175 100644 --- a/run.ps1 +++ b/run.ps1 @@ -52,8 +52,8 @@ in the file are overridden by command line parameters. Example config file: ```json { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master", "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" } ``` @@ -192,7 +192,7 @@ if (!$DotNetHome) { else { Join-Path $PSScriptRoot '.dotnet'} } -if (!$Channel) { $Channel = 'dev' } +if (!$Channel) { $Channel = 'master' } if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } # Execute diff --git a/run.sh b/run.sh index 02aac15874..4c1fed5646 100755 --- a/run.sh +++ b/run.sh @@ -220,7 +220,7 @@ if [ -f "$config_file" ]; then config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" else - _error "$config_file contains invalid JSON." + __error "$config_file contains invalid JSON." exit 1 fi elif __machine_has python ; then @@ -228,7 +228,7 @@ if [ -f "$config_file" ]; then config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" else - _error "$config_file contains invalid JSON." + __error "$config_file contains invalid JSON." exit 1 fi elif __machine_has python3 ; then @@ -236,11 +236,11 @@ if [ -f "$config_file" ]; then config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" else - _error "$config_file contains invalid JSON." + __error "$config_file contains invalid JSON." exit 1 fi else - _error 'Missing required command: jq or python. Could not parse the JSON file.' + __error 'Missing required command: jq or python. Could not parse the JSON file.' exit 1 fi @@ -248,7 +248,7 @@ if [ -f "$config_file" ]; then [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" fi -[ -z "$channel" ] && channel='dev' +[ -z "$channel" ] && channel='master' [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' get_korebuild From e8caccf009c24a846382ebb2abb1bc578973ff0c Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 30 Sep 2018 12:09:56 -0700 Subject: [PATCH 36/47] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 24 ++++++++++++------------ korebuild-lock.txt | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 54e156c97d..f633c76b03 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,20 +3,20 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180918.1 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 + 2.2.0-preview1-20180928.5 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 2.0.9 2.1.3 - 2.2.0-preview2-26905-02 + 2.2.0-preview3-26927-02 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 649bf2ba0b..26697a21fa 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180918.1 -commithash:ad5e3fc53442741a0dd49bce437d2ac72f4b5800 +version:2.2.0-preview1-20180928.5 +commithash:43faa29f679f47b88689d645b39e6be5e0055d70 From 6f76189846214f7a5e863e19c29c8acfb79bd5fa Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 2 Oct 2018 11:28:05 -0700 Subject: [PATCH 37/47] Normalize internationalized domain names when adding to CORS Fixes https://github.com/aspnet/Home/issues/3353 --- .../Infrastructure/CorsPolicyBuilder.cs | 44 +++++++++- .../CorsPolicyBuilderTests.cs | 84 ++++++++++++++++++- 2 files changed, 124 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyBuilder.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyBuilder.cs index 3953296168..145571ab60 100644 --- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyBuilder.cs +++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyBuilder.cs @@ -17,6 +17,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure /// Creates a new instance of the . /// /// list of origins which can be added. + /// for details on normalizing the origin value. public CorsPolicyBuilder(params string[] origins) { WithOrigins(origins); @@ -36,16 +37,55 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure /// /// The origins that are allowed. /// The current policy builder. + /// + /// This method normalizes the origin value prior to adding it to to match + /// the normalization performed by the browser on the value sent in the ORIGIN header. + /// + /// + /// If the specified origin has an internationalized domain name (IDN), the punycoded value is used. If the origin + /// specifies a default port (e.g. 443 for HTTPS or 80 for HTTP), this will be dropped as part of normalization. + /// Finally, the scheme and punycoded host name are culture invariant lower cased before being added to the + /// collection. + /// + /// + /// For all other origins, normalization involves performing a culture invariant lower casing of the host name. + /// + /// + /// public CorsPolicyBuilder WithOrigins(params string[] origins) { foreach (var origin in origins) { - _policy.Origins.Add(origin.ToLowerInvariant()); + var normalizedOrigin = GetNormalizedOrigin(origin); + _policy.Origins.Add(normalizedOrigin); } return this; } + internal static string GetNormalizedOrigin(string origin) + { + if (Uri.TryCreate(origin, UriKind.Absolute, out var uri) && + (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps) && + !string.Equals(uri.IdnHost, uri.Host, StringComparison.Ordinal)) + { + var builder = new UriBuilder(uri.Scheme.ToLowerInvariant(), uri.IdnHost.ToLowerInvariant()); + if (!uri.IsDefaultPort) + { + // Uri does not have a way to differentiate between a port value inferred by default (e.g. Port = 80 for http://www.example.com) and + // a default port value that is specified (e.g. Port = 80 for http://www.example.com:80). Although the HTTP or FETCH spec does not say + // anything about including the default port as part of the Origin header, at the time of writing, browsers drop "default" port when navigating + // and when sending the Origin header. All this goes to say, it appears OK to drop an explicitly specified port, + // if it is the default port when working with an IDN host. + builder.Port = uri.Port; + } + + return builder.Uri.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped); + } + + return origin.ToLowerInvariant(); + } + /// /// Adds the specified to the policy. /// @@ -222,4 +262,4 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure return this; } } -} \ No newline at end of file +} diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs index c9b3afca84..6aa6cd0cd7 100644 --- a/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs +++ b/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -299,5 +299,85 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var corsPolicy = builder.Build(); Assert.False(corsPolicy.SupportsCredentials); } + + [Theory] + [InlineData("Some-String", "some-string")] + [InlineData("x:\\Test", "x:\\test")] + [InlineData("FTP://Some-url", "ftp://some-url")] + public void GetNormalizedOrigin_ReturnsLowerCasedValue_IfStringIsNotHttpOrHttpsUrl(string origin, string expected) + { + // Act + var normalizedOrigin = CorsPolicyBuilder.GetNormalizedOrigin(origin); + + // Assert + Assert.Equal(expected, normalizedOrigin); + } + + [Fact] + public void GetNormalizedOrigin_DoesNotAddPort_IfUriDoesNotSpecifyOne() + { + // Arrange + var origin = "http://www.example.com"; + + // Act + var normalizedOrigin = CorsPolicyBuilder.GetNormalizedOrigin(origin); + + // Assert + Assert.Equal(origin, normalizedOrigin); + } + + [Fact] + public void GetNormalizedOrigin_LowerCasesScheme() + { + // Arrange + var origin = "HTTP://www.example.com"; + + // Act + var normalizedOrigin = CorsPolicyBuilder.GetNormalizedOrigin(origin); + + // Assert + Assert.Equal("http://www.example.com", normalizedOrigin); + } + + [Fact] + public void GetNormalizedOrigin_LowerCasesHost() + { + // Arrange + var origin = "http://www.Example.Com"; + + // Act + var normalizedOrigin = CorsPolicyBuilder.GetNormalizedOrigin(origin); + + // Assert + Assert.Equal("http://www.example.com", normalizedOrigin); + } + + [Theory] + [InlineData("http://www.Example.com:80", "http://www.example.com:80")] + [InlineData("https://www.Example.com:8080", "https://www.example.com:8080")] + public void GetNormalizedOrigin_PreservesPort_ForNonIdnHosts(string origin, string expected) + { + // Act + var normalizedOrigin = CorsPolicyBuilder.GetNormalizedOrigin(origin); + + // Assert + Assert.Equal(expected, normalizedOrigin); + } + + [Theory] + [InlineData("http://Bücher.example", "http://xn--bcher-kva.example")] + [InlineData("http://Bücher.example.com:83", "http://xn--bcher-kva.example.com:83")] + [InlineData("https://example.қаз", "https://example.xn--80ao21a")] + [InlineData("http://😉.fm", "http://xn--n28h.fm")] + // Note that in following case, the default port (443 for HTTPS) is not preserved. + [InlineData("https://www.example.இந்தியா:443", "https://www.example.xn--xkc2dl3a5ee0h")] + public void GetNormalizedOrigin_ReturnsPunyCodedOrigin(string origin, string expected) + { + // Act + var normalizedOrigin = CorsPolicyBuilder.GetNormalizedOrigin(origin); + + // Assert + Assert.Equal(expected, normalizedOrigin); + } } -} \ No newline at end of file +} From b9166f14f105cb163942b50f1a9a5b3e3f43e5a5 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 8 Oct 2018 09:03:24 -0700 Subject: [PATCH 38/47] Skipping test failing on Win2k8 R2 --- test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs index 6aa6cd0cd7..9cbf50611c 100644 --- a/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs +++ b/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs @@ -368,7 +368,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure [InlineData("http://Bücher.example", "http://xn--bcher-kva.example")] [InlineData("http://Bücher.example.com:83", "http://xn--bcher-kva.example.com:83")] [InlineData("https://example.қаз", "https://example.xn--80ao21a")] - [InlineData("http://😉.fm", "http://xn--n28h.fm")] + [InlineData("http://😉.fm", "http://xn--n28h.fm", Skip = "Fails on Win2k8 R2")] // Note that in following case, the default port (443 for HTTPS) is not preserved. [InlineData("https://www.example.இந்தியா:443", "https://www.example.xn--xkc2dl3a5ee0h")] public void GetNormalizedOrigin_ReturnsPunyCodedOrigin(string origin, string expected) From 2690a3f621578d8f656f4b21eef023f702a4a169 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 10 Aug 2018 17:51:34 -0700 Subject: [PATCH 39/47] Remove filtering from CorsService * Add browser based integration tests --- .travis.yml | 4 + .vsts-pipelines/builds/ci-internal.yml | 27 +- .vsts-pipelines/builds/ci-public.yml | 27 +- CORS.sln | 7 + build/buildpipeline/linux.groovy | 9 - build/buildpipeline/osx.groovy | 9 - build/buildpipeline/windows.groovy | 2 +- build/dependencies.props | 26 +- build/repo.targets | 11 + korebuild-lock.txt | 4 +- samples/SampleDestination/Program.cs | 2 +- samples/SampleDestination/SampleMiddleware.cs | 33 + samples/SampleDestination/Startup.cs | 78 +- samples/SampleOrigin/Program.cs | 2 +- samples/SampleOrigin/SampleOrigin.csproj | 7 + samples/SampleOrigin/Startup.cs | 11 +- samples/SampleOrigin/wwwroot/Index.html | 89 - samples/SampleOrigin/wwwroot/index.htm | 2 + samples/SampleOrigin/wwwroot/test.htm | 135 + .../Infrastructure/CorsMiddleware.cs | 101 +- .../Infrastructure/CorsResult.cs | 11 + .../Infrastructure/CorsService.cs | 237 +- .../Internal/CORSLoggerExtensions.cs | 22 + test/FunctionalTests/Assert.cs | 45 + .../CorsMiddlewareFunctionalTest.cs | 144 + test/FunctionalTests/FunctionalTests.csproj | 28 + test/FunctionalTests/ProcessManager.cs | 101 + test/FunctionalTests/ProcessResult.cs | 21 + test/FunctionalTests/package-lock.json | 5637 +++++++++++++++++ test/FunctionalTests/package.json | 10 + test/FunctionalTests/test.js | 280 + .../CorsMiddlewareFunctionalTest.cs | 98 - .../CorsMiddlewareTests.cs | 164 +- .../CorsServiceTests.cs | 614 +- .../CorsTestFixtureOfT.cs | 33 - .../DefaultCorsPolicyProviderTests.cs | 11 +- .../TestCorsOptions.cs | 12 - .../UriHelpersTests.cs | 4 +- 38 files changed, 7173 insertions(+), 885 deletions(-) create mode 100644 build/repo.targets create mode 100644 samples/SampleDestination/SampleMiddleware.cs delete mode 100644 samples/SampleOrigin/wwwroot/Index.html create mode 100644 samples/SampleOrigin/wwwroot/index.htm create mode 100644 samples/SampleOrigin/wwwroot/test.htm create mode 100644 test/FunctionalTests/Assert.cs create mode 100644 test/FunctionalTests/CorsMiddlewareFunctionalTest.cs create mode 100644 test/FunctionalTests/FunctionalTests.csproj create mode 100644 test/FunctionalTests/ProcessManager.cs create mode 100644 test/FunctionalTests/ProcessResult.cs create mode 100644 test/FunctionalTests/package-lock.json create mode 100644 test/FunctionalTests/package.json create mode 100644 test/FunctionalTests/test.js delete mode 100644 test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareFunctionalTest.cs delete mode 100644 test/Microsoft.AspNetCore.Cors.Test/CorsTestFixtureOfT.cs delete mode 100644 test/Microsoft.AspNetCore.Cors.Test/TestCorsOptions.cs diff --git a/.travis.yml b/.travis.yml index 1ad255d7b8..20565993c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,9 @@ mono: none os: - linux - osx +env: + global: + - TRAVIS_NODE_VERSION: 8.9.3 osx_image: xcode8.2 addons: apt: @@ -16,6 +19,7 @@ branches: - /^release\/.*$/ - /^(.*\/)?ci-.*$/ before_install: +- nvm install $TRAVIS_NODE_VERSION - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml index dc7b8a3cb9..a19cee5885 100644 --- a/.vsts-pipelines/builds/ci-internal.yml +++ b/.vsts-pipelines/builds/ci-internal.yml @@ -10,4 +10,29 @@ resources: ref: refs/heads/release/2.2 phases: -- template: .vsts-pipelines/templates/project-ci.yml@buildtools +- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools + parameters: + agentOs: Windows + beforeBuild: + - task: NodeTool@0 + displayName: Use Node 8.x + inputs: + versionSpec: 8.x + +- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools + parameters: + agentOs: macOS + beforeBuild: + - task: NodeTool@0 + displayName: Use Node 8.x + inputs: + versionSpec: 8.x + +- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools + parameters: + agentOs: Linux + beforeBuild: + - task: NodeTool@0 + displayName: Use Node 8.x + inputs: + versionSpec: 8.x diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml index f5087d9c30..1cca5b68cc 100644 --- a/.vsts-pipelines/builds/ci-public.yml +++ b/.vsts-pipelines/builds/ci-public.yml @@ -12,4 +12,29 @@ resources: ref: refs/heads/release/2.2 phases: -- template: .vsts-pipelines/templates/project-ci.yml@buildtools +- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools + parameters: + agentOs: Windows + beforeBuild: + - task: NodeTool@0 + displayName: Use Node 8.x + inputs: + versionSpec: 8.x + +- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools + parameters: + agentOs: macOS + beforeBuild: + - task: NodeTool@0 + displayName: Use Node 8.x + inputs: + versionSpec: 8.x + +- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools + parameters: + agentOs: Linux + beforeBuild: + - task: NodeTool@0 + displayName: Use Node 8.x + inputs: + versionSpec: 8.x diff --git a/CORS.sln b/CORS.sln index afdbf1fdc0..6ad6179b3f 100644 --- a/CORS.sln +++ b/CORS.sln @@ -45,6 +45,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution version.xml = version.xml EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FunctionalTests", "test\FunctionalTests\FunctionalTests.csproj", "{99EB6889-C7D8-4BC3-AF99-B966B9E64C81}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -71,6 +73,10 @@ Global {99460370-AE5D-4DC9-8DBF-04DF66D6B21D}.Debug|Any CPU.Build.0 = Debug|Any CPU {99460370-AE5D-4DC9-8DBF-04DF66D6B21D}.Release|Any CPU.ActiveCfg = Release|Any CPU {99460370-AE5D-4DC9-8DBF-04DF66D6B21D}.Release|Any CPU.Build.0 = Release|Any CPU + {99EB6889-C7D8-4BC3-AF99-B966B9E64C81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99EB6889-C7D8-4BC3-AF99-B966B9E64C81}.Debug|Any CPU.Build.0 = Debug|Any CPU + {99EB6889-C7D8-4BC3-AF99-B966B9E64C81}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99EB6889-C7D8-4BC3-AF99-B966B9E64C81}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -82,6 +88,7 @@ Global {B42D4844-FFF8-4EC2-88D1-3AE95234D9EB} = {538380BF-0D4C-4E30-8F41-E75C4B1C01FA} {F6675DC1-AA21-453B-89B6-DA425FB9C3A5} = {960E0703-A8A5-44DF-AA87-B7C614683B3C} {99460370-AE5D-4DC9-8DBF-04DF66D6B21D} = {960E0703-A8A5-44DF-AA87-B7C614683B3C} + {99EB6889-C7D8-4BC3-AF99-B966B9E64C81} = {F32074C7-087C-46CC-A913-422BFD2D6E0A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {F9ED9C53-44CD-4853-9621-D028B7B6A431} diff --git a/build/buildpipeline/linux.groovy b/build/buildpipeline/linux.groovy index 903f218bb8..791d923d0c 100644 --- a/build/buildpipeline/linux.groovy +++ b/build/buildpipeline/linux.groovy @@ -1,10 +1 @@ @Library('dotnet-ci') _ - -simpleNode('Ubuntu16.04', 'latest-or-auto-docker') { - stage ('Checking out source') { - checkout scm - } - stage ('Build') { - sh './build.sh --ci' - } -} diff --git a/build/buildpipeline/osx.groovy b/build/buildpipeline/osx.groovy index aaac63686b..791d923d0c 100644 --- a/build/buildpipeline/osx.groovy +++ b/build/buildpipeline/osx.groovy @@ -1,10 +1 @@ @Library('dotnet-ci') _ - -simpleNode('OSX10.12','latest') { - stage ('Checking out source') { - checkout scm - } - stage ('Build') { - sh './build.sh --ci' - } -} diff --git a/build/buildpipeline/windows.groovy b/build/buildpipeline/windows.groovy index 8d26f313d4..26f49c395d 100644 --- a/build/buildpipeline/windows.groovy +++ b/build/buildpipeline/windows.groovy @@ -2,7 +2,7 @@ // 'node' indicates to Jenkins that the enclosed block runs on a node that matches // the label 'windows-with-vs' -simpleNode('Windows_NT','latest') { +simpleNode('Windows.10.Amd64.EnterpriseRS3.ASPNET.Open') { stage ('Checking out source') { checkout scm } diff --git a/build/dependencies.props b/build/dependencies.props index f633c76b03..b9fda4f60d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,20 +3,22 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180928.5 - 2.2.0-preview3-35359 - 2.2.0-preview3-35359 - 2.2.0-preview3-35359 - 2.2.0-preview3-35359 - 2.2.0-preview3-35359 - 2.2.0-preview3-35359 - 2.2.0-preview3-35359 - 2.2.0-preview3-35359 - 2.2.0-preview3-35359 - 2.2.0-preview3-35359 + 2.2.0-preview2-20181004.6 + 2.2.0-preview3-35413 + 2.2.0-preview3-35413 + 0.6.0-preview3-35413 + 2.2.0-preview3-35413 + 2.2.0-preview3-35413 + 2.2.0-preview3-35413 + 2.2.0-preview3-35413 + 2.2.0-preview3-35413 + 2.2.0-preview3-35413 + 2.2.0-preview3-35413 + 2.2.0-preview3-35413 + 2.2.0-preview3-35413 2.0.9 2.1.3 - 2.2.0-preview3-26927-02 + 2.2.0-preview3-27001-02 15.6.1 4.7.49 2.0.3 diff --git a/build/repo.targets b/build/repo.targets new file mode 100644 index 0000000000..e2057ccf22 --- /dev/null +++ b/build/repo.targets @@ -0,0 +1,11 @@ + + + $(RestoreDependsOn);RestoreNpm + + + + + + + + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 26697a21fa..96fe3217ef 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180928.5 -commithash:43faa29f679f47b88689d645b39e6be5e0055d70 +version:2.2.0-preview2-20181004.6 +commithash:c04c4b2f5018632647f96210ab01876661302dac diff --git a/samples/SampleDestination/Program.cs b/samples/SampleDestination/Program.cs index 0c2bf0968f..8cef67c306 100644 --- a/samples/SampleDestination/Program.cs +++ b/samples/SampleDestination/Program.cs @@ -13,7 +13,7 @@ namespace SampleDestination { var host = new WebHostBuilder() .UseKestrel() - .UseUrls("http://*:5000") + .UseUrls("http://+:9000") .UseContentRoot(Directory.GetCurrentDirectory()) .ConfigureLogging(factory => factory.AddConsole()) .UseStartup() diff --git a/samples/SampleDestination/SampleMiddleware.cs b/samples/SampleDestination/SampleMiddleware.cs new file mode 100644 index 0000000000..ac53eb5908 --- /dev/null +++ b/samples/SampleDestination/SampleMiddleware.cs @@ -0,0 +1,33 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; + +namespace SampleDestination +{ + public class SampleMiddleware + { + private readonly RequestDelegate _next; + + public SampleMiddleware(RequestDelegate next) + { + _next = next; + } + + public Task Invoke(HttpContext context) + { + var content = Encoding.UTF8.GetBytes("Hello world"); + + context.Response.Headers["X-AllowedHeader"] = "Test-Value"; + context.Response.Headers["X-DisallowedHeader"] = "Test-Value"; + + context.Response.ContentType = "text/plain; charset=utf-8"; + context.Response.ContentLength = content.Length; + context.Response.Body.Write(content, 0, content.Length); + + return Task.CompletedTask; + } + } +} diff --git a/samples/SampleDestination/Startup.cs b/samples/SampleDestination/Startup.cs index 0664d84572..af93d605c9 100644 --- a/samples/SampleDestination/Startup.cs +++ b/samples/SampleDestination/Startup.cs @@ -1,6 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; +using System.Net; +using System.Text; +using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; @@ -11,6 +15,15 @@ namespace SampleDestination { public class Startup { + private static readonly string DefaultAllowedOrigin = $"http://{Dns.GetHostName()}:9001"; + private readonly ILogger _logger; + + public Startup(ILoggerFactory loggerFactory) + { + _logger = loggerFactory.CreateLogger(); + _logger.LogInformation($"Setting up CORS middleware to allow clients on {DefaultAllowedOrigin}"); + } + public void ConfigureServices(IServiceCollection services) { services.AddCors(); @@ -18,21 +31,60 @@ namespace SampleDestination public void Configure(IApplicationBuilder app, IHostingEnvironment env) { - app.UseCors(policy => policy - .WithOrigins("http://origin.example.com:5001") - .WithMethods("PUT") - .WithHeaders("Cache-Control")); - - app.Run(async context => + app.Map("/allow-origin", innerBuilder => { - var responseHeaders = context.Response.Headers; - context.Response.ContentType = "text/plain"; - foreach (var responseHeader in responseHeaders) - { - await context.Response.WriteAsync("\n" + responseHeader.Key + ": " + responseHeader.Value); - } + innerBuilder.UseCors(policy => policy + .WithOrigins(DefaultAllowedOrigin) + .AllowAnyMethod() + .AllowAnyHeader()); - await context.Response.WriteAsync("\nStatus code of your request: " + context.Response.StatusCode.ToString()); + innerBuilder.UseMiddleware(); + }); + + app.Map("/allow-header-method", innerBuilder => + { + innerBuilder.UseCors(policy => policy + .WithOrigins(DefaultAllowedOrigin) + .WithHeaders("X-Test", "Content-Type") + .WithMethods("PUT")); + + innerBuilder.UseMiddleware(); + }); + + app.Map("/allow-credentials", innerBuilder => + { + innerBuilder.UseCors(policy => policy + .WithOrigins(DefaultAllowedOrigin) + .AllowAnyHeader() + .WithMethods("GET", "PUT") + .AllowCredentials()); + + innerBuilder.UseMiddleware(); + }); + + app.Map("/exposed-header", innerBuilder => + { + innerBuilder.UseCors(policy => policy + .WithOrigins(DefaultAllowedOrigin) + .WithExposedHeaders("X-AllowedHeader", "Content-Length")); + + innerBuilder.UseMiddleware(); + }); + + app.Map("/allow-all", innerBuilder => + { + innerBuilder.UseCors(policy => policy + .AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); + + innerBuilder.UseMiddleware(); + }); + + app.Run(async (context) => + { + await context.Response.WriteAsync("Hello World!"); }); } } diff --git a/samples/SampleOrigin/Program.cs b/samples/SampleOrigin/Program.cs index 278c09f48a..576e25f0e3 100644 --- a/samples/SampleOrigin/Program.cs +++ b/samples/SampleOrigin/Program.cs @@ -13,7 +13,7 @@ namespace SampleOrigin { var host = new WebHostBuilder() .UseKestrel() - .UseUrls("http://*:5001") + .UseUrls("http://+:9001", "http://+:9002") .UseContentRoot(Directory.GetCurrentDirectory()) .ConfigureLogging(factory => factory.AddConsole()) .UseStartup() diff --git a/samples/SampleOrigin/SampleOrigin.csproj b/samples/SampleOrigin/SampleOrigin.csproj index 054a6eb713..441b40505f 100644 --- a/samples/SampleOrigin/SampleOrigin.csproj +++ b/samples/SampleOrigin/SampleOrigin.csproj @@ -6,7 +6,14 @@ + + + + PreserveNewest + + + diff --git a/samples/SampleOrigin/Startup.cs b/samples/SampleOrigin/Startup.cs index a442b98d68..37f49bdee0 100644 --- a/samples/SampleOrigin/Startup.cs +++ b/samples/SampleOrigin/Startup.cs @@ -1,11 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; namespace SampleOrigin { @@ -17,13 +17,8 @@ namespace SampleOrigin public void Configure(IApplicationBuilder app, IHostingEnvironment env) { - app.Run(context => - { - var fileInfoProvider = env.WebRootFileProvider; - var fileInfo = fileInfoProvider.GetFileInfo("/Index.html"); - context.Response.ContentType = "text/html"; - return context.Response.SendFileAsync(fileInfo); - }); + app.UseDefaultFiles(); + app.UseStaticFiles(); } } } diff --git a/samples/SampleOrigin/wwwroot/Index.html b/samples/SampleOrigin/wwwroot/Index.html deleted file mode 100644 index fad335b83f..0000000000 --- a/samples/SampleOrigin/wwwroot/Index.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - CORS Sample - - - - -

CORS Sample

- Method:

- Header Name: Header Value:

- - - -



- - Method DELETE is not allowed: - Method PUT is allowed:

- - Header 'Max-Forwards' not supported: - Header 'Cache-Control' is supported:

- - \ No newline at end of file diff --git a/samples/SampleOrigin/wwwroot/index.htm b/samples/SampleOrigin/wwwroot/index.htm new file mode 100644 index 0000000000..dbdd96c177 --- /dev/null +++ b/samples/SampleOrigin/wwwroot/index.htm @@ -0,0 +1,2 @@ +

Welcome to the CORS test suite. Please wait...

+Click here for the browser test suite. diff --git a/samples/SampleOrigin/wwwroot/test.htm b/samples/SampleOrigin/wwwroot/test.htm new file mode 100644 index 0000000000..6a2f4cddf1 --- /dev/null +++ b/samples/SampleOrigin/wwwroot/test.htm @@ -0,0 +1,135 @@ + + + + + + CORS Sample + + +

CORS Sample

+ + + + + + + + + + +
ScenarioResult
+ + + + diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs index fb3df360e6..f71c198de7 100644 --- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs +++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs @@ -7,21 +7,19 @@ using Microsoft.AspNetCore.Cors.Internal; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Primitives; namespace Microsoft.AspNetCore.Cors.Infrastructure { /// - /// An ASP.NET middleware for handling CORS. + /// A middleware for handling CORS. /// public class CorsMiddleware { + private readonly Func OnResponseStartingDelegate = OnResponseStarting; private readonly RequestDelegate _next; - private readonly ICorsService _corsService; private readonly ICorsPolicyProvider _corsPolicyProvider; private readonly CorsPolicy _policy; private readonly string _corsPolicyName; - private readonly ILogger _logger; /// /// Instantiates a new . @@ -122,10 +120,10 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure } _next = next; - _corsService = corsService; + CorsService = corsService; _corsPolicyProvider = policyProvider; _corsPolicyName = policyName; - _logger = loggerFactory.CreateLogger(); + Logger = loggerFactory.CreateLogger(); } /// @@ -162,60 +160,65 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure } _next = next; - _corsService = corsService; + CorsService = corsService; _policy = policy; - _logger = loggerFactory.CreateLogger(); + Logger = loggerFactory.CreateLogger(); } + private ICorsService CorsService { get; } + + private ILogger Logger { get; } + /// - public async Task Invoke(HttpContext context) + public Task Invoke(HttpContext context) { - if (context.Request.Headers.ContainsKey(CorsConstants.Origin)) + if (!context.Request.Headers.ContainsKey(CorsConstants.Origin)) { - var corsPolicy = _policy ?? await _corsPolicyProvider?.GetPolicyAsync(context, _corsPolicyName); - if (corsPolicy != null) - { - var accessControlRequestMethod = - context.Request.Headers[CorsConstants.AccessControlRequestMethod]; - if (string.Equals( - context.Request.Method, - CorsConstants.PreflightHttpMethod, - StringComparison.OrdinalIgnoreCase) && - !StringValues.IsNullOrEmpty(accessControlRequestMethod)) - { - ApplyCorsHeaders(context, corsPolicy); - - // Since there is a policy which was identified, - // always respond to preflight requests. - context.Response.StatusCode = StatusCodes.Status204NoContent; - return; - } - else - { - context.Response.OnStarting(state => - { - var (httpContext, policy) = (Tuple)state; - try - { - ApplyCorsHeaders(httpContext, policy); - } - catch (Exception exception) - { - _logger.FailedToSetCorsHeaders(exception); - } - return Task.CompletedTask; - }, Tuple.Create(context, corsPolicy)); - } - } + return _next(context); } - await _next(context); + return InvokeCore(context); } - private void ApplyCorsHeaders(HttpContext context, CorsPolicy corsPolicy) + private async Task InvokeCore(HttpContext context) { - var corsResult = _corsService.EvaluatePolicy(context, corsPolicy); - _corsService.ApplyResult(corsResult, context.Response); + var corsPolicy = _policy ?? await _corsPolicyProvider?.GetPolicyAsync(context, _corsPolicyName); + if (corsPolicy == null) + { + Logger?.NoCorsPolicyFound(); + await _next(context); + return; + } + + var corsResult = CorsService.EvaluatePolicy(context, corsPolicy); + if (corsResult.IsPreflightRequest) + { + CorsService.ApplyResult(corsResult, context.Response); + + // Since there is a policy which was identified, + // always respond to preflight requests. + context.Response.StatusCode = StatusCodes.Status204NoContent; + return; + } + else + { + context.Response.OnStarting(OnResponseStartingDelegate, Tuple.Create(this, context, corsResult)); + await _next(context); + } + } + + private static Task OnResponseStarting(object state) + { + var (middleware, context, result) = (Tuple)state; + try + { + middleware.CorsService.ApplyResult(result, context.Response); + } + catch (Exception exception) + { + middleware.Logger?.FailedToSetCorsHeaders(exception); + } + return Task.CompletedTask; } } } diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsResult.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsResult.cs index 99d38b9fd1..558a99a31d 100644 --- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsResult.cs +++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsResult.cs @@ -14,11 +14,22 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure { private TimeSpan? _preflightMaxAge; + /// + /// Gets or sets a value that determines if the current request is a CORS-preflight request. + /// + public bool IsPreflightRequest { get; set; } + /// /// Gets or sets the allowed origin. /// public string AllowedOrigin { get; set; } + /// + /// Gets or sets a value that determines if the origin is allowed. + /// When false, no CORS headers should be sent. + /// + public bool IsOriginAllowed { get; set; } + /// /// Gets or sets a value indicating whether the resource supports user credentials. /// diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs index 5be99f4f71..0ec9c030f3 100644 --- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs +++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs @@ -8,6 +8,7 @@ using System.Linq; using Microsoft.AspNetCore.Cors.Internal; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; @@ -25,8 +26,9 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure /// Creates a new instance of the . /// /// The option model representing . + [Obsolete("This constructor is obsolete and will be removed in a future version.")] public CorsService(IOptions options) - : this(options, loggerFactory: null) + : this(options, loggerFactory: NullLoggerFactory.Instance) { } @@ -42,8 +44,13 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure throw new ArgumentNullException(nameof(options)); } + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + _options = options.Value; - _logger = loggerFactory?.CreateLogger(); + _logger = loggerFactory.CreateLogger(); } /// @@ -78,12 +85,25 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure throw new ArgumentNullException(nameof(policy)); } - var corsResult = new CorsResult(); - var accessControlRequestMethod = context.Request.Headers[CorsConstants.AccessControlRequestMethod]; - if (string.Equals(context.Request.Method, CorsConstants.PreflightHttpMethod, StringComparison.OrdinalIgnoreCase) && - !StringValues.IsNullOrEmpty(accessControlRequestMethod)) + if (policy.AllowAnyOrigin && policy.SupportsCredentials) + { + _logger.InsecureConfiguration(); + } + + var origin = context.Request.Headers[CorsConstants.Origin]; + var requestHeaders = context.Request.Headers; + var isPreflightRequest = + string.Equals(context.Request.Method, CorsConstants.PreflightHttpMethod, StringComparison.OrdinalIgnoreCase) && + requestHeaders.ContainsKey(CorsConstants.AccessControlRequestMethod); + + var corsResult = new CorsResult + { + IsPreflightRequest = isPreflightRequest, + IsOriginAllowed = IsOriginAllowed(policy, origin), + }; + + if (isPreflightRequest) { - _logger?.IsPreflightRequest(); EvaluatePreflightRequest(context, policy, corsResult); } else @@ -94,78 +114,37 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure return corsResult; } - public virtual void EvaluateRequest(HttpContext context, CorsPolicy policy, CorsResult result) + private static void PopulateResult(HttpContext context, CorsPolicy policy, CorsResult result) { - var origin = context.Request.Headers[CorsConstants.Origin]; - if (!IsOriginAllowed(policy, origin)) + if (policy.AllowAnyOrigin) { - return; + result.AllowedOrigin = CorsConstants.AnyOrigin; + result.VaryByOrigin = policy.SupportsCredentials; + } + else + { + var origin = context.Request.Headers[CorsConstants.Origin]; + result.AllowedOrigin = origin; + result.VaryByOrigin = policy.Origins.Count > 1; } - AddOriginToResult(origin, policy, result); result.SupportsCredentials = policy.SupportsCredentials; + result.PreflightMaxAge = policy.PreflightMaxAge; + + AddHeaderValues(result.AllowedExposedHeaders, policy.ExposedHeaders); - _logger?.PolicySuccess(); + AddHeaderValues(result.AllowedMethods, policy.Methods); + AddHeaderValues(result.AllowedHeaders, policy.Headers); + } + + public virtual void EvaluateRequest(HttpContext context, CorsPolicy policy, CorsResult result) + { + PopulateResult(context, policy, result); } public virtual void EvaluatePreflightRequest(HttpContext context, CorsPolicy policy, CorsResult result) { - var origin = context.Request.Headers[CorsConstants.Origin]; - if (!IsOriginAllowed(policy, origin)) - { - return; - } - - var accessControlRequestMethod = context.Request.Headers[CorsConstants.AccessControlRequestMethod]; - if (StringValues.IsNullOrEmpty(accessControlRequestMethod)) - { - return; - } - - var requestHeaders = - context.Request.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlRequestHeaders); - - if (!policy.AllowAnyMethod) - { - var found = false; - for (var i = 0; i < policy.Methods.Count; i++) - { - var method = policy.Methods[i]; - if (string.Equals(method, accessControlRequestMethod, StringComparison.OrdinalIgnoreCase)) - { - found = true; - break; - } - } - - if (!found) - { - _logger?.PolicyFailure(); - _logger?.AccessControlMethodNotAllowed(accessControlRequestMethod); - return; - } - } - - if (!policy.AllowAnyHeader && - requestHeaders != null) - { - foreach (var requestHeader in requestHeaders) - { - if (!policy.Headers.Contains(requestHeader, StringComparer.OrdinalIgnoreCase)) - { - _logger?.PolicyFailure(); - _logger?.RequestHeaderNotAllowed(requestHeader); - return; - } - } - } - - AddOriginToResult(origin, policy, result); - result.SupportsCredentials = policy.SupportsCredentials; - result.PreflightMaxAge = policy.PreflightMaxAge; - result.AllowedMethods.Add(accessControlRequestMethod); - AddHeaderValues(result.AllowedHeaders, requestHeaders); - _logger?.PolicySuccess(); + PopulateResult(context, policy, result); } /// @@ -181,86 +160,67 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure throw new ArgumentNullException(nameof(response)); } - var headers = response.Headers; - - if (result.AllowedOrigin != null) + if (!result.IsOriginAllowed) { - headers[CorsConstants.AccessControlAllowOrigin] = result.AllowedOrigin; + // In case a server does not wish to participate in the CORS protocol, its HTTP response to the + // CORS or CORS-preflight request must not include any of the above headers. + return; + } + + response.Headers[CorsConstants.AccessControlAllowOrigin] = result.AllowedOrigin; + + if (result.SupportsCredentials) + { + response.Headers[CorsConstants.AccessControlAllowCredentials] = "true"; + } + + if (result.IsPreflightRequest) + { + _logger.IsPreflightRequest(); + + // An HTTP response to a CORS-preflight request can include the following headers: + // `Access-Control-Allow-Methods`, `Access-Control-Allow-Headers`, `Access-Control-Max-Age` + if (result.AllowedHeaders.Count > 0) + { + response.Headers.SetCommaSeparatedValues(CorsConstants.AccessControlAllowHeaders, result.AllowedHeaders.ToArray()); + } + + if (result.AllowedMethods.Count > 0) + { + response.Headers.SetCommaSeparatedValues(CorsConstants.AccessControlAllowMethods, result.AllowedMethods.ToArray()); + } + + if (result.PreflightMaxAge.HasValue) + { + response.Headers[CorsConstants.AccessControlMaxAge] = result.PreflightMaxAge.Value.TotalSeconds.ToString(CultureInfo.InvariantCulture); + } + } + else + { + // An HTTP response to a CORS request that is not a CORS-preflight request can also include the following header: + // `Access-Control-Expose-Headers` + if (result.AllowedExposedHeaders.Count > 0) + { + response.Headers.SetCommaSeparatedValues(CorsConstants.AccessControlExposeHeaders, result.AllowedExposedHeaders.ToArray()); + } } if (result.VaryByOrigin) { - headers["Vary"] = "Origin"; - } - - if (result.SupportsCredentials) - { - headers[CorsConstants.AccessControlAllowCredentials] = "true"; - } - - if (result.AllowedMethods.Count > 0) - { - headers.SetCommaSeparatedValues( - CorsConstants.AccessControlAllowMethods, - result.AllowedMethods.ToArray()); - } - - if (result.AllowedHeaders.Count > 0) - { - headers.SetCommaSeparatedValues( - CorsConstants.AccessControlAllowHeaders, - result.AllowedHeaders.ToArray()); - } - - if (result.AllowedExposedHeaders.Count > 0) - { - headers.SetCommaSeparatedValues( - CorsConstants.AccessControlExposeHeaders, - result.AllowedExposedHeaders.ToArray()); - } - - if (result.PreflightMaxAge.HasValue) - { - headers[CorsConstants.AccessControlMaxAge] - = result.PreflightMaxAge.Value.TotalSeconds.ToString(CultureInfo.InvariantCulture); + response.Headers.Append("Vary", "Origin"); } } - private void AddOriginToResult(string origin, CorsPolicy policy, CorsResult result) - { - if (policy.AllowAnyOrigin) - { - if (policy.SupportsCredentials) - { - result.AllowedOrigin = origin; - result.VaryByOrigin = true; - } - else - { - result.AllowedOrigin = CorsConstants.AnyOrigin; - } - } - else if (policy.IsOriginAllowed(origin)) - { - result.AllowedOrigin = origin; - - if(policy.Origins.Count > 1) - { - result.VaryByOrigin = true; - } - } - } - - private static void AddHeaderValues(IList target, IEnumerable headerValues) + private static void AddHeaderValues(IList target, IList headerValues) { if (headerValues == null) { return; } - foreach (var current in headerValues) + for (var i = 0; i < headerValues.Count; i++) { - target.Add(current); + target.Add(headerValues[i]); } } @@ -268,17 +228,18 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure { if (StringValues.IsNullOrEmpty(origin)) { - _logger?.RequestDoesNotHaveOriginHeader(); + _logger.RequestDoesNotHaveOriginHeader(); return false; } - _logger?.RequestHasOriginHeader(origin); + _logger.RequestHasOriginHeader(origin); if (policy.AllowAnyOrigin || policy.IsOriginAllowed(origin)) { + _logger.PolicySuccess(); return true; } - _logger?.PolicyFailure(); - _logger?.OriginNotAllowed(origin); + _logger.PolicyFailure(); + _logger.OriginNotAllowed(origin); return false; } } diff --git a/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs b/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs index bfcc82a2e6..d324aba1cf 100644 --- a/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs +++ b/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs @@ -17,6 +17,8 @@ namespace Microsoft.AspNetCore.Cors.Internal private static readonly Action _accessControlMethodNotAllowed; private static readonly Action _requestHeaderNotAllowed; private static readonly Action _failedToSetCorsHeaders; + private static readonly Action _noCorsPolicyFound; + private static readonly Action _insecureConfiguration; static CORSLoggerExtensions() { @@ -64,6 +66,16 @@ namespace Microsoft.AspNetCore.Cors.Internal LogLevel.Warning, 9, "Failed to apply CORS Response headers."); + + _noCorsPolicyFound = LoggerMessage.Define( + LogLevel.Information, + new EventId(10, "NoCorsPolicyFound"), + "No CORS policy found for the specified request."); + + _insecureConfiguration = LoggerMessage.Define( + LogLevel.Warning, + new EventId(11, "CorsInsecureConfiguration"), + "The CORS protocol does not allow specifying a wildcard (any) origin and credentials at the same time. Configure the policy by listing individual origins if credentials needs to be supported."); } public static void IsPreflightRequest(this ILogger logger) @@ -110,5 +122,15 @@ namespace Microsoft.AspNetCore.Cors.Internal { _failedToSetCorsHeaders(logger, exception); } + + public static void NoCorsPolicyFound(this ILogger logger) + { + _noCorsPolicyFound(logger, null); + } + + public static void InsecureConfiguration(this ILogger logger) + { + _insecureConfiguration(logger, null); + } } } diff --git a/test/FunctionalTests/Assert.cs b/test/FunctionalTests/Assert.cs new file mode 100644 index 0000000000..6e1ab583d7 --- /dev/null +++ b/test/FunctionalTests/Assert.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Text; +using Xunit.Sdk; + +namespace FunctionalTests +{ + public class Assert : Xunit.Assert + { + public static void Success(in ProcessResult processResult) + { + if (processResult.ExitCode != 0) + { + throw new ProcessAssertException(processResult); + } + } + + private class ProcessAssertException : XunitException + { + public ProcessAssertException(in ProcessResult processResult) + { + Result = processResult; + } + + public ProcessResult Result { get; } + + public override string Message + { + get + { + var message = new StringBuilder(); + message.Append(Result.ProcessStartInfo.FileName); + message.Append(" "); + message.Append(Result.ProcessStartInfo.Arguments); + message.Append($" exited with {Result.ExitCode}."); + message.AppendLine(); + message.AppendLine(); + message.Append(Result.Output); + return message.ToString(); + } + } + } + } +} diff --git a/test/FunctionalTests/CorsMiddlewareFunctionalTest.cs b/test/FunctionalTests/CorsMiddlewareFunctionalTest.cs new file mode 100644 index 0000000000..7c61d1f77b --- /dev/null +++ b/test/FunctionalTests/CorsMiddlewareFunctionalTest.cs @@ -0,0 +1,144 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Server.IntegrationTesting; +using Microsoft.AspNetCore.Testing; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Testing; +using Xunit; +using Xunit.Abstractions; + +namespace FunctionalTests +{ + public class CorsMiddlewareFunctionalTests : LoggedTest + { + public CorsMiddlewareFunctionalTests(ITestOutputHelper output) + : base(output) + { + Output = output; + } + + public ITestOutputHelper Output { get; } + + [Fact] + public async Task RunClientTests() + { + using (StartLog(out var loggerFactory)) + using (var deploymentResult = await CreateDeployments(loggerFactory)) + { + ProcessStartInfo processStartInfo; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + processStartInfo = new ProcessStartInfo + { + FileName = "cmd", + Arguments = "/c npm test --no-color", + }; + } + else + { + processStartInfo = new ProcessStartInfo + { + FileName = "npm", + Arguments = "test", + }; + } + + // Act + var result = await ProcessManager.RunProcessAsync(processStartInfo); + + // Assert + Assert.Success(result); + Assert.Contains("Test Suites: 1 passed, 1 total", result.Output); + } + } + + private static async Task CreateDeployments(ILoggerFactory loggerFactory) + { + var solutionPath = TestPathUtilities.GetSolutionRootDirectory("CORS"); + + var runtimeFlavor = GetRuntimeFlavor(); + var applicationType = runtimeFlavor == RuntimeFlavor.Clr ? ApplicationType.Standalone : ApplicationType.Portable; + + var configuration = +#if RELEASE + "Release"; +#else + "Debug"; +#endif + + var destinationParameters = new DeploymentParameters + { + RuntimeFlavor = runtimeFlavor, + ServerType = ServerType.Kestrel, + ApplicationPath = Path.Combine(solutionPath, "samples", "SampleDestination"), + PublishApplicationBeforeDeployment = false, + ApplicationType = applicationType, + Configuration = configuration, + }; + + var destinationFactory = ApplicationDeployerFactory.Create(destinationParameters, loggerFactory); + var destinationDeployment = await destinationFactory.DeployAsync(); + + var originParameters = new DeploymentParameters + { + RuntimeFlavor = runtimeFlavor, + ServerType = ServerType.Kestrel, + ApplicationPath = Path.Combine(solutionPath, "samples", "SampleOrigin"), + PublishApplicationBeforeDeployment = false, + ApplicationType = applicationType, + Configuration = configuration, + }; + + var originFactory = ApplicationDeployerFactory.Create(originParameters, loggerFactory); + var originDeployment = await originFactory.DeployAsync(); + + return new SamplesDeploymentResult(originFactory, originDeployment, destinationFactory, destinationDeployment); + } + + private static RuntimeFlavor GetRuntimeFlavor() + { +#if NET461 + return RuntimeFlavor.Clr; +#elif NETCOREAPP2_2 + return RuntimeFlavor.CoreClr; +#else +#error Target frameworks need to be updated +#endif + } + + private readonly struct SamplesDeploymentResult : IDisposable + { + public SamplesDeploymentResult( + ApplicationDeployer originDeployer, + DeploymentResult originResult, + ApplicationDeployer destinationDeployer, + DeploymentResult destinationResult) + { + OriginDeployer = originDeployer; + OriginResult = originResult; + DestinationDeployer = destinationDeployer; + DestinationResult = destinationResult; + } + + public ApplicationDeployer OriginDeployer { get; } + + public DeploymentResult OriginResult { get; } + + public ApplicationDeployer DestinationDeployer { get; } + + public DeploymentResult DestinationResult { get; } + + public void Dispose() + { + OriginDeployer.Dispose(); + DestinationDeployer.Dispose(); + } + } + } +} diff --git a/test/FunctionalTests/FunctionalTests.csproj b/test/FunctionalTests/FunctionalTests.csproj new file mode 100644 index 0000000000..edd7b696eb --- /dev/null +++ b/test/FunctionalTests/FunctionalTests.csproj @@ -0,0 +1,28 @@ + + + + $(StandardTestTfms) + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/FunctionalTests/ProcessManager.cs b/test/FunctionalTests/ProcessManager.cs new file mode 100644 index 0000000000..9689a2da7d --- /dev/null +++ b/test/FunctionalTests/ProcessManager.cs @@ -0,0 +1,101 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace FunctionalTests +{ + internal static class ProcessManager + { + private static readonly TimeSpan Timeout = TimeSpan.FromSeconds(60); + + public static Task RunProcessAsync(ProcessStartInfo processStartInfo) + { + processStartInfo.UseShellExecute = false; + processStartInfo.RedirectStandardError = true; + processStartInfo.RedirectStandardOutput = true; + + var process = new Process() + { + StartInfo = processStartInfo, + EnableRaisingEvents = true, + }; + + var output = new StringBuilder(); + var outputLock = new object(); + + process.ErrorDataReceived += Process_ErrorDataReceived; + process.OutputDataReceived += Process_OutputDataReceived; + + process.Start(); + process.BeginErrorReadLine(); + process.BeginOutputReadLine(); + + var timeoutTask = Task.Delay(Timeout).ContinueWith((t) => + { + // Don't timeout during debug sessions + while (Debugger.IsAttached) + { + Thread.Sleep(TimeSpan.FromSeconds(1)); + } + + if (process.HasExited) + { + // This will happen on success, the 'real' task has already completed so this value will + // never be visible. + return (ProcessResult)default; + } + + // This is a timeout. + process.Kill(); + throw new TimeoutException($"command '${process.StartInfo.FileName} {process.StartInfo.Arguments}' timed out after {Timeout}."); + }); + + var waitTask = Task.Run(() => + { + // We need to use two WaitForExit calls to ensure that all of the output/events are processed. Previously + // this code used Process.Exited, which could result in us missing some output due to the ordering of + // events. + // + // See the remarks here: https://msdn.microsoft.com/en-us/library/ty0d8k56(v=vs.110).aspx + if (!process.WaitForExit(int.MaxValue)) + { + // unreachable - the timeoutTask will kill the process before this happens. + throw new TimeoutException(); + } + + process.WaitForExit(); + + string outputString; + lock (outputLock) + { + outputString = output.ToString(); + } + + return new ProcessResult(processStartInfo, process.ExitCode, outputString); + }); + + return Task.WhenAny(waitTask, timeoutTask).Unwrap(); + + void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e) + { + lock (outputLock) + { + output.AppendLine(e.Data); + } + } + + void Process_OutputDataReceived(object sender, DataReceivedEventArgs e) + { + lock (outputLock) + { + output.AppendLine(e.Data); + } + } + } + } +} diff --git a/test/FunctionalTests/ProcessResult.cs b/test/FunctionalTests/ProcessResult.cs new file mode 100644 index 0000000000..8ff1f260bf --- /dev/null +++ b/test/FunctionalTests/ProcessResult.cs @@ -0,0 +1,21 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Diagnostics; + +namespace FunctionalTests +{ + public readonly struct ProcessResult + { + public ProcessResult(ProcessStartInfo processStartInfo, int exitCode, string output) + { + ProcessStartInfo = processStartInfo; + ExitCode = exitCode; + Output = output; + } + + public ProcessStartInfo ProcessStartInfo { get; } + public int ExitCode { get; } + public string Output { get; } + } +} diff --git a/test/FunctionalTests/package-lock.json b/test/FunctionalTests/package-lock.json new file mode 100644 index 0000000000..93547d2bde --- /dev/null +++ b/test/FunctionalTests/package-lock.json @@ -0,0 +1,5637 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "esutils": "2.0.2", + "js-tokens": "4.0.0" + }, + "dependencies": { + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + } + } + }, + "abab": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", + "dev": true + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "acorn-globals": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", + "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", + "dev": true, + "requires": { + "acorn": "6.0.1", + "acorn-walk": "6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.1.tgz", + "integrity": "sha512-SiwgrRuRD2D1R6qjwwoopKcCTkmmIWjy1M15Wv+Nk/7VUsBad4P8GOPft2t6coDZG0TuR5dq9o1v0g8wo7F6+A==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.0.1.tgz", + "integrity": "sha512-PqVQ8c6a3kyqdsUZlC7nljp3FFuxipBRHKu+7C1h8QygBFlzTaDX5HD383jej3Peed+1aDG8HwkfB1Z1HMNPkw==", + "dev": true + }, + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "dev": true, + "requires": { + "es6-promisify": "5.0.0" + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.3" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "3.1.10", + "normalize-path": "2.1.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.3", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } + } + }, + "append-transform": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", + "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", + "dev": true, + "requires": { + "default-require-extensions": "1.0.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true, + "requires": { + "lodash": "4.17.11" + } + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.6.0", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.11", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.11", + "source-map": "0.5.7", + "trim-right": "1.0.1" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-jest": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-23.6.0.tgz", + "integrity": "sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==", + "dev": true, + "requires": { + "babel-plugin-istanbul": "4.1.6", + "babel-preset-jest": "23.2.0" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-istanbul": { + "version": "4.1.6", + "resolved": "http://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz", + "integrity": "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "find-up": "2.1.0", + "istanbul-lib-instrument": "1.10.2", + "test-exclude": "4.2.3" + } + }, + "babel-plugin-jest-hoist": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz", + "integrity": "sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=", + "dev": true + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "babel-preset-jest": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz", + "integrity": "sha1-jsegOhOPABoaj7HoETZSvxpV2kY=", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "23.2.0", + "babel-plugin-syntax-object-rest-spread": "6.13.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "6.26.3", + "babel-runtime": "6.26.0", + "core-js": "2.5.7", + "home-or-tmp": "2.0.0", + "lodash": "4.17.11", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.5.7", + "regenerator-runtime": "0.11.1" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.11" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.4", + "lodash": "4.17.11" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.11", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.3" + } + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + } + }, + "bser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz", + "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", + "dev": true, + "requires": { + "node-int64": "0.4.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "capture-exit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-1.2.0.tgz", + "integrity": "sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28=", + "dev": true, + "requires": { + "rsvp": "3.6.2" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.5.0" + } + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true, + "optional": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" + } + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "cssom": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz", + "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==", + "dev": true + }, + "cssstyle": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.1.1.tgz", + "integrity": "sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog==", + "dev": true, + "requires": { + "cssom": "0.3.4" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "data-urls": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.1.tgz", + "integrity": "sha512-0HdcMZzK6ubMUnsMmQmG0AcLQPvbvb47R0+7CCZQCYgcd8OUWG91CG7sM6GoXgjz+WLl4ArFzHtBMy/QqSF4eg==", + "dev": true, + "requires": { + "abab": "2.0.0", + "whatwg-mimetype": "2.2.0", + "whatwg-url": "7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "dev": true, + "requires": { + "lodash.sortby": "4.7.0", + "tr46": "1.0.1", + "webidl-conversions": "4.0.2" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "default-require-extensions": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", + "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", + "dev": true, + "requires": { + "strip-bom": "2.0.0" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "4.0.2" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1", + "safer-buffer": "2.1.2" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es-abstract": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "dev": true, + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.3", + "is-callable": "1.1.4", + "is-regex": "1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, + "requires": { + "is-callable": "1.1.4", + "is-date-object": "1.0.1", + "is-symbol": "1.0.2" + } + }, + "es6-promise": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", + "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "4.2.5" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", + "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", + "dev": true, + "requires": { + "esprima": "3.1.3", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.6.1" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "exec-sh": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz", + "integrity": "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==", + "dev": true, + "requires": { + "merge": "1.2.0" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.4" + } + }, + "expect": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-23.6.0.tgz", + "integrity": "sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "jest-diff": "23.6.0", + "jest-get-type": "22.4.3", + "jest-matcher-utils": "23.6.0", + "jest-message-util": "23.4.0", + "jest-regex-util": "23.3.0" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "extract-zip": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", + "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", + "dev": true, + "requires": { + "concat-stream": "1.6.2", + "debug": "2.6.9", + "mkdirp": "0.5.1", + "yauzl": "2.4.1" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fb-watchman": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", + "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", + "dev": true, + "requires": { + "bser": "2.0.0" + } + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "1.2.0" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fileset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", + "dev": true, + "requires": { + "glob": "7.1.3", + "minimatch": "3.0.4" + } + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.1.0", + "repeat-element": "1.1.3", + "repeat-string": "1.6.1" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.20" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.6", + "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + } + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.11.0", + "node-pre-gyp": "0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", + "dev": true + }, + "handlebars": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", + "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", + "dev": true, + "requires": { + "async": "2.6.1", + "optimist": "0.6.1", + "source-map": "0.6.1", + "uglify-js": "3.4.9" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "dev": true, + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "1.0.4" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "dev": true, + "requires": { + "agent-base": "4.2.1", + "debug": "3.2.5" + }, + "dependencies": { + "debug": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", + "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", + "dev": true, + "requires": { + "ms": "2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "import-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", + "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", + "dev": true, + "requires": { + "pkg-dir": "2.0.0", + "resolve-cwd": "2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "1.4.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "requires": { + "ci-info": "1.6.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-generator-fn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-1.0.0.tgz", + "integrity": "sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "1.0.3" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul-api": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", + "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", + "dev": true, + "requires": { + "async": "2.6.1", + "fileset": "2.0.3", + "istanbul-lib-coverage": "1.2.1", + "istanbul-lib-hook": "1.2.2", + "istanbul-lib-instrument": "1.10.2", + "istanbul-lib-report": "1.1.5", + "istanbul-lib-source-maps": "1.2.6", + "istanbul-reports": "1.5.1", + "js-yaml": "3.12.0", + "mkdirp": "0.5.1", + "once": "1.4.0" + } + }, + "istanbul-lib-coverage": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", + "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", + "dev": true, + "requires": { + "append-transform": "0.4.0" + } + }, + "istanbul-lib-instrument": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", + "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "dev": true, + "requires": { + "babel-generator": "6.26.1", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "istanbul-lib-coverage": "1.2.1", + "semver": "5.5.1" + } + }, + "istanbul-lib-report": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", + "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "1.2.1", + "mkdirp": "0.5.1", + "path-parse": "1.0.6", + "supports-color": "3.2.3" + }, + "dependencies": { + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", + "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", + "dev": true, + "requires": { + "debug": "3.2.5", + "istanbul-lib-coverage": "1.2.1", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "source-map": "0.5.7" + }, + "dependencies": { + "debug": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", + "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", + "dev": true, + "requires": { + "ms": "2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", + "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", + "dev": true, + "requires": { + "handlebars": "4.0.12" + } + }, + "jest": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-23.6.0.tgz", + "integrity": "sha512-lWzcd+HSiqeuxyhG+EnZds6iO3Y3ZEnMrfZq/OTGvF/C+Z4fPMCdhWTGSAiO2Oym9rbEXfwddHhh6jqrTF3+Lw==", + "dev": true, + "requires": { + "import-local": "1.0.0", + "jest-cli": "23.6.0" + } + }, + "jest-changed-files": { + "version": "23.4.2", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-23.4.2.tgz", + "integrity": "sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA==", + "dev": true, + "requires": { + "throat": "4.1.0" + } + }, + "jest-cli": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-23.6.0.tgz", + "integrity": "sha512-hgeD1zRUp1E1zsiyOXjEn4LzRLWdJBV//ukAHGlx6s5mfCNJTbhbHjgxnDUXA8fsKWN/HqFFF6X5XcCwC/IvYQ==", + "dev": true, + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "exit": "0.1.2", + "glob": "7.1.3", + "graceful-fs": "4.1.11", + "import-local": "1.0.0", + "is-ci": "1.2.1", + "istanbul-api": "1.3.7", + "istanbul-lib-coverage": "1.2.1", + "istanbul-lib-instrument": "1.10.2", + "istanbul-lib-source-maps": "1.2.6", + "jest-changed-files": "23.4.2", + "jest-config": "23.6.0", + "jest-environment-jsdom": "23.4.0", + "jest-get-type": "22.4.3", + "jest-haste-map": "23.6.0", + "jest-message-util": "23.4.0", + "jest-regex-util": "23.3.0", + "jest-resolve-dependencies": "23.6.0", + "jest-runner": "23.6.0", + "jest-runtime": "23.6.0", + "jest-snapshot": "23.6.0", + "jest-util": "23.4.0", + "jest-validate": "23.6.0", + "jest-watcher": "23.4.0", + "jest-worker": "23.2.0", + "micromatch": "2.3.11", + "node-notifier": "5.2.1", + "prompts": "0.1.14", + "realpath-native": "1.0.2", + "rimraf": "2.6.2", + "slash": "1.0.0", + "string-length": "2.0.0", + "strip-ansi": "4.0.0", + "which": "1.3.1", + "yargs": "11.1.0" + } + }, + "jest-config": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-23.6.0.tgz", + "integrity": "sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ==", + "dev": true, + "requires": { + "babel-core": "6.26.3", + "babel-jest": "23.6.0", + "chalk": "2.4.1", + "glob": "7.1.3", + "jest-environment-jsdom": "23.4.0", + "jest-environment-node": "23.4.0", + "jest-get-type": "22.4.3", + "jest-jasmine2": "23.6.0", + "jest-regex-util": "23.3.0", + "jest-resolve": "23.6.0", + "jest-util": "23.4.0", + "jest-validate": "23.6.0", + "micromatch": "2.3.11", + "pretty-format": "23.6.0" + } + }, + "jest-diff": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-23.6.0.tgz", + "integrity": "sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "diff": "3.5.0", + "jest-get-type": "22.4.3", + "pretty-format": "23.6.0" + } + }, + "jest-docblock": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-23.2.0.tgz", + "integrity": "sha1-8IXh8YVI2Z/dabICB+b9VdkTg6c=", + "dev": true, + "requires": { + "detect-newline": "2.1.0" + } + }, + "jest-each": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-23.6.0.tgz", + "integrity": "sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "pretty-format": "23.6.0" + } + }, + "jest-environment-jsdom": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz", + "integrity": "sha1-BWp5UrP+pROsYqFAosNox52eYCM=", + "dev": true, + "requires": { + "jest-mock": "23.2.0", + "jest-util": "23.4.0", + "jsdom": "11.12.0" + } + }, + "jest-environment-node": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-23.4.0.tgz", + "integrity": "sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA=", + "dev": true, + "requires": { + "jest-mock": "23.2.0", + "jest-util": "23.4.0" + } + }, + "jest-get-type": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", + "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", + "dev": true + }, + "jest-haste-map": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-23.6.0.tgz", + "integrity": "sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg==", + "dev": true, + "requires": { + "fb-watchman": "2.0.0", + "graceful-fs": "4.1.11", + "invariant": "2.2.4", + "jest-docblock": "23.2.0", + "jest-serializer": "23.0.1", + "jest-worker": "23.2.0", + "micromatch": "2.3.11", + "sane": "2.5.2" + } + }, + "jest-jasmine2": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz", + "integrity": "sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ==", + "dev": true, + "requires": { + "babel-traverse": "6.26.0", + "chalk": "2.4.1", + "co": "4.6.0", + "expect": "23.6.0", + "is-generator-fn": "1.0.0", + "jest-diff": "23.6.0", + "jest-each": "23.6.0", + "jest-matcher-utils": "23.6.0", + "jest-message-util": "23.4.0", + "jest-snapshot": "23.6.0", + "jest-util": "23.4.0", + "pretty-format": "23.6.0" + } + }, + "jest-leak-detector": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz", + "integrity": "sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg==", + "dev": true, + "requires": { + "pretty-format": "23.6.0" + } + }, + "jest-matcher-utils": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz", + "integrity": "sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "jest-get-type": "22.4.3", + "pretty-format": "23.6.0" + } + }, + "jest-message-util": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-23.4.0.tgz", + "integrity": "sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8=", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0", + "chalk": "2.4.1", + "micromatch": "2.3.11", + "slash": "1.0.0", + "stack-utils": "1.0.1" + } + }, + "jest-mock": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-23.2.0.tgz", + "integrity": "sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=", + "dev": true + }, + "jest-regex-util": { + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-23.3.0.tgz", + "integrity": "sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=", + "dev": true + }, + "jest-resolve": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-23.6.0.tgz", + "integrity": "sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA==", + "dev": true, + "requires": { + "browser-resolve": "1.11.3", + "chalk": "2.4.1", + "realpath-native": "1.0.2" + } + }, + "jest-resolve-dependencies": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz", + "integrity": "sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA==", + "dev": true, + "requires": { + "jest-regex-util": "23.3.0", + "jest-snapshot": "23.6.0" + } + }, + "jest-runner": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-23.6.0.tgz", + "integrity": "sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA==", + "dev": true, + "requires": { + "exit": "0.1.2", + "graceful-fs": "4.1.11", + "jest-config": "23.6.0", + "jest-docblock": "23.2.0", + "jest-haste-map": "23.6.0", + "jest-jasmine2": "23.6.0", + "jest-leak-detector": "23.6.0", + "jest-message-util": "23.4.0", + "jest-runtime": "23.6.0", + "jest-util": "23.4.0", + "jest-worker": "23.2.0", + "source-map-support": "0.5.9", + "throat": "4.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "dev": true, + "requires": { + "buffer-from": "1.1.1", + "source-map": "0.6.1" + } + } + } + }, + "jest-runtime": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-23.6.0.tgz", + "integrity": "sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw==", + "dev": true, + "requires": { + "babel-core": "6.26.3", + "babel-plugin-istanbul": "4.1.6", + "chalk": "2.4.1", + "convert-source-map": "1.6.0", + "exit": "0.1.2", + "fast-json-stable-stringify": "2.0.0", + "graceful-fs": "4.1.11", + "jest-config": "23.6.0", + "jest-haste-map": "23.6.0", + "jest-message-util": "23.4.0", + "jest-regex-util": "23.3.0", + "jest-resolve": "23.6.0", + "jest-snapshot": "23.6.0", + "jest-util": "23.4.0", + "jest-validate": "23.6.0", + "micromatch": "2.3.11", + "realpath-native": "1.0.2", + "slash": "1.0.0", + "strip-bom": "3.0.0", + "write-file-atomic": "2.3.0", + "yargs": "11.1.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "jest-serializer": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-23.0.1.tgz", + "integrity": "sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU=", + "dev": true + }, + "jest-snapshot": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-23.6.0.tgz", + "integrity": "sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg==", + "dev": true, + "requires": { + "babel-types": "6.26.0", + "chalk": "2.4.1", + "jest-diff": "23.6.0", + "jest-matcher-utils": "23.6.0", + "jest-message-util": "23.4.0", + "jest-resolve": "23.6.0", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "pretty-format": "23.6.0", + "semver": "5.5.1" + } + }, + "jest-util": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-23.4.0.tgz", + "integrity": "sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE=", + "dev": true, + "requires": { + "callsites": "2.0.0", + "chalk": "2.4.1", + "graceful-fs": "4.1.11", + "is-ci": "1.2.1", + "jest-message-util": "23.4.0", + "mkdirp": "0.5.1", + "slash": "1.0.0", + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "jest-validate": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.6.0.tgz", + "integrity": "sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "jest-get-type": "22.4.3", + "leven": "2.1.0", + "pretty-format": "23.6.0" + } + }, + "jest-watcher": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-23.4.0.tgz", + "integrity": "sha1-0uKM50+NrWxq/JIrksq+9u0FyRw=", + "dev": true, + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "string-length": "2.0.0" + } + }, + "jest-worker": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-23.2.0.tgz", + "integrity": "sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=", + "dev": true, + "requires": { + "merge-stream": "1.0.1" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.1" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "requires": { + "abab": "2.0.0", + "acorn": "5.7.3", + "acorn-globals": "4.3.0", + "array-equal": "1.0.0", + "cssom": "0.3.4", + "cssstyle": "1.1.1", + "data-urls": "1.0.1", + "domexception": "1.0.1", + "escodegen": "1.11.0", + "html-encoding-sniffer": "1.0.2", + "left-pad": "1.3.0", + "nwsapi": "2.0.9", + "parse5": "4.0.0", + "pn": "1.1.0", + "request": "2.88.0", + "request-promise-native": "1.0.5", + "sax": "1.2.4", + "symbol-tree": "3.2.2", + "tough-cookie": "2.4.3", + "w3c-hr-time": "1.0.1", + "webidl-conversions": "4.0.2", + "whatwg-encoding": "1.0.4", + "whatwg-mimetype": "2.2.0", + "whatwg-url": "6.5.0", + "ws": "5.2.2", + "xml-name-validator": "3.0.0" + } + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "kleur": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-2.0.2.tgz", + "integrity": "sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==", + "dev": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "dev": true + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "dev": true, + "requires": { + "tmpl": "1.0.4" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "dev": true + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, + "merge": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", + "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=", + "dev": true + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "2.3.6" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "mime": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", + "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", + "dev": true + }, + "mime-db": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", + "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==", + "dev": true + }, + "mime-types": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", + "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "dev": true, + "requires": { + "mime-db": "1.36.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nan": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.0.tgz", + "integrity": "sha512-F4miItu2rGnV2ySkXOQoA8FKz/SR2Q2sWP0sbTxNxz/tuokeC8WxOhPMcwi0qIyGtVn/rrSeLbvVkznqCdwYnw==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true + }, + "node-notifier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.2.1.tgz", + "integrity": "sha512-MIBs+AAd6dJ2SklbbE8RUDRlIVhU8MaNLh1A9SUZDUHPiZkWLFde6UNwG41yQHZEToHgJMXqyVZ9UcS/ReOVTg==", + "dev": true, + "requires": { + "growly": "1.3.0", + "semver": "5.5.1", + "shellwords": "0.1.1", + "which": "1.3.1" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.7.1", + "is-builtin-module": "1.0.0", + "semver": "5.5.1", + "validate-npm-package-license": "3.0.4" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "nwsapi": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.9.tgz", + "integrity": "sha512-nlWFSCTYQcHk/6A9FFnfhKc14c3aFhfdNBXgo8Qgi9QTBu/qg3Ww+Uiz9wMzXd1T8GFxPc2QIHB6Qtf2XFryFQ==", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "1.1.3", + "es-abstract": "1.12.0" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.3.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.2" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "2.1.0" + } + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-format": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", + "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", + "dev": true, + "requires": { + "ansi-regex": "3.0.0", + "ansi-styles": "3.2.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "prompts": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-0.1.14.tgz", + "integrity": "sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w==", + "dev": true, + "requires": { + "kleur": "2.0.2", + "sisteransi": "0.1.1" + } + }, + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "puppeteer": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.8.0.tgz", + "integrity": "sha512-wJ7Fxs03l4dy/ZXQACUKBBobIuJaS4NHq44q7/QinpAXFMwJMJFEIPjzoksVzUhZxQe+RXnjXH69mg13yMh0BA==", + "dev": true, + "requires": { + "debug": "3.2.5", + "extract-zip": "1.6.7", + "https-proxy-agent": "2.2.1", + "mime": "2.3.1", + "progress": "2.0.0", + "proxy-from-env": "1.0.0", + "rimraf": "2.6.2", + "ws": "5.2.2" + }, + "dependencies": { + "debug": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", + "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", + "dev": true, + "requires": { + "ms": "2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "randomatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", + "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", + "dev": true, + "requires": { + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "realpath-native": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.0.2.tgz", + "integrity": "sha512-+S3zTvVt9yTntFrBpm7TQmQ3tzpCrnA1a/y+3cUHAc9ZR6aIjG0WNLR+Rj79QpJktY+VeW/TQtFlQ1bzsehI8g==", + "dev": true, + "requires": { + "util.promisify": "1.0.0" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.8.0", + "caseless": "0.12.0", + "combined-stream": "1.0.7", + "extend": "3.0.2", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.1.0", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.20", + "oauth-sign": "0.9.0", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.4.3", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" + } + }, + "request-promise-core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", + "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "dev": true, + "requires": { + "lodash": "4.17.11" + } + }, + "request-promise-native": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", + "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "dev": true, + "requires": { + "request-promise-core": "1.1.1", + "stealthy-require": "1.1.1", + "tough-cookie": "2.4.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.3" + } + }, + "rsvp": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", + "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sane": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/sane/-/sane-2.5.2.tgz", + "integrity": "sha1-tNwYYcIbQn6SlQej51HiosuKs/o=", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "capture-exit": "1.2.0", + "exec-sh": "0.2.2", + "fb-watchman": "2.0.0", + "fsevents": "1.2.4", + "micromatch": "3.1.10", + "minimist": "1.2.0", + "walker": "1.0.7", + "watch": "0.18.0" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.3", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sisteransi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-0.1.1.tgz", + "integrity": "sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "2.1.2", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "dev": true, + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.1" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.1" + } + }, + "spdx-license-ids": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", + "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "dev": true, + "requires": { + "asn1": "0.2.4", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.2", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" + } + }, + "stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha1-1PM6tU6OOHeLDKXP07OvsS22hiA=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "dev": true, + "requires": { + "astral-regex": "1.0.0", + "strip-ansi": "4.0.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "symbol-tree": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", + "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", + "dev": true + }, + "test-exclude": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.3.tgz", + "integrity": "sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "micromatch": "2.3.11", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "require-main-filename": "1.0.1" + } + }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", + "dev": true + }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + } + } + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "1.1.29", + "punycode": "1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "2.1.1" + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "dev": true, + "optional": true, + "requires": { + "commander": "2.17.1", + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "1.1.3", + "object.getownpropertydescriptors": "2.0.3" + } + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "0.1.3" + } + }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "dev": true, + "requires": { + "makeerror": "1.0.11" + } + }, + "watch": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz", + "integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=", + "dev": true, + "requires": { + "exec-sh": "0.2.2", + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.4.tgz", + "integrity": "sha512-vM9KWN6MP2mIHZ86ytcyIv7e8Cj3KTfO2nd2c8PFDqcI4bxFmQp83ibq4wadq7rL9l9sZV6o9B0LTt8ygGAAXg==", + "dev": true, + "requires": { + "iconv-lite": "0.4.23" + } + }, + "whatwg-mimetype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.2.0.tgz", + "integrity": "sha512-5YSO1nMd5D1hY3WzAQV3PzZL83W3YeyR1yW9PcH26Weh1t+Vzh9B6XkDh7aXm83HBZ4nSMvkjvN2H2ySWIvBgw==", + "dev": true + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "requires": { + "lodash.sortby": "4.7.0", + "tr46": "1.0.1", + "webidl-conversions": "4.0.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + } + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "1.0.0" + } + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "11.1.0", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", + "dev": true, + "requires": { + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.3", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" + } + }, + "yargs-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "dev": true, + "requires": { + "camelcase": "4.1.0" + } + }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true, + "requires": { + "fd-slicer": "1.0.1" + } + } + } +} diff --git a/test/FunctionalTests/package.json b/test/FunctionalTests/package.json new file mode 100644 index 0000000000..c5a8e5f365 --- /dev/null +++ b/test/FunctionalTests/package.json @@ -0,0 +1,10 @@ +{ + "devDependencies": { + "jest": "^23.6.0", + "puppeteer": "^1.8.0" + }, + "dependencies": {}, + "scripts": { + "test": "jest" + } +} diff --git a/test/FunctionalTests/test.js b/test/FunctionalTests/test.js new file mode 100644 index 0000000000..2fc14652e1 --- /dev/null +++ b/test/FunctionalTests/test.js @@ -0,0 +1,280 @@ +const puppeteer = require('puppeteer'); +const os = require("os"); +const hostname = os.hostname(); + +const corsServerPath = `http://${hostname}:9000`; + +// e.g., npm test --debug +// In debug mode we show the editor, slow down operations, and increase the timeout for each test +const debug = process.env.npm_config_debug || false; +jest.setTimeout(debug ? 60000 : 30000); + +let browser; + +beforeAll(async () => { + const options = debug ? + { headless: false, slowMo: 100 } : + { args: ['--no-sandbox'] }; + browser = await puppeteer.launch(options); + expect(browser).toBeDefined(); +}); + +afterAll(async () => { + await browser.close(); +}); + +describe('CORS allowed origin tests ', () => { + const testPagePath = `http://${hostname}:9001/`; + let page; + + beforeAll(async () => { + page = await browser.newPage(); + await page.goto(testPagePath); + }); + + test('allows simple GET requests', async () => { + const result = await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/allow-origin`; + const options = { method: 'GET', mode: 'cors' }; + + const response = await fetch(url, options); + return response.status; + }, corsServerPath); + + expect(result).toBe(200); + }); + + test('allows simple PUT requests when any method is allowed', async () => { + const result = await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/allow-origin`; + const options = { method: 'PUT', mode: 'cors' }; + + const response = await fetch(url, options); + return response.status; + }, corsServerPath); + + expect(result).toBe(200); + }); + + // This one is weird - although the server performs a preflight request and receives a Access-Control-Allow-Methods: PUT, + // the browser happily ignores the disallowed POST method. + test('allows POST requests when not explicitly allowed', async () => { + const result = await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/allow-header-method`; + const options = { + method: 'POST', + mode: 'cors', + body: JSON.stringify({ hello: 'world' }), + headers: new Headers({ "X-Test": "value", 'Content-Type': 'application/json' }) + }; + + const response = await fetch(url, options); + return response.status; + }, corsServerPath); + + expect(result).toBe(200); + }); + + test('allows header to be sent when allowed', async () => { + const result = await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/allow-header-method`; + const options = { method: 'PUT', mode: 'cors', headers: new Headers({ "X-Test": "value", 'Content-Type': 'application/json' }) }; + + const response = await fetch(url, options); + return response.status; + }, corsServerPath); + + expect(result).toBe(200); + }); + + test('does not allow disallowed HTTP Methods', async () => { + expect.assertions(1); + try { + await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/allow-header-method`; + const options = { method: 'DELETE', mode: 'cors', headers: new Headers({ "X-Test": "value", 'Content-Type': 'application/json' }) }; + + return await fetch(url, options); + }, corsServerPath); + } catch (e) { + expect(e).toBeDefined(); + } + }); + + test('does not allow disallowed header', async () => { + expect.assertions(1); + try { + await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/allow-header-method`; + const options = { method: 'PUT', mode: 'cors', headers: new Headers({ "X-Not-Test": "value", 'Content-Type': 'application/json' }) }; + + return await fetch(url, options); + }, corsServerPath); + } catch (e) { + expect(e).toBeDefined(); + } + }); + + test('does not allow fetch with credentials in non-Preflighted request', async () => { + expect.assertions(1); + try { + await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/allow-origin`; + const options = { method: 'POST', mode: 'cors', credentials: 'include' }; + + return await fetch(url, options); + }, corsServerPath); + } catch (e) { + expect(e).toBeDefined(); + } + }); + + test('does not allow fetch with credentials in Preflighted request', async () => { + expect.assertions(1); + try { + await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/allow-origin`; + const options = { method: 'PUT', mode: 'cors', credentials: 'include' }; + + return await fetch(url, options); + }, corsServerPath); + } catch (e) { + expect(e).toBeDefined(); + } + }); + + test('allows request with credentials', async () => { + const result = await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/allow-credentials`; + const options = { method: 'GET', mode: 'cors', credentials: 'include' }; + + const response = await fetch(url, options); + return response.status; + }, corsServerPath); + + expect(result).toBe(200); + }); + + test('allows Preflighted request with credentials', async () => { + const result = await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/allow-credentials`; + const options = { method: 'PUT', mode: 'cors', credentials: 'include' }; + + const response = await fetch(url, options); + return response.status; + }, corsServerPath); + + expect(result).toBe(200); + }); + + test('disallows accessing header when not included in exposed-header', async () => { + const result = await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/exposed-header`; + const options = { method: 'GET', mode: 'cors' }; + + const response = await fetch(url, options); + try { + return response.headers.get('x-disallowedheader'); + } catch (e) { + return null; + } + }, corsServerPath); + + expect(result).toBeNull(); + }); + + test('allows accessing header when included in exposed-header', async () => { + const result = await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/exposed-header`; + const options = { method: 'GET', mode: 'cors' }; + + const response = await fetch(url, options); + try { + return response.headers.get('x-allowedheader'); + } catch (e) { + return e; + } + }, corsServerPath); + + expect(result).toBe("Test-Value"); + }); +}); + +describe('CORS disallowed origin tests ', () => { + const testPagePath = `http://${hostname}:9002/`; + let page; + + beforeAll(async () => { + page = await browser.newPage(); + await page.goto(testPagePath); + }); + + test('allow opaque requests without CORS', async () => { + const result = await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/allow-origin`; + const options = { method: 'GET', mode: 'no-cors' }; + + // The request will succeed, but we get an opaque filtered response (https://fetch.spec.whatwg.org/#concept-filtered-response). + const response = await fetch(url, options); + return response.type; + }, corsServerPath); + + expect(result).toBe("opaque"); + }); + + test('does not allow requests when origin is disallowed', async () => { + expect.assertions(1); + try { + await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/allow-origin`; + const options = { method: 'GET', mode: 'cors' }; + + return await fetch(url, options); + }, corsServerPath); + } catch (e) { + expect(e).toBeDefined(); + } + }); + + test('does not allow preflight requests when origin is disallowed', async () => { + expect.assertions(1); + try { + await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/allow-origin`; + const options = { method: 'PUT', mode: 'cors' }; + + return await fetch(url, options); + }, corsServerPath); + } catch (e) { + expect(e).toBeDefined(); + } + }); + + test('allow requests to any origin endpoint', async () => { + const result = await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/allow-all`; + const options = { method: 'PUT', mode: 'cors' }; + + const response = await fetch(url, options); + return response.status; + }, corsServerPath); + + expect(result).toBe(200); + }); + + test('does not allow requests to any origin endpoint with credentials', async () => { + expect.assertions(1); + + try { + await page.evaluate(async (corsServerPath) => { + const url = `${corsServerPath}/allow-all`; + const options = { method: 'PUT', mode: 'cors', headers: new Headers({ "X-Test": "value", 'Content-Type': 'application/json' }), credentials: 'include' }; + + const response = await fetch(url, options); + return response.status; + }, corsServerPath); + } catch (e) { + expect(e).toBeDefined(); + } + }); +}); diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareFunctionalTest.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareFunctionalTest.cs deleted file mode 100644 index 008a4926d9..0000000000 --- a/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareFunctionalTest.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.AspNetCore.Cors.Infrastructure -{ - public class CorsMiddlewareFunctionalTests : IClassFixture> - { - public CorsMiddlewareFunctionalTests(CorsTestFixture fixture) - { - Client = fixture.Client; - } - - public HttpClient Client { get; } - - [Theory] - [InlineData("GET")] - [InlineData("HEAD")] - [InlineData("POST")] - public async Task ResourceWithSimpleRequestPolicy_Allows_SimpleRequests(string method) - { - // Arrange - var path = "/CorsMiddleware/EC6AA70D-BA3E-4B71-A87F-18625ADDB2BD"; - var origin = "http://example.com"; - var request = new HttpRequestMessage(new HttpMethod(method), path); - request.Headers.Add(CorsConstants.Origin, origin); - - // Act - var response = await Client.SendAsync(request); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var content = await response.Content.ReadAsStringAsync(); - Assert.Equal(path, content); - var responseHeaders = response.Headers; - var header = Assert.Single(response.Headers); - Assert.Equal(CorsConstants.AccessControlAllowOrigin, header.Key); - Assert.Equal(new[] { "http://example.com" }, header.Value.ToArray()); - } - - [Theory] - [InlineData("GET")] - [InlineData("HEAD")] - [InlineData("POST")] - [InlineData("PUT")] - public async Task PolicyFailed_Disallows_PreFlightRequest(string method) - { - // Arrange - var path = "/CorsMiddleware/9B8BB9C6-5BF2-4255-A636-DCB450D51AAE"; - var request = new HttpRequestMessage(new HttpMethod(CorsConstants.PreflightHttpMethod), path); - - // Adding a custom header makes it a non-simple request. - request.Headers.Add(CorsConstants.Origin, "http://example.com"); - request.Headers.Add(CorsConstants.AccessControlRequestMethod, method); - request.Headers.Add(CorsConstants.AccessControlRequestHeaders, "Custom"); - - // Act - var response = await Client.SendAsync(request); - - // Assert - // Middleware applied the policy and since that did not pass, there were no access control headers. - Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); - Assert.Empty(response.Headers); - - // It should short circuit and hence no result. - var content = await response.Content.ReadAsStringAsync(); - Assert.Equal(string.Empty, content); - } - - [Fact] - public async Task PolicyFailed_Allows_ActualRequest_WithMissingResponseHeaders() - { - // Arrange - var path = "/CorsMiddleware/1E6C6F4D-1E1C-450E-8BD0-73DBF089A78F"; - var request = new HttpRequestMessage(HttpMethod.Put, path); - - // Adding a custom header makes it a non simple request. - request.Headers.Add(CorsConstants.Origin, "http://example2.com"); - - // Act - var response = await Client.SendAsync(request); - - // Assert - // Middleware applied the policy and since that did not pass, there were no access control headers. - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Empty(response.Headers); - - // It still has executed the action. - var content = await response.Content.ReadAsStringAsync(); - Assert.Equal(path, content); - } - } -} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs index 44c6d5c1be..85b79949b4 100644 --- a/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs +++ b/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; @@ -18,6 +18,8 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure { public class CorsMiddlewareTests { + private const string OriginUrl = "http://api.example.com"; + [Theory] [InlineData("PuT")] [InlineData("PUT")] @@ -28,7 +30,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure .Configure(app => { app.UseCors(builder => - builder.WithOrigins("http://localhost:5001") + builder.WithOrigins(OriginUrl) .WithMethods("PUT")); app.Run(async context => { @@ -42,14 +44,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Act // Actual request. var response = await server.CreateRequest("/") - .AddHeader(CorsConstants.Origin, "http://localhost:5001") + .AddHeader(CorsConstants.Origin, OriginUrl) .SendAsync(accessControlRequestMethod); // Assert response.EnsureSuccessStatusCode(); Assert.Single(response.Headers); Assert.Equal("Cross origin response", await response.Content.ReadAsStringAsync()); - Assert.Equal("http://localhost:5001", response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault()); + Assert.Equal(OriginUrl, response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault()); } } @@ -61,7 +63,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure .Configure(app => { app.UseCors(builder => - builder.WithOrigins("http://localhost:5001") + builder.WithOrigins(OriginUrl) .WithMethods("PUT") .WithHeaders("Header1") .WithExposedHeaders("AllowedHeader")); @@ -77,14 +79,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Act // Actual request. var response = await server.CreateRequest("/") - .AddHeader(CorsConstants.Origin, "http://localhost:5001") + .AddHeader(CorsConstants.Origin, OriginUrl) .SendAsync("PUT"); // Assert response.EnsureSuccessStatusCode(); Assert.Equal(2, response.Headers.Count()); Assert.Equal("Cross origin response", await response.Content.ReadAsStringAsync()); - Assert.Equal("http://localhost:5001", response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault()); + Assert.Equal(OriginUrl, response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault()); Assert.Equal("AllowedHeader", response.Headers.GetValues(CorsConstants.AccessControlExposeHeaders).FirstOrDefault()); } } @@ -96,7 +98,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure { // Arrange var policy = new CorsPolicy(); - policy.Origins.Add("http://localhost:5001"); + policy.Origins.Add(OriginUrl); policy.Methods.Add("PUT"); var hostBuilder = new WebHostBuilder() @@ -121,13 +123,13 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Act // Preflight request. var response = await server.CreateRequest("/") - .AddHeader(CorsConstants.Origin, "http://localhost:5001") + .AddHeader(CorsConstants.Origin, OriginUrl) .SendAsync(preflightMethod); // Assert response.EnsureSuccessStatusCode(); Assert.Single(response.Headers); - Assert.Equal("http://localhost:5001", response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault()); + Assert.Equal(OriginUrl, response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault()); } } @@ -136,7 +138,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure { // Arrange var policy = new CorsPolicy(); - policy.Origins.Add("http://localhost:5001"); + policy.Origins.Add(OriginUrl); policy.Methods.Add("PUT"); policy.Headers.Add("Header1"); policy.ExposedHeaders.Add("AllowedHeader"); @@ -163,27 +165,105 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Act // Preflight request. var response = await server.CreateRequest("/") - .AddHeader(CorsConstants.Origin, "http://localhost:5001") + .AddHeader(CorsConstants.Origin, OriginUrl) .AddHeader(CorsConstants.AccessControlRequestMethod, "PUT") .SendAsync(CorsConstants.PreflightHttpMethod); // Assert response.EnsureSuccessStatusCode(); - Assert.Equal(2, response.Headers.Count()); - Assert.Equal("http://localhost:5001", response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault()); - Assert.Equal("PUT", response.Headers.GetValues(CorsConstants.AccessControlAllowMethods).FirstOrDefault()); + Assert.Collection( + response.Headers.OrderBy(h => h.Key), + kvp => + { + Assert.Equal(CorsConstants.AccessControlAllowHeaders, kvp.Key); + Assert.Equal(new[] { "Header1" }, kvp.Value); + }, + kvp => + { + Assert.Equal(CorsConstants.AccessControlAllowMethods, kvp.Key); + Assert.Equal(new[] { "PUT" }, kvp.Value); + }, + kvp => + { + Assert.Equal(CorsConstants.AccessControlAllowOrigin, kvp.Key); + Assert.Equal(new[] { OriginUrl }, kvp.Value); + }); } } [Fact] - public async Task PreFlightRequest_DoesNotMatchPolicy_DoesNotSetHeaders() + public async Task PreFlight_WithCredentialsAllowed_ReturnsWildcardValues() + { + // Arrange + var policy = new CorsPolicyBuilder(OriginUrl) + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials() + .Build(); + + var hostBuilder = new WebHostBuilder() + .Configure(app => + { + app.UseCors("customPolicy"); + app.Run(async context => + { + await context.Response.WriteAsync("Cross origin response"); + }); + }) + .ConfigureServices(services => + { + services.AddCors(options => + { + options.AddPolicy("customPolicy", policy); + }); + }); + + using (var server = new TestServer(hostBuilder)) + { + // Act + // Preflight request. + var response = await server.CreateRequest("/") + .AddHeader(CorsConstants.Origin, OriginUrl) + .AddHeader(CorsConstants.AccessControlRequestMethod, "PUT") + .AddHeader(CorsConstants.AccessControlRequestHeaders, "X-Test1,X-Test2") + .SendAsync(CorsConstants.PreflightHttpMethod); + + // Assert + response.EnsureSuccessStatusCode(); + Assert.Collection( + response.Headers.OrderBy(h => h.Key), + kvp => + { + Assert.Equal(CorsConstants.AccessControlAllowCredentials, kvp.Key); + Assert.Equal(new[] { "true" }, kvp.Value); + }, + kvp => + { + Assert.Equal(CorsConstants.AccessControlAllowHeaders, kvp.Key); + Assert.Equal(new[] { "*" }, kvp.Value); + }, + kvp => + { + Assert.Equal(CorsConstants.AccessControlAllowMethods, kvp.Key); + Assert.Equal(new[] { "*" }, kvp.Value); + }, + kvp => + { + Assert.Equal(CorsConstants.AccessControlAllowOrigin, kvp.Key); + Assert.Equal(new[] { OriginUrl }, kvp.Value); + }); + } + } + + [Fact] + public async Task PreFlightRequest_DoesNotMatchPolicy_DoesNotSetHeadersAndReturnsForbidden() { // Arrange var hostBuilder = new WebHostBuilder() .Configure(app => { app.UseCors(builder => - builder.WithOrigins("http://localhost:5001") + builder.WithOrigins(OriginUrl) .WithMethods("PUT") .WithHeaders("Header1") .WithExposedHeaders("AllowedHeader")); @@ -199,7 +279,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Act // Preflight request. var response = await server.CreateRequest("/") - .AddHeader(CorsConstants.Origin, "http://localhost:5002") + .AddHeader(CorsConstants.Origin, "http://test.example.com") .AddHeader(CorsConstants.AccessControlRequestMethod, "PUT") .SendAsync(CorsConstants.PreflightHttpMethod); @@ -217,7 +297,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure .Configure(app => { app.UseCors(builder => - builder.WithOrigins("http://localhost:5001") + builder.WithOrigins(OriginUrl) .WithMethods("PUT") .WithHeaders("Header1") .WithExposedHeaders("AllowedHeader")); @@ -233,7 +313,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Act // Actual request. var response = await server.CreateRequest("/") - .AddHeader(CorsConstants.Origin, "http://localhost:5002") + .AddHeader(CorsConstants.Origin, "http://test.example.com") .SendAsync("PUT"); // Assert @@ -248,7 +328,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Arrange var corsService = Mock.Of(); var mockProvider = new Mock(); - var loggerFactory = Mock.Of(); + var loggerFactory = NullLoggerFactory.Instance; mockProvider.Setup(o => o.GetPolicyAsync(It.IsAny(), It.IsAny())) .Returns(Task.FromResult(null)) .Verifiable(); @@ -278,7 +358,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Arrange var corsService = Mock.Of(); var mockProvider = new Mock(); - var loggerFactory = Mock.Of(); + var loggerFactory = NullLoggerFactory.Instance; mockProvider.Setup(o => o.GetPolicyAsync(It.IsAny(), It.IsAny())) .Returns(Task.FromResult(null)) .Verifiable(); @@ -324,7 +404,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure options.AddDefaultPolicy(policyBuilder => { policyBuilder - .WithOrigins("http://localhost:5001") + .WithOrigins(OriginUrl) .WithMethods("PUT") .WithHeaders("Header1") .WithExposedHeaders("AllowedHeader") @@ -333,7 +413,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure options.AddPolicy("policy2", policyBuilder => { policyBuilder - .WithOrigins("http://localhost:5002") + .WithOrigins("http://test.example.com") .Build(); }); }); @@ -344,15 +424,29 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Act // Preflight request. var response = await server.CreateRequest("/") - .AddHeader(CorsConstants.Origin, "http://localhost:5001") + .AddHeader(CorsConstants.Origin, OriginUrl) .AddHeader(CorsConstants.AccessControlRequestMethod, "PUT") .SendAsync(CorsConstants.PreflightHttpMethod); // Assert response.EnsureSuccessStatusCode(); - Assert.Equal(2, response.Headers.Count()); - Assert.Equal("http://localhost:5001", response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault()); - Assert.Equal("PUT", response.Headers.GetValues(CorsConstants.AccessControlAllowMethods).FirstOrDefault()); + Assert.Collection( + response.Headers.OrderBy(h => h.Key), + kvp => + { + Assert.Equal(CorsConstants.AccessControlAllowHeaders, kvp.Key); + Assert.Equal(new[] { "Header1" }, kvp.Value); + }, + kvp => + { + Assert.Equal(CorsConstants.AccessControlAllowMethods, kvp.Key); + Assert.Equal(new[] { "PUT" }, kvp.Value); + }, + kvp => + { + Assert.Equal(CorsConstants.AccessControlAllowOrigin, kvp.Key); + Assert.Equal(new[] { OriginUrl }, kvp.Value); + }); } } @@ -364,7 +458,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure .Configure(app => { app.UseCors(builder => - builder.WithOrigins("http://localhost:5001") + builder.WithOrigins(OriginUrl) .WithMethods("PUT") .WithHeaders("Header1") .WithExposedHeaders("AllowedHeader")); @@ -381,7 +475,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Act // Actual request. var response = await server.CreateRequest("/") - .AddHeader(CorsConstants.Origin, "http://localhost:5001") + .AddHeader(CorsConstants.Origin, OriginUrl) .SendAsync("PUT"); // Assert @@ -391,7 +485,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure kvp => { Assert.Equal(CorsConstants.AccessControlAllowOrigin, kvp.Key); - Assert.Equal("http://localhost:5001", Assert.Single(kvp.Value)); + Assert.Equal(OriginUrl, Assert.Single(kvp.Value)); }, kvp => { @@ -432,7 +526,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure }); app.UseCors(builder => - builder.WithOrigins("http://localhost:5001") + builder.WithOrigins(OriginUrl) .WithMethods("PUT") .WithHeaders("Header1") .WithExposedHeaders("AllowedHeader")); @@ -450,7 +544,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Act // Actual request. var response = await server.CreateRequest("/") - .AddHeader(CorsConstants.Origin, "http://localhost:5001") + .AddHeader(CorsConstants.Origin, OriginUrl) .SendAsync("PUT"); // Assert @@ -462,7 +556,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure kvp => { Assert.Equal(CorsConstants.AccessControlAllowOrigin, kvp.Key); - Assert.Equal("http://localhost:5001", Assert.Single(kvp.Value)); + Assert.Equal(OriginUrl, Assert.Single(kvp.Value)); }, kvp => { diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs index ebef888ad2..4430d6ec75 100644 --- a/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs +++ b/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs @@ -2,9 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Linq; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Logging.Testing; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using Xunit; namespace Microsoft.AspNetCore.Cors.Infrastructure @@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void EvaluatePolicy_NoOrigin_ReturnsInvalidResult() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext("GET", origin: null); // Act @@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void EvaluatePolicy_NoMatchingOrigin_ReturnsInvalidResult() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(origin: "http://example.com"); var policy = new CorsPolicy(); policy.Origins.Add("bar"); @@ -39,15 +39,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Null(result.AllowedOrigin); - Assert.False(result.VaryByOrigin); + Assert.False(result.IsOriginAllowed); } [Fact] public void EvaluatePolicy_EmptyOriginsPolicy_ReturnsInvalidResult() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(origin: "http://example.com"); var policy = new CorsPolicy(); @@ -55,15 +54,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Null(result.AllowedOrigin); - Assert.False(result.VaryByOrigin); + Assert.False(result.IsOriginAllowed); } [Fact] public void EvaluatePolicy_IsOriginAllowedReturnsFalse_ReturnsInvalidResult() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(origin: "http://example.com"); var policy = new CorsPolicy() { @@ -75,15 +73,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Null(result.AllowedOrigin); - Assert.False(result.VaryByOrigin); + Assert.False(result.IsOriginAllowed); } [Fact] - public void EvaluatePolicy_AllowAnyOrigin_DoesNotSupportCredentials_EmitsWildcardForOrigin() + public void EvaluatePolicy_AllowAnyOrigin_DoesNotSupportCredentials_EmitsOriginHeader() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(origin: "http://example.com"); var policy = new CorsPolicy @@ -101,10 +98,10 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure } [Fact] - public void EvaluatePolicy_AllowAnyOrigin_SupportsCredentials_AddsSpecificOrigin() + public void EvaluatePolicy_AllowAnyOrigin_AddsAnyOrigin() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(origin: "http://example.com"); var policy = new CorsPolicy { @@ -116,15 +113,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Equal("http://example.com", result.AllowedOrigin); - Assert.True(result.VaryByOrigin); + Assert.Equal("*", result.AllowedOrigin); } [Fact] public void EvaluatePolicy_DoesNotSupportCredentials_AllowCredentialsReturnsFalse() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(origin: "http://example.com"); var policy = new CorsPolicy { @@ -143,7 +139,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void EvaluatePolicy_SupportsCredentials_AllowCredentialsReturnsTrue() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(origin: "http://example.com"); var policy = new CorsPolicy { @@ -158,11 +154,84 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure Assert.True(result.SupportsCredentials); } + [Fact] + public void EvaluatePolicy_AllowAnyOrigin_DoesNotSupportsCredentials_DoesNotVaryByOrigin() + { + // Arrange + var corsService = GetCorsService(); + var requestContext = GetHttpContext(origin: "http://example.com"); + var policy = new CorsPolicy(); + policy.Origins.Add(CorsConstants.AnyOrigin); + + // Act + var result = corsService.EvaluatePolicy(requestContext, policy); + + // Assert + Assert.Equal("*", result.AllowedOrigin); + Assert.False(result.VaryByOrigin); + } + + [Fact] + public void EvaluatePolicy_AllowAnyOrigin_SupportsCredentials_DoesNotVaryByOrigin() + { + // Arrange + var corsService = GetCorsService(); + var requestContext = GetHttpContext(origin: "http://example.com"); + var policy = new CorsPolicy + { + SupportsCredentials = true + }; + policy.Origins.Add(CorsConstants.AnyOrigin); + + // Act + var result = corsService.EvaluatePolicy(requestContext, policy); + + // Assert + Assert.Equal("*", result.AllowedOrigin); + Assert.True(result.SupportsCredentials); + Assert.True(result.VaryByOrigin); + } + + [Fact] + public void EvaluatePolicy_AllowOneOrigin_DoesNotVaryByOrigin() + { + // Arrange + var corsService = GetCorsService(); + var requestContext = GetHttpContext(origin: "http://example.com"); + var policy = new CorsPolicy(); + policy.Origins.Add("http://example.com"); + + // Act + var result = corsService.EvaluatePolicy(requestContext, policy); + + // Assert + Assert.Equal("http://example.com", result.AllowedOrigin); + Assert.False(result.VaryByOrigin); + } + + [Fact] + public void EvaluatePolicy_AllowMultipleOrigins_VariesByOrigin() + { + // Arrange + var corsService = GetCorsService(); + var requestContext = GetHttpContext(origin: "http://example.com"); + var policy = new CorsPolicy(); + policy.Origins.Add("http://example.com"); + policy.Origins.Add("http://api.example.com"); + + // Act + var result = corsService.EvaluatePolicy(requestContext, policy); + + // Assert + Assert.Equal("http://example.com", result.AllowedOrigin); + Assert.True(result.VaryByOrigin); + } + [Fact] public void EvaluatePolicy_NoExposedHeaders_NoAllowExposedHeaders() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(origin: "http://example.com"); var policy = new CorsPolicy(); policy.Origins.Add(CorsConstants.AnyOrigin); @@ -178,7 +247,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void EvaluatePolicy_OneExposedHeaders_HeadersAllowed() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(origin: "http://example.com"); var policy = new CorsPolicy(); policy.Origins.Add(CorsConstants.AnyOrigin); @@ -188,15 +257,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Equal(1, result.AllowedExposedHeaders.Count); - Assert.Contains("foo", result.AllowedExposedHeaders); + Assert.Equal(new[] { "foo" }, result.AllowedExposedHeaders); } [Fact] public void EvaluatePolicy_ManyExposedHeaders_HeadersAllowed() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(origin: "http://example.com"); var policy = new CorsPolicy(); policy.Origins.Add(CorsConstants.AnyOrigin); @@ -208,17 +276,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Equal(3, result.AllowedExposedHeaders.Count); - Assert.Contains("foo", result.AllowedExposedHeaders); - Assert.Contains("bar", result.AllowedExposedHeaders); - Assert.Contains("baz", result.AllowedExposedHeaders); + Assert.Equal(new[] { "foo", "bar", "baz" }, result.AllowedExposedHeaders); } [Fact] - public void EvaluatePolicy_PreflightRequest_MethodNotAllowed_ReturnsInvalidResult() + public void EvaluatePolicy_PreflightRequest_MethodNotAllowed() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT"); var policy = new CorsPolicy(); policy.Origins.Add(CorsConstants.AnyOrigin); @@ -228,14 +293,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Empty(result.AllowedMethods); + Assert.Equal(new[] { "GET" }, result.AllowedMethods); } [Fact] public void EvaluatePolicy_PreflightRequest_MethodAllowed_ReturnsAllowMethods() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT"); var policy = new CorsPolicy(); policy.Origins.Add(CorsConstants.AnyOrigin); @@ -246,168 +311,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Assert Assert.NotNull(result); - Assert.Contains("PUT", result.AllowedMethods); - } - - public static TheoryData PreflightRequests_LoggingData - { - get - { - return new TheoryData - { - { - new LogData { - Origin = "http://example.com", - Method = "PUT", - Headers = null, - OriginLogMessage = "The request has an origin header: 'http://example.com'.", - PolicyLogMessage = "CORS policy execution failed.", - FailureReason = "Request origin http://example.com does not have permission to access the resource." - } - }, - { - new LogData { - Origin = "http://allowed.example.com", - Method = "DELETE", - Headers = null, - OriginLogMessage = "The request has an origin header: 'http://allowed.example.com'.", - PolicyLogMessage = "CORS policy execution failed.", - FailureReason = "Request method DELETE not allowed in CORS policy." - } - }, - { - new LogData { - Origin = "http://allowed.example.com", - Method = "PUT", - Headers = new[] { "test" }, - OriginLogMessage = "The request has an origin header: 'http://allowed.example.com'.", - PolicyLogMessage = "CORS policy execution failed.", - FailureReason = "Request header 'test' not allowed in CORS policy." - } - }, - }; - } - } - - [Theory] - [MemberData(nameof(PreflightRequests_LoggingData))] - public void EvaluatePolicy_LoggingForPreflightRequests_HasOriginHeader_PolicyFailed(LogData logData) - { - var sink = new TestSink(); - var loggerFactory = new TestLoggerFactory(sink, enabled: true); - - var corsService = new CorsService(new TestCorsOptions(), loggerFactory); - var requestContext = GetHttpContext(method: "OPTIONS", origin: logData.Origin, accessControlRequestMethod: logData.Method, accessControlRequestHeaders: logData.Headers); - var policy = new CorsPolicy(); - policy.Origins.Add("http://allowed.example.com"); - policy.Methods.Add("PUT"); - - // Act - var result = corsService.EvaluatePolicy(requestContext, policy); - - var writeList = sink.Writes.ToList(); - Assert.Equal("The request is a preflight request.", writeList[0].State.ToString()); - Assert.Equal(logData.OriginLogMessage, writeList[1].State.ToString()); - Assert.Equal(logData.PolicyLogMessage, writeList[2].State.ToString()); - Assert.Equal(logData.FailureReason, writeList[3].State.ToString()); - } - - [Fact] - public void EvaluatePolicy_LoggingForPreflightRequests_HasOriginHeader_PolicySucceeded() - { - var sink = new TestSink(); - var loggerFactory = new TestLoggerFactory(sink, enabled: true); - - var corsService = new CorsService(new TestCorsOptions(), loggerFactory); - var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://allowed.example.com", accessControlRequestMethod: "PUT"); - var policy = new CorsPolicy(); - policy.Origins.Add("http://allowed.example.com"); - policy.Methods.Add("PUT"); - - // Act - var result = corsService.EvaluatePolicy(requestContext, policy); - - var writeList = sink.Writes.ToList(); - Assert.Equal("The request is a preflight request.", writeList[0].State.ToString()); - Assert.Equal("The request has an origin header: 'http://allowed.example.com'.", writeList[1].State.ToString()); - Assert.Equal("CORS policy execution successful.", writeList[2].State.ToString()); - } - - [Fact] - public void EvaluatePolicy_LoggingForPreflightRequests_DoesNotHaveOriginHeader() - { - var sink = new TestSink(); - var loggerFactory = new TestLoggerFactory(sink, enabled: true); - - var corsService = new CorsService(new TestCorsOptions(), loggerFactory); - var requestContext = GetHttpContext(method: "OPTIONS", origin: null, accessControlRequestMethod: "PUT"); - var policy = new CorsPolicy(); - policy.Origins.Add("http://allowed.example.com"); - policy.Methods.Add("PUT"); - - // Act - var result = corsService.EvaluatePolicy(requestContext, policy); - - var writeList = sink.Writes.ToList(); - Assert.Equal("The request is a preflight request.", writeList[0].State.ToString()); - Assert.Equal("The request does not have an origin header.", writeList[1].State.ToString()); - } - - [Fact] - public void EvaluatePolicy_LoggingForNonPreflightRequests_HasOriginHeader_PolicyFailed() - { - var sink = new TestSink(); - var loggerFactory = new TestLoggerFactory(sink, enabled: true); - - var corsService = new CorsService(new TestCorsOptions(), loggerFactory); - var requestContext = GetHttpContext(origin: "http://example.com"); - var policy = new CorsPolicy(); - policy.Origins.Add("http://allowed.example.com"); - - // Act - var result = corsService.EvaluatePolicy(requestContext, policy); - - var writeList = sink.Writes.ToList(); - Assert.Equal("The request has an origin header: 'http://example.com'.", writeList[0].State.ToString()); - Assert.Equal("CORS policy execution failed.", writeList[1].State.ToString()); - Assert.Equal("Request origin http://example.com does not have permission to access the resource.", writeList[2].State.ToString()); - } - - [Fact] - public void EvaluatePolicy_LoggingForNonPreflightRequests_HasOriginHeader_PolicySucceeded() - { - var sink = new TestSink(); - var loggerFactory = new TestLoggerFactory(sink, enabled: true); - - var corsService = new CorsService(new TestCorsOptions(), loggerFactory); - var requestContext = GetHttpContext(origin: "http://allowed.example.com"); - var policy = new CorsPolicy(); - policy.Origins.Add("http://allowed.example.com"); - - // Act - var result = corsService.EvaluatePolicy(requestContext, policy); - - var writeList = sink.Writes.ToList(); - Assert.Equal("The request has an origin header: 'http://allowed.example.com'.", writeList[0].State.ToString()); - Assert.Equal("CORS policy execution successful.", writeList[1].State.ToString()); - } - - [Fact] - public void EvaluatePolicy_LoggingForNonPreflightRequests_DoesNotHaveOriginHeader() - { - var sink = new TestSink(); - var loggerFactory = new TestLoggerFactory(sink, enabled: true); - - var corsService = new CorsService(new TestCorsOptions(), loggerFactory); - var requestContext = GetHttpContext(origin: null); - var policy = new CorsPolicy(); - policy.Origins.Add("http://allowed.example.com"); - - // Act - var result = corsService.EvaluatePolicy(requestContext, policy); - - var logMessage = Assert.Single(sink.Writes); - Assert.Equal("The request does not have an origin header.", logMessage.State.ToString()); + Assert.Equal(new[] { "PUT" }, result.AllowedMethods); } [Theory] @@ -416,7 +320,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void EvaluatePolicy_CaseInsensitivePreflightRequest_OriginAllowed_ReturnsOrigin(string preflightMethod) { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext( method: preflightMethod, origin: "http://example.com", @@ -437,7 +341,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void EvaluatePolicy_PreflightRequest_IsOriginAllowedReturnsTrue_ReturnsOrigin() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext( method: "OPTIONS", origin: "http://example.com", @@ -459,7 +363,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void EvaluatePolicy_PreflightRequest_SupportsCredentials_AllowCredentialsReturnsTrue() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT"); var policy = new CorsPolicy { @@ -479,7 +383,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void EvaluatePolicy_PreflightRequest_NoPreflightMaxAge_NoPreflightMaxAgeSet() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT"); var policy = new CorsPolicy { @@ -499,7 +403,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void EvaluatePolicy_PreflightRequest_PreflightMaxAge_PreflightMaxAgeSet() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT"); var policy = new CorsPolicy { @@ -519,7 +423,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void EvaluatePolicy_PreflightRequest_AnyMethod_ReturnsRequestMethod() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "GET"); var policy = new CorsPolicy(); policy.Origins.Add(CorsConstants.AnyOrigin); @@ -529,17 +433,16 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Equal(1, result.AllowedMethods.Count); - Assert.Contains("GET", result.AllowedMethods); + Assert.Equal(new[] { "*" }, result.AllowedMethods); } [Theory] [InlineData("Put")] [InlineData("PUT")] - public void EvaluatePolicy_CaseInsensitivePreflightRequest_ListedMethod_ReturnsSubsetOfListedMethods(string method) + public void EvaluatePolicy_CaseInsensitivePreflightRequest_ReturnsAllowedMethods(string method) { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext( method: "OPTIONS", origin: "http://example.com", @@ -553,15 +456,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Equal(1, result.AllowedMethods.Count); - Assert.Contains(method, result.AllowedMethods); + Assert.Equal(new[] { "PUT", "DELETE" }, result.AllowedMethods); } [Fact] - public void EvaluatePolicy_PreflightRequest_NoHeadersRequested_AllowedAllHeaders_ReturnsEmptyHeaders() + public void EvaluatePolicy_PreflightRequest_NoHeadersRequested_AllowedAllHeaders() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT"); var policy = new CorsPolicy(); policy.Origins.Add(CorsConstants.AnyOrigin); @@ -572,14 +474,15 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Empty(result.AllowedHeaders); + Assert.Equal(new[] { "*" }, result.AllowedHeaders); + Assert.Equal(new[] { "*" }, result.AllowedMethods); } [Fact] - public void EvaluatePolicy_PreflightRequest_HeadersRequested_AllowAllHeaders_ReturnsRequestedHeaders() + public void EvaluatePolicy_PreflightRequest_AllowAllHeaders() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext( method: "OPTIONS", origin: "http://example.com", @@ -589,21 +492,21 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure policy.Origins.Add(CorsConstants.AnyOrigin); policy.Methods.Add("*"); policy.Headers.Add("*"); + policy.SupportsCredentials = true; // Act var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Equal(2, result.AllowedHeaders.Count); - Assert.Contains("foo", result.AllowedHeaders); - Assert.Contains("bar", result.AllowedHeaders); + Assert.Equal(new[] { "*" }, result.AllowedHeaders); + Assert.Equal(new[] { "*" }, result.AllowedMethods); } - + [Fact] public void EvaluatePolicy_PreflightRequest_HeadersRequested_NotAllHeaderMatches_ReturnsInvalidResult() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext( method: "OPTIONS", origin: "http://example.com", @@ -619,76 +522,30 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Empty(result.AllowedHeaders); - Assert.Empty(result.AllowedMethods); - Assert.Empty(result.AllowedExposedHeaders); - Assert.Null(result.AllowedOrigin); + Assert.Equal(new[] { "match", "foo" }, result.AllowedHeaders); + Assert.Equal(new[] { "*" }, result.AllowedMethods); } [Fact] - public void EvaluatePolicy_DoesCaseSensitiveComparison() + public void EvaluatePolicy_PreflightRequest_WithCredentials_ReturnsWildCard() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); - + var corsService = GetCorsService(); + var httpContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT"); var policy = new CorsPolicy(); - policy.Methods.Add("POST"); - var httpContext = GetHttpContext(origin: null, accessControlRequestMethod: "post"); + policy.Origins.Add(CorsConstants.AnyOrigin); + policy.Methods.Add("*"); + policy.Headers.Add("*"); + policy.SupportsCredentials = true; // Act var result = corsService.EvaluatePolicy(httpContext, policy); // Assert - Assert.Empty(result.AllowedHeaders); - Assert.Empty(result.AllowedMethods); - Assert.Empty(result.AllowedExposedHeaders); - Assert.Null(result.AllowedOrigin); - } - - [Fact] - public void TryValidateOrigin_DoesCaseSensitiveComparison() - { - // Arrange - var corsService = new CorsService(new TestCorsOptions()); - - var policy = new CorsPolicy(); - policy.Origins.Add("http://Example.com"); - var httpContext = GetHttpContext(origin: "http://example.com"); - - // Act - var result = corsService.EvaluatePolicy(httpContext, policy); - - // Assert - Assert.Empty(result.AllowedHeaders); - Assert.Empty(result.AllowedMethods); - Assert.Empty(result.AllowedExposedHeaders); - Assert.Null(result.AllowedOrigin); - } - - [Fact] - public void ApplyResult_SimpleRequests_IgnoresFiltering() - { - // Arrange - var result = new CorsResult(); - result.AllowedHeaders.Add("Content-Type"); - result.AllowedHeaders.Add("Date"); - result.AllowedMethods.Add("GET"); - result.AllowedMethods.Add("PUT"); - - var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); - - - // Act - service.ApplyResult(result, httpContext.Response); - - // Assert - string[] arMethods = httpContext.Response.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlAllowMethods); - Assert.Contains("GET", arMethods); - Assert.Contains("PUT", arMethods); - string[] arHeaders = httpContext.Response.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlAllowHeaders); - Assert.Contains("Content-Type", arHeaders); - Assert.Contains("Date", arHeaders); + Assert.NotNull(result); + Assert.Equal(new[] { "*" }, result.AllowedMethods); + Assert.Equal(new[] { "*" }, result.AllowedHeaders); + Assert.True(result.SupportsCredentials); } [Fact] @@ -697,7 +554,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Arrange var result = new CorsResult(); var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); + var service = GetCorsService(); // Act service.ApplyResult(result, httpContext.Response); @@ -712,11 +569,12 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Arrange var result = new CorsResult { + IsOriginAllowed = true, AllowedOrigin = "http://example.com" }; var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); + var service = GetCorsService(); // Act service.ApplyResult(result, httpContext.Response); @@ -731,11 +589,12 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Arrange var result = new CorsResult { + IsOriginAllowed = true, AllowedOrigin = null }; var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); + var service = GetCorsService(); // Act service.ApplyResult(result, httpContext.Response); @@ -750,10 +609,11 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Arrange var result = new CorsResult { + IsOriginAllowed = true, SupportsCredentials = true }; - var service = new CorsService(new TestCorsOptions()); + var service = GetCorsService(); // Act var httpContext = new DefaultHttpContext(); @@ -769,11 +629,12 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Arrange var result = new CorsResult { + IsOriginAllowed = true, VaryByOrigin = true }; var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); + var service = GetCorsService(); // Act service.ApplyResult(result, httpContext.Response); @@ -782,17 +643,39 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure Assert.Equal("Origin", httpContext.Response.Headers["Vary"]); } + [Fact] + public void ApplyResult_AppendsVaryHeader() + { + // Arrange + var result = new CorsResult + { + IsOriginAllowed = true, + VaryByOrigin = true + }; + + var httpContext = new DefaultHttpContext(); + httpContext.Response.Headers["Vary"] = "Cookie"; + var service = GetCorsService(); + + // Act + service.ApplyResult(result, httpContext.Response); + + // Assert + Assert.Equal("Cookie,Origin", httpContext.Response.Headers["Vary"]); + } + [Fact] public void ApplyResult_NoAllowCredentials_AllowCredentialsHeaderNotAdded() { // Arrange var result = new CorsResult { + IsOriginAllowed = true, SupportsCredentials = false }; var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); + var service = GetCorsService(); // Act service.ApplyResult(result, httpContext.Response); @@ -807,11 +690,12 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Arrange var result = new CorsResult { + IsOriginAllowed = true, // AllowMethods is empty by default }; var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); + var service = GetCorsService(); // Act service.ApplyResult(result, httpContext.Response); @@ -824,11 +708,15 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void ApplyResult_OneAllowMethods_AllowMethodsHeaderAdded() { // Arrange - var result = new CorsResult(); - result.AllowedMethods.Add("PUT"); + var result = new CorsResult + { + IsOriginAllowed = true, + IsPreflightRequest = true, + AllowedMethods = { "PUT" } + }; var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); + var service = GetCorsService(); // Act service.ApplyResult(result, httpContext.Response); @@ -836,6 +724,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Assert Assert.Equal("PUT", httpContext.Response.Headers["Access-Control-Allow-Methods"]); } + [Fact] public void ApplyResult_NoAllowHeaders_AllowHeadersHeaderNotAdded() { @@ -843,10 +732,11 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = new CorsResult { // AllowHeaders is empty by default + IsOriginAllowed = true, }; var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); + var service = GetCorsService(); // Act service.ApplyResult(result, httpContext.Response); @@ -859,11 +749,15 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void ApplyResult_OneAllowHeaders_AllowHeadersHeaderAdded() { // Arrange - var result = new CorsResult(); - result.AllowedHeaders.Add("foo"); + var result = new CorsResult + { + IsOriginAllowed = true, + IsPreflightRequest = true, + AllowedHeaders = { "foo" } + }; var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); + var service = GetCorsService(); // Act service.ApplyResult(result, httpContext.Response); @@ -872,32 +766,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure Assert.Equal("foo", httpContext.Response.Headers["Access-Control-Allow-Headers"]); } - [Fact] - public void ApplyResult_ManyAllowHeaders_AllowHeadersHeaderAdded() - { - // Arrange - var result = new CorsResult(); - result.AllowedHeaders.Add("foo"); - result.AllowedHeaders.Add("bar"); - result.AllowedHeaders.Add("baz"); - var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); - - // Act - service.ApplyResult(result, httpContext.Response); - - // Assert - Assert.Contains("Access-Control-Allow-Headers", httpContext.Response.Headers.Keys); - var value = Assert.Single(httpContext.Response.Headers.Values); - Assert.Equal(new[] { "foo,bar,baz" }, value); - string[] headerValues = httpContext.Response.Headers.GetCommaSeparatedValues("Access-Control-Allow-Headers"); - Assert.Equal(3, headerValues.Length); - Assert.Contains("foo", headerValues); - Assert.Contains("bar", headerValues); - Assert.Contains("baz", headerValues); - } - [Fact] public void ApplyResult_NoAllowExposedHeaders_ExposedHeadersHeaderNotAdded() { @@ -905,10 +774,11 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = new CorsResult { // AllowExposedHeaders is empty by default + IsOriginAllowed = true, }; var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); + var service = GetCorsService(); // Act service.ApplyResult(result, httpContext.Response); @@ -917,15 +787,61 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure Assert.DoesNotContain("Access-Control-Expose-Headers", httpContext.Response.Headers.Keys); } + [Fact] + public void ApplyResult_PreflightRequest_ExposesHeadersNotAdded() + { + // Arrange + var result = new CorsResult + { + IsOriginAllowed = true, + IsPreflightRequest = true, + AllowedExposedHeaders = { "foo", "bar" }, + }; + + var httpContext = new DefaultHttpContext(); + var service = GetCorsService(); + + // Act + service.ApplyResult(result, httpContext.Response); + + // Assert + Assert.DoesNotContain("Access-Control-Expose-Headers", httpContext.Response.Headers.Keys); + } + + [Fact] + public void ApplyResult_NoPreflightRequest_ExposesHeadersAdded() + { + // Arrange + var result = new CorsResult + { + IsOriginAllowed = true, + IsPreflightRequest = false, + AllowedExposedHeaders = { "foo", "bar" }, + }; + + var httpContext = new DefaultHttpContext(); + var service = GetCorsService(); + + // Act + service.ApplyResult(result, httpContext.Response); + + // Assert + Assert.Equal("foo,bar", httpContext.Response.Headers[CorsConstants.AccessControlExposeHeaders]); + } + + [Fact] public void ApplyResult_OneAllowExposedHeaders_ExposedHeadersHeaderAdded() { // Arrange - var result = new CorsResult(); - result.AllowedExposedHeaders.Add("foo"); + var result = new CorsResult + { + IsOriginAllowed = true, + AllowedExposedHeaders = { "foo" }, + }; var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); + var service = GetCorsService(); // Act service.ApplyResult(result, httpContext.Response); @@ -934,43 +850,19 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure Assert.Equal("foo", httpContext.Response.Headers["Access-Control-Expose-Headers"]); } - [Fact] - public void ApplyResult_ManyAllowExposedHeaders_ExposedHeadersHeaderAdded() - { - // Arrange - var result = new CorsResult(); - result.AllowedExposedHeaders.Add("foo"); - result.AllowedExposedHeaders.Add("bar"); - result.AllowedExposedHeaders.Add("baz"); - - var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); - - // Act - service.ApplyResult(result, httpContext.Response); - - // Assert - Assert.Contains("Access-Control-Expose-Headers", httpContext.Response.Headers.Keys); - var value = Assert.Single(httpContext.Response.Headers.Values); - Assert.Equal(new[] { "foo,bar,baz" }, value); - string[] exposedHeaderValues = httpContext.Response.Headers.GetCommaSeparatedValues("Access-Control-Expose-Headers"); - Assert.Equal(3, exposedHeaderValues.Length); - Assert.Contains("foo", exposedHeaderValues); - Assert.Contains("bar", exposedHeaderValues); - Assert.Contains("baz", exposedHeaderValues); - } - [Fact] public void ApplyResult_NoPreflightMaxAge_MaxAgeHeaderNotAdded() { // Arrange var result = new CorsResult { - PreflightMaxAge = null + IsOriginAllowed = true, + IsPreflightRequest = false, + PreflightMaxAge = TimeSpan.FromSeconds(30), }; var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); + var service = GetCorsService(); // Act service.ApplyResult(result, httpContext.Response); @@ -985,10 +877,12 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Arrange var result = new CorsResult { - PreflightMaxAge = TimeSpan.FromSeconds(30) + IsOriginAllowed = true, + IsPreflightRequest = true, + PreflightMaxAge = TimeSpan.FromSeconds(30), }; var httpContext = new DefaultHttpContext(); - var service = new CorsService(new TestCorsOptions()); + var service = GetCorsService(); // Act service.ApplyResult(result, httpContext.Response); @@ -1001,7 +895,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void EvaluatePolicy_MultiOriginsPolicy_ReturnsVaryByOriginHeader() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(origin: "http://example.com"); var policy = new CorsPolicy(); policy.Origins.Add("http://example.com"); @@ -1019,7 +913,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void EvaluatePolicy_MultiOriginsPolicy_NoMatchingOrigin_ReturnsInvalidResult() { // Arrange - var corsService = new CorsService(new TestCorsOptions()); + var corsService = GetCorsService(); var requestContext = GetHttpContext(origin: "http://example.com"); var policy = new CorsPolicy(); policy.Origins.Add("http://example-two.com"); @@ -1029,10 +923,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Null(result.AllowedOrigin); - Assert.False(result.VaryByOrigin); + Assert.False(result.IsOriginAllowed); } + private static CorsService GetCorsService(CorsOptions options = null) + { + options = options ?? new CorsOptions(); + return new CorsService(Options.Create(options), NullLoggerFactory.Instance); + } private static HttpContext GetHttpContext( string method = null, @@ -1064,15 +962,5 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure return context; } - - public class LogData - { - public string Origin { get; set; } - public string Method { get; set; } - public string[] Headers { get; set; } - public string OriginLogMessage { get; set; } - public string PolicyLogMessage { get; set; } - public string FailureReason { get; set; } - } } } diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsTestFixtureOfT.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsTestFixtureOfT.cs deleted file mode 100644 index aa698c62f2..0000000000 --- a/test/Microsoft.AspNetCore.Cors.Test/CorsTestFixtureOfT.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Net.Http; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; - -namespace Microsoft.AspNetCore.Cors.Infrastructure -{ - public class CorsTestFixture : IDisposable - where TStartup : class - { - private readonly TestServer _server; - - public CorsTestFixture() - { - var builder = new WebHostBuilder().UseStartup(); - _server = new TestServer(builder); - - Client = _server.CreateClient(); - Client.BaseAddress = new Uri("http://localhost"); - } - - public HttpClient Client { get; } - - public void Dispose() - { - Client.Dispose(); - _server.Dispose(); - } - } -} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Cors.Test/DefaultCorsPolicyProviderTests.cs b/test/Microsoft.AspNetCore.Cors.Test/DefaultCorsPolicyProviderTests.cs index d66b0e5653..e3764bc84e 100644 --- a/test/Microsoft.AspNetCore.Cors.Test/DefaultCorsPolicyProviderTests.cs +++ b/test/Microsoft.AspNetCore.Cors.Test/DefaultCorsPolicyProviderTests.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; using Xunit; namespace Microsoft.AspNetCore.Cors.Infrastructure @@ -17,10 +18,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var policy = new CorsPolicy(); options.AddPolicy(options.DefaultPolicyName, policy); - var corsOptions = new TestCorsOptions - { - Value = options - }; + var corsOptions = Options.Create(options); var policyProvider = new DefaultCorsPolicyProvider(corsOptions); // Act @@ -40,10 +38,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var policy = new CorsPolicy(); options.AddPolicy(policyName, policy); - var corsOptions = new TestCorsOptions - { - Value = options - }; + var corsOptions = Options.Create(options); var policyProvider = new DefaultCorsPolicyProvider(corsOptions); // Act diff --git a/test/Microsoft.AspNetCore.Cors.Test/TestCorsOptions.cs b/test/Microsoft.AspNetCore.Cors.Test/TestCorsOptions.cs deleted file mode 100644 index 782ebb2db7..0000000000 --- a/test/Microsoft.AspNetCore.Cors.Test/TestCorsOptions.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.Extensions.Options; - -namespace Microsoft.AspNetCore.Cors.Infrastructure -{ - public class TestCorsOptions : IOptions - { - public CorsOptions Value { get; set; } - } -} diff --git a/test/Microsoft.AspNetCore.Cors.Test/UriHelpersTests.cs b/test/Microsoft.AspNetCore.Cors.Test/UriHelpersTests.cs index ac04cfc3fd..7b28d6aa64 100644 --- a/test/Microsoft.AspNetCore.Cors.Test/UriHelpersTests.cs +++ b/test/Microsoft.AspNetCore.Cors.Test/UriHelpersTests.cs @@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void TestIsSubdomainOf(Uri subdomain, Uri domain) { // Act - bool isSubdomain = UriHelpers.IsSubdomainOf(subdomain, domain); + var isSubdomain = UriHelpers.IsSubdomainOf(subdomain, domain); // Assert Assert.True(isSubdomain); @@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure public void TestIsSubdomainOf_ReturnsFalse_WhenNotSubdomain(Uri subdomain, Uri domain) { // Act - bool isSubdomain = UriHelpers.IsSubdomainOf(subdomain, domain); + var isSubdomain = UriHelpers.IsSubdomainOf(subdomain, domain); // Assert Assert.False(isSubdomain); From e6bdf128f2a748e7bb8f783da7644c3ee8e95eca Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 11 Oct 2018 12:45:56 -0700 Subject: [PATCH 40/47] Log when a request is an OPTIONS request but not a preflight request Fixes https://github.com/aspnet/AspNetCore/issues/2375 --- .../Infrastructure/CorsService.cs | 11 ++++++++--- .../Internal/CORSLoggerExtensions.cs | 11 +++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs index 0ec9c030f3..0d52489d81 100644 --- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs +++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs @@ -92,9 +92,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var origin = context.Request.Headers[CorsConstants.Origin]; var requestHeaders = context.Request.Headers; - var isPreflightRequest = - string.Equals(context.Request.Method, CorsConstants.PreflightHttpMethod, StringComparison.OrdinalIgnoreCase) && - requestHeaders.ContainsKey(CorsConstants.AccessControlRequestMethod); + + var isOptionsRequest = string.Equals(context.Request.Method, CorsConstants.PreflightHttpMethod, StringComparison.OrdinalIgnoreCase); + var isPreflightRequest = isOptionsRequest && requestHeaders.ContainsKey(CorsConstants.AccessControlRequestMethod); + + if (isOptionsRequest && !isPreflightRequest) + { + _logger.IsNotPreflightRequest(); + } var corsResult = new CorsResult { diff --git a/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs b/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs index d324aba1cf..ee6533bbed 100644 --- a/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs +++ b/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs @@ -19,6 +19,7 @@ namespace Microsoft.AspNetCore.Cors.Internal private static readonly Action _failedToSetCorsHeaders; private static readonly Action _noCorsPolicyFound; private static readonly Action _insecureConfiguration; + private static readonly Action _isNotPreflightRequest; static CORSLoggerExtensions() { @@ -76,6 +77,11 @@ namespace Microsoft.AspNetCore.Cors.Internal LogLevel.Warning, new EventId(11, "CorsInsecureConfiguration"), "The CORS protocol does not allow specifying a wildcard (any) origin and credentials at the same time. Configure the policy by listing individual origins if credentials needs to be supported."); + + _isNotPreflightRequest = LoggerMessage.Define( + LogLevel.Debug, + new EventId(12, "OptionsRequestWithoutAccessControlRequestMethodHeader"), + "This request uses the HTTP OPTIONS method but does not have an Access-Control-Request-Method header. This request will not be treated as a CORS preflight request."); } public static void IsPreflightRequest(this ILogger logger) @@ -132,5 +138,10 @@ namespace Microsoft.AspNetCore.Cors.Internal { _insecureConfiguration(logger, null); } + + public static void IsNotPreflightRequest(this ILogger logger) + { + _isNotPreflightRequest(logger, null); + } } } From 8ad589c4d1be35232694e17f38de06c1614b213d Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 12 Oct 2018 17:08:58 -0700 Subject: [PATCH 41/47] Provide better errors if launching the browser failed --- korebuild.json | 8 +++++++- test/FunctionalTests/test.js | 24 +++++++++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/korebuild.json b/korebuild.json index d217d06e3e..78afb8c137 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,4 +1,10 @@ { "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.2/tools/korebuild.schema.json", - "channel": "release/2.2" + "channel": "release/2.2", + "toolsets": { + "nodejs": { + "required": true, + "minVersion": "8.0" + } + } } diff --git a/test/FunctionalTests/test.js b/test/FunctionalTests/test.js index 2fc14652e1..0f81bd3597 100644 --- a/test/FunctionalTests/test.js +++ b/test/FunctionalTests/test.js @@ -10,19 +10,37 @@ const debug = process.env.npm_config_debug || false; jest.setTimeout(debug ? 60000 : 30000); let browser; +let error; beforeAll(async () => { const options = debug ? { headless: false, slowMo: 100 } : { args: ['--no-sandbox'] }; - browser = await puppeteer.launch(options); - expect(browser).toBeDefined(); + + try { + browser = await puppeteer.launch(options); + } catch (ex) { + error = ex; + } }); afterAll(async () => { - await browser.close(); + if (browser) { + await browser.close(); + } }); +describe('Browser is initialized', () => { + // Workaround for https://github.com/jasmine/jasmine/issues/1533. + // Jasmine will not report errors from beforeAll and instead fail all the tests that + // expect the browser to be available. This test allows us to ensure the setup was successful + // and if unsuccessful report the error + test('no errors on launch', () => { + expect(error).toBeUndefined(); + expect(browser).toBeDefined(); + }) +}) + describe('CORS allowed origin tests ', () => { const testPagePath = `http://${hostname}:9001/`; let page; From 393815b8ad5c0b694fcf33e2ceffbff07f686e5b Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 16 Oct 2018 09:57:34 -0700 Subject: [PATCH 42/47] Increase test timeout to accomodate slow machines --- test/FunctionalTests/ProcessManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/FunctionalTests/ProcessManager.cs b/test/FunctionalTests/ProcessManager.cs index 9689a2da7d..77bebe26c8 100644 --- a/test/FunctionalTests/ProcessManager.cs +++ b/test/FunctionalTests/ProcessManager.cs @@ -11,7 +11,7 @@ namespace FunctionalTests { internal static class ProcessManager { - private static readonly TimeSpan Timeout = TimeSpan.FromSeconds(60); + private static readonly TimeSpan Timeout = TimeSpan.FromMinutes(3); public static Task RunProcessAsync(ProcessStartInfo processStartInfo) { From 50dff844b2ce7ff8a0f810cfd96b70d13fff970a Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 16 Oct 2018 12:48:11 -0700 Subject: [PATCH 43/47] Update package branding for 2.2 RTM --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 704cac087b..4889a26987 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.2.0 - preview3 + rtm $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From aa88f16b08d239b93075f56b587dc4e650e05572 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Wed, 24 Oct 2018 12:56:07 -0700 Subject: [PATCH 44/47] Fix cors with creds (#193) --- .../Infrastructure/CorsService.cs | 13 ++++++++++--- test/FunctionalTests/test.js | 12 ++++++++---- .../CorsMiddlewareTests.cs | 6 +++--- .../CorsServiceTests.cs | 7 +++---- test/WebSites/CorsMiddlewareWebSite/web.config | 4 +++- 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs index 0d52489d81..78e2371c78 100644 --- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs +++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs @@ -136,10 +136,17 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure result.SupportsCredentials = policy.SupportsCredentials; result.PreflightMaxAge = policy.PreflightMaxAge; - + // https://fetch.spec.whatwg.org/#http-new-header-syntax AddHeaderValues(result.AllowedExposedHeaders, policy.ExposedHeaders); - AddHeaderValues(result.AllowedMethods, policy.Methods); - AddHeaderValues(result.AllowedHeaders, policy.Headers); + + var allowedMethods = policy.AllowAnyMethod && policy.SupportsCredentials ? + new[] { result.IsPreflightRequest ? (string)context.Request.Headers[CorsConstants.AccessControlRequestMethod] : context.Request.Method } + : policy.Methods; + AddHeaderValues(result.AllowedMethods, allowedMethods); + + var allowedHeaders = policy.AllowAnyHeader && policy.SupportsCredentials ? + context.Request.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlRequestHeaders) : policy.Headers; + AddHeaderValues(result.AllowedHeaders, allowedHeaders); } public virtual void EvaluateRequest(HttpContext context, CorsPolicy policy, CorsResult result) diff --git a/test/FunctionalTests/test.js b/test/FunctionalTests/test.js index 0f81bd3597..c39ffeaa6b 100644 --- a/test/FunctionalTests/test.js +++ b/test/FunctionalTests/test.js @@ -6,7 +6,7 @@ const corsServerPath = `http://${hostname}:9000`; // e.g., npm test --debug // In debug mode we show the editor, slow down operations, and increase the timeout for each test -const debug = process.env.npm_config_debug || false; +let debug = process.env.npm_config_debug || false; jest.setTimeout(debug ? 60000 : 30000); let browser; @@ -38,8 +38,8 @@ describe('Browser is initialized', () => { test('no errors on launch', () => { expect(error).toBeUndefined(); expect(browser).toBeDefined(); - }) -}) + }); +}); describe('CORS allowed origin tests ', () => { const testPagePath = `http://${hostname}:9001/`; @@ -176,7 +176,11 @@ describe('CORS allowed origin tests ', () => { test('allows Preflighted request with credentials', async () => { const result = await page.evaluate(async (corsServerPath) => { const url = `${corsServerPath}/allow-credentials`; - const options = { method: 'PUT', mode: 'cors', credentials: 'include' }; + const options = { + method: 'PUT', mode: 'cors', credentials: 'include', headers: new Headers({ + 'X-Custom-Header': 'X-Custom-Value' + }) + }; const response = await fetch(url, options); return response.status; diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs index 85b79949b4..7d80e29fba 100644 --- a/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs +++ b/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs @@ -192,7 +192,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure } [Fact] - public async Task PreFlight_WithCredentialsAllowed_ReturnsWildcardValues() + public async Task PreFlight_WithCredentialsAllowed_ReflectsRequestHeaders() { // Arrange var policy = new CorsPolicyBuilder(OriginUrl) @@ -240,12 +240,12 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure kvp => { Assert.Equal(CorsConstants.AccessControlAllowHeaders, kvp.Key); - Assert.Equal(new[] { "*" }, kvp.Value); + Assert.Equal(new[] { "X-Test1,X-Test2" }, kvp.Value); }, kvp => { Assert.Equal(CorsConstants.AccessControlAllowMethods, kvp.Key); - Assert.Equal(new[] { "*" }, kvp.Value); + Assert.Equal(new[] { "PUT" }, kvp.Value); }, kvp => { diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs index 4430d6ec75..fb47a3f70e 100644 --- a/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs +++ b/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs @@ -492,7 +492,6 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure policy.Origins.Add(CorsConstants.AnyOrigin); policy.Methods.Add("*"); policy.Headers.Add("*"); - policy.SupportsCredentials = true; // Act var result = corsService.EvaluatePolicy(requestContext, policy); @@ -527,7 +526,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure } [Fact] - public void EvaluatePolicy_PreflightRequest_WithCredentials_ReturnsWildCard() + public void EvaluatePolicy_PreflightRequest_WithCredentials_ReflectsHeaders() { // Arrange var corsService = GetCorsService(); @@ -543,8 +542,8 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Assert Assert.NotNull(result); - Assert.Equal(new[] { "*" }, result.AllowedMethods); - Assert.Equal(new[] { "*" }, result.AllowedHeaders); + Assert.Equal(new[] { "PUT" }, result.AllowedMethods); + Assert.Empty(result.AllowedHeaders); Assert.True(result.SupportsCredentials); } diff --git a/test/WebSites/CorsMiddlewareWebSite/web.config b/test/WebSites/CorsMiddlewareWebSite/web.config index f7ac679334..e149af83da 100644 --- a/test/WebSites/CorsMiddlewareWebSite/web.config +++ b/test/WebSites/CorsMiddlewareWebSite/web.config @@ -4,6 +4,8 @@ - + + + \ No newline at end of file From a74235c7ec22c8801619550f7d6a223a08890a9a Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 26 Oct 2018 10:12:00 -0700 Subject: [PATCH 45/47] Reflect Access-Control-Request-Headers and Access-Control-Request-Method when policy is configured to support wildcard Fixes https://github.com/aspnet/AspNetCore/issues/3684 --- .../Infrastructure/CorsService.cs | 11 ++++++----- .../CorsServiceTests.cs | 14 +++++++------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs index 78e2371c78..16670add2c 100644 --- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs +++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs @@ -139,13 +139,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // https://fetch.spec.whatwg.org/#http-new-header-syntax AddHeaderValues(result.AllowedExposedHeaders, policy.ExposedHeaders); - var allowedMethods = policy.AllowAnyMethod && policy.SupportsCredentials ? - new[] { result.IsPreflightRequest ? (string)context.Request.Headers[CorsConstants.AccessControlRequestMethod] : context.Request.Method } - : policy.Methods; + var allowedMethods = policy.AllowAnyMethod ? + new[] { result.IsPreflightRequest ? (string)context.Request.Headers[CorsConstants.AccessControlRequestMethod] : context.Request.Method } : + policy.Methods; AddHeaderValues(result.AllowedMethods, allowedMethods); - var allowedHeaders = policy.AllowAnyHeader && policy.SupportsCredentials ? - context.Request.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlRequestHeaders) : policy.Headers; + var allowedHeaders = policy.AllowAnyHeader ? + context.Request.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlRequestHeaders) : + policy.Headers; AddHeaderValues(result.AllowedHeaders, allowedHeaders); } diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs index fb47a3f70e..a2ab09d2a0 100644 --- a/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs +++ b/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs @@ -433,7 +433,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Equal(new[] { "*" }, result.AllowedMethods); + Assert.Equal(new[] { "GET" }, result.AllowedMethods); } [Theory] @@ -474,12 +474,12 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Equal(new[] { "*" }, result.AllowedHeaders); - Assert.Equal(new[] { "*" }, result.AllowedMethods); + Assert.Empty(result.AllowedHeaders); + Assert.Equal(new[] { "PUT" }, result.AllowedMethods); } [Fact] - public void EvaluatePolicy_PreflightRequest_AllowAllHeaders() + public void EvaluatePolicy_PreflightRequest_AllowAllHeaders_ReflectsRequestHeaders() { // Arrange var corsService = GetCorsService(); @@ -497,8 +497,8 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure var result = corsService.EvaluatePolicy(requestContext, policy); // Assert - Assert.Equal(new[] { "*" }, result.AllowedHeaders); - Assert.Equal(new[] { "*" }, result.AllowedMethods); + Assert.Equal(new[] { "foo", "bar" }, result.AllowedHeaders); + Assert.Equal(new[] { "PUT" }, result.AllowedMethods); } [Fact] @@ -522,7 +522,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure // Assert Assert.Equal(new[] { "match", "foo" }, result.AllowedHeaders); - Assert.Equal(new[] { "*" }, result.AllowedMethods); + Assert.Equal(new[] { "PUT" }, result.AllowedMethods); } [Fact] From f05b0e792d2361be214947798857ef3eac77825d Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 8 Nov 2018 11:28:52 -0800 Subject: [PATCH 46/47] Add some logging for functional tests --- .../CorsMiddlewareFunctionalTest.cs | 2 +- test/FunctionalTests/ProcessManager.cs | 8 ++++++-- test/FunctionalTests/test.js | 15 ++++++++++----- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/test/FunctionalTests/CorsMiddlewareFunctionalTest.cs b/test/FunctionalTests/CorsMiddlewareFunctionalTest.cs index 7c61d1f77b..ebeebb2d74 100644 --- a/test/FunctionalTests/CorsMiddlewareFunctionalTest.cs +++ b/test/FunctionalTests/CorsMiddlewareFunctionalTest.cs @@ -50,7 +50,7 @@ namespace FunctionalTests } // Act - var result = await ProcessManager.RunProcessAsync(processStartInfo); + var result = await ProcessManager.RunProcessAsync(processStartInfo, loggerFactory.CreateLogger("ProcessManager")); // Assert Assert.Success(result); diff --git a/test/FunctionalTests/ProcessManager.cs b/test/FunctionalTests/ProcessManager.cs index 77bebe26c8..40091810d0 100644 --- a/test/FunctionalTests/ProcessManager.cs +++ b/test/FunctionalTests/ProcessManager.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Text; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; namespace FunctionalTests { @@ -13,7 +14,7 @@ namespace FunctionalTests { private static readonly TimeSpan Timeout = TimeSpan.FromMinutes(3); - public static Task RunProcessAsync(ProcessStartInfo processStartInfo) + public static Task RunProcessAsync(ProcessStartInfo processStartInfo, ILogger logger) { processStartInfo.UseShellExecute = false; processStartInfo.RedirectStandardError = true; @@ -31,6 +32,7 @@ namespace FunctionalTests process.ErrorDataReceived += Process_ErrorDataReceived; process.OutputDataReceived += Process_OutputDataReceived; + logger.LogInformation($"Executing command '{process.StartInfo.FileName} {process.StartInfo.Arguments}'"); process.Start(); process.BeginErrorReadLine(); process.BeginOutputReadLine(); @@ -52,7 +54,7 @@ namespace FunctionalTests // This is a timeout. process.Kill(); - throw new TimeoutException($"command '${process.StartInfo.FileName} {process.StartInfo.Arguments}' timed out after {Timeout}."); + throw new TimeoutException($"command '{process.StartInfo.FileName} {process.StartInfo.Arguments}' timed out after {Timeout}."); }); var waitTask = Task.Run(() => @@ -83,6 +85,7 @@ namespace FunctionalTests void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e) { + logger.LogInformation(e.Data); lock (outputLock) { output.AppendLine(e.Data); @@ -91,6 +94,7 @@ namespace FunctionalTests void Process_OutputDataReceived(object sender, DataReceivedEventArgs e) { + logger.LogInformation(e.Data); lock (outputLock) { output.AppendLine(e.Data); diff --git a/test/FunctionalTests/test.js b/test/FunctionalTests/test.js index c39ffeaa6b..f994029bf2 100644 --- a/test/FunctionalTests/test.js +++ b/test/FunctionalTests/test.js @@ -16,12 +16,17 @@ beforeAll(async () => { const options = debug ? { headless: false, slowMo: 100 } : { args: ['--no-sandbox'] }; + const label = 'Launch puppeteer '; - try { - browser = await puppeteer.launch(options); - } catch (ex) { - error = ex; - } + console.log('Begin launching puppeteer'); + console.time(label); + + try { + browser = await puppeteer.launch(options); + } catch (ex) { + error = ex; + } + console.timeEnd(label); }); afterAll(async () => { From e8849f6626eabc7f68b1904ee6623c42e9609b0b Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Wed, 21 Nov 2018 16:01:19 -0800 Subject: [PATCH 47/47] Reorganize source code in preparation to move into aspnet/AspNetCore Prior to reorganization, this source code was found in https://github.com/aspnet/CORS/tree/f05b0e792d2361be214947798857ef3eac77825d --- .appveyor.yml | 13 - .gitattributes | 51 ---- .github/ISSUE_TEMPLATE.md | 3 - .travis.yml | 27 -- .vsts-pipelines/builds/ci-internal.yml | 38 --- .vsts-pipelines/builds/ci-public.yml | 40 --- CONTRIBUTING.md | 4 - LICENSE.txt | 14 - NuGet.config | 7 - build.cmd | 2 - build.sh | 8 - korebuild-lock.txt | 2 - korebuild.json | 10 - run.cmd | 2 - run.ps1 | 209 -------------- run.sh | 256 ------------------ .gitignore => src/CORS/.gitignore | 0 CORS.sln => src/CORS/CORS.sln | 0 .../CORS/Directory.Build.props | 0 .../CORS/Directory.Build.targets | 0 .../CORS/NuGetPackageVerifier.json | 0 README.md => src/CORS/README.md | 0 {build => src/CORS/build}/Key.snk | Bin .../CORS/build}/buildpipeline/linux.groovy | 0 .../CORS/build}/buildpipeline/osx.groovy | 0 .../CORS/build}/buildpipeline/pipeline.groovy | 0 .../CORS/build}/buildpipeline/windows.groovy | 0 {build => src/CORS/build}/dependencies.props | 0 {build => src/CORS/build}/repo.props | 0 {build => src/CORS/build}/repo.targets | 0 {build => src/CORS/build}/sources.props | 0 {samples => src/CORS/samples}/README.md | 0 .../samples}/SampleDestination/Program.cs | 0 .../SampleDestination.csproj | 0 .../SampleDestination/SampleMiddleware.cs | 0 .../samples}/SampleDestination/Startup.cs | 0 .../CORS/samples}/SampleOrigin/Program.cs | 0 .../samples}/SampleOrigin/SampleOrigin.csproj | 0 .../CORS/samples}/SampleOrigin/Startup.cs | 0 .../samples}/SampleOrigin/wwwroot/index.htm | 0 .../samples}/SampleOrigin/wwwroot/test.htm | 0 src/{ => CORS/src}/Directory.Build.props | 0 .../CorsServiceCollectionExtensions.cs | 0 .../DisableCorsAttribute.cs | 0 .../EnableCorsAttribute.cs | 0 .../Infrastructure/CorsConstants.cs | 0 .../Infrastructure/CorsMiddleware.cs | 0 .../CorsMiddlewareExtensions.cs | 0 .../Infrastructure/CorsOptions.cs | 0 .../Infrastructure/CorsPolicy.cs | 0 .../Infrastructure/CorsPolicyBuilder.cs | 0 .../Infrastructure/CorsPolicyExtensions.cs | 0 .../Infrastructure/CorsResult.cs | 0 .../Infrastructure/CorsService.cs | 0 .../DefaultCorsPolicyProvider.cs | 0 .../Infrastructure/ICorsPolicyProvider.cs | 0 .../Infrastructure/ICorsService.cs | 0 .../Infrastructure/IDisableCorsAttribute.cs | 0 .../Infrastructure/IEnableCorsAttribute.cs | 0 .../Infrastructure/UriHelpers.cs | 0 .../Internal/CORSLoggerExtensions.cs | 0 .../Microsoft.AspNetCore.Cors.csproj | 0 .../Properties/AssemblyInfo.cs | 0 .../Resources.Designer.cs | 0 .../Microsoft.AspNetCore.Cors/Resources.resx | 0 .../baseline.netcore.json | 0 {test => src/CORS/test}/Directory.Build.props | 0 .../CORS/test}/FunctionalTests/Assert.cs | 0 .../CorsMiddlewareFunctionalTest.cs | 0 .../FunctionalTests/FunctionalTests.csproj | 0 .../test}/FunctionalTests/ProcessManager.cs | 0 .../test}/FunctionalTests/ProcessResult.cs | 0 .../test}/FunctionalTests/package-lock.json | 0 .../CORS/test}/FunctionalTests/package.json | 0 .../CORS/test}/FunctionalTests/test.js | 0 .../CorsMiddlewareTests.cs | 0 .../CorsOptionsTest.cs | 0 .../CorsPolicyBuilderTests.cs | 0 .../CorsPolicyExtensionsTests.cs | 0 .../CorsPolicyTests.cs | 0 .../CorsResultTests.cs | 0 .../CorsServiceTests.cs | 0 .../DefaultCorsPolicyProviderTests.cs | 0 .../Microsoft.AspNetCore.Cors.Test.csproj | 0 .../UriHelpersTests.cs | 0 .../CorsMiddlewareWebSite.csproj | 0 .../CorsMiddlewareWebSite/EchoMiddleware.cs | 0 .../WebSites/CorsMiddlewareWebSite/Startup.cs | 0 .../WebSites/CorsMiddlewareWebSite/readme.md | 0 .../WebSites/CorsMiddlewareWebSite/web.config | 0 version.props => src/CORS/version.props | 0 91 files changed, 686 deletions(-) delete mode 100644 .appveyor.yml delete mode 100644 .gitattributes delete mode 100644 .github/ISSUE_TEMPLATE.md delete mode 100644 .travis.yml delete mode 100644 .vsts-pipelines/builds/ci-internal.yml delete mode 100644 .vsts-pipelines/builds/ci-public.yml delete mode 100644 CONTRIBUTING.md delete mode 100644 LICENSE.txt delete mode 100644 NuGet.config delete mode 100644 build.cmd delete mode 100755 build.sh delete mode 100644 korebuild-lock.txt delete mode 100644 korebuild.json delete mode 100644 run.cmd delete mode 100644 run.ps1 delete mode 100755 run.sh rename .gitignore => src/CORS/.gitignore (100%) rename CORS.sln => src/CORS/CORS.sln (100%) rename Directory.Build.props => src/CORS/Directory.Build.props (100%) rename Directory.Build.targets => src/CORS/Directory.Build.targets (100%) rename NuGetPackageVerifier.json => src/CORS/NuGetPackageVerifier.json (100%) rename README.md => src/CORS/README.md (100%) rename {build => src/CORS/build}/Key.snk (100%) rename {build => src/CORS/build}/buildpipeline/linux.groovy (100%) rename {build => src/CORS/build}/buildpipeline/osx.groovy (100%) rename {build => src/CORS/build}/buildpipeline/pipeline.groovy (100%) rename {build => src/CORS/build}/buildpipeline/windows.groovy (100%) rename {build => src/CORS/build}/dependencies.props (100%) rename {build => src/CORS/build}/repo.props (100%) rename {build => src/CORS/build}/repo.targets (100%) rename {build => src/CORS/build}/sources.props (100%) rename {samples => src/CORS/samples}/README.md (100%) rename {samples => src/CORS/samples}/SampleDestination/Program.cs (100%) rename {samples => src/CORS/samples}/SampleDestination/SampleDestination.csproj (100%) rename {samples => src/CORS/samples}/SampleDestination/SampleMiddleware.cs (100%) rename {samples => src/CORS/samples}/SampleDestination/Startup.cs (100%) rename {samples => src/CORS/samples}/SampleOrigin/Program.cs (100%) rename {samples => src/CORS/samples}/SampleOrigin/SampleOrigin.csproj (100%) rename {samples => src/CORS/samples}/SampleOrigin/Startup.cs (100%) rename {samples => src/CORS/samples}/SampleOrigin/wwwroot/index.htm (100%) rename {samples => src/CORS/samples}/SampleOrigin/wwwroot/test.htm (100%) rename src/{ => CORS/src}/Directory.Build.props (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/CorsServiceCollectionExtensions.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/DisableCorsAttribute.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/EnableCorsAttribute.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Infrastructure/CorsConstants.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddlewareExtensions.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Infrastructure/CorsOptions.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicy.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyBuilder.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyExtensions.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Infrastructure/CorsResult.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Infrastructure/DefaultCorsPolicyProvider.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Infrastructure/ICorsPolicyProvider.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Infrastructure/ICorsService.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Infrastructure/IDisableCorsAttribute.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Infrastructure/IEnableCorsAttribute.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Infrastructure/UriHelpers.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Microsoft.AspNetCore.Cors.csproj (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Properties/AssemblyInfo.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Resources.Designer.cs (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/Resources.resx (100%) rename src/{ => CORS/src}/Microsoft.AspNetCore.Cors/baseline.netcore.json (100%) rename {test => src/CORS/test}/Directory.Build.props (100%) rename {test => src/CORS/test}/FunctionalTests/Assert.cs (100%) rename {test => src/CORS/test}/FunctionalTests/CorsMiddlewareFunctionalTest.cs (100%) rename {test => src/CORS/test}/FunctionalTests/FunctionalTests.csproj (100%) rename {test => src/CORS/test}/FunctionalTests/ProcessManager.cs (100%) rename {test => src/CORS/test}/FunctionalTests/ProcessResult.cs (100%) rename {test => src/CORS/test}/FunctionalTests/package-lock.json (100%) rename {test => src/CORS/test}/FunctionalTests/package.json (100%) rename {test => src/CORS/test}/FunctionalTests/test.js (100%) rename {test => src/CORS/test}/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs (100%) rename {test => src/CORS/test}/Microsoft.AspNetCore.Cors.Test/CorsOptionsTest.cs (100%) rename {test => src/CORS/test}/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs (100%) rename {test => src/CORS/test}/Microsoft.AspNetCore.Cors.Test/CorsPolicyExtensionsTests.cs (100%) rename {test => src/CORS/test}/Microsoft.AspNetCore.Cors.Test/CorsPolicyTests.cs (100%) rename {test => src/CORS/test}/Microsoft.AspNetCore.Cors.Test/CorsResultTests.cs (100%) rename {test => src/CORS/test}/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs (100%) rename {test => src/CORS/test}/Microsoft.AspNetCore.Cors.Test/DefaultCorsPolicyProviderTests.cs (100%) rename {test => src/CORS/test}/Microsoft.AspNetCore.Cors.Test/Microsoft.AspNetCore.Cors.Test.csproj (100%) rename {test => src/CORS/test}/Microsoft.AspNetCore.Cors.Test/UriHelpersTests.cs (100%) rename {test => src/CORS/test}/WebSites/CorsMiddlewareWebSite/CorsMiddlewareWebSite.csproj (100%) rename {test => src/CORS/test}/WebSites/CorsMiddlewareWebSite/EchoMiddleware.cs (100%) rename {test => src/CORS/test}/WebSites/CorsMiddlewareWebSite/Startup.cs (100%) rename {test => src/CORS/test}/WebSites/CorsMiddlewareWebSite/readme.md (100%) rename {test => src/CORS/test}/WebSites/CorsMiddlewareWebSite/web.config (100%) rename version.props => src/CORS/version.props (100%) diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index d9c226b09f..0000000000 --- a/.appveyor.yml +++ /dev/null @@ -1,13 +0,0 @@ -init: -- git config --global core.autocrlf true -branches: - only: - - dev - - /^release\/.*$/ - - /^(.*\/)?ci-.*$/ -build_script: -- ps: .\run.ps1 -CI default-build -clone_depth: 1 -test: 'off' -deploy: 'off' -os: Visual Studio 2017 diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 97b827b758..0000000000 --- a/.gitattributes +++ /dev/null @@ -1,51 +0,0 @@ -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain - -*.jpg binary -*.png binary -*.gif binary - -*.cs text=auto diff=csharp -*.vb text=auto -*.resx text=auto -*.c text=auto -*.cpp text=auto -*.cxx text=auto -*.h text=auto -*.hxx text=auto -*.py text=auto -*.rb text=auto -*.java text=auto -*.html text=auto -*.htm text=auto -*.css text=auto -*.scss text=auto -*.sass text=auto -*.less text=auto -*.js text=auto -*.lisp text=auto -*.clj text=auto -*.sql text=auto -*.php text=auto -*.lua text=auto -*.m text=auto -*.asm text=auto -*.erl text=auto -*.fs text=auto -*.fsx text=auto -*.hs text=auto - -*.csproj text=auto -*.vbproj text=auto -*.fsproj text=auto -*.dbproj text=auto -*.sln text=auto eol=crlf -*.sh eol=lf diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 101a084f0a..0000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,3 +0,0 @@ -THIS ISSUE TRACKER IS CLOSED - please log new issues here: https://github.com/aspnet/Home/issues - -For information about this change, see https://github.com/aspnet/Announcements/issues/283 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 20565993c2..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -language: csharp -sudo: false -dist: trusty -mono: none -os: -- linux -- osx -env: - global: - - TRAVIS_NODE_VERSION: 8.9.3 -osx_image: xcode8.2 -addons: - apt: - packages: - - libunwind8 -branches: - only: - - dev - - /^release\/.*$/ - - /^(.*\/)?ci-.*$/ -before_install: -- nvm install $TRAVIS_NODE_VERSION -- if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s - /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib - /usr/local/lib/; fi -script: -- ./build.sh --ci diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml deleted file mode 100644 index a19cee5885..0000000000 --- a/.vsts-pipelines/builds/ci-internal.yml +++ /dev/null @@ -1,38 +0,0 @@ -trigger: -- master -- release/* - -resources: - repositories: - - repository: buildtools - type: git - name: aspnet-BuildTools - ref: refs/heads/release/2.2 - -phases: -- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools - parameters: - agentOs: Windows - beforeBuild: - - task: NodeTool@0 - displayName: Use Node 8.x - inputs: - versionSpec: 8.x - -- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools - parameters: - agentOs: macOS - beforeBuild: - - task: NodeTool@0 - displayName: Use Node 8.x - inputs: - versionSpec: 8.x - -- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools - parameters: - agentOs: Linux - beforeBuild: - - task: NodeTool@0 - displayName: Use Node 8.x - inputs: - versionSpec: 8.x diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml deleted file mode 100644 index 1cca5b68cc..0000000000 --- a/.vsts-pipelines/builds/ci-public.yml +++ /dev/null @@ -1,40 +0,0 @@ -trigger: -- master -- release/* - -# See https://github.com/aspnet/BuildTools -resources: - repositories: - - repository: buildtools - type: github - endpoint: DotNet-Bot GitHub Connection - name: aspnet/BuildTools - ref: refs/heads/release/2.2 - -phases: -- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools - parameters: - agentOs: Windows - beforeBuild: - - task: NodeTool@0 - displayName: Use Node 8.x - inputs: - versionSpec: 8.x - -- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools - parameters: - agentOs: macOS - beforeBuild: - - task: NodeTool@0 - displayName: Use Node 8.x - inputs: - versionSpec: 8.x - -- template: .vsts-pipelines/templates/phases/default-build.yml@buildtools - parameters: - agentOs: Linux - beforeBuild: - - task: NodeTool@0 - displayName: Use Node 8.x - inputs: - versionSpec: 8.x diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 64ff041d5c..0000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,4 +0,0 @@ -Contributing -====== - -Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/dev/CONTRIBUTING.md) in the Home repo. diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index 7b2956ecee..0000000000 --- a/LICENSE.txt +++ /dev/null @@ -1,14 +0,0 @@ -Copyright (c) .NET Foundation and Contributors - -All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. diff --git a/NuGet.config b/NuGet.config deleted file mode 100644 index e32bddfd51..0000000000 --- a/NuGet.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/build.cmd b/build.cmd deleted file mode 100644 index c0050bda12..0000000000 --- a/build.cmd +++ /dev/null @@ -1,2 +0,0 @@ -@ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE" diff --git a/build.sh b/build.sh deleted file mode 100755 index 98a4b22765..0000000000 --- a/build.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -# Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs) -chmod +x "$DIR/run.sh"; sync -"$DIR/run.sh" default-build "$@" diff --git a/korebuild-lock.txt b/korebuild-lock.txt deleted file mode 100644 index 96fe3217ef..0000000000 --- a/korebuild-lock.txt +++ /dev/null @@ -1,2 +0,0 @@ -version:2.2.0-preview2-20181004.6 -commithash:c04c4b2f5018632647f96210ab01876661302dac diff --git a/korebuild.json b/korebuild.json deleted file mode 100644 index 78afb8c137..0000000000 --- a/korebuild.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.2/tools/korebuild.schema.json", - "channel": "release/2.2", - "toolsets": { - "nodejs": { - "required": true, - "minVersion": "8.0" - } - } -} diff --git a/run.cmd b/run.cmd deleted file mode 100644 index d52d5c7e68..0000000000 --- a/run.cmd +++ /dev/null @@ -1,2 +0,0 @@ -@ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE" diff --git a/run.ps1 b/run.ps1 deleted file mode 100644 index 34604c7175..0000000000 --- a/run.ps1 +++ /dev/null @@ -1,209 +0,0 @@ -#!/usr/bin/env powershell -#requires -version 4 - -<# -.SYNOPSIS -Executes KoreBuild commands. - -.DESCRIPTION -Downloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`. - -.PARAMETER Command -The KoreBuild command to run. - -.PARAMETER Path -The folder to build. Defaults to the folder containing this script. - -.PARAMETER Channel -The channel of KoreBuild to download. Overrides the value from the config file. - -.PARAMETER DotNetHome -The directory where .NET Core tools will be stored. - -.PARAMETER ToolsSource -The base url where build tools can be downloaded. Overrides the value from the config file. - -.PARAMETER Update -Updates KoreBuild to the latest version even if a lock file is present. - -.PARAMETER Reinstall -Re-installs KoreBuild - -.PARAMETER ConfigFile -The path to the configuration file that stores values. Defaults to korebuild.json. - -.PARAMETER ToolsSourceSuffix -The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores. - -.PARAMETER CI -Sets up CI specific settings and variables. - -.PARAMETER Arguments -Arguments to be passed to the command - -.NOTES -This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be. -When the lockfile is not present, KoreBuild will create one using latest available version from $Channel. - -The $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set -in the file are overridden by command line parameters. - -.EXAMPLE -Example config file: -```json -{ - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", - "channel": "master", - "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" -} -``` -#> -[CmdletBinding(PositionalBinding = $false)] -param( - [Parameter(Mandatory = $true, Position = 0)] - [string]$Command, - [string]$Path = $PSScriptRoot, - [Alias('c')] - [string]$Channel, - [Alias('d')] - [string]$DotNetHome, - [Alias('s')] - [string]$ToolsSource, - [Alias('u')] - [switch]$Update, - [switch]$Reinstall, - [string]$ToolsSourceSuffix, - [string]$ConfigFile = $null, - [switch]$CI, - [Parameter(ValueFromRemainingArguments = $true)] - [string[]]$Arguments -) - -Set-StrictMode -Version 2 -$ErrorActionPreference = 'Stop' - -# -# Functions -# - -function Get-KoreBuild { - - $lockFile = Join-Path $Path 'korebuild-lock.txt' - - if (!(Test-Path $lockFile) -or $Update) { - Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile $ToolsSourceSuffix - } - - $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1 - if (!$version) { - Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'" - } - $version = $version.TrimStart('version:').Trim() - $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version) - - if ($Reinstall -and (Test-Path $korebuildPath)) { - Remove-Item -Force -Recurse $korebuildPath - } - - if (!(Test-Path $korebuildPath)) { - Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version" - New-Item -ItemType Directory -Path $korebuildPath | Out-Null - $remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip" - - try { - $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" - Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix - if (Get-Command -Name 'Microsoft.PowerShell.Archive\Expand-Archive' -ErrorAction Ignore) { - # Use built-in commands where possible as they are cross-plat compatible - Microsoft.PowerShell.Archive\Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath - } - else { - # Fallback to old approach for old installations of PowerShell - Add-Type -AssemblyName System.IO.Compression.FileSystem - [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath) - } - } - catch { - Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore - throw - } - finally { - Remove-Item $tmpfile -ErrorAction Ignore - } - } - - return $korebuildPath -} - -function Join-Paths([string]$path, [string[]]$childPaths) { - $childPaths | ForEach-Object { $path = Join-Path $path $_ } - return $path -} - -function Get-RemoteFile([string]$RemotePath, [string]$LocalPath, [string]$RemoteSuffix) { - if ($RemotePath -notlike 'http*') { - Copy-Item $RemotePath $LocalPath - return - } - - $retries = 10 - while ($retries -gt 0) { - $retries -= 1 - try { - Invoke-WebRequest -UseBasicParsing -Uri $($RemotePath + $RemoteSuffix) -OutFile $LocalPath - return - } - catch { - Write-Verbose "Request failed. $retries retries remaining" - } - } - - Write-Error "Download failed: '$RemotePath'." -} - -# -# Main -# - -# Load configuration or set defaults - -$Path = Resolve-Path $Path -if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' } - -if (Test-Path $ConfigFile) { - try { - $config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json - if ($config) { - if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel } - if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource} - } - } - catch { - Write-Host -ForegroundColor Red $Error[0] - Write-Error "$ConfigFile contains invalid JSON." - exit 1 - } -} - -if (!$DotNetHome) { - $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } ` - elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} ` - elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}` - else { Join-Path $PSScriptRoot '.dotnet'} -} - -if (!$Channel) { $Channel = 'master' } -if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } - -# Execute - -$korebuildPath = Get-KoreBuild -Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') - -try { - Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile -CI:$CI - Invoke-KoreBuildCommand $Command @Arguments -} -finally { - Remove-Module 'KoreBuild' -ErrorAction Ignore -} diff --git a/run.sh b/run.sh deleted file mode 100755 index 4c1fed5646..0000000000 --- a/run.sh +++ /dev/null @@ -1,256 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# -# variables -# - -RESET="\033[0m" -RED="\033[0;31m" -YELLOW="\033[0;33m" -MAGENTA="\033[0;95m" -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" -verbose=false -update=false -reinstall=false -repo_path="$DIR" -channel='' -tools_source='' -tools_source_suffix='' -ci=false - -# -# Functions -# -__usage() { - echo "Usage: $(basename "${BASH_SOURCE[0]}") command [options] [[--] ...]" - echo "" - echo "Arguments:" - echo " command The command to be run." - echo " ... Arguments passed to the command. Variable number of arguments allowed." - echo "" - echo "Options:" - echo " --verbose Show verbose output." - echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." - echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json." - echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." - echo " --path The directory to build. Defaults to the directory containing the script." - echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." - echo " --tools-source-suffix|-ToolsSourceSuffix The suffix to append to tools-source. Useful for query strings." - echo " -u|--update Update to the latest KoreBuild even if the lock file is present." - echo " --reinstall Reinstall KoreBuild." - echo " --ci Apply CI specific settings and environment variables." - echo "" - echo "Description:" - echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." - echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel." - - if [[ "${1:-}" != '--no-exit' ]]; then - exit 2 - fi -} - -get_korebuild() { - local version - local lock_file="$repo_path/korebuild-lock.txt" - if [ ! -f "$lock_file" ] || [ "$update" = true ]; then - __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" "$tools_source_suffix" - fi - version="$(grep 'version:*' -m 1 "$lock_file")" - if [[ "$version" == '' ]]; then - __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" - return 1 - fi - version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" - local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" - - if [ "$reinstall" = true ] && [ -d "$korebuild_path" ]; then - rm -rf "$korebuild_path" - fi - - { - if [ ! -d "$korebuild_path" ]; then - mkdir -p "$korebuild_path" - local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" - tmpfile="$(mktemp)" - echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" - if __get_remote_file "$remote_path" "$tmpfile" "$tools_source_suffix"; then - unzip -q -d "$korebuild_path" "$tmpfile" - fi - rm "$tmpfile" || true - fi - - source "$korebuild_path/KoreBuild.sh" - } || { - if [ -d "$korebuild_path" ]; then - echo "Cleaning up after failed installation" - rm -rf "$korebuild_path" || true - fi - return 1 - } -} - -__error() { - echo -e "${RED}error: $*${RESET}" 1>&2 -} - -__warn() { - echo -e "${YELLOW}warning: $*${RESET}" -} - -__machine_has() { - hash "$1" > /dev/null 2>&1 - return $? -} - -__get_remote_file() { - local remote_path=$1 - local local_path=$2 - local remote_path_suffix=$3 - - if [[ "$remote_path" != 'http'* ]]; then - cp "$remote_path" "$local_path" - return 0 - fi - - local failed=false - if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "${remote_path}${remote_path_suffix}" || failed=true - else - failed=true - fi - - if [ "$failed" = true ] && __machine_has curl; then - failed=false - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "${remote_path}${remote_path_suffix}" || failed=true - fi - - if [ "$failed" = true ]; then - __error "Download failed: $remote_path" 1>&2 - return 1 - fi -} - -# -# main -# - -command="${1:-}" -shift - -while [[ $# -gt 0 ]]; do - case $1 in - -\?|-h|--help) - __usage --no-exit - exit 0 - ;; - -c|--channel|-Channel) - shift - channel="${1:-}" - [ -z "$channel" ] && __usage - ;; - --config-file|-ConfigFile) - shift - config_file="${1:-}" - [ -z "$config_file" ] && __usage - if [ ! -f "$config_file" ]; then - __error "Invalid value for --config-file. $config_file does not exist." - exit 1 - fi - ;; - -d|--dotnet-home|-DotNetHome) - shift - DOTNET_HOME="${1:-}" - [ -z "$DOTNET_HOME" ] && __usage - ;; - --path|-Path) - shift - repo_path="${1:-}" - [ -z "$repo_path" ] && __usage - ;; - -s|--tools-source|-ToolsSource) - shift - tools_source="${1:-}" - [ -z "$tools_source" ] && __usage - ;; - --tools-source-suffix|-ToolsSourceSuffix) - shift - tools_source_suffix="${1:-}" - [ -z "$tools_source_suffix" ] && __usage - ;; - -u|--update|-Update) - update=true - ;; - --reinstall|-[Rr]einstall) - reinstall=true - ;; - --ci|-[Cc][Ii]) - ci=true - ;; - --verbose|-Verbose) - verbose=true - ;; - --) - shift - break - ;; - *) - break - ;; - esac - shift -done - -if ! __machine_has unzip; then - __error 'Missing required command: unzip' - exit 1 -fi - -if ! __machine_has curl && ! __machine_has wget; then - __error 'Missing required command. Either wget or curl is required.' - exit 1 -fi - -[ -z "${config_file:-}" ] && config_file="$repo_path/korebuild.json" -if [ -f "$config_file" ]; then - if __machine_has jq ; then - if jq '.' "$config_file" >/dev/null ; then - config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" - config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" - else - __error "$config_file contains invalid JSON." - exit 1 - fi - elif __machine_has python ; then - if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then - config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" - config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" - else - __error "$config_file contains invalid JSON." - exit 1 - fi - elif __machine_has python3 ; then - if python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then - config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" - config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" - else - __error "$config_file contains invalid JSON." - exit 1 - fi - else - __error 'Missing required command: jq or python. Could not parse the JSON file.' - exit 1 - fi - - [ ! -z "${config_channel:-}" ] && channel="$config_channel" - [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" -fi - -[ -z "$channel" ] && channel='master' -[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' - -get_korebuild -set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" "$ci" -invoke_korebuild_command "$command" "$@" diff --git a/.gitignore b/src/CORS/.gitignore similarity index 100% rename from .gitignore rename to src/CORS/.gitignore diff --git a/CORS.sln b/src/CORS/CORS.sln similarity index 100% rename from CORS.sln rename to src/CORS/CORS.sln diff --git a/Directory.Build.props b/src/CORS/Directory.Build.props similarity index 100% rename from Directory.Build.props rename to src/CORS/Directory.Build.props diff --git a/Directory.Build.targets b/src/CORS/Directory.Build.targets similarity index 100% rename from Directory.Build.targets rename to src/CORS/Directory.Build.targets diff --git a/NuGetPackageVerifier.json b/src/CORS/NuGetPackageVerifier.json similarity index 100% rename from NuGetPackageVerifier.json rename to src/CORS/NuGetPackageVerifier.json diff --git a/README.md b/src/CORS/README.md similarity index 100% rename from README.md rename to src/CORS/README.md diff --git a/build/Key.snk b/src/CORS/build/Key.snk similarity index 100% rename from build/Key.snk rename to src/CORS/build/Key.snk diff --git a/build/buildpipeline/linux.groovy b/src/CORS/build/buildpipeline/linux.groovy similarity index 100% rename from build/buildpipeline/linux.groovy rename to src/CORS/build/buildpipeline/linux.groovy diff --git a/build/buildpipeline/osx.groovy b/src/CORS/build/buildpipeline/osx.groovy similarity index 100% rename from build/buildpipeline/osx.groovy rename to src/CORS/build/buildpipeline/osx.groovy diff --git a/build/buildpipeline/pipeline.groovy b/src/CORS/build/buildpipeline/pipeline.groovy similarity index 100% rename from build/buildpipeline/pipeline.groovy rename to src/CORS/build/buildpipeline/pipeline.groovy diff --git a/build/buildpipeline/windows.groovy b/src/CORS/build/buildpipeline/windows.groovy similarity index 100% rename from build/buildpipeline/windows.groovy rename to src/CORS/build/buildpipeline/windows.groovy diff --git a/build/dependencies.props b/src/CORS/build/dependencies.props similarity index 100% rename from build/dependencies.props rename to src/CORS/build/dependencies.props diff --git a/build/repo.props b/src/CORS/build/repo.props similarity index 100% rename from build/repo.props rename to src/CORS/build/repo.props diff --git a/build/repo.targets b/src/CORS/build/repo.targets similarity index 100% rename from build/repo.targets rename to src/CORS/build/repo.targets diff --git a/build/sources.props b/src/CORS/build/sources.props similarity index 100% rename from build/sources.props rename to src/CORS/build/sources.props diff --git a/samples/README.md b/src/CORS/samples/README.md similarity index 100% rename from samples/README.md rename to src/CORS/samples/README.md diff --git a/samples/SampleDestination/Program.cs b/src/CORS/samples/SampleDestination/Program.cs similarity index 100% rename from samples/SampleDestination/Program.cs rename to src/CORS/samples/SampleDestination/Program.cs diff --git a/samples/SampleDestination/SampleDestination.csproj b/src/CORS/samples/SampleDestination/SampleDestination.csproj similarity index 100% rename from samples/SampleDestination/SampleDestination.csproj rename to src/CORS/samples/SampleDestination/SampleDestination.csproj diff --git a/samples/SampleDestination/SampleMiddleware.cs b/src/CORS/samples/SampleDestination/SampleMiddleware.cs similarity index 100% rename from samples/SampleDestination/SampleMiddleware.cs rename to src/CORS/samples/SampleDestination/SampleMiddleware.cs diff --git a/samples/SampleDestination/Startup.cs b/src/CORS/samples/SampleDestination/Startup.cs similarity index 100% rename from samples/SampleDestination/Startup.cs rename to src/CORS/samples/SampleDestination/Startup.cs diff --git a/samples/SampleOrigin/Program.cs b/src/CORS/samples/SampleOrigin/Program.cs similarity index 100% rename from samples/SampleOrigin/Program.cs rename to src/CORS/samples/SampleOrigin/Program.cs diff --git a/samples/SampleOrigin/SampleOrigin.csproj b/src/CORS/samples/SampleOrigin/SampleOrigin.csproj similarity index 100% rename from samples/SampleOrigin/SampleOrigin.csproj rename to src/CORS/samples/SampleOrigin/SampleOrigin.csproj diff --git a/samples/SampleOrigin/Startup.cs b/src/CORS/samples/SampleOrigin/Startup.cs similarity index 100% rename from samples/SampleOrigin/Startup.cs rename to src/CORS/samples/SampleOrigin/Startup.cs diff --git a/samples/SampleOrigin/wwwroot/index.htm b/src/CORS/samples/SampleOrigin/wwwroot/index.htm similarity index 100% rename from samples/SampleOrigin/wwwroot/index.htm rename to src/CORS/samples/SampleOrigin/wwwroot/index.htm diff --git a/samples/SampleOrigin/wwwroot/test.htm b/src/CORS/samples/SampleOrigin/wwwroot/test.htm similarity index 100% rename from samples/SampleOrigin/wwwroot/test.htm rename to src/CORS/samples/SampleOrigin/wwwroot/test.htm diff --git a/src/Directory.Build.props b/src/CORS/src/Directory.Build.props similarity index 100% rename from src/Directory.Build.props rename to src/CORS/src/Directory.Build.props diff --git a/src/Microsoft.AspNetCore.Cors/CorsServiceCollectionExtensions.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/CorsServiceCollectionExtensions.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/CorsServiceCollectionExtensions.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/CorsServiceCollectionExtensions.cs diff --git a/src/Microsoft.AspNetCore.Cors/DisableCorsAttribute.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/DisableCorsAttribute.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/DisableCorsAttribute.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/DisableCorsAttribute.cs diff --git a/src/Microsoft.AspNetCore.Cors/EnableCorsAttribute.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/EnableCorsAttribute.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/EnableCorsAttribute.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/EnableCorsAttribute.cs diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsConstants.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsConstants.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Infrastructure/CorsConstants.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsConstants.cs diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddlewareExtensions.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddlewareExtensions.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddlewareExtensions.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddlewareExtensions.cs diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsOptions.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsOptions.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Infrastructure/CorsOptions.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsOptions.cs diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicy.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicy.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicy.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicy.cs diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyBuilder.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyBuilder.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyBuilder.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyBuilder.cs diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyExtensions.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyExtensions.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyExtensions.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsPolicyExtensions.cs diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsResult.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsResult.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Infrastructure/CorsResult.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsResult.cs diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsService.cs diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/DefaultCorsPolicyProvider.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/DefaultCorsPolicyProvider.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Infrastructure/DefaultCorsPolicyProvider.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/DefaultCorsPolicyProvider.cs diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/ICorsPolicyProvider.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/ICorsPolicyProvider.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Infrastructure/ICorsPolicyProvider.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/ICorsPolicyProvider.cs diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/ICorsService.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/ICorsService.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Infrastructure/ICorsService.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/ICorsService.cs diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/IDisableCorsAttribute.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/IDisableCorsAttribute.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Infrastructure/IDisableCorsAttribute.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/IDisableCorsAttribute.cs diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/IEnableCorsAttribute.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/IEnableCorsAttribute.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Infrastructure/IEnableCorsAttribute.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/IEnableCorsAttribute.cs diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/UriHelpers.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/UriHelpers.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Infrastructure/UriHelpers.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Infrastructure/UriHelpers.cs diff --git a/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Internal/CORSLoggerExtensions.cs diff --git a/src/Microsoft.AspNetCore.Cors/Microsoft.AspNetCore.Cors.csproj b/src/CORS/src/Microsoft.AspNetCore.Cors/Microsoft.AspNetCore.Cors.csproj similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Microsoft.AspNetCore.Cors.csproj rename to src/CORS/src/Microsoft.AspNetCore.Cors/Microsoft.AspNetCore.Cors.csproj diff --git a/src/Microsoft.AspNetCore.Cors/Properties/AssemblyInfo.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Properties/AssemblyInfo.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Properties/AssemblyInfo.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Properties/AssemblyInfo.cs diff --git a/src/Microsoft.AspNetCore.Cors/Resources.Designer.cs b/src/CORS/src/Microsoft.AspNetCore.Cors/Resources.Designer.cs similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Resources.Designer.cs rename to src/CORS/src/Microsoft.AspNetCore.Cors/Resources.Designer.cs diff --git a/src/Microsoft.AspNetCore.Cors/Resources.resx b/src/CORS/src/Microsoft.AspNetCore.Cors/Resources.resx similarity index 100% rename from src/Microsoft.AspNetCore.Cors/Resources.resx rename to src/CORS/src/Microsoft.AspNetCore.Cors/Resources.resx diff --git a/src/Microsoft.AspNetCore.Cors/baseline.netcore.json b/src/CORS/src/Microsoft.AspNetCore.Cors/baseline.netcore.json similarity index 100% rename from src/Microsoft.AspNetCore.Cors/baseline.netcore.json rename to src/CORS/src/Microsoft.AspNetCore.Cors/baseline.netcore.json diff --git a/test/Directory.Build.props b/src/CORS/test/Directory.Build.props similarity index 100% rename from test/Directory.Build.props rename to src/CORS/test/Directory.Build.props diff --git a/test/FunctionalTests/Assert.cs b/src/CORS/test/FunctionalTests/Assert.cs similarity index 100% rename from test/FunctionalTests/Assert.cs rename to src/CORS/test/FunctionalTests/Assert.cs diff --git a/test/FunctionalTests/CorsMiddlewareFunctionalTest.cs b/src/CORS/test/FunctionalTests/CorsMiddlewareFunctionalTest.cs similarity index 100% rename from test/FunctionalTests/CorsMiddlewareFunctionalTest.cs rename to src/CORS/test/FunctionalTests/CorsMiddlewareFunctionalTest.cs diff --git a/test/FunctionalTests/FunctionalTests.csproj b/src/CORS/test/FunctionalTests/FunctionalTests.csproj similarity index 100% rename from test/FunctionalTests/FunctionalTests.csproj rename to src/CORS/test/FunctionalTests/FunctionalTests.csproj diff --git a/test/FunctionalTests/ProcessManager.cs b/src/CORS/test/FunctionalTests/ProcessManager.cs similarity index 100% rename from test/FunctionalTests/ProcessManager.cs rename to src/CORS/test/FunctionalTests/ProcessManager.cs diff --git a/test/FunctionalTests/ProcessResult.cs b/src/CORS/test/FunctionalTests/ProcessResult.cs similarity index 100% rename from test/FunctionalTests/ProcessResult.cs rename to src/CORS/test/FunctionalTests/ProcessResult.cs diff --git a/test/FunctionalTests/package-lock.json b/src/CORS/test/FunctionalTests/package-lock.json similarity index 100% rename from test/FunctionalTests/package-lock.json rename to src/CORS/test/FunctionalTests/package-lock.json diff --git a/test/FunctionalTests/package.json b/src/CORS/test/FunctionalTests/package.json similarity index 100% rename from test/FunctionalTests/package.json rename to src/CORS/test/FunctionalTests/package.json diff --git a/test/FunctionalTests/test.js b/src/CORS/test/FunctionalTests/test.js similarity index 100% rename from test/FunctionalTests/test.js rename to src/CORS/test/FunctionalTests/test.js diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs b/src/CORS/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs similarity index 100% rename from test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs rename to src/CORS/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsOptionsTest.cs b/src/CORS/test/Microsoft.AspNetCore.Cors.Test/CorsOptionsTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.Cors.Test/CorsOptionsTest.cs rename to src/CORS/test/Microsoft.AspNetCore.Cors.Test/CorsOptionsTest.cs diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs b/src/CORS/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs similarity index 100% rename from test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs rename to src/CORS/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyBuilderTests.cs diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyExtensionsTests.cs b/src/CORS/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyExtensionsTests.cs similarity index 100% rename from test/Microsoft.AspNetCore.Cors.Test/CorsPolicyExtensionsTests.cs rename to src/CORS/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyExtensionsTests.cs diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyTests.cs b/src/CORS/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyTests.cs similarity index 100% rename from test/Microsoft.AspNetCore.Cors.Test/CorsPolicyTests.cs rename to src/CORS/test/Microsoft.AspNetCore.Cors.Test/CorsPolicyTests.cs diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsResultTests.cs b/src/CORS/test/Microsoft.AspNetCore.Cors.Test/CorsResultTests.cs similarity index 100% rename from test/Microsoft.AspNetCore.Cors.Test/CorsResultTests.cs rename to src/CORS/test/Microsoft.AspNetCore.Cors.Test/CorsResultTests.cs diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs b/src/CORS/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs similarity index 100% rename from test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs rename to src/CORS/test/Microsoft.AspNetCore.Cors.Test/CorsServiceTests.cs diff --git a/test/Microsoft.AspNetCore.Cors.Test/DefaultCorsPolicyProviderTests.cs b/src/CORS/test/Microsoft.AspNetCore.Cors.Test/DefaultCorsPolicyProviderTests.cs similarity index 100% rename from test/Microsoft.AspNetCore.Cors.Test/DefaultCorsPolicyProviderTests.cs rename to src/CORS/test/Microsoft.AspNetCore.Cors.Test/DefaultCorsPolicyProviderTests.cs diff --git a/test/Microsoft.AspNetCore.Cors.Test/Microsoft.AspNetCore.Cors.Test.csproj b/src/CORS/test/Microsoft.AspNetCore.Cors.Test/Microsoft.AspNetCore.Cors.Test.csproj similarity index 100% rename from test/Microsoft.AspNetCore.Cors.Test/Microsoft.AspNetCore.Cors.Test.csproj rename to src/CORS/test/Microsoft.AspNetCore.Cors.Test/Microsoft.AspNetCore.Cors.Test.csproj diff --git a/test/Microsoft.AspNetCore.Cors.Test/UriHelpersTests.cs b/src/CORS/test/Microsoft.AspNetCore.Cors.Test/UriHelpersTests.cs similarity index 100% rename from test/Microsoft.AspNetCore.Cors.Test/UriHelpersTests.cs rename to src/CORS/test/Microsoft.AspNetCore.Cors.Test/UriHelpersTests.cs diff --git a/test/WebSites/CorsMiddlewareWebSite/CorsMiddlewareWebSite.csproj b/src/CORS/test/WebSites/CorsMiddlewareWebSite/CorsMiddlewareWebSite.csproj similarity index 100% rename from test/WebSites/CorsMiddlewareWebSite/CorsMiddlewareWebSite.csproj rename to src/CORS/test/WebSites/CorsMiddlewareWebSite/CorsMiddlewareWebSite.csproj diff --git a/test/WebSites/CorsMiddlewareWebSite/EchoMiddleware.cs b/src/CORS/test/WebSites/CorsMiddlewareWebSite/EchoMiddleware.cs similarity index 100% rename from test/WebSites/CorsMiddlewareWebSite/EchoMiddleware.cs rename to src/CORS/test/WebSites/CorsMiddlewareWebSite/EchoMiddleware.cs diff --git a/test/WebSites/CorsMiddlewareWebSite/Startup.cs b/src/CORS/test/WebSites/CorsMiddlewareWebSite/Startup.cs similarity index 100% rename from test/WebSites/CorsMiddlewareWebSite/Startup.cs rename to src/CORS/test/WebSites/CorsMiddlewareWebSite/Startup.cs diff --git a/test/WebSites/CorsMiddlewareWebSite/readme.md b/src/CORS/test/WebSites/CorsMiddlewareWebSite/readme.md similarity index 100% rename from test/WebSites/CorsMiddlewareWebSite/readme.md rename to src/CORS/test/WebSites/CorsMiddlewareWebSite/readme.md diff --git a/test/WebSites/CorsMiddlewareWebSite/web.config b/src/CORS/test/WebSites/CorsMiddlewareWebSite/web.config similarity index 100% rename from test/WebSites/CorsMiddlewareWebSite/web.config rename to src/CORS/test/WebSites/CorsMiddlewareWebSite/web.config diff --git a/version.props b/src/CORS/version.props similarity index 100% rename from version.props rename to src/CORS/version.props