diff --git a/.eslintignore b/.eslintignore index 0de6d839dc2ba..91d7e7b48c508 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,4 @@ test/fixtures/scenarios -optimize +/optimize test/fixtures/scenarios diff --git a/.eslintrc b/.eslintrc index 7a623df06a6ca..1904222b3cfa9 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,2 +1,8 @@ --- extends: '@elastic/kibana' +rules: + no-unused-vars: off + no-var: off + prefer-const: off + no-extra-semi: off + quotes: off diff --git a/config/kibana.yml b/config/kibana.yml index 7358fd5b06a36..6535dcbee6a6a 100644 --- a/config/kibana.yml +++ b/config/kibana.yml @@ -1,8 +1,10 @@ # Kibana is served by a back end server. This setting specifies the port to use. # server.port: 5601 -# This setting specifies the IP address of the back end server. -# server.host: "0.0.0.0" +# Specifies the address to which the Kibana server will bind. IP addresses and host names are both valid values. +# The default is 'localhost', which usually means remote machines will not be able to connect. +# To allow connections from remote users, set this parameter to a non-loopback address. +# server.host: "localhost" # Enables you to specify a path to mount Kibana at if you are running behind a proxy. This setting # cannot end in a slash. diff --git a/docs/kibana-yml.asciidoc b/docs/kibana-yml.asciidoc index 0a4e2a20d5a9a..2a5e7fc86dde2 100644 --- a/docs/kibana-yml.asciidoc +++ b/docs/kibana-yml.asciidoc @@ -1,7 +1,7 @@ .Kibana Configuration Settings [horizontal] `server.port:`:: *Default: 5601* Kibana is served by a back end server. This setting specifies the port to use. -`server.host:`:: *Default: "0.0.0.0"* This setting specifies the IP address of the back end server. +`server.host:`:: *Default: "localhost"* This setting specifies the host of the back end server. `server.basePath:`:: Enables you to specify a path to mount Kibana at if you are running behind a proxy. This setting cannot end in a slash (`/`). `server.maxPayloadBytes:`:: *Default: 1048576* The maximum payload size in bytes for incoming server requests. diff --git a/docs/settings.asciidoc b/docs/settings.asciidoc index 51ae6716105b0..8b9ee99997458 100644 --- a/docs/settings.asciidoc +++ b/docs/settings.asciidoc @@ -295,7 +295,7 @@ deprecated[4.2, The names of several Kibana server properties changed in the 4.2 + *alias*: `host` deprecated[4.2] + -*default*: `"0.0.0.0"` +*default*: `"localhost"` `elasticsearch.url` added[4.2]:: The Elasticsearch instance where the indices you want to query reside. + diff --git a/package.json b/package.json index 683d4fed98ec9..2449a1f49b8a7 100644 --- a/package.json +++ b/package.json @@ -154,16 +154,16 @@ "wreck": "6.2.0" }, "devDependencies": { - "@elastic/eslint-config-kibana": "0.0.3", + "@elastic/eslint-config-kibana": "0.2.0", "Nonsense": "0.1.2", "angular-mocks": "1.4.7", "auto-release-sinon": "1.0.3", - "babel-eslint": "4.1.8", + "babel-eslint": "6.1.2", "chokidar": "1.6.0", "chromedriver": "2.22.1", "elasticdump": "2.1.1", - "eslint": "1.10.3", - "eslint-plugin-mocha": "1.1.0", + "eslint": "3.3.1", + "eslint-plugin-mocha": "4.4.0", "event-stream": "3.3.2", "expect.js": "0.3.1", "faker": "1.1.0", @@ -177,7 +177,7 @@ "grunt-karma": "2.0.0", "grunt-run": "0.6.0", "grunt-simple-mocha": "0.4.0", - "gruntify-eslint": "1.0.1", + "gruntify-eslint": "3.0.0", "handlebars": "4.0.5", "husky": "0.8.1", "image-diff": "1.6.0", diff --git a/src/cli/cluster/__tests__/_mock_cluster_fork.js b/src/cli/cluster/__tests__/_mock_cluster_fork.js index 2671ca08bdb9a..0915d172a4cd6 100644 --- a/src/cli/cluster/__tests__/_mock_cluster_fork.js +++ b/src/cli/cluster/__tests__/_mock_cluster_fork.js @@ -24,7 +24,7 @@ export default class MockClusterFork extends EventEmitter { dead = true; this.emit('exit'); cluster.emit('exit', this, this.exitCode || 0); - }()); + })(); }), }, isDead: sinon.spy(() => dead), @@ -39,6 +39,6 @@ export default class MockClusterFork extends EventEmitter { await wait(); dead = false; this.emit('online'); - }()); + })(); } } diff --git a/src/cli/cluster/cluster_manager.js b/src/cli/cluster/cluster_manager.js index 685c64db1246f..2e98b3bcbcfe7 100644 --- a/src/cli/cluster/cluster_manager.js +++ b/src/cli/cluster/cluster_manager.js @@ -85,19 +85,16 @@ module.exports = class ClusterManager { const chokidar = require('chokidar'); const fromRoot = require('../../utils/from_root'); - const watchPaths = uniq( - [ - fromRoot('src/core_plugins'), - fromRoot('src/server'), - fromRoot('src/ui'), - fromRoot('src/utils'), - fromRoot('config'), - ...extraPaths - ] - .map(path => resolve(path)) - ); - - this.watcher = chokidar.watch(watchPaths, { + const watchPaths = [ + fromRoot('src/core_plugins'), + fromRoot('src/server'), + fromRoot('src/ui'), + fromRoot('src/utils'), + fromRoot('config'), + ...extraPaths + ].map(path => resolve(path)); + + this.watcher = chokidar.watch(uniq(watchPaths), { cwd: fromRoot('.'), ignored: /[\\\/](\..*|node_modules|bower_components|public|__tests__)[\\\/]/ }); diff --git a/src/core_plugins/console/.eslintrc b/src/core_plugins/console/.eslintrc index c5fcfc4ff6fda..f539f6cd5878f 100644 --- a/src/core_plugins/console/.eslintrc +++ b/src/core_plugins/console/.eslintrc @@ -1,34 +1,36 @@ --- root: true -extends: '@elastic/kibana' +extends: '../../../.eslintrc' rules: - block-scoped-var: [0] - camelcase: [0] - curly: [0] - dot-location: [0] - dot-notation: [0] - eqeqeq: [0] - guard-for-in: [0] - indent: [0] - max-len: [0] - new-cap: [0] - no-caller: [0] - no-empty: [0] - no-extend-native: [0] - no-loop-func: [0] - no-multi-str: [0] - no-nested-ternary: [0] - no-proto: [0] - no-sequences: [0] - no-undef: [0] - no-use-before-define: [0] - one-var: [0] - quotes: [0] - space-before-blocks: [0] - space-in-parens: [0] - space-infix-ops: [0] - semi: [0] - strict: [0] - wrap-iife: [0] + block-scoped-var: off + camelcase: off + curly: off + dot-location: off + dot-notation: off + eqeqeq: off + guard-for-in: off + indent: off + max-len: off + new-cap: off + no-caller: off + no-empty: off + no-extend-native: off + no-loop-func: off + no-multi-str: off + no-nested-ternary: off + no-proto: off + no-sequences: off + no-undef: off + no-use-before-define: off + one-var: off + quotes: off + space-before-blocks: off + space-in-parens: off + space-infix-ops: off + semi: off + strict: off + wrap-iife: off + no-var: off + prefer-const: off diff --git a/src/server/config/__tests__/config.js b/src/server/config/__tests__/config.js index cf43ce256f585..0dc60f98f6004 100644 --- a/src/server/config/__tests__/config.js +++ b/src/server/config/__tests__/config.js @@ -54,7 +54,7 @@ describe('lib/config/config', function () { it('should allow keys in the schema', function () { let config = new Config(schema); let run = function () { - config.set('test.client.host', 'http://0.0.0.0'); + config.set('test.client.host', 'http://localhost'); }; expect(run).to.not.throwException(); }); diff --git a/src/server/config/schema.js b/src/server/config/schema.js index cf6790b82ea46..074ccec05b579 100644 --- a/src/server/config/schema.js +++ b/src/server/config/schema.js @@ -34,7 +34,7 @@ module.exports = () => Joi.object({ server: Joi.object({ name: Joi.string().default(os.hostname()), - host: Joi.string().hostname().default('0.0.0.0'), + host: Joi.string().hostname().default('localhost'), port: Joi.number().default(5601), maxPayloadBytes: Joi.number().default(1048576), autoListen: Joi.boolean().default(true), diff --git a/src/ui/public/kbn_top_nav/__tests__/kbn_top_nav_controller.js b/src/ui/public/kbn_top_nav/__tests__/kbn_top_nav_controller.js index f72f13f2cf083..36614f1e9b7e9 100644 --- a/src/ui/public/kbn_top_nav/__tests__/kbn_top_nav_controller.js +++ b/src/ui/public/kbn_top_nav/__tests__/kbn_top_nav_controller.js @@ -64,16 +64,19 @@ describe('KbnTopNavController', function () { }); describe('hideButton:', function () { - it('defaults to false', function () { + it('defaults to a function that returns false', function () { const controller = new KbnTopNavController([ { key: 'foo' }, { key: '1234' }, ]); - expect(pluck(controller.opts, 'hideButton')).to.eql([false, false]); + pluck(controller.opts, 'hideButton').forEach(prop => { + expect(prop).to.be.a(Function); + expect(prop()).to.eql(false); + }); }); - it('excludes opts from opts when true', function () { + it('excludes opts from opts when set to true', function () { const controller = new KbnTopNavController([ { key: 'foo' }, { key: '1234', hideButton: true }, @@ -81,27 +84,42 @@ describe('KbnTopNavController', function () { expect(controller.menuItems).to.have.length(1); }); + + it('excludes opts from opts when set to a function that returns true', function () { + const controller = new KbnTopNavController([ + { key: 'foo' }, + { key: '1234', hideButton: () => true }, + ]); + + expect(controller.menuItems).to.have.length(1); + }); }); describe('disableButton:', function () { - it('defaults to false', function () { + it('defaults to a function that returns false', function () { const controller = new KbnTopNavController([ { key: 'foo' }, { key: '1234' }, ]); - expect(pluck(controller.opts, 'disableButton')).to.eql([false, false]); + pluck(controller.opts, 'disableButton').forEach(prop => { + expect(prop).to.be.a(Function); + expect(prop()).to.eql(false); + }); }); }); describe('tooltip:', function () { - it('defaults to empty string', function () { + it('defaults to a function that returns undefined', function () { const controller = new KbnTopNavController([ { key: 'foo' }, { key: '1234' }, ]); - expect(pluck(controller.opts, 'tooltip')).to.eql(['', '']); + pluck(controller.opts, 'tooltip').forEach(prop => { + expect(prop).to.be.a(Function); + expect(prop()).to.eql(undefined); + }); }); }); diff --git a/src/ui/public/kbn_top_nav/kbn_top_nav.html b/src/ui/public/kbn_top_nav/kbn_top_nav.html index 0414340e2c2ac..5a26efde52b3f 100644 --- a/src/ui/public/kbn_top_nav/kbn_top_nav.html +++ b/src/ui/public/kbn_top_nav/kbn_top_nav.html @@ -6,10 +6,10 @@ aria-label="{{::menuItem.description}}" aria-haspopup="{{!menuItem.hasFunction}}" aria-expanded="{{kbnTopNav.isCurrent(menuItem.key)}}" - ng-class="{active: kbnTopNav.isCurrent(menuItem.key), 'is-kbn-top-nav-button-disabled': menuItem.disableButton}" - ng-click="menuItem.run(menuItem, kbnTopNav)" + ng-class="{active: kbnTopNav.isCurrent(menuItem.key), 'is-kbn-top-nav-button-disabled': menuItem.disableButton()}" + ng-click="kbnTopNav.handleClick(menuItem)" ng-bind="menuItem.label" - tooltip="{{menuItem.tooltip}}" + tooltip="{{menuItem.tooltip()}}" tooltip-placement="bottom" tooltip-popup-delay="400" tooltip-append-to-body="1" diff --git a/src/ui/public/kbn_top_nav/kbn_top_nav_controller.js b/src/ui/public/kbn_top_nav/kbn_top_nav_controller.js index 9446639eaaea0..43eeaf13f4f5a 100644 --- a/src/ui/public/kbn_top_nav/kbn_top_nav_controller.js +++ b/src/ui/public/kbn_top_nav/kbn_top_nav_controller.js @@ -1,4 +1,4 @@ -import { capitalize, isArray, isFunction, result } from 'lodash'; +import { capitalize, isArray, isFunction } from 'lodash'; import uiModules from 'ui/modules'; import filterTemplate from 'ui/chrome/config/filter.html'; @@ -29,7 +29,7 @@ export default function ($compile) { const opt = this._applyOptDefault(rawOpt); if (!opt.key) throw new TypeError('KbnTopNav: menu items must have a key'); this.opts.push(opt); - if (!opt.hideButton) this.menuItems.push(opt); + if (!opt.hideButton()) this.menuItems.push(opt); if (opt.template) this.templates[opt.key] = opt.template; }); } @@ -50,19 +50,24 @@ export default function ($compile) { open(key) { this.setCurrent(key); } close(key) { (!key || this.isCurrent(key)) && this.setCurrent(null); } toggle(key) { this.setCurrent(this.isCurrent(key) ? null : key); } - + handleClick(menuItem) { + if (menuItem.disableButton()) { + return false; + } + menuItem.run(menuItem, this); + } // apply the defaults to individual options _applyOptDefault(opt = {}) { const defaultedOpt = Object.assign({ label: capitalize(opt.key), hasFunction: !!opt.run, description: opt.run ? opt.key : `Toggle ${opt.key} view`, - run: (item) => !item.disableButton && this.toggle(item.key) + run: (item) => this.toggle(item.key) }, opt); - defaultedOpt.hideButton = result(opt, 'hideButton', false); - defaultedOpt.disableButton = result(opt, 'disableButton', false); - defaultedOpt.tooltip = result(opt, 'tooltip', ''); + defaultedOpt.hideButton = isFunction(opt.hideButton) ? opt.hideButton : () => !!opt.hideButton; + defaultedOpt.disableButton = isFunction(opt.disableButton) ? opt.disableButton : () => !!opt.disableButton; + defaultedOpt.tooltip = isFunction(opt.tooltip) ? opt.tooltip : () => opt.tooltip; return defaultedOpt; } diff --git a/src/ui/public/share/directives/share_object_url.js b/src/ui/public/share/directives/share_object_url.js index d20a1c4c00305..f49c8dbcdf645 100644 --- a/src/ui/public/share/directives/share_object_url.js +++ b/src/ui/public/share/directives/share_object_url.js @@ -1,10 +1,10 @@ -const app = uiModules.get('kibana'); import Clipboard from 'clipboard'; import '../styles/index.less'; import LibUrlShortenerProvider from '../lib/url_shortener'; import uiModules from 'ui/modules'; import shareObjectUrlTemplate from 'ui/share/views/share_object_url.html'; +const app = uiModules.get('kibana'); app.directive('shareObjectUrl', function (Private, Notifier) { const urlShortener = Private(LibUrlShortenerProvider); diff --git a/src/ui/ui_bundle_collection.js b/src/ui/ui_bundle_collection.js index 3e652a176974c..a6b87779486b8 100644 --- a/src/ui/ui_bundle_collection.js +++ b/src/ui/ui_bundle_collection.js @@ -1,8 +1,3 @@ -const rimraf = promisify(require('rimraf')); -const mkdirp = promisify(require('mkdirp')); -const unlink = promisify(require('fs').unlink); -const readdir = promisify(require('fs').readdir); - import UiBundle from './ui_bundle'; import appEntryTemplate from './app_entry_template'; import { readFileSync as readSync } from 'fs'; @@ -11,6 +6,11 @@ import { join } from 'path'; import { resolve, promisify } from 'bluebird'; import { makeRe } from 'minimatch'; +const rimraf = promisify(require('rimraf')); +const mkdirp = promisify(require('mkdirp')); +const unlink = promisify(require('fs').unlink); +const readdir = promisify(require('fs').readdir); + class UiBundleCollection { constructor(bundlerEnv, filter) { this.each = [];