From 1fa5e18d440b971fca6655d116f9c140c4bde382 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 21 May 2018 09:08:22 -0400 Subject: [PATCH 01/66] Make description of prehashed a bit more friendly --- website/source/api/secret/transit/index.html.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/website/source/api/secret/transit/index.html.md b/website/source/api/secret/transit/index.html.md index 4c2758deff..29c0244e05 100644 --- a/website/source/api/secret/transit/index.html.md +++ b/website/source/api/secret/transit/index.html.md @@ -803,9 +803,14 @@ supports signing. Required if key derivation is enabled; currently only available with ed25519 keys. -- `prehashed` `(bool: false)` - Set to `true` when the input is already - hashed. If the key type is `rsa-2048` or `rsa-4096`, then the algorithm used - to hash the input should be indicated by the `hash_algorithm` parameter. +- `prehashed` `(bool: false)` - Set to `true` when the input is already hashed. + If the key type is `rsa-2048` or `rsa-4096`, then the algorithm used to hash + the input should be indicated by the `hash_algorithm` parameter. Just as the + value to sign should be the base64-encoded representation of the exact binary + data you want signed, when set, `input` is expected to be base64-encoded + binary hashed data, not hex-formatted. (As an example, on the command line, + you could generate a suitable input via `openssl dgst -sha256 -binary | + base64`.) - `signature_algorithm` `(string: "pss")` – When using a RSA key, specifies the RSA signature algorithm to use for signing. Supported signature types are: From c368238fe0eb06b39bab9477f6e31ba4118626b6 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 21 May 2018 09:21:24 -0400 Subject: [PATCH 02/66] changelog++ --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78c9dd1c97..dbd22c992f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ BUG FIXES: require `authorized_addrs` to be set [GH-4065] * core: Fix panic when certain combinations of policy paths and allowed/denied parameters were used [GH-4582] + * secret/gcp: Make `bound_region` able to use short names * secret/kv: Fix response wrapping for KV v2 [GH-4511] * secret/pki: Fix `key_type` not being allowed to be set to `any` [GH-4595] * secret/pki: Fix path length parameter being ignored when using From e49e261f8ce9b78fd8bb897996be097365bd502b Mon Sep 17 00:00:00 2001 From: Brian Kassouf Date: Mon, 21 May 2018 11:05:04 -0700 Subject: [PATCH 03/66] Don't reload singleton mounts (#4593) --- vault/plugin_reload.go | 7 +++++++ vault/token_store.go | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/vault/plugin_reload.go b/vault/plugin_reload.go index 2192ebdf15..c71adbf572 100644 --- a/vault/plugin_reload.go +++ b/vault/plugin_reload.go @@ -7,6 +7,7 @@ import ( "github.com/hashicorp/errwrap" multierror "github.com/hashicorp/go-multierror" + "github.com/hashicorp/vault/helper/strutil" "github.com/hashicorp/vault/logical" ) @@ -77,6 +78,12 @@ func (c *Core) reloadMatchingPlugin(ctx context.Context, pluginName string) erro // reloadBackendCommon is a generic method to reload a backend provided a // MountEntry. func (c *Core) reloadBackendCommon(ctx context.Context, entry *MountEntry, isAuth bool) error { + // We don't want to reload the singleton mounts. They often have specific + // inmemory elements and we don't want to touch them here. + if strutil.StrListContains(singletonMounts, entry.Type) { + return nil + } + path := entry.Path if isAuth { diff --git a/vault/token_store.go b/vault/token_store.go index 12ebfe31db..220d57053e 100644 --- a/vault/token_store.go +++ b/vault/token_store.go @@ -3,6 +3,7 @@ package vault import ( "context" "encoding/json" + "errors" "fmt" "sync" "sync/atomic" @@ -1004,7 +1005,7 @@ func (ts *TokenStore) lookupSalted(ctx context.Context, saltedID string, tainted // If we are still restoring the expiration manager, we want to ensure the // token is not expired if ts.expiration == nil { - return nil, nil + return nil, errors.New("expiration manager is nil on tokenstore") } check, err := ts.expiration.RestoreSaltedTokenCheck(entry.Path, saltedID) if err != nil { From ca2bdbb8c049fa0ab4b2eb7f37df7d50adb2d081 Mon Sep 17 00:00:00 2001 From: Becca Petrin Date: Mon, 21 May 2018 11:47:28 -0700 Subject: [PATCH 04/66] Restrict userpass logins & tokens by CIDR (#4557) --- builtin/credential/userpass/backend_test.go | 35 +++------------------ builtin/credential/userpass/path_login.go | 14 +++++++++ builtin/credential/userpass/path_users.go | 23 ++++++++++++-- vault/request_handling_test.go | 3 ++ 4 files changed, 41 insertions(+), 34 deletions(-) diff --git a/builtin/credential/userpass/backend_test.go b/builtin/credential/userpass/backend_test.go index 807c8879f0..355f94e5a5 100644 --- a/builtin/credential/userpass/backend_test.go +++ b/builtin/credential/userpass/backend_test.go @@ -7,6 +7,8 @@ import ( "testing" "time" + "crypto/tls" + "github.com/hashicorp/vault/helper/policyutil" "github.com/hashicorp/vault/logical" logicaltest "github.com/hashicorp/vault/logical/testing" @@ -225,36 +227,6 @@ func testUpdatePolicies(t *testing.T, user, policies string) logicaltest.TestSte } } -func testUsersWrite(t *testing.T, user string, data map[string]interface{}, expectError bool) logicaltest.TestStep { - return logicaltest.TestStep{ - Operation: logical.UpdateOperation, - Path: "users/" + user, - Data: data, - ErrorOk: true, - Check: func(resp *logical.Response) error { - if resp == nil && expectError { - return fmt.Errorf("expected error but received nil") - } - return nil - }, - } -} - -func testLoginWrite(t *testing.T, user string, data map[string]interface{}, expectError bool) logicaltest.TestStep { - return logicaltest.TestStep{ - Operation: logical.UpdateOperation, - Path: "login/" + user, - Data: data, - ErrorOk: true, - Check: func(resp *logical.Response) error { - if resp == nil && expectError { - return fmt.Errorf("expected error but received nil") - } - return nil - }, - } -} - func testAccStepList(t *testing.T, users []string) logicaltest.TestStep { return logicaltest.TestStep{ Operation: logical.ListOperation, @@ -282,7 +254,8 @@ func testAccStepLogin(t *testing.T, user string, pass string, policies []string) }, Unauthenticated: true, - Check: logicaltest.TestCheckAuth(policies), + Check: logicaltest.TestCheckAuth(policies), + ConnState: &tls.ConnectionState{}, } } diff --git a/builtin/credential/userpass/path_login.go b/builtin/credential/userpass/path_login.go index 4164196b29..c495875c43 100644 --- a/builtin/credential/userpass/path_login.go +++ b/builtin/credential/userpass/path_login.go @@ -3,9 +3,11 @@ package userpass import ( "context" "crypto/subtle" + "errors" "fmt" "strings" + "github.com/hashicorp/vault/helper/cidrutil" "github.com/hashicorp/vault/helper/policyutil" "github.com/hashicorp/vault/logical" "github.com/hashicorp/vault/logical/framework" @@ -69,6 +71,11 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, d *framew return logical.ErrorResponse("invalid username or password"), nil } + // Check for a CIDR match. + if !cidrutil.RemoteAddrIsOk(req.Connection.RemoteAddr, user.BoundCIDRs) { + return logical.ErrorResponse("login request originated from invalid CIDR"), nil + } + // Check for a password match. Check for a hash collision for Vault 0.2+, // but handle the older legacy passwords with a constant time comparison. passwordBytes := []byte(password) @@ -97,6 +104,7 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, d *framew Alias: &logical.Alias{ Name: username, }, + BoundCIDRs: user.BoundCIDRs, }, }, nil } @@ -116,9 +124,15 @@ func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, d *f return nil, fmt.Errorf("policies have changed, not renewing") } + // Check for a CIDR match. + if !cidrutil.RemoteAddrIsOk(req.Connection.RemoteAddr, user.BoundCIDRs) { + return nil, errors.New("renewal request originated from invalid CIDR") + } + resp := &logical.Response{Auth: req.Auth} resp.Auth.TTL = user.TTL resp.Auth.MaxTTL = user.MaxTTL + resp.Auth.BoundCIDRs = user.BoundCIDRs return resp, nil } diff --git a/builtin/credential/userpass/path_users.go b/builtin/credential/userpass/path_users.go index 9a748c5c7d..0e8eee886f 100644 --- a/builtin/credential/userpass/path_users.go +++ b/builtin/credential/userpass/path_users.go @@ -6,6 +6,8 @@ import ( "strings" "time" + "github.com/hashicorp/go-sockaddr" + "github.com/hashicorp/vault/helper/parseutil" "github.com/hashicorp/vault/helper/policyutil" "github.com/hashicorp/vault/logical" "github.com/hashicorp/vault/logical/framework" @@ -52,6 +54,12 @@ func pathUsers(b *backend) *framework.Path { Type: framework.TypeDurationSecond, Description: "Maximum duration after which authentication will be expired", }, + + "bound_cidrs": &framework.FieldSchema{ + Type: framework.TypeCommaStringSlice, + Description: `Comma separated string or list of CIDR blocks. If set, specifies the blocks of +IP addresses which can perform the login operation.`, + }, }, Callbacks: map[logical.Operation]framework.OperationFunc{ @@ -135,9 +143,10 @@ func (b *backend) pathUserRead(ctx context.Context, req *logical.Request, d *fra return &logical.Response{ Data: map[string]interface{}{ - "policies": user.Policies, - "ttl": user.TTL.Seconds(), - "max_ttl": user.MaxTTL.Seconds(), + "policies": user.Policies, + "ttl": user.TTL.Seconds(), + "max_ttl": user.MaxTTL.Seconds(), + "bound_cidrs": user.BoundCIDRs, }, }, nil } @@ -177,6 +186,12 @@ func (b *backend) userCreateUpdate(ctx context.Context, req *logical.Request, d userEntry.MaxTTL = time.Duration(maxTTL.(int)) * time.Second } + boundCIDRs, err := parseutil.ParseAddrs(d.Get("bound_cidrs")) + if err != nil { + return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest + } + userEntry.BoundCIDRs = boundCIDRs + return nil, b.setUser(ctx, req.Storage, username, userEntry) } @@ -204,6 +219,8 @@ type UserEntry struct { // Maximum duration for which user can be valid MaxTTL time.Duration + + BoundCIDRs []*sockaddr.SockAddrMarshaler } const pathUserHelpSyn = ` diff --git a/vault/request_handling_test.go b/vault/request_handling_test.go index fe91cc20cf..2a47c3f9d8 100644 --- a/vault/request_handling_test.go +++ b/vault/request_handling_test.go @@ -80,6 +80,7 @@ func TestRequestHandling_LoginWrapping(t *testing.T) { Data: map[string]interface{}{ "type": "userpass", }, + Connection: &logical.Connection{}, } resp, err := core.HandleRequest(req) if err != nil { @@ -108,6 +109,7 @@ func TestRequestHandling_LoginWrapping(t *testing.T) { Data: map[string]interface{}{ "password": "foo", }, + Connection: &logical.Connection{}, } resp, err = core.HandleRequest(req) if err != nil { @@ -129,6 +131,7 @@ func TestRequestHandling_LoginWrapping(t *testing.T) { Data: map[string]interface{}{ "password": "foo", }, + Connection: &logical.Connection{}, } resp, err = core.HandleRequest(req) if err != nil { From 6888781969d7660e8571e00e270d7ea95db1486a Mon Sep 17 00:00:00 2001 From: madalynrose Date: Mon, 21 May 2018 14:50:54 -0400 Subject: [PATCH 05/66] update hmac form and component to use 'algorithm' instead of 'hash-algorithm' (#4604) --- ui/app/components/transit-key-actions.js | 3 ++- .../components/transit-key-action/hmac.hbs | 12 +++++----- .../components/transit-key-actions-test.js | 24 +++++++++++++++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/ui/app/components/transit-key-actions.js b/ui/app/components/transit-key-actions.js index e1d73d9099..9719605926 100644 --- a/ui/app/components/transit-key-actions.js +++ b/ui/app/components/transit-key-actions.js @@ -3,6 +3,7 @@ const { get, set } = Ember; const TRANSIT_PARAMS = { hash_algorithm: 'sha2-256', + algorithm: 'sha2-256', signature_algorithm: 'pss', bits: 256, bytes: 32, @@ -31,7 +32,7 @@ const TRANSIT_PARAMS = { const PARAMS_FOR_ACTION = { sign: ['input', 'hash_algorithm', 'key_version', 'prehashed', 'signature_algorithm'], verify: ['input', 'hmac', 'signature', 'hash_algorithm', 'prehashed'], - hmac: ['input', 'hash_algorithm', 'key_version'], + hmac: ['input', 'algorithm', 'key_version'], encrypt: ['plaintext', 'context', 'nonce', 'key_version'], decrypt: ['ciphertext', 'context', 'nonce'], rewrap: ['ciphertext', 'context', 'nonce', 'key_version'], diff --git a/ui/app/templates/components/transit-key-action/hmac.hbs b/ui/app/templates/components/transit-key-action/hmac.hbs index 1f7450e3da..93e958b096 100644 --- a/ui/app/templates/components/transit-key-action/hmac.hbs +++ b/ui/app/templates/components/transit-key-action/hmac.hbs @@ -1,4 +1,4 @@ -
+ {{#if hmac}}
@@ -42,16 +42,16 @@
- +
+{{#tool-tip horizontalPosition="auto-right" verticalPosition=(if isFullscreen "above" "below") as |d|}} + {{#d.trigger tagName="button" type="button" class=(concat "button is-compact" (if isFullscreen " active")) click=(action "fullscreen") data-test-tool-tip-trigger=true}} + {{i-con glyph=(if isFullscreen "fullscreen-close" "fullscreen-open") aria-hidden="true" size=16}} + {{/d.trigger}} + {{#d.content class="tool-tip"}} +
+ {{#if isFullscreen}} + Minimize + {{else}} + Maximize + {{/if}} +
+ {{/d.content}} +{{/tool-tip}} diff --git a/ui/app/templates/components/console/log-command.hbs b/ui/app/templates/components/console/log-command.hbs new file mode 100644 index 0000000000..39b9e7d1f2 --- /dev/null +++ b/ui/app/templates/components/console/log-command.hbs @@ -0,0 +1 @@ +
{{i-con glyph="chevron-right" size=12}}{{content}}
diff --git a/ui/app/templates/components/console/log-error.hbs b/ui/app/templates/components/console/log-error.hbs new file mode 100644 index 0000000000..add86ec492 --- /dev/null +++ b/ui/app/templates/components/console/log-error.hbs @@ -0,0 +1,4 @@ +
+ {{i-con glyph="close-circled" aria-hidden="true" size=12}} +
{{content}}
+
diff --git a/ui/app/templates/components/console/log-help.hbs b/ui/app/templates/components/console/log-help.hbs new file mode 100644 index 0000000000..0022c1f399 --- /dev/null +++ b/ui/app/templates/components/console/log-help.hbs @@ -0,0 +1,16 @@ +
+{{i-con glyph="information-circled" aria-hidden="true" size=12}} +
Usage: vault <command> [args]
+
+Commands:
+  read        Read data and retrieves secrets
+  write       Write data, configuration, and secrets
+  delete      Delete secrets and configuration
+  list        List data or secrets
+
+Web CLI Commands:
+  fullscreen  Toggle fullscreen display
+  clear       Clear output from the log
+  clearall    Clear output and command history
+
+
diff --git a/ui/app/templates/components/console/log-json.hbs b/ui/app/templates/components/console/log-json.hbs new file mode 100644 index 0000000000..293ee6f238 --- /dev/null +++ b/ui/app/templates/components/console/log-json.hbs @@ -0,0 +1,10 @@ +{{json-editor + value=(stringify content) + options=(hash + readOnly=true + lineNumbers=false + autoHeight=true + gutters=false + theme='hashi auto-height' + ) + }} diff --git a/ui/app/templates/components/console/log-list.hbs b/ui/app/templates/components/console/log-list.hbs new file mode 100644 index 0000000000..83fc544bdc --- /dev/null +++ b/ui/app/templates/components/console/log-list.hbs @@ -0,0 +1,21 @@ +
+
Keys
+{{#each list as |item|}}
+{{item}}
+{{/each}}
+
+
+ {{#tool-tip renderInPlace=true as |d|}} + {{#d.trigger data-test-tool-tip-trigger=true}} + {{#copy-button clipboardText=(multi-line-join list) class="button is-compact"}} + {{i-con glyph="copy" aria-hidden="true" size=16}} + {{/copy-button}} + {{/d.trigger}} + {{#d.content class="tool-tip"}} +
+ Copy +
+ {{/d.content}} + {{/tool-tip}} +
+
diff --git a/ui/app/templates/components/console/log-object.hbs b/ui/app/templates/components/console/log-object.hbs new file mode 100644 index 0000000000..3c8d77cf4a --- /dev/null +++ b/ui/app/templates/components/console/log-object.hbs @@ -0,0 +1,18 @@ +
+
{{columns}}
+ +
+ {{#tool-tip renderInPlace=true as |d|}} + {{#d.trigger data-test-tool-tip-trigger=true}} + {{#copy-button clipboardText=columns class="button is-compact"}} + {{i-con glyph="copy" aria-hidden="true" size=16}} + {{/copy-button}} + {{/d.trigger}} + {{#d.content class="tool-tip"}} +
+ Copy +
+ {{/d.content}} + {{/tool-tip}} +
+
diff --git a/ui/app/templates/components/console/log-success.hbs b/ui/app/templates/components/console/log-success.hbs new file mode 100644 index 0000000000..e16ae924c5 --- /dev/null +++ b/ui/app/templates/components/console/log-success.hbs @@ -0,0 +1,4 @@ +
+ {{i-con glyph="checkmark-circled" aria-hidden="true" size=12}} +
{{content}}
+
diff --git a/ui/app/templates/components/console/log-text.hbs b/ui/app/templates/components/console/log-text.hbs new file mode 100644 index 0000000000..3da4104754 --- /dev/null +++ b/ui/app/templates/components/console/log-text.hbs @@ -0,0 +1 @@ +
{{content}}
\ No newline at end of file diff --git a/ui/app/templates/components/console/output-log.hbs b/ui/app/templates/components/console/output-log.hbs new file mode 100644 index 0000000000..e464c7fa0b --- /dev/null +++ b/ui/app/templates/components/console/output-log.hbs @@ -0,0 +1,5 @@ +{{#each log as |message|}} + {{#unless message.hidden}} + {{component (concat 'console/log-' message.type) content=message.content}} + {{/unless}} +{{/each}} diff --git a/ui/app/templates/components/console/ui-panel.hbs b/ui/app/templates/components/console/ui-panel.hbs new file mode 100644 index 0000000000..f374e20d29 --- /dev/null +++ b/ui/app/templates/components/console/ui-panel.hbs @@ -0,0 +1,16 @@ +
+
+

+ The Vault Browser CLI provides an easy way to execute the most common CLI commands, such as write, read, delete, and list. +

+
+ {{console/output-log log=log}} + {{console/command-input + isFullscreen=isFullscreen + value=inputValue + onValueUpdate=(action (mut inputValue)) + onFullscreen=(action 'toggleFullscreen') + onExecuteCommand=(action 'executeCommand') + onShiftCommand=(action 'shiftCommandIndex') + }} +
diff --git a/ui/app/templates/svg/icons/console-active.hbs b/ui/app/templates/svg/icons/console-active.hbs new file mode 100644 index 0000000000..aa155909cd --- /dev/null +++ b/ui/app/templates/svg/icons/console-active.hbs @@ -0,0 +1,21 @@ + + + + + + diff --git a/ui/app/templates/svg/icons/console.hbs b/ui/app/templates/svg/icons/console.hbs new file mode 100644 index 0000000000..f201234cc2 --- /dev/null +++ b/ui/app/templates/svg/icons/console.hbs @@ -0,0 +1,17 @@ + + + + + diff --git a/ui/app/templates/svg/icons/copy.hbs b/ui/app/templates/svg/icons/copy.hbs new file mode 100644 index 0000000000..5a1bfb1b1e --- /dev/null +++ b/ui/app/templates/svg/icons/copy.hbs @@ -0,0 +1 @@ + diff --git a/ui/app/templates/svg/icons/fullscreen-close.hbs b/ui/app/templates/svg/icons/fullscreen-close.hbs new file mode 100644 index 0000000000..43f026bb9b --- /dev/null +++ b/ui/app/templates/svg/icons/fullscreen-close.hbs @@ -0,0 +1 @@ + diff --git a/ui/app/templates/svg/icons/fullscreen-open.hbs b/ui/app/templates/svg/icons/fullscreen-open.hbs new file mode 100644 index 0000000000..3702768ce7 --- /dev/null +++ b/ui/app/templates/svg/icons/fullscreen-open.hbs @@ -0,0 +1 @@ + diff --git a/ui/ember-cli-build.js b/ui/ember-cli-build.js index f758b6d63b..74461efe3c 100644 --- a/ui/ember-cli-build.js +++ b/ui/ember-cli-build.js @@ -55,6 +55,18 @@ module.exports = function(defaults) { app.import('node_modules/text-encoder-lite/index.js'); app.import('node_modules/Duration.js/duration.js'); + app.import('node_modules/columnify/columnify.js', { + using: [ + { transformation: 'cjs', as: 'columnify' } + ] + }); + + app.import('node_modules/yargs-parser/lib/tokenize-arg-string.js', { + using: [ + { transformation: 'cjs', as: 'yargs-parser-tokenizer' } + ] + }); + // Use `app.import` to add additional libraries to the generated // output files. // diff --git a/ui/package.json b/ui/package.json index 89bd31042b..9263e7039b 100644 --- a/ui/package.json +++ b/ui/package.json @@ -14,7 +14,7 @@ "start2": "ember server --proxy=http://localhost:8202 --port=4202", "test": "node scripts/start-vault.js & ember test", "test-oss": "yarn run test -f='!enterprise'", - "fmt-js": "prettier-eslint --single-quote --trailing-comma es5 --print-width=110 --write {app,tests,config,lib,mirage}/**/*.js", + "fmt-js": "prettier-eslint --single-quote --no-use-tabs --trailing-comma es5 --print-width=110 --write '{app,tests,config,lib,mirage}/**/*.js'", "fmt-styles": "prettier --write app/styles/**/*.*", "fmt": "yarn run fmt-js && yarn run fmt-styles", "precommit": "lint-staged" @@ -33,19 +33,24 @@ } }, "devDependencies": { + "Duration.js": "icholy/Duration.js#golang_compatible", + "autosize": "3.0.17", "babel-plugin-transform-object-rest-spread": "^6.23.0", + "base64-js": "1.2.1", "broccoli-asset-rev": "^2.4.5", "broccoli-sri-hash": "meirish/broccoli-sri-hash#rooturl", "bulma": "^0.5.2", "bulma-switch": "^0.0.1", + "codemirror": "5.15.2", "cool-checkboxes-for-bulma.io": "^1.1.0", "ember-ajax": "^3.0.0", "ember-api-actions": "^0.1.8", "ember-basic-dropdown": "^0.33.5", "ember-basic-dropdown-hover": "^0.2.0", - "ember-cli": "~2.15.0", + "ember-cli": "~2.16.0", "ember-cli-autoprefixer": "^0.8.1", "ember-cli-babel": "^6.3.0", + "ember-cli-cjs-transform": "^1.2.0", "ember-cli-clipboard": "^0.8.0", "ember-cli-content-security-policy": "^1.0.0", "ember-cli-dependency-checker": "^1.3.0", @@ -83,18 +88,16 @@ "ember-test-selectors": "^0.3.6", "ember-truth-helpers": "1.2.0", "ivy-codemirror": "2.1.0", + "jsonlint": "1.6.0", "loader.js": "^4.2.3", "normalize.css": "4.1.1", "prettier": "^1.5.3", "prettier-eslint-cli": "^4.2.1", "qunit-dom": "^0.6.2", + "string.prototype.startswith": "mathiasbynens/String.prototype.startsWith", "text-encoder-lite": "1.0.0", - "base64-js": "1.2.1", - "autosize": "3.0.17", - "jsonlint": "1.6.0", - "codemirror": "5.15.2", - "Duration.js": "icholy/Duration.js#golang_compatible", - "string.prototype.startswith": "mathiasbynens/String.prototype.startsWith" + "columnify": "^1.5.4", + "yargs-parser": "^10.0.0" }, "engines": { "node": "^4.5 || 6.* || >= 7.*" diff --git a/ui/tests/integration/components/console/log-command-test.js b/ui/tests/integration/components/console/log-command-test.js new file mode 100644 index 0000000000..72a9514ac7 --- /dev/null +++ b/ui/tests/integration/components/console/log-command-test.js @@ -0,0 +1,15 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('console/log-command', 'Integration | Component | console/log command', { + integration: true, +}); + +test('it renders', function(assert) { + const commandText = 'list this/path'; + this.set('content', commandText); + + this.render(hbs`{{console/log-command content=content}}`); + + assert.dom('pre').includesText(commandText); +}); diff --git a/ui/tests/integration/components/console/log-error-test.js b/ui/tests/integration/components/console/log-error-test.js new file mode 100644 index 0000000000..f32c2dad9e --- /dev/null +++ b/ui/tests/integration/components/console/log-error-test.js @@ -0,0 +1,13 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('console/log-error', 'Integration | Component | console/log error', { + integration: true, +}); + +test('it renders', function(assert) { + const errorText = 'Error deleting at: sys/foo.\nURL: v1/sys/foo\nCode: 404'; + this.set('content', errorText); + this.render(hbs`{{console/log-error content=content}}`); + assert.dom('pre').includesText(errorText); +}); diff --git a/ui/tests/integration/components/console/log-json-test.js b/ui/tests/integration/components/console/log-json-test.js new file mode 100644 index 0000000000..353835df01 --- /dev/null +++ b/ui/tests/integration/components/console/log-json-test.js @@ -0,0 +1,24 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('console/log-json', 'Integration | Component | console/log json', { + integration: true, + + beforeEach() { + this.inject.service('code-mirror', { as: 'codeMirror' }); + }, +}); + +test('it renders', function(assert) { + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.on('myAction', function(val) { ... }); + const objectContent = { one: 'two', three: 'four', seven: { five: 'six' }, eight: [5, 6] }; + const expectedText = JSON.stringify(objectContent, null, 2); + + this.set('content', objectContent); + + this.render(hbs`{{console/log-json content=content}}`); + const instance = this.codeMirror.instanceFor(this.$('[data-test-component=json-editor]').attr('id')); + + assert.equal(instance.getValue(), expectedText); +}); diff --git a/ui/tests/integration/components/console/log-list-test.js b/ui/tests/integration/components/console/log-list-test.js new file mode 100644 index 0000000000..625787b54b --- /dev/null +++ b/ui/tests/integration/components/console/log-list-test.js @@ -0,0 +1,19 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('console/log-list', 'Integration | Component | console/log list', { + integration: true, +}); + +test('it renders', function(assert) { + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.on('myAction', function(val) { ... }); + const listContent = { keys: ['one', 'two'] }; + const expectedText = 'Keys\none\ntwo'; + + this.set('content', listContent); + + this.render(hbs`{{console/log-list content=content}}`); + + assert.dom('pre').includesText(`${expectedText}`); +}); diff --git a/ui/tests/integration/components/console/log-object-test.js b/ui/tests/integration/components/console/log-object-test.js new file mode 100644 index 0000000000..1b53470046 --- /dev/null +++ b/ui/tests/integration/components/console/log-object-test.js @@ -0,0 +1,27 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; +import columnify from 'columnify'; +import { capitalize } from 'vault/helpers/capitalize'; +import { stringifyObjectValues } from 'vault/components/console/log-object'; + +moduleForComponent('console/log-object', 'Integration | Component | console/log object', { + integration: true, +}); + +test('it renders', function(assert) { + const objectContent = { one: 'two', three: 'four', seven: { five: 'six' }, eight: [5, 6] }; + const data = { one: 'two', three: 'four', seven: { five: 'six' }, eight: [5, 6] }; + stringifyObjectValues(data); + const expectedText = columnify(data, { + preserveNewLines: true, + headingTransform: function(heading) { + return capitalize([heading]); + }, + }); + + this.set('content', objectContent); + + this.render(hbs`{{console/log-object content=content}}`); + + assert.dom('pre').includesText(`${expectedText}`); +}); diff --git a/ui/tests/integration/components/console/log-text-test.js b/ui/tests/integration/components/console/log-text-test.js new file mode 100644 index 0000000000..357c99cc89 --- /dev/null +++ b/ui/tests/integration/components/console/log-text-test.js @@ -0,0 +1,17 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('console/log-text', 'Integration | Component | console/log text', { + integration: true, +}); + +test('it renders', function(assert) { + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.on('myAction', function(val) { ... }); + const text = 'Success! You did a thing!'; + this.set('content', text); + + this.render(hbs`{{console/log-text content=content}}`); + + assert.dom('pre').includesText(text); +}); diff --git a/ui/tests/integration/components/console/ui-panel-test.js b/ui/tests/integration/components/console/ui-panel-test.js new file mode 100644 index 0000000000..57d6b8d384 --- /dev/null +++ b/ui/tests/integration/components/console/ui-panel-test.js @@ -0,0 +1,118 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import { create } from 'ember-cli-page-object'; +import wait from 'ember-test-helpers/wait'; +import uiPanel from 'vault/tests/pages/components/console/ui-panel'; +import hbs from 'htmlbars-inline-precompile'; + +const component = create(uiPanel); + +moduleForComponent('console/ui-panel', 'Integration | Component | console/ui panel', { + integration: true, + + beforeEach() { + component.setContext(this); + }, + + afterEach() { + component.removeContext(); + }, +}); + +test('it renders', function(assert) { + this.render(hbs`{{console/ui-panel}}`); + assert.ok(component.hasInput); +}); + +test('it clears console input on enter', function(assert) { + this.render(hbs`{{console/ui-panel}}`); + component.consoleInput('list this/thing/here').enter(); + return wait().then(() => { + assert.equal(component.consoleInputValue, '', 'empties input field on enter'); + }); +}); + +test('it clears the log when using clear command', function(assert) { + this.render(hbs`{{console/ui-panel}}`); + component.consoleInput('list this/thing/here').enter(); + component.consoleInput('list this/other/thing').enter(); + component.consoleInput('read another/thing').enter(); + wait().then(() => { + assert.notEqual(component.logOutput, '', 'there is output in the log'); + component.consoleInput('clear').enter(); + }); + + wait().then(() => component.up()); + return wait().then(() => { + assert.equal(component.logOutput, '', 'clears the output log'); + assert.equal( + component.consoleInputValue, + 'clear', + 'populates console input with previous command on up after enter' + ); + }); +}); + +test('it adds command to history on enter', function(assert) { + this.render(hbs`{{console/ui-panel}}`); + component.consoleInput('list this/thing/here').enter(); + wait().then(() => component.up()); + wait().then(() => { + assert.equal( + component.consoleInputValue, + 'list this/thing/here', + 'populates console input with previous command on up after enter' + ); + }); + wait().then(() => component.down()); + return wait().then(() => { + assert.equal(component.consoleInputValue, '', 'populates console input with next command on down'); + }); +}); + +test('it cycles through history with more than one command', function(assert) { + this.render(hbs`{{console/ui-panel}}`); + component.consoleInput('list this/thing/here').enter(); + wait().then(() => component.consoleInput('read that/thing/there').enter()); + wait().then(() => component.consoleInput('qwerty').enter()); + + wait().then(() => component.up()); + wait().then(() => { + assert.equal( + component.consoleInputValue, + 'qwerty', + 'populates console input with previous command on up after enter' + ); + }); + wait().then(() => component.up()); + wait().then(() => { + assert.equal( + component.consoleInputValue, + 'read that/thing/there', + 'populates console input with previous command on up' + ); + }); + wait().then(() => component.up()); + wait().then(() => { + assert.equal( + component.consoleInputValue, + 'list this/thing/here', + 'populates console input with previous command on up' + ); + }); + wait().then(() => component.up()); + wait().then(() => { + assert.equal( + component.consoleInputValue, + 'qwerty', + 'populates console input with initial command if cycled through all previous commands' + ); + }); + wait().then(() => component.down()); + return wait().then(() => { + assert.equal( + component.consoleInputValue, + '', + 'clears console input if down pressed after history is on most recent command' + ); + }); +}); diff --git a/ui/tests/pages/components/console/ui-panel.js b/ui/tests/pages/components/console/ui-panel.js new file mode 100644 index 0000000000..b17858a0aa --- /dev/null +++ b/ui/tests/pages/components/console/ui-panel.js @@ -0,0 +1,18 @@ +import { text, triggerable, fillable, value, isPresent } from 'ember-cli-page-object'; +import keys from 'vault/lib/keycodes'; + +export default { + consoleInput: fillable('[data-test-component="console/command-input"] input'), + consoleInputValue: value('[data-test-component="console/command-input"] input'), + logOutput: text('[data-test-component="console/output-log"]'), + up: triggerable('keyup', '[data-test-component="console/command-input"] input', { + eventProperties: { keyCode: keys.UP }, + }), + down: triggerable('keyup', '[data-test-component="console/command-input"] input', { + eventProperties: { keyCode: keys.DOWN }, + }), + enter: triggerable('keyup', '[data-test-component="console/command-input"] input', { + eventProperties: { keyCode: keys.ENTER }, + }), + hasInput: isPresent('[data-test-component="console/command-input"] input'), +}; diff --git a/ui/tests/unit/adapters/console-test.js b/ui/tests/unit/adapters/console-test.js new file mode 100644 index 0000000000..6d6fd2da92 --- /dev/null +++ b/ui/tests/unit/adapters/console-test.js @@ -0,0 +1,13 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('adapter:console', 'Unit | Adapter | console', { + needs: ['service:auth', 'service:flash-messages', 'service:version'], +}); + +test('it builds the correct URL', function(assert) { + let adapter = this.subject(); + let sysPath = 'sys/health'; + let awsPath = 'aws/roles/my-other-role'; + assert.equal(adapter.buildURL(sysPath), '/v1/sys/health'); + assert.equal(adapter.buildURL(awsPath), '/v1/aws/roles/my-other-role'); +}); diff --git a/ui/tests/unit/lib/console-helpers-test.js b/ui/tests/unit/lib/console-helpers-test.js new file mode 100644 index 0000000000..ea63e1e410 --- /dev/null +++ b/ui/tests/unit/lib/console-helpers-test.js @@ -0,0 +1,328 @@ +import { module, test } from 'qunit'; +import { + parseCommand, + extractDataAndFlags, + logFromResponse, + logFromError, + logErrorFromInput, +} from 'vault/lib/console-helpers'; + +module('lib/console-helpers', 'Unit | Lib | console helpers'); + +const testCommands = [ + { + name: 'write with data', + command: `vault write aws/config/root \ + access_key=AKIAJWVN5Z4FOFT7NLNA \ + secret_key=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 \ + region=us-east-1`, + expected: [ + 'write', + [], + 'aws/config/root', + [ + 'access_key=AKIAJWVN5Z4FOFT7NLNA', + 'secret_key=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', + 'region=us-east-1', + ], + ], + }, + { + name: 'read with field', + command: `vault read -field=access_key aws/creds/my-role`, + expected: ['read', ['-field=access_key'], 'aws/creds/my-role', []], + }, +]; + +testCommands.forEach(function(testCase) { + test(`#parseCommand: ${testCase.name}`, function(assert) { + let result = parseCommand(testCase.command); + assert.deepEqual(result, testCase.expected); + }); +}); + +test('#parseCommand: invalid commands', function(assert) { + let command = 'vault kv get foo'; + let result = parseCommand(command); + assert.equal(result, false, 'parseCommand returns false by default'); + + assert.throws( + () => { + parseCommand(command, true); + }, + /invalid command/, + 'throws on invalid command when `shouldThrow` is true' + ); +}); + +const testExtractCases = [ + { + name: 'data fields', + input: [ + [ + 'access_key=AKIAJWVN5Z4FOFT7NLNA', + 'secret_key=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', + 'region=us-east-1', + ], + [], + ], + expected: { + data: { + access_key: 'AKIAJWVN5Z4FOFT7NLNA', + secret_key: 'R4nm063hgMVo4BTT5xOs5nHLeLXA6lar7ZJ3Nt0i', + region: 'us-east-1', + }, + flags: {}, + }, + }, + { + name: 'repeated data and a flag', + input: [['allowed_domains=example.com', 'allowed_domains=foo.example.com'], ['-wrap-ttl=2h']], + expected: { + data: { + allowed_domains: ['example.com', 'foo.example.com'], + }, + flags: { + wrapTTL: '2h', + }, + }, + }, + { + name: 'data with more than one equals sign', + input: [['foo=bar=baz', 'foo=baz=bop', 'some=value=val'], []], + expected: { + data: { + foo: ['bar=baz', 'baz=bop'], + some: 'value=val', + }, + flags: {}, + }, + }, +]; + +testExtractCases.forEach(function(testCase) { + test(`#extractDataAndFlags: ${testCase.name}`, function(assert) { + let { data, flags } = extractDataAndFlags(...testCase.input); + assert.deepEqual(data, testCase.expected.data, 'has expected data'); + assert.deepEqual(flags, testCase.expected.flags, 'has expected flags'); + }); +}); + +let testResponseCases = [ + { + name: 'write response, no content', + args: [null, 'foo/bar', 'write', {}], + expectedData: { + type: 'success', + content: 'Success! Data written to: foo/bar', + }, + }, + { + name: 'delete response, no content', + args: [null, 'foo/bar', 'delete', {}], + expectedData: { + type: 'success', + content: 'Success! Data deleted (if it existed) at: foo/bar', + }, + }, + { + name: 'write, with content', + args: [{ data: { one: 'two' } }, 'foo/bar', 'write', {}], + expectedData: { + type: 'object', + content: { one: 'two' }, + }, + }, + { + name: 'with wrap-ttl flag', + args: [{ wrap_info: { one: 'two' } }, 'foo/bar', 'read', { wrapTTL: '1h' }], + expectedData: { + type: 'object', + content: { one: 'two' }, + }, + }, + { + name: 'with -format=json flag and wrap-ttl flag', + args: [{ foo: 'bar', wrap_info: { one: 'two' } }, 'foo/bar', 'read', { format: 'json', wrapTTL: '1h' }], + expectedData: { + type: 'json', + content: { foo: 'bar', wrap_info: { one: 'two' } }, + }, + }, + { + name: 'with -format=json and -field flags', + args: [{ foo: 'bar', data: { one: 'two' } }, 'foo/bar', 'read', { format: 'json', field: 'one' }], + expectedData: { + type: 'json', + content: 'two', + }, + }, + { + name: 'with -format=json and -field, and -wrap-ttl flags', + args: [ + { foo: 'bar', wrap_info: { one: 'two' } }, + 'foo/bar', + 'read', + { format: 'json', wrapTTL: '1h', field: 'one' }, + ], + expectedData: { + type: 'json', + content: 'two', + }, + }, + { + name: 'with string field flag and wrap-ttl flag', + args: [{ foo: 'bar', wrap_info: { one: 'two' } }, 'foo/bar', 'read', { field: 'one', wrapTTL: '1h' }], + expectedData: { + type: 'text', + content: 'two', + }, + }, + { + name: 'with object field flag and wrap-ttl flag', + args: [ + { foo: 'bar', wrap_info: { one: { two: 'three' } } }, + 'foo/bar', + 'read', + { field: 'one', wrapTTL: '1h' }, + ], + expectedData: { + type: 'object', + content: { two: 'three' }, + }, + }, + { + name: 'with response data and string field flag', + args: [{ foo: 'bar', data: { one: 'two' } }, 'foo/bar', 'read', { field: 'one', wrapTTL: '1h' }], + expectedData: { + type: 'text', + content: 'two', + }, + }, + { + name: 'with response data and object field flag ', + args: [ + { foo: 'bar', data: { one: { two: 'three' } } }, + 'foo/bar', + 'read', + { field: 'one', wrapTTL: '1h' }, + ], + expectedData: { + type: 'object', + content: { two: 'three' }, + }, + }, + { + name: 'response with data', + args: [{ foo: 'bar', data: { one: 'two' } }, 'foo/bar', 'read', {}], + expectedData: { + type: 'object', + content: { one: 'two' }, + }, + }, + { + name: 'with response data, field flag, and field missing', + args: [{ foo: 'bar', data: { one: 'two' } }, 'foo/bar', 'read', { field: 'foo' }], + expectedData: { + type: 'error', + content: 'Field "foo" not present in secret', + }, + }, + { + name: 'with response data and auth block', + args: [{ data: { one: 'two' }, auth: { three: 'four' } }, 'auth/token/create', 'write', {}], + expectedData: { + type: 'object', + content: { three: 'four' }, + }, + }, + { + name: 'with -field and -format with an object field', + args: [{ data: { one: { three: 'two' } } }, 'sys/mounts', 'read', { field: 'one', format: 'json' }], + expectedData: { + type: 'json', + content: { three: 'two' }, + }, + }, + { + name: 'with -field and -format with a string field', + args: [{ data: { one: 'two' } }, 'sys/mounts', 'read', { field: 'one', format: 'json' }], + expectedData: { + type: 'json', + content: 'two', + }, + }, +]; + +testResponseCases.forEach(function(testCase) { + test(`#logFromResponse: ${testCase.name}`, function(assert) { + let data = logFromResponse(...testCase.args); + assert.deepEqual(data, testCase.expectedData); + }); +}); + +let testErrorCases = [ + { + name: 'AdapterError write', + args: [{ httpStatus: 404, path: 'v1/sys/foo', errors: [{}] }, 'sys/foo', 'write'], + expectedContent: 'Error writing to: sys/foo.\nURL: v1/sys/foo\nCode: 404', + }, + { + name: 'AdapterError read', + args: [{ httpStatus: 404, path: 'v1/sys/foo', errors: [{}] }, 'sys/foo', 'read'], + expectedContent: 'Error reading from: sys/foo.\nURL: v1/sys/foo\nCode: 404', + }, + { + name: 'AdapterError list', + args: [{ httpStatus: 404, path: 'v1/sys/foo', errors: [{}] }, 'sys/foo', 'list'], + expectedContent: 'Error listing: sys/foo.\nURL: v1/sys/foo\nCode: 404', + }, + { + name: 'AdapterError delete', + args: [{ httpStatus: 404, path: 'v1/sys/foo', errors: [{}] }, 'sys/foo', 'delete'], + expectedContent: 'Error deleting at: sys/foo.\nURL: v1/sys/foo\nCode: 404', + }, + { + name: 'VaultError single error', + args: [{ httpStatus: 404, path: 'v1/sys/foo', errors: ['no client token'] }, 'sys/foo', 'delete'], + expectedContent: 'Error deleting at: sys/foo.\nURL: v1/sys/foo\nCode: 404\nErrors:\n no client token', + }, + { + name: 'VaultErrors multiple errors', + args: [ + { httpStatus: 404, path: 'v1/sys/foo', errors: ['no client token', 'this is an error'] }, + 'sys/foo', + 'delete', + ], + expectedContent: + 'Error deleting at: sys/foo.\nURL: v1/sys/foo\nCode: 404\nErrors:\n no client token\n this is an error', + }, +]; + +testErrorCases.forEach(function(testCase) { + test(`#logFromError: ${testCase.name}`, function(assert) { + let data = logFromError(...testCase.args); + assert.deepEqual(data, { type: 'error', content: testCase.expectedContent }, 'returns the expected data'); + }); +}); + +const testCommandCases = [ + { + name: 'errors when command does not include a path', + args: [], + expectedContent: 'A path is required to make a request.', + }, + { + name: 'errors when write command does not include data and does not have force tag', + args: ['foo/bar', 'write', {}, []], + expectedContent: 'Must supply data or use -force', + }, +]; + +testCommandCases.forEach(function(testCase) { + test(`#logErrorFromInput: ${testCase.name}`, function(assert) { + let data = logErrorFromInput(...testCase.args); + + assert.deepEqual(data, { type: 'error', content: testCase.expectedContent }, 'returns the pcorrect data'); + }); +}); diff --git a/ui/tests/unit/services/console-test.js b/ui/tests/unit/services/console-test.js new file mode 100644 index 0000000000..0f4adca4df --- /dev/null +++ b/ui/tests/unit/services/console-test.js @@ -0,0 +1,94 @@ +import { moduleFor, test } from 'ember-qunit'; +import { sanitizePath, ensureTrailingSlash } from 'vault/services/console'; +import sinon from 'sinon'; + +moduleFor('service:console', 'Unit | Service | console', { + needs: ['service:auth'], + beforeEach() {}, + afterEach() {}, +}); + +test('#sanitizePath', function(assert) { + assert.equal(sanitizePath(' /foo/bar/baz/ '), 'foo/bar/baz', 'removes spaces and slashs on either side'); + assert.equal(sanitizePath('//foo/bar/baz/'), 'foo/bar/baz', 'removes more than one slash'); +}); + +test('#ensureTrailingSlash', function(assert) { + assert.equal(ensureTrailingSlash('foo/bar'), 'foo/bar/', 'adds trailing slash'); + assert.equal(ensureTrailingSlash('baz/'), 'baz/', 'keeps trailing slash if there is one'); +}); + +let testCases = [ + { + method: 'read', + args: ['/sys/health', {}], + expectedURL: 'sys/health', + expectedVerb: 'GET', + expectedOptions: { data: undefined, wrapTTL: undefined }, + }, + + { + method: 'read', + args: ['/secrets/foo/bar', {}, '30m'], + expectedURL: 'secrets/foo/bar', + expectedVerb: 'GET', + expectedOptions: { data: undefined, wrapTTL: '30m' }, + }, + + { + method: 'write', + args: ['aws/roles/my-other-role', { arn: 'arn=arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess' }], + expectedURL: 'aws/roles/my-other-role', + expectedVerb: 'POST', + expectedOptions: { + data: { arn: 'arn=arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess' }, + wrapTTL: undefined, + }, + }, + + { + method: 'list', + args: ['secret/mounts', {}], + expectedURL: 'secret/mounts/', + expectedVerb: 'GET', + expectedOptions: { data: { list: true }, wrapTTL: undefined }, + }, + + { + method: 'list', + args: ['secret/mounts', {}, '1h'], + expectedURL: 'secret/mounts/', + expectedVerb: 'GET', + expectedOptions: { data: { list: true }, wrapTTL: '1h' }, + }, + + { + method: 'delete', + args: ['secret/secrets/kv'], + expectedURL: 'secret/secrets/kv', + expectedVerb: 'DELETE', + expectedOptions: { data: undefined, wrapTTL: undefined }, + }, +]; + +test('it reads, writes, lists, deletes', function(assert) { + let ajax = sinon.stub(); + let uiConsole = this.subject({ + adapter() { + return { + buildURL(url) { + return url; + }, + ajax, + }; + }, + }); + + testCases.forEach(testCase => { + uiConsole[testCase.method](...testCase.args); + let [url, verb, options] = ajax.lastCall.args; + assert.equal(url, testCase.expectedURL, `${testCase.method}: uses trimmed passed url`); + assert.equal(verb, testCase.expectedVerb, `${testCase.method}: uses the correct verb`); + assert.deepEqual(options, testCase.expectedOptions, `${testCase.method}: uses the correct options`); + }); +}); diff --git a/ui/yarn.lock b/ui/yarn.lock index 18f4f4fa8c..5fa12cc113 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -82,6 +82,14 @@ dependencies: "@glimmer/util" "^0.22.3" +"@types/estree@0.0.38": + version "0.0.38" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.38.tgz#c1be40aa933723c608820a99a373a16d215a1ca2" + +"@types/node@*": + version "10.0.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.0.4.tgz#130598ee56e9a1210a53f557d64935571f05390d" + Duration.js@icholy/Duration.js#golang_compatible: version "2.0.0" resolved "https://codeload.github.com/icholy/Duration.js/tar.gz/cb1c58efc2772ef0f261da9e2535890734a86417" @@ -178,6 +186,12 @@ amd-name-resolver@0.0.7: dependencies: ensure-posix-path "^1.0.1" +amd-name-resolver@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/amd-name-resolver/-/amd-name-resolver-1.0.0.tgz#0e593b28d6fa3326ab1798107edaea961046e8d8" + dependencies: + ensure-posix-path "^1.0.1" + amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" @@ -274,10 +288,18 @@ arr-diff@^2.0.0: dependencies: arr-flatten "^1.0.1" -arr-flatten@^1.0.1: +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + +arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" @@ -314,6 +336,10 @@ array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + arraybuffer.slice@0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca" @@ -338,6 +364,10 @@ assertion-error@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.0.tgz#c7f85438fdd466bc7ca16ab90c81513797a5d23b" +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + ast-traverse@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ast-traverse/-/ast-traverse-0.1.1.tgz#69cf2b8386f19dcda1bb1e05d68fe359d8897de6" @@ -398,6 +428,10 @@ asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" +atob@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" + autoprefixer@^7.0.0: version "7.2.6" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.2.6.tgz#256672f86f7c735da849c4f07d008abb056067dc" @@ -1091,6 +1125,18 @@ base64id@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/base64id/-/base64id-0.1.0.tgz#02ce0fdeee0cef4f40080e1e73e834f0b1bfce3f" +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + basic-auth@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.1.0.tgz#45221ee429f7ee1e5035be3f51533f1cdfd29884" @@ -1216,6 +1262,21 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + dependencies: + 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.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + breakable@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/breakable/-/breakable-1.0.0.tgz#784a797915a38ead27bad456b5572cb4bbaa78c1" @@ -1381,6 +1442,17 @@ broccoli-debug@^0.6.1, broccoli-debug@^0.6.2: symlink-or-copy "^1.1.8" tree-sync "^1.2.2" +broccoli-debug@^0.6.3, broccoli-debug@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/broccoli-debug/-/broccoli-debug-0.6.4.tgz#986eb3d2005e00e3bb91f9d0a10ab137210cd150" + dependencies: + broccoli-plugin "^1.2.1" + fs-tree-diff "^0.5.2" + heimdalljs "^0.2.1" + heimdalljs-logger "^0.1.7" + symlink-or-copy "^1.1.8" + tree-sync "^1.2.2" + broccoli-favicon@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/broccoli-favicon/-/broccoli-favicon-1.0.0.tgz#c770a5aa16032fbaf1b5c9c033f71b9cc5a5cb51" @@ -1735,6 +1807,10 @@ builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" +builtin-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-2.0.0.tgz#60b7ef5ae6546bd7deefa74b08b62a43a232648e" + builtins@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" @@ -1759,6 +1835,20 @@ bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + dependencies: + 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" + calculate-cache-key-for-tree@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/calculate-cache-key-for-tree/-/calculate-cache-key-for-tree-1.1.0.tgz#0c3e42c9c134f3c9de5358c0f16793627ea976d6" @@ -1890,6 +1980,14 @@ chalk@^2.0.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" +chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + chalk@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" @@ -1941,6 +2039,15 @@ circular-json@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d" +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + clean-base-url@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clean-base-url/-/clean-base-url-1.0.0.tgz#c901cf0a20b972435b0eccd52d056824a4351b7b" @@ -1960,7 +2067,7 @@ clean-css@^3.4.5: commander "2.8.x" source-map "0.4.x" -cli-cursor@^1.0.1, cli-cursor@^1.0.2: +cli-cursor@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" dependencies: @@ -1972,9 +2079,9 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" -cli-spinners@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c" +cli-spinners@^1.1.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" cli-table2@^0.2.0: version "0.2.0" @@ -2051,6 +2158,13 @@ coffee-script@^1.10.0: version "1.12.7" resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.12.7.tgz#c05dae0cb79591d05b3070a8433a98c9a89ccc53" +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + color-convert@^1.0.0: version "1.9.0" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" @@ -2075,6 +2189,13 @@ colors@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" +columnify@^1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" + dependencies: + strip-ansi "^3.0.0" + wcwidth "^1.0.0" + combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" @@ -2125,7 +2246,7 @@ component-emitter@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.1.2.tgz#296594f2753daa63996d2af08d15a95116c9aec3" -component-emitter@1.2.1: +component-emitter@1.2.1, component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" @@ -2186,14 +2307,16 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" -console-ui@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/console-ui/-/console-ui-1.0.3.tgz#31c524461b63422769f9e89c173495d91393721c" +console-ui@^2.0.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/console-ui/-/console-ui-2.2.2.tgz#b294a2934de869dd06789ab4be69555411edef29" dependencies: - chalk "^1.1.3" - inquirer "^1.2.3" - ora "^0.2.0" + chalk "^2.1.0" + inquirer "^2" + json-stable-stringify "^1.0.1" + ora "^2.0.0" through "^2.3.8" + user-info "^1.0.0" consolidate@^0.14.0: version "0.14.5" @@ -2237,6 +2360,10 @@ copy-dereference@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/copy-dereference/-/copy-dereference-1.0.0.tgz#6b131865420fd81b413ba994b44d3655311152b6" +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + core-js@^1.0.0: version "1.2.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" @@ -2371,7 +2498,7 @@ debug@2.6.8, debug@^2.1.0, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.4. dependencies: ms "2.0.0" -debug@2.6.9: +debug@2.6.9, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: @@ -2381,18 +2508,43 @@ decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + deep-extend@~0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" -deep-freeze@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/deep-freeze/-/deep-freeze-0.0.1.tgz#3a0b0005de18672819dfd38cd31f91179c893e84" - deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + dependencies: + clone "^1.0.2" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + defined@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" @@ -2679,6 +2831,21 @@ ember-cli-broccoli-sane-watcher@^2.0.4: rsvp "^3.0.18" sane "^1.1.1" +ember-cli-cjs-transform@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ember-cli-cjs-transform/-/ember-cli-cjs-transform-1.2.0.tgz#34a0d2667673caec0248f500a954f45668027e8b" + dependencies: + broccoli-debug "^0.6.4" + broccoli-plugin "^1.3.0" + ember-cli-babel "^6.6.0" + fs-extra "^5.0.0" + hash-for-dep "^1.2.3" + pkg-dir "^2.0.0" + rollup "^0.58.1" + rollup-plugin-commonjs "^9.1.0" + rollup-plugin-node-resolve "^3.3.0" + username "^3.0.0" + ember-cli-clipboard@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/ember-cli-clipboard/-/ember-cli-clipboard-0.8.0.tgz#c2e91290b2746c1a4903097f5d7a55406de539b1" @@ -2805,10 +2972,14 @@ ember-cli-legacy-blueprints@^0.1.2: rsvp "^3.0.17" silent-error "^1.0.0" -ember-cli-lodash-subset@^1.0.11, ember-cli-lodash-subset@^1.0.7: +ember-cli-lodash-subset@^1.0.7: version "1.0.12" resolved "https://registry.yarnpkg.com/ember-cli-lodash-subset/-/ember-cli-lodash-subset-1.0.12.tgz#af2e77eba5dcb0d77f3308d3a6fd7d3450f6e537" +ember-cli-lodash-subset@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ember-cli-lodash-subset/-/ember-cli-lodash-subset-2.0.1.tgz#20cb68a790fe0fde2488ddfd8efbb7df6fe766f2" + ember-cli-mirage@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/ember-cli-mirage/-/ember-cli-mirage-0.4.1.tgz#bfdfe61e5e74dc3881ed31f12112dae1a29f0d4c" @@ -3000,11 +3171,11 @@ ember-cli-version-checker@^2.1.0: resolve "^1.3.3" semver "^5.3.0" -ember-cli@~2.15.0: - version "2.15.1" - resolved "https://registry.yarnpkg.com/ember-cli/-/ember-cli-2.15.1.tgz#773add3cc18e5068f1c5f43a77544efa2712e47b" +ember-cli@~2.16.0: + version "2.16.2" + resolved "https://registry.yarnpkg.com/ember-cli/-/ember-cli-2.16.2.tgz#53b922073a8e6f34255a6e0dcb1794a91ba3e1b7" dependencies: - amd-name-resolver "0.0.7" + amd-name-resolver "1.0.0" babel-plugin-transform-es2015-modules-amd "^6.24.0" bower-config "^1.3.0" bower-endpoint-parser "0.2.2" @@ -3014,7 +3185,8 @@ ember-cli@~2.15.0: broccoli-concat "^3.2.2" broccoli-config-loader "^1.0.0" broccoli-config-replace "^1.1.2" - broccoli-funnel "^1.0.6" + broccoli-debug "^0.6.3" + broccoli-funnel "^2.0.0" broccoli-funnel-reducer "^1.0.0" broccoli-merge-trees "^2.0.0" broccoli-middleware "^1.0.0" @@ -3022,31 +3194,30 @@ ember-cli@~2.15.0: broccoli-stew "^1.2.0" calculate-cache-key-for-tree "^1.0.0" capture-exit "^1.1.0" - chalk "^1.1.3" + chalk "^2.0.1" clean-base-url "^1.0.0" compression "^1.4.4" configstore "^3.0.0" - console-ui "^1.0.2" + console-ui "^2.0.0" core-object "^3.1.3" dag-map "^2.0.2" - deep-freeze "^0.0.1" diff "^3.2.0" ember-cli-broccoli-sane-watcher "^2.0.4" ember-cli-is-package-missing "^1.0.0" ember-cli-legacy-blueprints "^0.1.2" - ember-cli-lodash-subset "^1.0.11" + ember-cli-lodash-subset "^2.0.1" ember-cli-normalize-entity-name "^1.0.0" ember-cli-preprocess-registry "^3.1.0" ember-cli-string-utils "^1.0.0" ember-try "^0.2.15" ensure-posix-path "^1.0.2" - execa "^0.7.0" + execa "^0.8.0" exists-sync "0.0.4" exit "^0.1.2" express "^4.12.3" filesize "^3.1.3" find-up "^2.1.0" - fs-extra "^3.0.0" + fs-extra "^4.0.0" fs-tree-diff "^0.5.2" get-caller-file "^1.0.0" git-repo-info "^1.4.1" @@ -3074,7 +3245,7 @@ ember-cli@~2.15.0: promise-map-series "^0.2.1" quick-temp "^0.1.8" resolve "^1.3.0" - rsvp "^3.3.3" + rsvp "^3.6.0" sane "^1.6.0" semver "^5.1.1" silent-error "^1.0.0" @@ -3660,6 +3831,10 @@ estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" +estree-walker@^0.5.1, estree-walker@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.2.tgz#d3850be7529c9580d815600b53126515e146dd39" + esutils@^2.0.0, esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" @@ -3683,6 +3858,14 @@ events-to-array@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/events-to-array/-/events-to-array-1.1.2.tgz#2d41f563e1fe400ed4962fe1a4d5c6a7539df7f6" +exec-file-sync@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/exec-file-sync/-/exec-file-sync-2.0.2.tgz#58d441db46e40de6d1f30de5be022785bd89e328" + dependencies: + is-obj "^1.0.0" + object-assign "^4.0.1" + spawn-sync "^1.0.11" + exec-sh@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.0.tgz#14f75de3f20d286ef933099b2ce50a90359cef10" @@ -3701,6 +3884,18 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + exif-parser@^0.1.9: version "0.1.11" resolved "https://registry.yarnpkg.com/exif-parser/-/exif-parser-0.1.11.tgz#8a97d1c9315ffd4754b6ae938ce4488d1b1a26b7" @@ -3731,6 +3926,18 @@ expand-brackets@^0.1.4: dependencies: is-posix-bracket "^0.1.0" +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + expand-range@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" @@ -3776,6 +3983,19 @@ express@^4.10.7, express@^4.12.3: utils-merge "1.0.0" vary "~1.1.1" +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + extend@^3.0.0, extend@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" @@ -3802,6 +4022,19 @@ extglob@^0.3.1: dependencies: is-extglob "^1.0.0" +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + dependencies: + 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.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + extract-zip@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.5.0.tgz#92ccf6d81ef70a9fa4c1747114ccef6d8688a6c4" @@ -3943,6 +4176,15 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + finalhandler@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.3.tgz#ef47e77950e999780e86022a560e3217e0d0cc89" @@ -4006,7 +4248,7 @@ for-each@^0.3.2: dependencies: is-function "~1.0.0" -for-in@^1.0.1: +for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -4038,6 +4280,12 @@ forwarded@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.0.tgz#19ef9874c4ae1c297bcf078fde63a09b66a84363" +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + dependencies: + map-cache "^0.2.2" + fresh@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.0.tgz#f474ca5e6a9246d6fd8e0953cfa9b9c805afa78e" @@ -4090,12 +4338,20 @@ fs-extra@^2.0.0: graceful-fs "^4.1.2" jsonfile "^2.1.0" -fs-extra@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291" +fs-extra@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" dependencies: graceful-fs "^4.1.2" - jsonfile "^3.0.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" universalify "^0.1.0" fs-readdir-recursive@^0.1.0: @@ -4191,6 +4447,10 @@ get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -4429,6 +4689,33 @@ has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + hash-for-dep@^1.0.2: version "1.1.2" resolved "https://registry.yarnpkg.com/hash-for-dep/-/hash-for-dep-1.1.2.tgz#e3347ed92960eb0bb53a2c6c2b70e36d75b7cd0c" @@ -4438,6 +4725,15 @@ hash-for-dep@^1.0.2: heimdalljs-logger "^0.1.7" resolve "^1.1.6" +hash-for-dep@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/hash-for-dep/-/hash-for-dep-1.2.3.tgz#5ec69fca32c23523972d52acb5bb65ffc3664cab" + dependencies: + broccoli-kitchen-sink-helpers "^0.3.1" + heimdalljs "^0.2.3" + heimdalljs-logger "^0.1.7" + resolve "^1.4.0" + hasha@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/hasha/-/hasha-2.2.0.tgz#78d7cbfc1e6d66303fe79837365984517b2f6ee1" @@ -4657,22 +4953,22 @@ inquirer@^0.12.0: strip-ansi "^3.0.0" through "^2.3.6" -inquirer@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-1.2.3.tgz#4dec6f32f37ef7bb0b2ed3f1d1a5c3f545074918" +inquirer@^2: + version "2.0.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-2.0.0.tgz#e1351687b90d150ca403ceaa3cefb1e3065bef4b" dependencies: ansi-escapes "^1.1.0" chalk "^1.0.0" cli-cursor "^1.0.1" cli-width "^2.0.0" external-editor "^1.1.0" - figures "^1.3.5" + figures "^2.0.0" lodash "^4.3.0" mute-stream "0.0.6" pinkie-promise "^2.0.0" run-async "^2.2.0" rx "^4.1.0" - string-width "^1.0.1" + string-width "^2.0.0" strip-ansi "^3.0.0" through "^2.3.6" @@ -4717,6 +5013,18 @@ ipaddr.js@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.3.0.tgz#1e03a52fdad83a8bbb2b25cbf4998b4cffcd3dec" +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + dependencies: + kind-of "^6.0.0" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -4737,6 +5045,34 @@ is-builtin-module@^1.0.0: dependencies: builtin-modules "^1.0.0" +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -4747,10 +5083,16 @@ is-equal-shallow@^0.1.3: dependencies: is-primitive "^2.0.0" -is-extendable@^0.1.1: +is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + dependencies: + is-plain-object "^2.0.4" + is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" @@ -4795,6 +5137,10 @@ is-integer@^1.0.4: dependencies: is-finite "^1.0.0" +is-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + is-my-json-valid@^2.10.0, is-my-json-valid@^2.12.4: version "2.16.0" resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693" @@ -4816,10 +5162,20 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" +is-odd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24" + dependencies: + is-number "^4.0.0" + is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" @@ -4836,6 +5192,12 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + dependencies: + isobject "^3.0.1" + is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" @@ -4880,6 +5242,10 @@ is-windows@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -4902,6 +5268,10 @@ isobject@^2.0.0: dependencies: isarray "1.0.0" +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + isstream@0.1.x, isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -5049,9 +5419,9 @@ jsonfile@^2.1.0: optionalDependencies: graceful-fs "^4.1.6" -jsonfile@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" optionalDependencies: graceful-fs "^4.1.6" @@ -5100,7 +5470,7 @@ kew@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/kew/-/kew-0.7.0.tgz#79d93d2d33363d6fdd2970b335d9141ad591d79b" -kind-of@^3.0.2: +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" dependencies: @@ -5112,6 +5482,14 @@ kind-of@^4.0.0: dependencies: is-buffer "^1.1.5" +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" @@ -5393,6 +5771,12 @@ lodash@~2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e" +log-symbols@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + dependencies: + chalk "^2.0.1" + loglevel-colored-level-prefix@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz#6a40218fdc7ae15fc76c3d0f3e676c465388603e" @@ -5440,6 +5824,12 @@ lru-cache@^4.0.1: pseudomap "^1.0.2" yallist "^2.1.2" +magic-string@^0.22.4: + version "0.22.5" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" + dependencies: + vlq "^0.2.2" + make-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.0.0.tgz#97a011751e91dd87cfadef58832ebb04936de978" @@ -5458,6 +5848,10 @@ makeerror@1.0.x: dependencies: tmpl "1.0.x" +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" @@ -5466,6 +5860,12 @@ map-obj@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + dependencies: + object-visit "^1.0.0" + markdown-it-terminal@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/markdown-it-terminal/-/markdown-it-terminal-0.1.0.tgz#545abd8dd01c3d62353bfcea71db580b51d22bd9" @@ -5510,13 +5910,19 @@ media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + dependencies: + mimic-fn "^1.0.0" + memory-streams@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/memory-streams/-/memory-streams-0.1.2.tgz#273ff777ab60fec599b116355255282cca2c50c2" dependencies: readable-stream "~1.0.2" -meow@^3.7.0: +meow@^3.4.0, meow@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" dependencies: @@ -5592,6 +5998,24 @@ micromatch@^2.1.5, micromatch@^2.3.7: parse-glob "^3.0.4" regex-cache "^0.4.2" +micromatch@^3.1.10: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + 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.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + "mime-db@>= 1.27.0 < 2": version "1.29.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.29.0.tgz#48d26d235589651704ac5916ca06001914266878" @@ -5661,6 +6085,13 @@ minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" +mixin-deep@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + mkdirp@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" @@ -5761,6 +6192,23 @@ nan@^2.3.0: version "2.6.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45" +nanomatch@^1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.9.tgz#879f7150cb2dab7a471259066c104eee6e0fa7c2" + dependencies: + 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-odd "^2.0.0" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + native-promise-only@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11" @@ -5977,6 +6425,20 @@ object-component@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + dependencies: + isobject "^3.0.0" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -5984,6 +6446,12 @@ object.omit@^2.0.0: for-own "^0.1.4" is-extendable "^0.1.1" +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + dependencies: + isobject "^3.0.1" + on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -6032,14 +6500,16 @@ options@>=0.0.5: version "0.0.6" resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" -ora@^0.2.0: - version "0.2.3" - resolved "https://registry.yarnpkg.com/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4" +ora@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-2.1.0.tgz#6caf2830eb924941861ec53a173799e008b51e5b" dependencies: - chalk "^1.1.1" - cli-cursor "^1.0.2" - cli-spinners "^0.1.2" - object-assign "^4.0.1" + chalk "^2.3.1" + cli-cursor "^2.1.0" + cli-spinners "^1.1.0" + log-symbols "^2.2.0" + strip-ansi "^4.0.0" + wcwidth "^1.0.1" os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" @@ -6157,6 +6627,16 @@ parseurl@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56" +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + +passwd-user@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/passwd-user/-/passwd-user-1.2.1.tgz#a01a5dc639ef007dc56364b8178569080ad3a7b8" + dependencies: + exec-file-sync "^2.0.0" + path-exists@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-1.0.0.tgz#d5a8998eb71ef37a74c34eb0d9eba6e878eea081" @@ -6251,6 +6731,12 @@ pixelmatch@^4.0.0: dependencies: pngjs "^3.0.0" +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + dependencies: + find-up "^2.1.0" + pluralize@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" @@ -6275,6 +6761,10 @@ portfinder@^1.0.7: debug "^2.2.0" mkdirp "0.5.x" +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + postcss-value-parser@^3.2.3: version "3.3.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" @@ -6651,6 +7141,13 @@ regex-cache@^0.4.2: is-equal-shallow "^0.1.3" is-primitive "^2.0.0" +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" @@ -6687,7 +7184,7 @@ repeat-element@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" -repeat-string@^1.5.2: +repeat-string@^1.5.2, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" @@ -6814,6 +7311,10 @@ resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + resolve@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.2.tgz#1f0442c9e0cbb8136e87b9305f932f46c7f28235" @@ -6826,6 +7327,12 @@ resolve@^1.1.2, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.0, resolve@^1.3.3: dependencies: path-parse "^1.0.5" +resolve@^1.4.0, resolve@^1.5.0: + version "1.7.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" + dependencies: + path-parse "^1.0.5" + restore-cursor@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" @@ -6840,6 +7347,10 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" @@ -6856,6 +7367,38 @@ rimraf@~2.2.6: version "2.2.8" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" +rollup-plugin-commonjs@^9.1.0: + version "9.1.3" + resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.1.3.tgz#37bfbf341292ea14f512438a56df8f9ca3ba4d67" + dependencies: + estree-walker "^0.5.1" + magic-string "^0.22.4" + resolve "^1.5.0" + rollup-pluginutils "^2.0.1" + +rollup-plugin-node-resolve@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.3.0.tgz#c26d110a36812cbefa7ce117cadcd3439aa1c713" + dependencies: + builtin-modules "^2.0.0" + is-module "^1.0.0" + resolve "^1.1.6" + +rollup-pluginutils@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.1.0.tgz#4ee80b1bbc8eaed67aabf7f55b4fe9ccf9fd3c3a" + dependencies: + estree-walker "^0.5.2" + micromatch "^3.1.10" + tosource "^1.0.0" + +rollup@^0.58.1: + version "0.58.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.58.2.tgz#2feddea8c0c022f3e74b35c48e3c21b3433803ce" + dependencies: + "@types/estree" "0.0.38" + "@types/node" "*" + route-recognizer@^0.2.3: version "0.2.10" resolved "https://registry.yarnpkg.com/route-recognizer/-/route-recognizer-0.2.10.tgz#024b2283c2e68d13a7c7f5173a5924645e8902df" @@ -6868,6 +7411,10 @@ rsvp@^3.0.14, rsvp@^3.0.16, rsvp@^3.0.17, rsvp@^3.0.18, rsvp@^3.0.21, rsvp@^3.0. version "3.6.1" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.1.tgz#34f4a7ac2859f7bacc8f49789c5604f1e26ae702" +rsvp@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" + rsvp@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.7.0.tgz#dc1b0b1a536f7dec9d2be45e0a12ad4197c9fd96" @@ -6924,6 +7471,12 @@ safe-json-parse@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/safe-json-parse/-/safe-json-parse-1.0.1.tgz#3e76723e38dfdda13c9b1d29a1e07ffee4b30b57" +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + dependencies: + ret "~0.1.10" + samsam@1.x, samsam@^1.1.3: version "1.3.0" resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" @@ -7011,6 +7564,24 @@ set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" +set-value@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.1" + to-object-path "^0.3.0" + +set-value@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + setprototypeof@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" @@ -7103,6 +7674,33 @@ slide@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + sntp@1.x.x: version "1.0.9" resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" @@ -7163,6 +7761,16 @@ sort-package-json@^1.4.0: dependencies: sort-object-keys "^1.1.1" +source-map-resolve@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.1.tgz#7ad0f593f2281598e854df80f19aae4b92d7a11a" + dependencies: + atob "^2.0.0" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + source-map-support@^0.2.10: version "0.2.10" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.2.10.tgz#ea5a3900a1c1cb25096a0ae8cc5c2b4b10ded3dc" @@ -7179,6 +7787,10 @@ source-map-url@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9" +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + source-map@0.1.32: version "0.1.32" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.32.tgz#c8b6c167797ba4740a8ea33252162ff08591b266" @@ -7203,7 +7815,7 @@ spawn-args@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/spawn-args/-/spawn-args-0.2.0.tgz#fb7d0bd1d70fd4316bd9e3dec389e65f9d6361bb" -spawn-sync@^1.0.15: +spawn-sync@^1.0.11, spawn-sync@^1.0.15: version "1.0.15" resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476" dependencies: @@ -7224,6 +7836,12 @@ spdx-license-ids@^1.0.2: version "1.2.2" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + dependencies: + extend-shallow "^3.0.0" + sprintf-js@^1.0.3, sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -7254,6 +7872,13 @@ stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + "statuses@>= 1.3.1 < 2", statuses@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" @@ -7599,6 +8224,32 @@ to-ico@^1.1.2: parse-png "^1.0.0" resize-img "^1.1.0" +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +tosource@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/tosource/-/tosource-1.0.0.tgz#42d88dd116618bcf00d6106dd5446f3427902ff1" + tough-cookie@~2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" @@ -7724,6 +8375,15 @@ underscore@~1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8" +union-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^0.4.3" + unique-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" @@ -7738,18 +8398,35 @@ unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + untildify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-2.1.0.tgz#17eb2807987f76952e9c0485fc311d06a826a2e0" dependencies: os-homedir "^1.0.0" +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + url-regex@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/url-regex/-/url-regex-3.2.0.tgz#dbad1e0c9e29e105dd0b1f09f6862f7fdb482724" dependencies: ip-regex "^1.0.1" +use@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.0.tgz#14716bf03fdfefd03040aef58d8b4b85f3a7c544" + dependencies: + kind-of "^6.0.2" + user-home@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" @@ -7760,10 +8437,31 @@ user-home@^2.0.0: dependencies: os-homedir "^1.0.0" +user-info@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/user-info/-/user-info-1.0.0.tgz#81c82b7ed63e674c2475667653413b3c76fde239" + dependencies: + os-homedir "^1.0.1" + passwd-user "^1.2.1" + username "^1.0.1" + username-sync@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/username-sync/-/username-sync-1.0.1.tgz#1cde87eefcf94b8822984d938ba2b797426dae1f" +username@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/username/-/username-1.0.1.tgz#e1f72295e3e58e06f002c6327ce06897a99cd67f" + dependencies: + meow "^3.4.0" + +username@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/username/-/username-3.0.0.tgz#b3dba982a72b4ce59d52f159fa1aeba266af5fc8" + dependencies: + execa "^0.7.0" + mem "^1.1.0" + util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -7807,6 +8505,10 @@ vinyl@^1.1.0: clone-stats "^0.0.1" replace-ext "0.0.1" +vlq@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" + walk-sync@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-0.3.1.tgz#558a16aeac8c0db59c028b73c66f397684ece465" @@ -7842,6 +8544,12 @@ watch@~0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/watch/-/watch-0.10.0.tgz#77798b2da0f9910d595f1ace5b0c2258521f21dc" +wcwidth@^1.0.0, wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + dependencies: + defaults "^1.0.3" + websocket-driver@>=0.5.1: version "0.6.5" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.6.5.tgz#5cb2556ceb85f4373c6d8238aa691c8454e13a36" @@ -8006,6 +8714,12 @@ yam@0.0.22: fs-extra "^0.30.0" lodash.merge "^4.4.0" +yargs-parser@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.0.0.tgz#c737c93de2567657750cb1f2c00be639fd19c994" + dependencies: + camelcase "^4.1.0" + yargs-parser@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" From dcbc3dd921c342a87dfef759573b063d0b7b8a3b Mon Sep 17 00:00:00 2001 From: madalynrose Date: Fri, 25 May 2018 16:43:16 -0400 Subject: [PATCH 58/66] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0e9880a32..c7c4911b07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ FEATURES: * Userpass auth CIDR restrictions: When using the `userpass` auth method you can now limit authentication to specific CIDRs; these will also be encoded in resultant tokens to limit their use. + * Vault Browser CLI: The UI now supports usage of read/write/list/delete + commands in a CLI that can be accessed from the nav bar. Complex inputs such + as JSON files are not currently supported. This surfaces features otherwise + unsupported in Vault's UI. IMPROVEMENTS: From 51c69f734a352b3e01d56e772b030f67eb938bc2 Mon Sep 17 00:00:00 2001 From: Joshua Ogle Date: Fri, 25 May 2018 15:28:03 -0600 Subject: [PATCH 59/66] Add shadow to console --- ui/app/styles/components/console-ui-panel.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/app/styles/components/console-ui-panel.scss b/ui/app/styles/components/console-ui-panel.scss index 9649bb8bb1..31d91603bd 100644 --- a/ui/app/styles/components/console-ui-panel.scss +++ b/ui/app/styles/components/console-ui-panel.scss @@ -117,8 +117,10 @@ } .panel-open .console-ui-panel-scroller { + box-shadow: $box-shadow-highest; transform: translate3d(0, 0, 0); } + .panel-open .console-ui-panel-scroller.fullscreen { bottom: 0; top: 0; From c87f6ea62a16aa144070917eb4ef07424ced600a Mon Sep 17 00:00:00 2001 From: Joshua Ogle Date: Fri, 25 May 2018 16:23:54 -0600 Subject: [PATCH 60/66] Fix upgrade link --- ui/tests/integration/components/upgrade-link-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/tests/integration/components/upgrade-link-test.js b/ui/tests/integration/components/upgrade-link-test.js index 6b67c4aa28..c2e64f8c4e 100644 --- a/ui/tests/integration/components/upgrade-link-test.js +++ b/ui/tests/integration/components/upgrade-link-test.js @@ -20,7 +20,7 @@ test('it renders with overlay', function(assert) { 'contains overlay content' ); assert.equal( - this.$('#modal-wormhole a[href^="http://hashicorp.com/products/vault/trial?source=vaultui"]').length, + this.$('#modal-wormhole a[href^="https://hashicorp.com/products/vault/trial?source=vaultui"]').length, 1, 'contains info link' ); From edf4f7a5e0629c58a51ff6e2880cfae3b05e8920 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 28 May 2018 12:08:22 -0400 Subject: [PATCH 61/66] Ensure safety_buffer in PKI is greater than zero (#4643) Fixes #4641 --- builtin/logical/pki/path_tidy.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/builtin/logical/pki/path_tidy.go b/builtin/logical/pki/path_tidy.go index b254321a36..9b0a86df9c 100644 --- a/builtin/logical/pki/path_tidy.go +++ b/builtin/logical/pki/path_tidy.go @@ -53,6 +53,10 @@ func (b *backend) pathTidyWrite(ctx context.Context, req *logical.Request, d *fr tidyCertStore := d.Get("tidy_cert_store").(bool) tidyRevocationList := d.Get("tidy_revocation_list").(bool) + if safetyBuffer < 1 { + return logical.ErrorResponse("safety_buffer must be greater than zero"), nil + } + bufferDuration := time.Duration(safetyBuffer) * time.Second var resp *logical.Response From eeda29855690237d404a171e8374a4ab62c04bbc Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 28 May 2018 12:09:07 -0400 Subject: [PATCH 62/66] changelog++ --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7c4911b07..865d595c20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,8 @@ BUG FIXES: * secret/gcp: Make `bound_region` able to use short names * secret/kv: Fix response wrapping for KV v2 [GH-4511] * secret/kv: Fix address flag not being honored correctly [GH-4617] + * secret/pki: Fix `safety_buffer` for tidy being allowed to be negative, + clearing all certs [GH-4641] * secret/pki: Fix `key_type` not being allowed to be set to `any` [GH-4595] * secret/pki: Fix path length parameter being ignored when using `use_csr_values` and signing an intermediate CA cert [GH-4459] From ec58e395981e6dc5596f71b9a96db79ee1c03489 Mon Sep 17 00:00:00 2001 From: Matthew Irish Date: Mon, 28 May 2018 21:50:37 -0500 Subject: [PATCH 63/66] UI - wrapping lookup path (#4644) * add creation path to the display on wrapping lookup * fix z-index issue with console-panel and the subnav on smaller viewports * use position:fixed for all of the global flash stuff * tweaks for the console on mobile devices --- ui/app/styles/components/console-ui-panel.scss | 9 ++++++--- ui/app/styles/components/global-flash.scss | 11 ++--------- ui/app/styles/core/tabs.scss | 1 + ui/app/templates/components/console/command-input.hbs | 2 +- ui/app/templates/partials/tools/lookup.hbs | 1 + 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/ui/app/styles/components/console-ui-panel.scss b/ui/app/styles/components/console-ui-panel.scss index 31d91603bd..b9e75b261d 100644 --- a/ui/app/styles/components/console-ui-panel.scss +++ b/ui/app/styles/components/console-ui-panel.scss @@ -2,13 +2,14 @@ background: linear-gradient(to right, #191A1C, #1B212D); height: 0; left: 0; - min-height: 400px; overflow: auto; - position: fixed; + position: absolute; + min-height: 0; right: 0; transform: translate3d(0, -400px, 0); transition: min-height $speed ease-out, transform $speed ease-in; will-change: transform, min-height; + -webkit-overflow-scrolling: touch; z-index: 199; } @@ -69,7 +70,7 @@ color: $white; flex: 1; font-family: $family-monospace; - font-size: $body-size; + font-size: 16px; font-weight: $font-weight-bold; margin-left: -$size-10; outline: none; @@ -119,11 +120,13 @@ .panel-open .console-ui-panel-scroller { box-shadow: $box-shadow-highest; transform: translate3d(0, 0, 0); + min-height: 400px; } .panel-open .console-ui-panel-scroller.fullscreen { bottom: 0; top: 0; + position: fixed; min-height: 100%; } diff --git a/ui/app/styles/components/global-flash.scss b/ui/app/styles/components/global-flash.scss index f0819100e7..c4d2fd29bb 100644 --- a/ui/app/styles/components/global-flash.scss +++ b/ui/app/styles/components/global-flash.scss @@ -1,14 +1,7 @@ .global-flash { position: fixed; - @include until($desktop) { - position: -webkit-sticky; - position: sticky; - top: 0; - bottom: auto; - margin: 0 auto; - width: 95%; - } - width: 450px; + max-width: 450px; + width: 95%; bottom: 0; left: 0; margin: 10px; diff --git a/ui/app/styles/core/tabs.scss b/ui/app/styles/core/tabs.scss index 27b5d1c1f9..23c8b45407 100644 --- a/ui/app/styles/core/tabs.scss +++ b/ui/app/styles/core/tabs.scss @@ -5,6 +5,7 @@ padding: $size-10 $size-10; @include until($tablet) { + position:relative; background-color: $grey; flex: 0 0 100%; height: 3rem; diff --git a/ui/app/templates/components/console/command-input.hbs b/ui/app/templates/components/console/command-input.hbs index 3d14968688..83fd9981cf 100644 --- a/ui/app/templates/components/console/command-input.hbs +++ b/ui/app/templates/components/console/command-input.hbs @@ -1,5 +1,5 @@ {{i-con glyph="chevron-right" size=12}} - + {{#tool-tip horizontalPosition="auto-right" verticalPosition=(if isFullscreen "above" "below") as |d|}} {{#d.trigger tagName="button" type="button" class=(concat "button is-compact" (if isFullscreen " active")) click=(action "fullscreen") data-test-tool-tip-trigger=true}} {{i-con glyph=(if isFullscreen "fullscreen-close" "fullscreen-open") aria-hidden="true" size=16}} diff --git a/ui/app/templates/partials/tools/lookup.hbs b/ui/app/templates/partials/tools/lookup.hbs index 875281d3d6..673637e85d 100644 --- a/ui/app/templates/partials/tools/lookup.hbs +++ b/ui/app/templates/partials/tools/lookup.hbs @@ -10,6 +10,7 @@ {{#if (or creation_time creation_ttl)}}
+ {{info-table-row label="Creation path" value=creation_path data-test-tools="token-lookup-row"}} {{info-table-row label="Creation time" value=creation_time data-test-tools="token-lookup-row"}} {{info-table-row label="Creation TTL" value=creation_ttl data-test-tools="token-lookup-row"}} {{#if expirationDate}} From 8061bc4eff95e5eb5e17e7f7747cf1d6fb672b4d Mon Sep 17 00:00:00 2001 From: Matthew Irish Date: Mon, 28 May 2018 21:55:22 -0500 Subject: [PATCH 64/66] changelog++ --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 865d595c20..74fd34a7ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,9 @@ IMPROVEMENTS: of just slot number * expiration: Allow revoke-prefix and revoke-force to work on single leases as well as prefixes [GH-4450] + * ui: wrapping lookup now distplays the path [GH-4644] + * ui: Identity interface now has more inline actions to make editing and adding + aliases to an entity or group easier [GH-4502] BUG FIXES: @@ -59,6 +62,8 @@ BUG FIXES: [GH-4570] * ui: Fix HMAC algorithm in transit [GH-4604] * ui: Fix unwrap of auth responses via the UI's unwrap tool [GH-4611] + * ui (enterprise): Fix parsing of version string that blocked some users from seeing + enterprise-specific pages in the UI [GH-4547] * replication: Fix error while running plugins on a newly created replication secondary * replication: Fix issue with token store lookups after a secondary's mount table From 3325813341349425bb8ddcadaf6a163a0146958a Mon Sep 17 00:00:00 2001 From: Kloppi313 <36038231+Kloppi313@users.noreply.github.com> Date: Tue, 29 May 2018 15:28:08 +0200 Subject: [PATCH 65/66] Typo in operator_rekey.go (#4646) --- command/operator_rekey.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command/operator_rekey.go b/command/operator_rekey.go index c82b44706b..7420977411 100644 --- a/command/operator_rekey.go +++ b/command/operator_rekey.go @@ -655,7 +655,7 @@ func (c *OperatorRekeyCommand) printUnsealKeys(status *api.RekeyStatusResponse, c.UI.Output("") c.UI.Output(wrapAtLength(fmt.Sprintf( - "Vault rekeyed with %d key shares an a key threshold of %d. Please "+ + "Vault rekeyed with %d key shares and a key threshold of %d. Please "+ "securely distributed the key shares printed above. When the Vault is "+ "re-sealed, restarted, or stopped, you must supply at least %d of "+ "these keys to unseal it before it can start servicing requests.", From 2f67754951b993e49dff1e40ce17d5315a302e22 Mon Sep 17 00:00:00 2001 From: Matthew Irish Date: Tue, 29 May 2018 09:14:31 -0500 Subject: [PATCH 66/66] UI - Active Directory secrets (#4647) * add AD secrets in the ui and move deprecated engines to the bottom of the list * fix tools tests * prettier --- ui/app/components/console/command-input.js | 2 +- ui/app/components/console/ui-panel.js | 16 ++++-- ui/app/components/identity/_popup-base.js | 2 +- ui/app/components/identity/edit-form.js | 12 ++-- ui/app/components/identity/item-details.js | 9 +-- ui/app/components/upgrade-link.js | 4 +- .../cluster/access/identity/aliases/index.js | 4 +- .../vault/cluster/access/identity/create.js | 20 +++---- .../vault/cluster/access/identity/index.js | 5 +- .../cluster/settings/mount-secret-backend.js | 11 ++-- ui/app/lib/console-helpers.js | 10 ++-- ui/app/models/identity/group-alias.js | 1 - ui/app/routes/vault/cluster.js | 2 +- .../cluster/access/identity/aliases/index.js | 2 +- .../vault/cluster/access/identity/index.js | 2 +- .../vault/cluster/secrets/backend/list.js | 2 +- ui/app/services/console.js | 6 +- .../access/identity/_shared-alias-tests.js | 39 ++++++++++--- .../access/identity/_shared-tests.js | 49 +++++++++++++---- .../identity/entities/aliases/create-test.js | 2 - .../access/identity/entities/create-test.js | 1 - .../identity/groups/aliases/create-test.js | 2 - .../settings/mount-secret-backend-test.js | 2 +- ui/tests/acceptance/tools-test.js | 12 ++-- .../components/identity/item-details-test.js | 6 +- .../components/transit-key-actions-test.js | 2 +- .../pages/access/identity/aliases/show.js | 2 +- ui/tests/pages/access/identity/create.js | 6 +- ui/tests/pages/access/identity/show.js | 2 +- .../components/identity/edit-form-test.js | 6 +- ui/tests/unit/services/store-test.js | 55 ++++++++++--------- 31 files changed, 171 insertions(+), 125 deletions(-) diff --git a/ui/app/components/console/command-input.js b/ui/app/components/console/command-input.js index 5ee6eeffe1..43854b0b7d 100644 --- a/ui/app/components/console/command-input.js +++ b/ui/app/components/console/command-input.js @@ -31,6 +31,6 @@ export default Ember.Component.extend({ }, fullscreen() { this.get('onFullscreen')(); - } + }, }, }); diff --git a/ui/app/components/console/ui-panel.js b/ui/app/components/console/ui-panel.js index fe35294d3b..61c782a817 100644 --- a/ui/app/components/console/ui-panel.js +++ b/ui/app/components/console/ui-panel.js @@ -26,8 +26,15 @@ export default Ember.Component.extend({ executeCommand(command, shouldThrow = false) { let service = this.get('console'); let serviceArgs; - - if(executeUICommand(command, (args) => this.logAndOutput(args), (args) => service.clearLog(args), () => this.toggleProperty('isFullscreen'))){ + + if ( + executeUICommand( + command, + args => this.logAndOutput(args), + args => service.clearLog(args), + () => this.toggleProperty('isFullscreen') + ) + ) { return; } @@ -55,7 +62,8 @@ export default Ember.Component.extend({ return; } let serviceFn = service[method]; - serviceFn.call(service, path, data, flags.wrapTTL) + serviceFn + .call(service, path, data, flags.wrapTTL) .then(resp => { this.logAndOutput(command, logFromResponse(resp, path, method, flags)); }) @@ -65,7 +73,7 @@ export default Ember.Component.extend({ }, shiftCommandIndex(keyCode) { - this.get('console').shiftCommandIndex(keyCode, (val) => { + this.get('console').shiftCommandIndex(keyCode, val => { this.set('inputValue', val); }); }, diff --git a/ui/app/components/identity/_popup-base.js b/ui/app/components/identity/_popup-base.js index 0cda95bc23..c74803ade2 100644 --- a/ui/app/components/identity/_popup-base.js +++ b/ui/app/components/identity/_popup-base.js @@ -16,7 +16,7 @@ export default Component.extend({ model.rollbackAttributes(); } }, - onSuccess(){}, + onSuccess() {}, // override and return a promise transaction() { assert('override transaction call in an extension of popup-base', false); diff --git a/ui/app/components/identity/edit-form.js b/ui/app/components/identity/edit-form.js index d9f1eb8c9d..59e6173b55 100644 --- a/ui/app/components/identity/edit-form.js +++ b/ui/app/components/identity/edit-form.js @@ -60,7 +60,7 @@ export default Ember.Component.extend({ return; } this.get('flashMessages').success(message); - yield this.get('onSave')({saveType: 'save', model}); + yield this.get('onSave')({ saveType: 'save', model }); }).drop(), willDestroy() { @@ -74,12 +74,10 @@ export default Ember.Component.extend({ deleteItem(model) { let message = this.getMessage(model, true); let flash = this.get('flashMessages'); - model - .destroyRecord() - .then(() => { - flash.success(message); - return this.get('onSave')({saveType: 'delete', model}); - }); + model.destroyRecord().then(() => { + flash.success(message); + return this.get('onSave')({ saveType: 'delete', model }); + }); }, }, }); diff --git a/ui/app/components/identity/item-details.js b/ui/app/components/identity/item-details.js index eae4d92b2a..eafc9fb5d8 100644 --- a/ui/app/components/identity/item-details.js +++ b/ui/app/components/identity/item-details.js @@ -9,8 +9,9 @@ export default Ember.Component.extend({ enable(model) { model.set('disabled', false); - model.save(). - then(() => { + model + .save() + .then(() => { this.get('flashMessages').success(`Successfully enabled entity: ${model.id}`); }) .catch(e => { @@ -18,6 +19,6 @@ export default Ember.Component.extend({ `There was a problem enabling the entity: ${model.id} - ${e.error.join(' ') || e.message}` ); }); - } - } + }, + }, }); diff --git a/ui/app/components/upgrade-link.js b/ui/app/components/upgrade-link.js index 95dd2dcf15..01bc9ea11d 100644 --- a/ui/app/components/upgrade-link.js +++ b/ui/app/components/upgrade-link.js @@ -7,10 +7,10 @@ export default Ember.Component.extend({ isActive: false, tagName: 'span', trackingSource: computed('pageName', function() { - let trackingSource = "vaultui"; + let trackingSource = 'vaultui'; let pageName = this.get('pageName'); if (pageName) { - trackingSource = trackingSource + "_" + encodeURIComponent(pageName); + trackingSource = trackingSource + '_' + encodeURIComponent(pageName); } return trackingSource; }), diff --git a/ui/app/controllers/vault/cluster/access/identity/aliases/index.js b/ui/app/controllers/vault/cluster/access/identity/aliases/index.js index a35db205a2..10d0973925 100644 --- a/ui/app/controllers/vault/cluster/access/identity/aliases/index.js +++ b/ui/app/controllers/vault/cluster/access/identity/aliases/index.js @@ -5,6 +5,6 @@ export default Ember.Controller.extend(ListController, { actions: { onDelete() { this.send('reload'); - } - } + }, + }, }); diff --git a/ui/app/controllers/vault/cluster/access/identity/create.js b/ui/app/controllers/vault/cluster/access/identity/create.js index 46c8a30c6e..a94bf3b4b0 100644 --- a/ui/app/controllers/vault/cluster/access/identity/create.js +++ b/ui/app/controllers/vault/cluster/access/identity/create.js @@ -4,26 +4,20 @@ import { task } from 'ember-concurrency'; export default Ember.Controller.extend({ showRoute: 'vault.cluster.access.identity.show', showTab: 'details', - navAfterSave: task(function*({saveType, model}) { + navAfterSave: task(function*({ saveType, model }) { let isDelete = saveType === 'delete'; let type = model.get('identityType'); - let listRoutes= { + let listRoutes = { 'entity-alias': 'vault.cluster.access.identity.aliases.index', 'group-alias': 'vault.cluster.access.identity.aliases.index', - 'group': 'vault.cluster.access.identity.index', - 'entity': 'vault.cluster.access.identity.index', + group: 'vault.cluster.access.identity.index', + entity: 'vault.cluster.access.identity.index', }; - let routeName = listRoutes[type] + let routeName = listRoutes[type]; if (!isDelete) { - yield this.transitionToRoute( - this.get('showRoute'), - model.id, - this.get('showTab') - ); + yield this.transitionToRoute(this.get('showRoute'), model.id, this.get('showTab')); return; } - yield this.transitionToRoute( - routeName - ); + yield this.transitionToRoute(routeName); }), }); diff --git a/ui/app/controllers/vault/cluster/access/identity/index.js b/ui/app/controllers/vault/cluster/access/identity/index.js index 6cc77a8dc7..0bfe797cff 100644 --- a/ui/app/controllers/vault/cluster/access/identity/index.js +++ b/ui/app/controllers/vault/cluster/access/identity/index.js @@ -29,8 +29,9 @@ export default Ember.Controller.extend(ListController, { let id = model.id; model.toggleProperty('disabled'); - model.save(). - then(() => { + model + .save() + .then(() => { this.get('flashMessages').success(`Successfully ${action[0]} ${type}: ${id}`); }) .catch(e => { diff --git a/ui/app/controllers/vault/cluster/settings/mount-secret-backend.js b/ui/app/controllers/vault/cluster/settings/mount-secret-backend.js index 569a281148..973d0544e9 100644 --- a/ui/app/controllers/vault/cluster/settings/mount-secret-backend.js +++ b/ui/app/controllers/vault/cluster/settings/mount-secret-backend.js @@ -7,22 +7,23 @@ const { computed } = Ember; export default Ember.Controller.extend({ mountTypes: [ + { label: 'Active Directory', value: 'ad' }, { label: 'AWS', value: 'aws' }, - { label: 'Cassandra', value: 'cassandra', deprecated: true }, { label: 'Consul', value: 'consul' }, { label: 'Databases', value: 'database' }, { label: 'Google Cloud', value: 'gcp' }, { label: 'KV', value: 'kv' }, - { label: 'MongoDB', value: 'mongodb', deprecated: true }, - { label: 'MSSQL', value: 'mssql', deprecated: true }, - { label: 'MySQL', value: 'mysql', deprecated: true }, { label: 'Nomad', value: 'nomad' }, { label: 'PKI', value: 'pki' }, - { label: 'PostgreSQL', value: 'postgresql', deprecated: true }, { label: 'RabbitMQ', value: 'rabbitmq' }, { label: 'SSH', value: 'ssh' }, { label: 'Transit', value: 'transit' }, { label: 'TOTP', value: 'totp' }, + { label: 'Cassandra', value: 'cassandra', deprecated: true }, + { label: 'MongoDB', value: 'mongodb', deprecated: true }, + { label: 'MSSQL', value: 'mssql', deprecated: true }, + { label: 'MySQL', value: 'mysql', deprecated: true }, + { label: 'PostgreSQL', value: 'postgresql', deprecated: true }, ], selectedType: null, diff --git a/ui/app/lib/console-helpers.js b/ui/app/lib/console-helpers.js index 0d8b12128d..1637063352 100644 --- a/ui/app/lib/console-helpers.js +++ b/ui/app/lib/console-helpers.js @@ -29,12 +29,12 @@ export function extractDataAndFlags(data, flags) { }, { data: {}, flags: {} }); } -export function executeUICommand(command, logAndOutput, clearLog, toggleFullscreen){ +export function executeUICommand(command, logAndOutput, clearLog, toggleFullscreen) { const isUICommand = uiCommands.includes(command); - if(isUICommand){ + if (isUICommand) { logAndOutput(command); } - switch(command){ + switch (command) { case 'clearall': clearLog(true); break; @@ -149,7 +149,9 @@ export function shiftCommandIndex(keyCode, history, index) { let newInputValue; let commandHistoryLength = history.length; - if (!commandHistoryLength) { return []; } + if (!commandHistoryLength) { + return []; + } if (keyCode === keys.UP) { index -= 1; diff --git a/ui/app/models/identity/group-alias.js b/ui/app/models/identity/group-alias.js index 3f40ca7126..47a74ebb28 100644 --- a/ui/app/models/identity/group-alias.js +++ b/ui/app/models/identity/group-alias.js @@ -35,5 +35,4 @@ export default IdentityModel.extend({ updatePath: identityCapabilities(), canDelete: computed.alias('updatePath.canDelete'), canEdit: computed.alias('updatePath.canUpdate'), - }); diff --git a/ui/app/routes/vault/cluster.js b/ui/app/routes/vault/cluster.js index 433c7f701d..a099784c91 100644 --- a/ui/app/routes/vault/cluster.js +++ b/ui/app/routes/vault/cluster.js @@ -32,7 +32,7 @@ export default Ember.Route.extend(ModelBoundaryRoute, ClusterRoute, { model(params) { const id = this.getClusterId(params); - return this.get('store').findRecord('cluster', id); + return this.get('store').findRecord('cluster', id); }, stopPoll: Ember.on('deactivate', function() { diff --git a/ui/app/routes/vault/cluster/access/identity/aliases/index.js b/ui/app/routes/vault/cluster/access/identity/aliases/index.js index df1100eae9..b0b27d0e32 100644 --- a/ui/app/routes/vault/cluster/access/identity/aliases/index.js +++ b/ui/app/routes/vault/cluster/access/identity/aliases/index.js @@ -35,6 +35,6 @@ export default Ember.Route.extend(ListRoute, { reload() { this.store.clearAllDatasets(); this.refresh(); - } + }, }, }); diff --git a/ui/app/routes/vault/cluster/access/identity/index.js b/ui/app/routes/vault/cluster/access/identity/index.js index cf43c6d6df..4b19fcb80a 100644 --- a/ui/app/routes/vault/cluster/access/identity/index.js +++ b/ui/app/routes/vault/cluster/access/identity/index.js @@ -37,6 +37,6 @@ export default Ember.Route.extend(ListRoute, { reload() { this.store.clearAllDatasets(); this.refresh(); - } + }, }, }); diff --git a/ui/app/routes/vault/cluster/secrets/backend/list.js b/ui/app/routes/vault/cluster/secrets/backend/list.js index 1731c1525a..0c8bfb5702 100644 --- a/ui/app/routes/vault/cluster/secrets/backend/list.js +++ b/ui/app/routes/vault/cluster/secrets/backend/list.js @@ -162,6 +162,6 @@ export default Ember.Route.extend({ reload() { this.refresh(); this.store.clearAllDatasets(); - } + }, }, }); diff --git a/ui/app/services/console.js b/ui/app/services/console.js index e35555f3bf..3e17842b8e 100644 --- a/ui/app/services/console.js +++ b/ui/app/services/console.js @@ -1,9 +1,7 @@ // Low level service that allows users to input paths to make requests to vault // this service provides the UI synecdote to the cli commands read, write, delete, and list import Ember from 'ember'; -import { - shiftCommandIndex, -} from 'vault/lib/console-helpers'; +import { shiftCommandIndex } from 'vault/lib/console-helpers'; const { Service, getOwner, computed } = Ember; @@ -48,7 +46,7 @@ export default Service.extend({ } }, - clearLog(clearAll=false) { + clearLog(clearAll = false) { let log = this.get('log'); let history; if (!clearAll) { diff --git a/ui/tests/acceptance/access/identity/_shared-alias-tests.js b/ui/tests/acceptance/access/identity/_shared-alias-tests.js index 284c50f7e9..7f4440bc78 100644 --- a/ui/tests/acceptance/access/identity/_shared-alias-tests.js +++ b/ui/tests/acceptance/access/identity/_shared-alias-tests.js @@ -27,21 +27,31 @@ export const testAliasCRUD = (name, itemType, assert) => { 'navigates to the correct route' ); assert.ok( - aliasShowPage.flashMessage.latestMessage.startsWith('Successfully saved', `${itemType}: shows a flash message`) + aliasShowPage.flashMessage.latestMessage.startsWith( + 'Successfully saved', + `${itemType}: shows a flash message` + ) ); assert.ok(aliasShowPage.nameContains(name), `${itemType}: renders the name on the show page`); }); aliasIndexPage.visit({ item_type: itemType }); andThen(() => { - assert.equal(aliasIndexPage.items.filterBy('id', aliasID).length, 1, `${itemType}: lists the entity in the entity list`); + assert.equal( + aliasIndexPage.items.filterBy('id', aliasID).length, + 1, + `${itemType}: lists the entity in the entity list` + ); aliasIndexPage.items.filterBy('id', aliasID)[0].menu(); }); aliasIndexPage.delete().confirmDelete(); andThen(() => { assert.equal(aliasIndexPage.items.filterBy('id', aliasID).length, 0, `${itemType}: the row is deleted`); - aliasIndexPage.flashMessage.latestMessage.startsWith('Successfully deleted', `${itemType}: shows flash message`); + aliasIndexPage.flashMessage.latestMessage.startsWith( + 'Successfully deleted', + `${itemType}: shows flash message` + ); }); }; @@ -66,12 +76,27 @@ export const testAliasDeleteFromForm = (name, itemType, assert) => { aliasShowPage.edit(); andThen(() => { - assert.equal(currentRouteName(), 'vault.cluster.access.identity.aliases.edit', `${itemType}: navigates to edit on create`); + assert.equal( + currentRouteName(), + 'vault.cluster.access.identity.aliases.edit', + `${itemType}: navigates to edit on create` + ); }); page.editForm.delete().confirmDelete(); andThen(() => { - assert.equal(currentRouteName(), 'vault.cluster.access.identity.aliases.index', `${itemType}: navigates to list page on delete`); - assert.equal(aliasIndexPage.items.filterBy('id', aliasID).length, 0, `${itemType}: the row does not show in the list`); - aliasIndexPage.flashMessage.latestMessage.startsWith('Successfully deleted', `${itemType}: shows flash message`); + assert.equal( + currentRouteName(), + 'vault.cluster.access.identity.aliases.index', + `${itemType}: navigates to list page on delete` + ); + assert.equal( + aliasIndexPage.items.filterBy('id', aliasID).length, + 0, + `${itemType}: the row does not show in the list` + ); + aliasIndexPage.flashMessage.latestMessage.startsWith( + 'Successfully deleted', + `${itemType}: shows flash message` + ); }); }; diff --git a/ui/tests/acceptance/access/identity/_shared-tests.js b/ui/tests/acceptance/access/identity/_shared-tests.js index d91409ea5d..b7fe3de59a 100644 --- a/ui/tests/acceptance/access/identity/_shared-tests.js +++ b/ui/tests/acceptance/access/identity/_shared-tests.js @@ -9,43 +9,70 @@ export const testCRUD = (name, itemType, assert) => { andThen(() => { let idRow = showPage.rows.filterBy('hasLabel').filterBy('rowLabel', 'ID')[0]; id = idRow.rowValue; - assert.equal(currentRouteName(), 'vault.cluster.access.identity.show', `${itemType}: navigates to show on create`); + assert.equal( + currentRouteName(), + 'vault.cluster.access.identity.show', + `${itemType}: navigates to show on create` + ); assert.ok( - showPage.flashMessage.latestMessage.startsWith('Successfully saved', `${itemType}: shows a flash message`) + showPage.flashMessage.latestMessage.startsWith( + 'Successfully saved', + `${itemType}: shows a flash message` + ) ); assert.ok(showPage.nameContains(name), `${itemType}: renders the name on the show page`); }); indexPage.visit({ item_type: itemType }); andThen(() => { - assert.equal(indexPage.items.filterBy('id', id).length, 1, `${itemType}: lists the entity in the entity list`); + assert.equal( + indexPage.items.filterBy('id', id).length, + 1, + `${itemType}: lists the entity in the entity list` + ); indexPage.items.filterBy('id', id)[0].menu(); }); indexPage.delete().confirmDelete(); andThen(() => { assert.equal(indexPage.items.filterBy('id', id).length, 0, `${itemType}: the row is deleted`); - indexPage.flashMessage.latestMessage.startsWith('Successfully deleted', `${itemType}: shows flash message`); + indexPage.flashMessage.latestMessage.startsWith( + 'Successfully deleted', + `${itemType}: shows flash message` + ); }); }; - export const testDeleteFromForm = (name, itemType, assert) => { let id; page.visit({ item_type: itemType }); page.editForm.name(name).submit(); andThen(() => { - id = showPage.rows.filterBy('hasLabel').filterBy('rowLabel', 'ID')[0].rowValue + id = showPage.rows.filterBy('hasLabel').filterBy('rowLabel', 'ID')[0].rowValue; }); showPage.edit(); andThen(() => { - assert.equal(currentRouteName(), 'vault.cluster.access.identity.edit', `${itemType}: navigates to edit on create`); + assert.equal( + currentRouteName(), + 'vault.cluster.access.identity.edit', + `${itemType}: navigates to edit on create` + ); }); page.editForm.delete().confirmDelete(); andThen(() => { - assert.equal(currentRouteName(), 'vault.cluster.access.identity.index', `${itemType}: navigates to list page on delete`); - assert.equal(indexPage.items.filterBy('id', id).length, 0, `${itemType}: the row does not show in the list`); - indexPage.flashMessage.latestMessage.startsWith('Successfully deleted', `${itemType}: shows flash message`); + assert.equal( + currentRouteName(), + 'vault.cluster.access.identity.index', + `${itemType}: navigates to list page on delete` + ); + assert.equal( + indexPage.items.filterBy('id', id).length, + 0, + `${itemType}: the row does not show in the list` + ); + indexPage.flashMessage.latestMessage.startsWith( + 'Successfully deleted', + `${itemType}: shows flash message` + ); }); }; - diff --git a/ui/tests/acceptance/access/identity/entities/aliases/create-test.js b/ui/tests/acceptance/access/identity/entities/aliases/create-test.js index 81e9e2b51a..d58abe26ad 100644 --- a/ui/tests/acceptance/access/identity/entities/aliases/create-test.js +++ b/ui/tests/acceptance/access/identity/entities/aliases/create-test.js @@ -8,7 +8,6 @@ moduleForAcceptance('Acceptance | /access/identity/entities/aliases/add', { }, }); - test('it allows create, list, delete of an entity alias', function(assert) { let name = `alias-${Date.now()}`; testAliasCRUD(name, 'entities', assert); @@ -18,4 +17,3 @@ test('it allows delete from the edit form', function(assert) { let name = `alias-${Date.now()}`; testAliasDeleteFromForm(name, 'entities', assert); }); - diff --git a/ui/tests/acceptance/access/identity/entities/create-test.js b/ui/tests/acceptance/access/identity/entities/create-test.js index 12b0642295..fd953e750e 100644 --- a/ui/tests/acceptance/access/identity/entities/create-test.js +++ b/ui/tests/acceptance/access/identity/entities/create-test.js @@ -29,4 +29,3 @@ test('it can be deleted from the edit form', function(assert) { let name = `entity-${Date.now()}`; testDeleteFromForm(name, 'entities', assert); }); - diff --git a/ui/tests/acceptance/access/identity/groups/aliases/create-test.js b/ui/tests/acceptance/access/identity/groups/aliases/create-test.js index d40f94e907..4a09df8be0 100644 --- a/ui/tests/acceptance/access/identity/groups/aliases/create-test.js +++ b/ui/tests/acceptance/access/identity/groups/aliases/create-test.js @@ -8,7 +8,6 @@ moduleForAcceptance('Acceptance | /access/identity/groups/aliases/add', { }, }); - test('it allows create, list, delete of an entity alias', function(assert) { let name = `alias-${Date.now()}`; testAliasCRUD(name, 'groups', assert); @@ -18,4 +17,3 @@ test('it allows delete from the edit form', function(assert) { let name = `alias-${Date.now()}`; testAliasDeleteFromForm(name, 'groups', assert); }); - diff --git a/ui/tests/acceptance/settings/mount-secret-backend-test.js b/ui/tests/acceptance/settings/mount-secret-backend-test.js index 2b761bf7c1..6708f091f2 100644 --- a/ui/tests/acceptance/settings/mount-secret-backend-test.js +++ b/ui/tests/acceptance/settings/mount-secret-backend-test.js @@ -30,7 +30,7 @@ test('it sets the ttl corrects when mounting', function(assert) { .maxTTLUnit('h') .submit(); - configPage.visit({backend: path}); + configPage.visit({ backend: path }); andThen(() => { assert.equal(configPage.defaultTTL, defaultTTLSeconds, 'shows the proper TTL'); assert.equal(configPage.maxTTL, maxTTLSeconds, 'shows the proper max TTL'); diff --git a/ui/tests/acceptance/tools-test.js b/ui/tests/acceptance/tools-test.js index e5d05d2215..36b61c7a76 100644 --- a/ui/tests/acceptance/tools-test.js +++ b/ui/tests/acceptance/tools-test.js @@ -59,14 +59,10 @@ test('tools functionality', function(assert) { }); click('[data-test-tools-submit]'); andThen(() => { - assert.ok( - find('[data-test-tools="token-lookup-row"]:eq(0)').text().match(/Creation time/i), - 'show creation time row' - ); - assert.ok( - find('[data-test-tools="token-lookup-row"]:eq(1)').text().match(/Creation ttl/i), - 'show creation ttl row' - ); + let rows = document.querySelectorAll('[data-test-tools="token-lookup-row"]'); + assert.dom(rows[0]).hasText(/Creation path/, 'show creation path row'); + assert.dom(rows[1]).hasText(/Creation time/, 'show creation time row'); + assert.dom(rows[2]).hasText(/Creation TTL/, 'show creation ttl row'); }); //rewrap diff --git a/ui/tests/integration/components/identity/item-details-test.js b/ui/tests/integration/components/identity/item-details-test.js index 4cced3a440..3e54efbdf0 100644 --- a/ui/tests/integration/components/identity/item-details-test.js +++ b/ui/tests/integration/components/identity/item-details-test.js @@ -16,7 +16,7 @@ moduleForComponent('identity/item-details', 'Integration | Component | identity/ }, afterEach() { component.removeContext(); - } + }, }); test('it renders the disabled warning', function(assert) { @@ -25,7 +25,7 @@ test('it renders the disabled warning', function(assert) { return Ember.RSVP.resolve(); }, disabled: true, - canEdit: true + canEdit: true, }); sinon.spy(model, 'save'); this.set('model', model); @@ -38,7 +38,7 @@ test('it renders the disabled warning', function(assert) { test('it does not render the button if canEdit is false', function(assert) { let model = Ember.Object.create({ - disabled: true + disabled: true, }); this.set('model', model); diff --git a/ui/tests/integration/components/transit-key-actions-test.js b/ui/tests/integration/components/transit-key-actions-test.js index 82bbb24f0b..a6e29f1d47 100644 --- a/ui/tests/integration/components/transit-key-actions-test.js +++ b/ui/tests/integration/components/transit-key-actions-test.js @@ -279,7 +279,7 @@ test('it includes algorithm param for HMAC', function(assert) { backend: 'transit', id: 'akey', payload: { - algorithm: "sha2-384" + algorithm: 'sha2-384', }, }, 'passes expected args to the adapter' diff --git a/ui/tests/pages/access/identity/aliases/show.js b/ui/tests/pages/access/identity/aliases/show.js index 5ca908ad8d..d12dc6c33a 100644 --- a/ui/tests/pages/access/identity/aliases/show.js +++ b/ui/tests/pages/access/identity/aliases/show.js @@ -7,5 +7,5 @@ export default create({ flashMessage, nameContains: contains('[data-test-alias-name]'), rows: collection('[data-test-component="info-table-row"]', infoTableRow), - edit: clickable('[data-test-alias-edit-link]') + edit: clickable('[data-test-alias-edit-link]'), }); diff --git a/ui/tests/pages/access/identity/create.js b/ui/tests/pages/access/identity/create.js index 8fbaac076a..2fa8092a86 100644 --- a/ui/tests/pages/access/identity/create.js +++ b/ui/tests/pages/access/identity/create.js @@ -6,8 +6,8 @@ export default create({ editForm, createItem(item_type, type) { if (type) { - return this.visit({item_type}).editForm.type(type).submit(); + return this.visit({ item_type }).editForm.type(type).submit(); } - return this.visit({item_type}).editForm.submit(); - } + return this.visit({ item_type }).editForm.submit(); + }, }); diff --git a/ui/tests/pages/access/identity/show.js b/ui/tests/pages/access/identity/show.js index ffaf79da08..12971978a5 100644 --- a/ui/tests/pages/access/identity/show.js +++ b/ui/tests/pages/access/identity/show.js @@ -7,5 +7,5 @@ export default create({ flashMessage, nameContains: contains('[data-test-identity-item-name]'), rows: collection('[data-test-component="info-table-row"]', infoTableRow), - edit: clickable('[data-test-entity-edit-link]') + edit: clickable('[data-test-entity-edit-link]'), }); diff --git a/ui/tests/unit/components/identity/edit-form-test.js b/ui/tests/unit/components/identity/edit-form-test.js index 82aae87cdb..3006c1b9cf 100644 --- a/ui/tests/unit/components/identity/edit-form-test.js +++ b/ui/tests/unit/components/identity/edit-form-test.js @@ -64,10 +64,6 @@ testCases.forEach(function(testCase) { component.set('mode', testCase.mode); component.set('model', model); - assert.equal( - component.get('cancelLink'), - testCase.expected, - 'cancel link is correct' - ); + assert.equal(component.get('cancelLink'), testCase.expected, 'cancel link is correct'); }); }); diff --git a/ui/tests/unit/services/store-test.js b/ui/tests/unit/services/store-test.js index 4476176c3d..2b5b620262 100644 --- a/ui/tests/unit/services/store-test.js +++ b/ui/tests/unit/services/store-test.js @@ -129,14 +129,16 @@ test('store.fetchPage', function(assert) { ); Ember.run(() => { - store.fetchPage('transit-key', { - size: pageSize, - page: 3, - responsePath: 'data.keys', - }).then(r => { - result = r; - done() - }); + store + .fetchPage('transit-key', { + size: pageSize, + page: 3, + responsePath: 'data.keys', + }) + .then(r => { + result = r; + done(); + }); }); const pageThreeEnd = 3 * pageSize; @@ -148,15 +150,16 @@ test('store.fetchPage', function(assert) { ); Ember.run(() => { - store.fetchPage('transit-key', { - size: pageSize, - page: 99, - responsePath: 'data.keys', - }).then(r => { - - result = r; - done(); - }); + store + .fetchPage('transit-key', { + size: pageSize, + page: 99, + responsePath: 'data.keys', + }) + .then(r => { + result = r; + done(); + }); }); assert.deepEqual( @@ -166,14 +169,16 @@ test('store.fetchPage', function(assert) { ); Ember.run(() => { - store.fetchPage('transit-key', { - size: pageSize, - page: 0, - responsePath: 'data.keys', - }).then(r => { - result = r; - done(); - }); + store + .fetchPage('transit-key', { + size: pageSize, + page: 0, + responsePath: 'data.keys', + }) + .then(r => { + result = r; + done(); + }); }); assert.deepEqual( result.mapBy('id'),