From 67e05dbcc0158d13f384431ce75bcd0de94faaee Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Fri, 11 May 2018 15:26:30 -0400
Subject: [PATCH 01/38] round 1
---
.../plugins/security/public/objects/index.js | 11 +
.../security/public/objects/lib/get_fields.js | 14 +
.../security/public/objects/lib/get_roles.js | 19 +
.../security/public/objects/lib/get_users.js | 14 +
.../plugins/security/public/objects/role.js | 13 +
.../public/services/role_privileges.js | 42 ++
.../public/views/management/edit_role.html | 186 +--------
.../public/views/management/edit_role.js | 136 ++-----
.../components/cluster_privileges.js | 58 +++
.../edit_role/components/edit_role_page.js | 360 ++++++++++++++++++
.../components/index_privilege_form.js | 192 ++++++++++
.../edit_role/components/page_header.js | 43 +++
.../edit_role/lib/is_reserved_role.js | 9 +
13 files changed, 818 insertions(+), 279 deletions(-)
create mode 100644 x-pack/plugins/security/public/objects/index.js
create mode 100644 x-pack/plugins/security/public/objects/lib/get_fields.js
create mode 100644 x-pack/plugins/security/public/objects/lib/get_roles.js
create mode 100644 x-pack/plugins/security/public/objects/lib/get_users.js
create mode 100644 x-pack/plugins/security/public/objects/role.js
create mode 100644 x-pack/plugins/security/public/services/role_privileges.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/cluster_privileges.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/index_privilege_form.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/page_header.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/lib/is_reserved_role.js
diff --git a/x-pack/plugins/security/public/objects/index.js b/x-pack/plugins/security/public/objects/index.js
new file mode 100644
index 0000000000000..ce1c8f6aac3df
--- /dev/null
+++ b/x-pack/plugins/security/public/objects/index.js
@@ -0,0 +1,11 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { getRole } from './lib/get_roles';
+
+export { getUsers } from './lib/get_users';
+
+export { getFields } from './lib/get_fields';
diff --git a/x-pack/plugins/security/public/objects/lib/get_fields.js b/x-pack/plugins/security/public/objects/lib/get_fields.js
new file mode 100644
index 0000000000000..a80f6bfe8eed1
--- /dev/null
+++ b/x-pack/plugins/security/public/objects/lib/get_fields.js
@@ -0,0 +1,14 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import chrome from 'ui/chrome';
+
+const apiBase = chrome.addBasePath(`/api/security/v1/fields`);
+
+export async function getFields($http, query) {
+ return await $http
+ .get(`${apiBase}/${query}`)
+ .then(response => response.data || []);
+}
diff --git a/x-pack/plugins/security/public/objects/lib/get_roles.js b/x-pack/plugins/security/public/objects/lib/get_roles.js
new file mode 100644
index 0000000000000..784ba57570605
--- /dev/null
+++ b/x-pack/plugins/security/public/objects/lib/get_roles.js
@@ -0,0 +1,19 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import chrome from 'ui/chrome';
+
+const apiBase = chrome.addBasePath(`/api/security/v1/roles`);
+
+export async function getRole($http, name) {
+ try {
+ return await $http.get(`${apiBase}/${name}`);
+ } catch (response) {
+ if (response.status === 404) {
+ return null;
+ }
+ throw response;
+ }
+}
diff --git a/x-pack/plugins/security/public/objects/lib/get_users.js b/x-pack/plugins/security/public/objects/lib/get_users.js
new file mode 100644
index 0000000000000..fd82b62d0f928
--- /dev/null
+++ b/x-pack/plugins/security/public/objects/lib/get_users.js
@@ -0,0 +1,14 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import chrome from 'ui/chrome';
+
+const apiBase = chrome.addBasePath(`/api/security/v1/users`);
+
+export async function getUsers($http) {
+ return await $http
+ .get(apiBase)
+ .then(response => response.data || []);
+}
diff --git a/x-pack/plugins/security/public/objects/role.js b/x-pack/plugins/security/public/objects/role.js
new file mode 100644
index 0000000000000..98448db207cea
--- /dev/null
+++ b/x-pack/plugins/security/public/objects/role.js
@@ -0,0 +1,13 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export class Role {
+ name = null;
+ cluster = [];
+ indices = [];
+ run_as = []; //eslint-disable-line camelcase
+ applications = [];
+}
diff --git a/x-pack/plugins/security/public/services/role_privileges.js b/x-pack/plugins/security/public/services/role_privileges.js
new file mode 100644
index 0000000000000..794a4b30674e5
--- /dev/null
+++ b/x-pack/plugins/security/public/services/role_privileges.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+const clusterPrivileges = [
+ 'all',
+ 'monitor',
+ 'manage',
+ 'manage_security',
+ 'manage_index_templates',
+ 'manage_pipeline',
+ 'manage_ingest_pipelines',
+ 'transport_client',
+ 'manage_ml',
+ 'monitor_ml',
+ 'manage_watcher',
+ 'monitor_watcher',
+];
+const indexPrivileges = [
+ 'all',
+ 'manage',
+ 'monitor',
+ 'read',
+ 'index',
+ 'create',
+ 'delete',
+ 'write',
+ 'delete_index',
+ 'create_index',
+ 'view_index_metadata',
+ 'read_cross_cluster',
+];
+
+export function getClusterPrivileges() {
+ return [...clusterPrivileges];
+}
+
+export function getIndexPrivileges() {
+ return [...indexPrivileges];
+}
diff --git a/x-pack/plugins/security/public/views/management/edit_role.html b/x-pack/plugins/security/public/views/management/edit_role.html
index 768f50a210758..5539f0521dd79 100644
--- a/x-pack/plugins/security/public/views/management/edit_role.html
+++ b/x-pack/plugins/security/public/views/management/edit_role.html
@@ -1,185 +1 @@
-
-
-
-
-
-
-
-
-
- New Role
-
-
- “{{ role.name }}” Role
-
-
-
-
-
-
-
-
-
- Delete role
-
-
-
-
- Reserved
-
-
-
-
-
-
-
-
+
diff --git a/x-pack/plugins/security/public/views/management/edit_role.js b/x-pack/plugins/security/public/views/management/edit_role.js
index 349807d1836c8..33cc6c42a4f40 100644
--- a/x-pack/plugins/security/public/views/management/edit_role.js
+++ b/x-pack/plugins/security/public/views/management/edit_role.js
@@ -6,9 +6,7 @@
import _ from 'lodash';
import routes from 'ui/routes';
-import { fatalError, toastNotifications } from 'ui/notify';
-import { toggle } from 'plugins/security/lib/util';
-import { isRoleEnabled } from 'plugins/security/lib/role';
+import { fatalError } from 'ui/notify';
import template from 'plugins/security/views/management/edit_role.html';
import 'angular-ui-select';
import 'plugins/security/services/application_privilege';
@@ -21,6 +19,10 @@ import { IndexPatternsProvider } from 'ui/index_patterns/index_patterns';
import { XPackInfoProvider } from 'plugins/xpack_main/services/xpack_info';
import { checkLicenseError } from 'plugins/security/lib/check_license_error';
import { EDIT_ROLES_PATH, ROLES_PATH } from './management_urls';
+import { EditRolePage } from './edit_role/components/edit_role_page';
+
+import React from 'react';
+import { render, unmountComponentAtNode } from 'react-dom';
routes.when(`${EDIT_ROLES_PATH}/:name?`, {
template,
@@ -64,104 +66,50 @@ routes.when(`${EDIT_ROLES_PATH}/:name?`, {
}
},
controllerAs: 'editRole',
- controller($injector, $scope, rbacEnabled) {
+ controller($injector, $scope, $http, rbacEnabled) {
const $route = $injector.get('$route');
- const kbnUrl = $injector.get('kbnUrl');
- const shieldPrivileges = $injector.get('shieldPrivileges');
- const Notifier = $injector.get('Notifier');
const Private = $injector.get('Private');
- const confirmModal = $injector.get('confirmModal');
- const shieldIndices = $injector.get('shieldIndices');
-
- $scope.role = $route.current.locals.role;
- $scope.users = $route.current.locals.users;
- $scope.indexPatterns = $route.current.locals.indexPatterns;
- $scope.privileges = shieldPrivileges;
- $scope.kibanaPrivileges = $route.current.locals.kibanaPrivileges;
- $scope.rbacEnabled = rbacEnabled;
- $scope.rolesHref = `#${ROLES_PATH}`;
-
- this.isNewRole = $route.current.params.name == null;
- this.fieldOptions = {};
-
- const notifier = new Notifier();
-
- $scope.deleteRole = (role) => {
- const doDelete = () => {
- role.$delete()
- .then(() => toastNotifications.addSuccess('Deleted role'))
- .then($scope.goToRoleList)
- .catch(error => notifier.error(_.get(error, 'data.message')));
- };
- const confirmModalOptions = {
- confirmButtonText: 'Delete role',
- onConfirm: doDelete
- };
- confirmModal('Are you sure you want to delete this role? This action is irreversible!', confirmModalOptions);
- };
-
- $scope.saveRole = (role) => {
- role.indices = role.indices.filter((index) => index.names.length);
- role.indices.forEach((index) => index.query || delete index.query);
- return role.$save()
- .then(() => toastNotifications.addSuccess('Updated role'))
- .then($scope.goToRoleList)
- .catch(error => notifier.error(_.get(error, 'data.message')));
- };
-
- $scope.goToRoleList = () => {
- kbnUrl.redirect(ROLES_PATH);
- };
-
- $scope.addIndex = indices => {
- indices.push({ names: [], privileges: [], field_security: { grant: ['*'] } });
- };
-
- $scope.areIndicesValid = (indices) => {
- return indices
- .filter((index) => index.names.length)
- .find((index) => index.privileges.length === 0) == null;
- };
-
- $scope.fetchFieldOptions = (index) => {
- const indices = index.names.join(',');
- const fieldOptions = this.fieldOptions;
- if (indices && fieldOptions[indices] == null) {
- shieldIndices.getFields(indices)
- .then((fields) => fieldOptions[indices] = fields)
- .catch(() => fieldOptions[indices] = []);
- }
- };
-
- $scope.isRoleEnabled = isRoleEnabled;
const xpackInfo = Private(XPackInfoProvider);
- $scope.allowDocumentLevelSecurity = xpackInfo.get('features.security.allowRoleDocumentLevelSecurity');
- $scope.allowFieldLevelSecurity = xpackInfo.get('features.security.allowRoleFieldLevelSecurity');
+ const allowDocumentLevelSecurity = xpackInfo.get('features.security.allowRoleDocumentLevelSecurity');
+ const allowFieldLevelSecurity = xpackInfo.get('features.security.allowRoleFieldLevelSecurity');
- $scope.$watch('role.indices', (indices) => {
- if (!indices.length) $scope.addIndex(indices);
- else indices.forEach($scope.fetchFieldOptions);
- }, true);
+ const domNode = document.getElementById('editRoleReactRoot');
- $scope.toggle = toggle;
- $scope.includes = _.includes;
- $scope.togglePermission = (role, permission) => {
- const shouldRemove = $scope.hasPermission(role, permission);
- const rolePermissions = role.applications || [];
- if (shouldRemove) {
- role.applications = rolePermissions.filter(rolePermission => rolePermission.name === permission.name);
- } else {
- role.applications = rolePermissions.concat([permission]);
- }
- };
+ const {
+ role,
+ users,
+ indexPatterns,
+ } = $route.current.locals;
- $scope.hasPermission = (role, permission) => {
- // TODO(legrego): faking until ES is implemented
- const rolePermissions = role.applications || [];
- return rolePermissions.find(rolePermission => permission.name === rolePermission.name);
- };
+ this.fieldOptions = {};
+
+ const roleToEdit = role.toJSON();
+ if (roleToEdit.indices.length === 0) {
+ roleToEdit.indices.push({
+ names: [],
+ privileges: [],
+ field_security: {
+ grant: ['*']
+ }
+ });
+ }
- $scope.union = _.flow(_.union, _.compact);
+ render( , domNode);
+
+ // unmount react on controller destroy
+ $scope.$on('$destroy', () => {
+ unmountComponentAtNode(domNode);
+ });
}
});
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/cluster_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/cluster_privileges.js
new file mode 100644
index 0000000000000..8486dc3bf70e1
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/cluster_privileges.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { getClusterPrivileges } from '../../../../services/role_privileges';
+import { isReservedRole } from '../lib/is_reserved_role';
+import {
+ EuiCheckboxGroup
+} from '@elastic/eui';
+
+export class ClusterPrivileges extends Component {
+ static propTypes = {
+ role: PropTypes.object.isRequired,
+ onChange: PropTypes.func.isRequired
+ };
+
+ render() {
+ const checkboxes = getClusterPrivileges().map(p => ({
+ id: p,
+ label: p
+ }));
+
+ const { role } = this.props;
+
+ const selectionMap = (role.cluster || [])
+ .map(k => ({ [k]: true }))
+ .reduce((acc, o) => ({ ...acc, ...o }), {});
+
+ return (
+
+ );
+ }
+
+ onClusterPrivilegesChange = (privilege) => {
+ const { cluster } = this.props.role;
+ const indexOfExistingPrivilege = cluster.indexOf(privilege);
+
+ const shouldRemove = indexOfExistingPrivilege >= 0;
+
+ const newClusterPrivs = [...cluster];
+ if (shouldRemove) {
+ newClusterPrivs.splice(indexOfExistingPrivilege, 1);
+ } else {
+ newClusterPrivs.push(privilege);
+ }
+
+ this.props.onChange(newClusterPrivs);
+ }
+}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
new file mode 100644
index 0000000000000..31c4794bcccbd
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
@@ -0,0 +1,360 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React, { Component, Fragment } from 'react';
+import PropTypes from 'prop-types';
+import { difference } from 'lodash';
+import {
+ EuiText,
+ EuiSpacer,
+ EuiIcon,
+ EuiAccordion,
+ EuiComboBox,
+ EuiPage,
+ EuiPageContent,
+ EuiPanel,
+ EuiForm,
+ EuiFormRow,
+ EuiFieldText,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiButton,
+ EuiBadge,
+} from '@elastic/eui';
+import { PageHeader } from './page_header';
+import { IndexPrivilegeForm } from './index_privilege_form';
+import { ClusterPrivileges } from './cluster_privileges';
+import { getFields } from '../../../../objects';
+import { isReservedRole } from '../lib/is_reserved_role';
+
+export class EditRolePage extends Component {
+ static propTypes = {
+ role: PropTypes.object.isRequired,
+ runAsUsers: PropTypes.array.isRequired,
+ indexPatterns: PropTypes.array.isRequired,
+ httpClient: PropTypes.func.isRequired,
+ rbacEnabled: PropTypes.bool.isRequired,
+ spacesEnabled: PropTypes.bool.isRequired,
+ allowDocumentLevelSecurity: PropTypes.bool.isRequired,
+ allowFieldLevelSecurity: PropTypes.bool.isRequired
+ };
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ role: props.role,
+ availableFields: {}
+ };
+ }
+
+ componentDidMount() {
+ this.loadAvailableFields(this.state.role.indices);
+ }
+
+ loadAvailableFields(indices) {
+ const patterns = indices.map(index => index.names.join(','));
+
+ const cachedPatterns = Object.keys(this.state.availableFields);
+ const patternsToFetch = difference(patterns, cachedPatterns);
+
+ const fetchRequests = patternsToFetch.map(this.loadFieldsForPattern);
+
+ Promise.all(fetchRequests)
+ .then(response => {
+
+ this.setState({
+ availableFields: {
+ ...this.state.availableFields,
+ ...response.reduce((acc, o) => ({ ...acc, ...o }), {})
+ }
+ });
+ });
+ }
+
+ loadFieldsForPattern = async (pattern) => {
+ if (!pattern) return { [pattern]: [] };
+
+ try {
+ return {
+ [pattern]: await getFields(this.props.httpClient, pattern)
+ };
+
+ } catch (e) {
+ return {
+ [pattern]: []
+ };
+ }
+ }
+
+ render() {
+ return (
+
+
+
+
+
+
+ {this.getTitle()}
+
+ {this.getActionButton()}
+
+
+
+
+
+
+
+
+
+ {isReservedRole(this.props.role)
+ && Reserved Role }
+
+
+
+
+ {this.getElasticsearchPrivileges()}
+
+ {this.getKibanaPrivileges()}
+
+
+
+ Save
+
+
+
+ Cancel
+
+
+
+
+
+
+ );
+ }
+
+ getTitle = () => {
+ if (this.editingExistingRole()) {
+ return `Edit role`;
+ }
+ return `New Role`;
+ };
+
+ getActionButton = () => {
+ if (this.editingExistingRole() && !isReservedRole(this.props.role)) {
+ return (
+
+ Delete role
+
+ );
+ }
+
+ return null;
+ };
+
+ onNameChange = (name) => {
+ this.setState({
+ role: {
+ ...this.state.role,
+ name
+ }
+ });
+ }
+
+ getElasticsearchPrivileges = () => {
+ const {
+ role
+ } = this.state;
+
+ return (
+
+
+ Cluster Privileges ({role.cluster.length})}
+ >
+
+
+
+
+
+
+
+ Index Privileges (
+ {role.indices.filter(i => i.names.length).length})
+
+ }
+ >
+
+
+
+ Index Privileges allow you to foo the bar while baring the baz
+
+
+
+ {this.getIndexPrivileges()}
+
+
+
+
+
+ Run As Privileges ({role.run_as.length})}
+ >
+
+ ({ id: username, label: username }))}
+ selectedOptions={this.state.role.run_as.map(u => ({ label: u }))}
+ onChange={this.onRunAsUserChange}
+ />
+
+
+
+
+ );
+ };
+
+ getIndexPrivileges = () => {
+ const { indices = [] } = this.state.role;
+
+ const {
+ indexPatterns,
+ allowDocumentLevelSecurity,
+ allowFieldLevelSecurity
+ } = this.props;
+
+ const props = {
+ indexPatterns,
+ allowDocumentLevelSecurity,
+ allowFieldLevelSecurity,
+ isReservedRole: isReservedRole(this.props.role)
+ };
+
+ const forms = indices.map((indexPrivilege, idx) => (
+
+ ));
+
+ const button = isReservedRole(this.props.role)
+ ? null
+ : (
+
+
+
+ New Index Privilege
+
+
+
+ );
+
+ return (
+
+ {forms}
+ {button}
+
+ );
+ };
+
+ addIndexPrivilege = () => {
+ const { role } = this.state;
+
+ this.setState({
+ role: {
+ ...role,
+ indices: [...role.indices, {
+ names: [],
+ privileges: [],
+ field_security: {
+ grant: ['*']
+ }
+ }]
+ }
+ });
+ };
+
+ onIndexPrivilegeChange = (index) => {
+ return (updatedPrivilege) => {
+ const { role } = this.state;
+ const { indices } = role;
+
+ const newIndicesState = [...indices];
+ newIndicesState[index] = updatedPrivilege;
+
+ this.setState({
+ role: {
+ ...role,
+ indices: newIndicesState
+ }
+ });
+
+ this.loadAvailableFields(newIndicesState);
+ };
+ };
+
+ deleteIndexPrivilege = (privilegeIndex) => {
+ this.setState({
+ role: {
+ ...this.state.role,
+ indices: this.state.indices.splice(privilegeIndex, 1)
+ }
+ });
+ }
+
+ onClusterPrivilegesChange = (cluster) => {
+ this.setState({
+ role: {
+ ...this.state.role,
+ cluster
+ }
+ });
+ }
+
+ onRunAsUserChange = (users) => {
+ this.setState({
+ role: {
+ ...this.state.role,
+ run_as: users.map(u => u.label)
+ }
+ });
+ }
+
+ getKibanaPrivileges = () => {
+ if (!this.props.kibanaPrivilegesEnabled) {
+ return null;
+ }
+
+ return (
+
+
+ Cluster Privileges}
+ >
+
+ { }}/>
+
+
+
+ );
+ };
+
+ editingExistingRole = () => {
+ return !!this.props.role.name;
+ };
+}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/index_privilege_form.js b/x-pack/plugins/security/public/views/management/edit_role/components/index_privilege_form.js
new file mode 100644
index 0000000000000..1b0f0a75416f2
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/index_privilege_form.js
@@ -0,0 +1,192 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React, { Component, Fragment } from 'react';
+import PropTypes from 'prop-types';
+import {
+ EuiComboBox,
+ EuiTextArea,
+ EuiFormRow,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiButton,
+ EuiSpacer,
+ EuiHorizontalRule,
+} from '@elastic/eui';
+import { getIndexPrivileges } from '../../../../services/role_privileges';
+
+const fromOption = (option) => option.label;
+const toOption = (value) => ({ label: value });
+
+export class IndexPrivilegeForm extends Component {
+ static propTypes = {
+ indexPrivilege: PropTypes.object.isRequired,
+ indexPatterns: PropTypes.array.isRequired,
+ availableFields: PropTypes.array,
+ onChange: PropTypes.func.isRequired,
+ isReservedRole: PropTypes.bool.isRequired,
+ allowDocumentLevelSecurity: PropTypes.bool.isRequired,
+ allowFieldLevelSecurity: PropTypes.bool.isRequired,
+ };
+
+ render() {
+ return (
+
+
+
+ {this.getPrivilegeForm()}
+
+ {(
+
+
+
+ )}
+
+
+
+ );
+ }
+
+ getPrivilegeForm = () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {this.getConditionalFeatures()}
+
+ );
+ };
+
+ getConditionalFeatures = () => {
+ const {
+ allowDocumentLevelSecurity,
+ allowFieldLevelSecurity,
+ indexPrivilege,
+ availableFields,
+ } = this.props;
+
+ if (!allowFieldLevelSecurity && !allowDocumentLevelSecurity) {
+ return null;
+ }
+
+ const features = [];
+ if (allowDocumentLevelSecurity) {
+ features.push((
+
+
+
+
+
+ ));
+ }
+
+ if (allowFieldLevelSecurity) {
+
+ const { grant = [] } = indexPrivilege.field_security || {};
+
+ features.push((
+
+
+
+
+
+ ));
+ }
+
+ return (
+
+
+
+ {features}
+
+
+ );
+ };
+
+ onCreateIndexPatternOption = (option) => {
+ const newIndexPatterns = this.props.indexPrivilege.names.concat([option]);
+
+ this.props.onChange({
+ ...this.props.indexPrivilege,
+ names: newIndexPatterns,
+ });
+ };
+
+ onIndexPatternsChange = (newPatterns) => {
+ this.props.onChange({
+ ...this.props.indexPrivilege,
+ names: newPatterns.map(fromOption),
+ });
+ };
+
+ onPrivilegeChange = (newPrivileges) => {
+ this.props.onChange({
+ ...this.props.indexPrivilege,
+ privileges: newPrivileges.map(fromOption),
+ });
+ };
+
+ onQueryChange = (e) => {
+ this.props.onChange({
+ ...this.props.indexPrivilege,
+ query: e.target.value,
+ });
+ };
+
+ onCreateGrantedField = (grant) => {
+ const newGrants = this.props.indexPrivilege.field_security.grant.concat([grant]);
+
+ this.props.onChange({
+ ...this.props.indexPrivilege,
+ field_security: {
+ ...this.props.indexPrivilege.field_security,
+ grant: newGrants,
+ },
+ });
+ };
+
+ onGrantedFieldsChange = (grantedFields) => {
+ this.props.onChange({
+ ...this.props.indexPrivilege,
+ field_security: {
+ ...this.props.indexPrivilege.field_security,
+ grant: grantedFields.map(fromOption),
+ },
+ });
+ };
+}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/page_header.js b/x-pack/plugins/security/public/views/management/edit_role/components/page_header.js
new file mode 100644
index 0000000000000..956c2809b325f
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/page_header.js
@@ -0,0 +1,43 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+import {
+ EuiHeader,
+ EuiHeaderSection,
+ EuiHeaderBreadcrumb,
+ EuiHeaderBreadcrumbs
+} from '@elastic/eui';
+
+export class PageHeader extends Component {
+ render() {
+ return (
+
+
+
+ {this.props.breadcrumbs.map(this.buildBreadcrumb)}
+
+
+
+ );
+ }
+
+ buildBreadcrumb = (breadcrumb) => {
+ return (
+
+ {breadcrumb.display}
+
+ );
+ }
+}
+
+
+
+PageHeader.propTypes = {
+ breadcrumbs: PropTypes.array.isRequired
+};
diff --git a/x-pack/plugins/security/public/views/management/edit_role/lib/is_reserved_role.js b/x-pack/plugins/security/public/views/management/edit_role/lib/is_reserved_role.js
new file mode 100644
index 0000000000000..05a76d7f516c7
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/lib/is_reserved_role.js
@@ -0,0 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export function isReservedRole(role) {
+ return role && role.metadata && role.metadata._reserved;
+}
From 904a6b772f8cb942220ad6a85f4c4788f4c0b52e Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Mon, 14 May 2018 09:17:42 -0400
Subject: [PATCH 02/38] validation and cleanup
---
.../components/cluster_privileges.js | 31 ++--
.../components/delete_role_button.js | 78 ++++++++++
.../edit_role/components/edit_role_page.js | 145 ++++++++++++------
.../components/index_privilege_form.js | 13 +-
.../components/reserved_role_badge.js | 37 +++++
.../management/edit_role/lib/constants.js | 7 +
.../management/edit_role/lib/validate_role.js | 84 ++++++++++
7 files changed, 339 insertions(+), 56 deletions(-)
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/delete_role_button.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/lib/constants.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.js
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/cluster_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/cluster_privileges.js
index 8486dc3bf70e1..8ed97e8aad5c1 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/cluster_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/cluster_privileges.js
@@ -4,18 +4,22 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { Component } from 'react';
+import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { getClusterPrivileges } from '../../../../services/role_privileges';
import { isReservedRole } from '../lib/is_reserved_role';
import {
- EuiCheckboxGroup
+ EuiCheckboxGroup,
+ EuiText,
+ EuiSpacer,
+ EuiLink,
} from '@elastic/eui';
+import { CLUSTER_PRIVS_DOC_LINK } from '../lib/constants';
export class ClusterPrivileges extends Component {
static propTypes = {
role: PropTypes.object.isRequired,
- onChange: PropTypes.func.isRequired
+ onChange: PropTypes.func.isRequired,
};
render() {
@@ -31,12 +35,21 @@ export class ClusterPrivileges extends Component {
.reduce((acc, o) => ({ ...acc, ...o }), {});
return (
-
+
+
+
+ Manage the actions this role can perform against your cluster.
+ Learn more
+
+
+
+
+
);
}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/delete_role_button.js b/x-pack/plugins/security/public/views/management/edit_role/components/delete_role_button.js
new file mode 100644
index 0000000000000..805dfb232fff4
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/delete_role_button.js
@@ -0,0 +1,78 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { Component, Fragment } from 'react';
+import PropTypes from 'prop-types';
+import {
+ EuiButton,
+ EuiOverlayMask,
+ EuiConfirmModal,
+} from '@elastic/eui';
+
+export class DeleteRoleButton extends Component {
+ static propTypes = {
+ canDelete: PropTypes.bool.isRequired,
+ onDelete: PropTypes.func.isRequired
+ }
+
+ state = {
+ showModal: false
+ }
+
+ render() {
+ if (!this.props.canDelete) {
+ return null;
+ }
+
+ return (
+
+
+ Delete Role
+
+ {this.maybeShowModal()}
+
+ );
+ }
+
+ maybeShowModal = () => {
+ if (!this.state.showModal) {
+ return null;
+ }
+ return (
+
+
+ Are you sure you want to delete this role?
+ This action cannot be undone!
+
+
+ );
+ }
+
+ closeModal = () => {
+ this.setState({
+ showModal: false
+ });
+ }
+
+ showModal = () => {
+ this.setState({
+ showModal: true
+ });
+ }
+
+ onConfirmDelete = () => {
+ this.closeModal();
+ this.props.onDelete();
+ }
+}
+
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
index 31c4794bcccbd..c61a2b9b28a7f 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
@@ -21,13 +21,17 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiButton,
- EuiBadge,
+ EuiTitle,
} from '@elastic/eui';
import { PageHeader } from './page_header';
import { IndexPrivilegeForm } from './index_privilege_form';
import { ClusterPrivileges } from './cluster_privileges';
import { getFields } from '../../../../objects';
import { isReservedRole } from '../lib/is_reserved_role';
+import { RoleValidator } from '../lib/validate_role';
+import { ReservedRoleBadge } from './reserved_role_badge';
+import { ROLES_PATH } from '../../management_urls';
+import { DeleteRoleButton } from './delete_role_button';
export class EditRolePage extends Component {
static propTypes = {
@@ -45,8 +49,10 @@ export class EditRolePage extends Component {
super(props);
this.state = {
role: props.role,
- availableFields: {}
+ availableFields: {},
+ formError: null
};
+ this.validator = new RoleValidator({ shouldValidate: false });
}
componentDidMount() {
@@ -89,11 +95,15 @@ export class EditRolePage extends Component {
}
render() {
+ const {
+ validator
+ } = this;
+
return (
-
+
{this.getTitle()}
@@ -104,7 +114,7 @@ export class EditRolePage extends Component {
-
+
- {isReservedRole(this.props.role)
- && Reserved Role }
+
@@ -123,12 +132,14 @@ export class EditRolePage extends Component {
{this.getKibanaPrivileges()}
+
+
- Save
+ Save
-
+
Cancel
@@ -150,7 +161,7 @@ export class EditRolePage extends Component {
if (this.editingExistingRole() && !isReservedRole(this.props.role)) {
return (
- Delete role
+
);
}
@@ -158,11 +169,11 @@ export class EditRolePage extends Component {
return null;
};
- onNameChange = (name) => {
+ onNameChange = (e) => {
this.setState({
role: {
...this.state.role,
- name
+ name: e.target.value
}
});
}
@@ -174,17 +185,23 @@ export class EditRolePage extends Component {
return (
-
+
+ Elasticsearch
+
+
+
+
+
Cluster Privileges ({role.cluster.length})}
>
-
-
-
+
-
-
+
+
+
+
}
>
-
-
-
- Index Privileges allow you to foo the bar while baring the baz
-
-
-
- {this.getIndexPrivileges()}
-
+
+
+ Index Privileges allow you to foo the bar while baring the baz
+
+
+
+ {this.getIndexPrivileges()}
-
+
+
-
+
Run As Privileges ({role.run_as.length})}
>
-
- ({ id: username, label: username }))}
- selectedOptions={this.state.role.run_as.map(u => ({ label: u }))}
- onChange={this.onRunAsUserChange}
- />
-
+
+
+ Run As Privileges allow you to foo the bar while baring the baz
+
+
+
+ ({ id: username, label: username }))}
+ selectedOptions={this.state.role.run_as.map(u => ({ label: u }))}
+ onChange={this.onRunAsUserChange}
+ />
-
+
);
};
@@ -245,9 +265,12 @@ export class EditRolePage extends Component {
));
@@ -307,13 +330,20 @@ export class EditRolePage extends Component {
};
};
- deleteIndexPrivilege = (privilegeIndex) => {
- this.setState({
- role: {
- ...this.state.role,
- indices: this.state.indices.splice(privilegeIndex, 1)
- }
- });
+ onIndexPrivilegeDelete = (privilegeIndex) => {
+ return () => {
+ const { role } = this.state;
+
+ const newIndicesState = [...role.indices];
+ newIndicesState.splice(privilegeIndex, 1);
+
+ this.setState({
+ role: {
+ ...role,
+ indices: newIndicesState
+ }
+ });
+ };
}
onClusterPrivilegesChange = (cluster) => {
@@ -357,4 +387,31 @@ export class EditRolePage extends Component {
editingExistingRole = () => {
return !!this.props.role.name;
};
+
+ isPlaceholderPrivilege = (indexPrivilege) => {
+ return indexPrivilege.names.length === 0;
+ };
+
+ saveRole = () => {
+ this.validator.enableValidation();
+
+ const result = this.validator.validateForSave(this.state.role);
+ if (result.isInvalid) {
+ this.setState({
+ formError: result
+ });
+ } else {
+ this.setState({
+ formError: null
+ });
+ }
+ };
+
+ deleteRole = () => {
+
+ };
+
+ backToRoleList = () => {
+ window.location.hash = ROLES_PATH;
+ };
}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/index_privilege_form.js b/x-pack/plugins/security/public/views/management/edit_role/components/index_privilege_form.js
index 1b0f0a75416f2..da1df33d69d20 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/index_privilege_form.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/index_privilege_form.js
@@ -27,8 +27,10 @@ export class IndexPrivilegeForm extends Component {
availableFields: PropTypes.array,
onChange: PropTypes.func.isRequired,
isReservedRole: PropTypes.bool.isRequired,
+ allowDelete: PropTypes.bool.isRequired,
allowDocumentLevelSecurity: PropTypes.bool.isRequired,
allowFieldLevelSecurity: PropTypes.bool.isRequired,
+ validator: PropTypes.object.isRequired,
};
render() {
@@ -38,9 +40,14 @@ export class IndexPrivilegeForm extends Component {
{this.getPrivilegeForm()}
- {(
+ {this.props.allowDelete && (
-
+
)}
@@ -54,7 +61,7 @@ export class IndexPrivilegeForm extends Component {
-
+
{
+ const {
+ role
+ } = props;
+
+ if (isReservedRole(role)) {
+ return (
+
+
+ Reserved Role
+
+
+ );
+ }
+ return null;
+};
+
+ReservedRoleBadge.propTypes = {
+ role: PropTypes.object.isRequired
+};
diff --git a/x-pack/plugins/security/public/views/management/edit_role/lib/constants.js b/x-pack/plugins/security/public/views/management/edit_role/lib/constants.js
new file mode 100644
index 0000000000000..6518df48847e9
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/lib/constants.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export const CLUSTER_PRIVS_DOC_LINK = `https://www.elastic.co/guide/en/x-pack/current/security-privileges.html#security-privileges`;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.js b/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.js
new file mode 100644
index 0000000000000..3c7ffa0b667eb
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.js
@@ -0,0 +1,84 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export class RoleValidator {
+ constructor(options = {}) {
+ this._shouldValidate = options.shouldValidate;
+ }
+
+ enableValidation() {
+ this._shouldValidate = true;
+ }
+
+ disableValidation() {
+ this._shouldValidate = false;
+ }
+
+ validateRoleName(role) {
+ if (!this._shouldValidate) return valid();
+
+ if (!role.name) {
+ return invalid(`Please provide a role name`);
+ }
+ if (role.name.length > 30) {
+ return invalid(`Name must not exceed 30 characters`);
+ }
+ if (!role.name.match(/^[a-zA-Z_][a-zA-Z0-9_@\-\$\.]*$/)) {
+ return invalid(`Name must begin with a letter or underscore and contain only letters, underscores, and numbers.`);
+ }
+ return valid();
+ }
+
+ validateIndexPrivileges(role) {
+ if (!this._shouldValidate) return valid();
+
+ if (Array.isArray(role.indices)) {
+ const areIndicesValid = role.indices
+ .map(this.validateIndexPrivilege.bind(this))
+ .find((result) => result.isInvalid) == null;
+
+ if (areIndicesValid) {
+ return valid();
+ }
+ return invalid();
+ }
+ }
+
+ validateIndexPrivilege(indexPrivilege) {
+ if (!this._shouldValidate) return valid();
+
+ if (indexPrivilege.names.length && !indexPrivilege.privileges.length) {
+ return invalid(`At least one privilege is required`);
+ }
+ return valid();
+ }
+
+ validateForSave(role) {
+ const { isInvalid: isNameInvalid } = this.validateRoleName(role);
+ const { isInvalid: areIndicesInvalid } = this.validateIndexPrivileges(role);
+
+ if (isNameInvalid || areIndicesInvalid) {
+ return invalid();
+ }
+
+ return valid();
+ }
+
+}
+
+function invalid(error) {
+ return {
+ isInvalid: true,
+ error
+ };
+}
+
+function valid() {
+ return {
+ isInvalid: false
+ };
+}
+
From 8ae7325c5c5222b5cc7b8d26cb774438fc696d69 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Mon, 14 May 2018 09:23:13 -0400
Subject: [PATCH 03/38] Fix react warnings
---
.../views/management/edit_role/components/edit_role_page.js | 2 +-
.../public/views/management/edit_role/lib/is_reserved_role.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
index c61a2b9b28a7f..94ba1482604c8 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
@@ -117,7 +117,7 @@ export class EditRolePage extends Component {
diff --git a/x-pack/plugins/security/public/views/management/edit_role/lib/is_reserved_role.js b/x-pack/plugins/security/public/views/management/edit_role/lib/is_reserved_role.js
index 05a76d7f516c7..84d003e1b6033 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/lib/is_reserved_role.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/lib/is_reserved_role.js
@@ -5,5 +5,5 @@
*/
export function isReservedRole(role) {
- return role && role.metadata && role.metadata._reserved;
+ return (role && role.metadata && role.metadata._reserved) || false;
}
From 2c70cc162fe3ee99ee99dace164e35618d323fa0 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Mon, 14 May 2018 09:59:03 -0400
Subject: [PATCH 04/38] Hook UI actions to API
---
.../plugins/security/public/objects/index.js | 2 +-
.../objects/lib/{get_roles.js => roles.js} | 8 +++
.../public/views/management/edit_role.js | 2 +
.../edit_role/components/edit_role_page.js | 70 ++++++++++++++-----
4 files changed, 63 insertions(+), 19 deletions(-)
rename x-pack/plugins/security/public/objects/lib/{get_roles.js => roles.js} (72%)
diff --git a/x-pack/plugins/security/public/objects/index.js b/x-pack/plugins/security/public/objects/index.js
index ce1c8f6aac3df..88575e4e24677 100644
--- a/x-pack/plugins/security/public/objects/index.js
+++ b/x-pack/plugins/security/public/objects/index.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { getRole } from './lib/get_roles';
+export { getRole, saveRole, deleteRole } from './lib/roles';
export { getUsers } from './lib/get_users';
diff --git a/x-pack/plugins/security/public/objects/lib/get_roles.js b/x-pack/plugins/security/public/objects/lib/roles.js
similarity index 72%
rename from x-pack/plugins/security/public/objects/lib/get_roles.js
rename to x-pack/plugins/security/public/objects/lib/roles.js
index 784ba57570605..c6b68d283569c 100644
--- a/x-pack/plugins/security/public/objects/lib/get_roles.js
+++ b/x-pack/plugins/security/public/objects/lib/roles.js
@@ -7,6 +7,10 @@ import chrome from 'ui/chrome';
const apiBase = chrome.addBasePath(`/api/security/v1/roles`);
+export async function saveRole($http, role) {
+ return await $http.post(`${apiBase}/${role.name}`, role);
+}
+
export async function getRole($http, name) {
try {
return await $http.get(`${apiBase}/${name}`);
@@ -17,3 +21,7 @@ export async function getRole($http, name) {
throw response;
}
}
+
+export async function deleteRole($http, name) {
+ return await $http.delete(`${apiBase}/${name}`);
+}
diff --git a/x-pack/plugins/security/public/views/management/edit_role.js b/x-pack/plugins/security/public/views/management/edit_role.js
index 33cc6c42a4f40..3110c0f8aedda 100644
--- a/x-pack/plugins/security/public/views/management/edit_role.js
+++ b/x-pack/plugins/security/public/views/management/edit_role.js
@@ -69,6 +69,7 @@ routes.when(`${EDIT_ROLES_PATH}/:name?`, {
controller($injector, $scope, $http, rbacEnabled) {
const $route = $injector.get('$route');
const Private = $injector.get('Private');
+ const Notifier = $injector.get('Notifier');
const xpackInfo = Private(XPackInfoProvider);
const allowDocumentLevelSecurity = xpackInfo.get('features.security.allowRoleDocumentLevelSecurity');
@@ -105,6 +106,7 @@ routes.when(`${EDIT_ROLES_PATH}/:name?`, {
breadcrumbs={routes.getBreadcrumbs()}
allowDocumentLevelSecurity={allowDocumentLevelSecurity}
allowFieldLevelSecurity={allowFieldLevelSecurity}
+ notifier={Notifier}
/>, domNode);
// unmount react on controller destroy
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
index 94ba1482604c8..9124816a03aa8 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
@@ -5,7 +5,8 @@
*/
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
-import { difference } from 'lodash';
+import { difference, get } from 'lodash';
+import { Notifier, toastNotifications } from 'ui/notify';
import {
EuiText,
EuiSpacer,
@@ -26,13 +27,15 @@ import {
import { PageHeader } from './page_header';
import { IndexPrivilegeForm } from './index_privilege_form';
import { ClusterPrivileges } from './cluster_privileges';
-import { getFields } from '../../../../objects';
+import { getFields, saveRole, deleteRole } from '../../../../objects';
import { isReservedRole } from '../lib/is_reserved_role';
import { RoleValidator } from '../lib/validate_role';
import { ReservedRoleBadge } from './reserved_role_badge';
import { ROLES_PATH } from '../../management_urls';
import { DeleteRoleButton } from './delete_role_button';
+const notifier = new Notifier();
+
export class EditRolePage extends Component {
static propTypes = {
role: PropTypes.object.isRequired,
@@ -42,7 +45,7 @@ export class EditRolePage extends Component {
rbacEnabled: PropTypes.bool.isRequired,
spacesEnabled: PropTypes.bool.isRequired,
allowDocumentLevelSecurity: PropTypes.bool.isRequired,
- allowFieldLevelSecurity: PropTypes.bool.isRequired
+ allowFieldLevelSecurity: PropTypes.bool.isRequired,
};
constructor(props) {
@@ -101,7 +104,7 @@ export class EditRolePage extends Component {
return (
-
+
@@ -111,7 +114,7 @@ export class EditRolePage extends Component {
{this.getActionButton()}
-
+
@@ -119,14 +122,14 @@ export class EditRolePage extends Component {
name={'name'}
value={this.state.role.name || ''}
onChange={this.onNameChange}
- readOnly={isReservedRole(this.props.role)}
+ readOnly={isReservedRole(this.props.role) || this.editingExistingRole()}
/>
-
+
{this.getElasticsearchPrivileges()}
@@ -161,7 +164,7 @@ export class EditRolePage extends Component {
if (this.editingExistingRole() && !isReservedRole(this.props.role)) {
return (
-
+
);
}
@@ -194,9 +197,9 @@ export class EditRolePage extends Component {
Cluster Privileges ({role.cluster.length})}
+ buttonContent={ Cluster Privileges ({role.cluster.length})
}
>
-
+
@@ -206,7 +209,7 @@ export class EditRolePage extends Component {
id={'indexPrivilegesAccordion'}
buttonContent={
- Index Privileges (
+ Index Privileges (
{role.indices.filter(i => i.names.length).length})
}
@@ -216,7 +219,7 @@ export class EditRolePage extends Component {
Index Privileges allow you to foo the bar while baring the baz
-
+
{this.getIndexPrivileges()}
@@ -225,14 +228,14 @@ export class EditRolePage extends Component {
Run As Privileges ({role.run_as.length})}
+ buttonContent={ Run As Privileges ({role.run_as.length})
}
>
Run As Privileges allow you to foo the bar while baring the baz
-
+
({ id: username, label: username }))}
@@ -374,10 +377,10 @@ export class EditRolePage extends Component {
Cluster Privileges}
+ buttonContent={ Cluster Privileges
}
>
-
- { }}/>
+
+ { }} />
@@ -404,11 +407,42 @@ export class EditRolePage extends Component {
this.setState({
formError: null
});
+
+ const {
+ httpClient,
+ } = this.props;
+
+ const role = {
+ ...this.state.role
+ };
+
+ role.indices = role.indices.filter(i => !this.isPlaceholderPrivilege(i));
+
+ saveRole(httpClient, role)
+ .then(() => {
+ toastNotifications.addSuccess('Saved role');
+ this.backToRoleList();
+ })
+ .catch(error => {
+ notifier.error(get(error, 'data.message'));
+ });
}
};
- deleteRole = () => {
+ handleDeleteRole = () => {
+ const {
+ httpClient,
+ role,
+ } = this.props;
+ deleteRole(httpClient, role.name)
+ .then(() => {
+ toastNotifications.addSuccess('Deleted role');
+ this.backToRoleList();
+ })
+ .catch(error => {
+ notifier.error(get(error, 'data.message'));
+ });
};
backToRoleList = () => {
From 036c4e438588ed02e9fb5c7432ed38525946320b Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Mon, 14 May 2018 10:29:28 -0400
Subject: [PATCH 05/38] adds some testing
---
.../components/delete_role_button.test.js | 41 +++++++++
.../components/reserved_role_badge.test.js | 32 +++++++
.../edit_role/lib/validate_role.test.js | 85 +++++++++++++++++++
3 files changed, 158 insertions(+)
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/delete_role_button.test.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.test.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.test.js
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/delete_role_button.test.js b/x-pack/plugins/security/public/views/management/edit_role/components/delete_role_button.test.js
new file mode 100644
index 0000000000000..477ffbebf8699
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/delete_role_button.test.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import {
+ EuiButton,
+ EuiConfirmModal,
+} from '@elastic/eui';
+import { DeleteRoleButton } from './delete_role_button';
+import {
+ shallow,
+ mount
+} from 'enzyme';
+
+test('it renders without crashing', () => {
+ const deleteHandler = jest.fn();
+ const wrapper = shallow( );
+ expect(wrapper.find(EuiButton)).toHaveLength(1);
+ expect(deleteHandler).toHaveBeenCalledTimes(0);
+});
+
+test('it shows a confirmation dialog when clicked', () => {
+ const deleteHandler = jest.fn();
+ const wrapper = mount( );
+
+ wrapper.find(EuiButton).simulate('click');
+
+ expect(wrapper.find(EuiConfirmModal)).toHaveLength(1);
+
+ expect(deleteHandler).toHaveBeenCalledTimes(0);
+});
+
+test('it renders nothing when canDelete is false', () => {
+ const deleteHandler = jest.fn();
+ const wrapper = shallow( );
+ expect(wrapper.find('*')).toHaveLength(0);
+ expect(deleteHandler).toHaveBeenCalledTimes(0);
+});
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.test.js b/x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.test.js
new file mode 100644
index 0000000000000..c9227a415f9ff
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.test.js
@@ -0,0 +1,32 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import {
+ EuiBadge
+} from '@elastic/eui';
+import { ReservedRoleBadge } from './reserved_role_badge';
+import {
+ shallow
+} from 'enzyme';
+
+const reservedRole = {
+ metadata: {
+ _reserved: true
+ }
+};
+
+const unreservedRole = {};
+
+test('it renders without crashing', () => {
+ const wrapper = shallow( );
+ expect(wrapper.find(EuiBadge)).toHaveLength(1);
+});
+
+test('it renders nothing for an unreserved role', () => {
+ const wrapper = shallow( );
+ expect(wrapper.find('*')).toHaveLength(0);
+});
diff --git a/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.test.js b/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.test.js
new file mode 100644
index 0000000000000..eea22c4d75fb0
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.test.js
@@ -0,0 +1,85 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import { RoleValidator } from "./validate_role";
+
+let validator;
+
+describe('validateRoleName', () => {
+ beforeEach(() => {
+ validator = new RoleValidator({ shouldValidate: true });
+ });
+
+ test('it allows an alphanumeric role name', () => {
+ const role = {
+ name: 'This-is-30-character-role-name'
+ };
+
+ expect(validator.validateRoleName(role)).toEqual({ isInvalid: false });
+ });
+
+ test('it requires a non-empty value', () => {
+ const role = {
+ name: ''
+ };
+
+ expect(validator.validateRoleName(role)).toEqual({ isInvalid: true, error: `Please provide a role name` });
+ });
+
+ test('it cannot exceed 30 characters', () => {
+ const role = {
+ name: 'This-is-a31-character-role-name'
+ };
+
+ expect(validator.validateRoleName(role)).toEqual({ isInvalid: true, error: `Name must not exceed 30 characters` });
+ });
+
+ const charList = `!#%^&*()+=[]{}\|';:"/,<>?`.split('');
+ charList.forEach(element => {
+ test(`it cannot support the "${element}" character`, () => {
+ const role = {
+ name: `role-${element}`
+ };
+
+ expect(validator.validateRoleName(role)).toEqual(
+ { isInvalid: true,
+ error: `Name must begin with a letter or underscore and contain only letters, underscores, and numbers.`
+ }
+ );
+ });
+ });
+});
+
+describe('validateIndexPrivileges', () => {
+ beforeEach(() => {
+ validator = new RoleValidator({ shouldValidate: true });
+ });
+
+ test('it ignores privilegs with no indices defined', () => {
+ const role = {
+ indices: [{
+ names: [],
+ privileges: []
+ }]
+ };
+
+ expect(validator.validateIndexPrivileges(role)).toEqual({
+ isInvalid: false
+ });
+ });
+
+ test('it requires privilges when an index is defined', () => {
+ const role = {
+ indices: [{
+ names: ['index-*'],
+ privileges: []
+ }]
+ };
+
+ expect(validator.validateIndexPrivileges(role)).toEqual({
+ isInvalid: true
+ });
+ });
+});
From 378e78cd65802a2d15ec0884743bce30a0ab21e5 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Mon, 14 May 2018 12:56:10 -0400
Subject: [PATCH 06/38] replace spaces with dashes when typing role name
---
.../views/management/edit_role/components/edit_role_page.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
index 9124816a03aa8..ac4668b2b71ab 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
@@ -173,10 +173,13 @@ export class EditRolePage extends Component {
};
onNameChange = (e) => {
+ const rawValue = e.target.value;
+ const name = rawValue.replace(/\s/g, '-');
+
this.setState({
role: {
...this.state.role,
- name: e.target.value
+ name
}
});
}
From d888a93bc82c87550f1693e091210af6dff7f38f Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Tue, 15 May 2018 08:03:04 -0400
Subject: [PATCH 07/38] use new isDisabled prop for EuiComoBoxes
---
.../views/management/edit_role/components/edit_role_page.js | 1 +
.../management/edit_role/components/index_privilege_form.js | 6 +++---
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
index ac4668b2b71ab..8f87ff58260ae 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
@@ -244,6 +244,7 @@ export class EditRolePage extends Component {
options={this.props.runAsUsers.map(username => ({ id: username, label: username }))}
selectedOptions={this.state.role.run_as.map(u => ({ label: u }))}
onChange={this.onRunAsUserChange}
+ isDisabled={isReservedRole(this.props.role)}
/>
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/index_privilege_form.js b/x-pack/plugins/security/public/views/management/edit_role/components/index_privilege_form.js
index da1df33d69d20..138fe723793b3 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/index_privilege_form.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/index_privilege_form.js
@@ -67,7 +67,7 @@ export class IndexPrivilegeForm extends Component {
selectedOptions={this.props.indexPrivilege.names.map(toOption)}
onCreateOption={this.onCreateIndexPatternOption}
onChange={this.onIndexPatternsChange}
- disabled={this.props.isReservedRole}
+ isDisabled={this.props.isReservedRole}
/>
@@ -77,7 +77,7 @@ export class IndexPrivilegeForm extends Component {
options={getIndexPrivileges().map(toOption)}
selectedOptions={this.props.indexPrivilege.privileges.map(toOption)}
onChange={this.onPrivilegeChange}
- disabled={this.props.isReservedRole}
+ isDisabled={this.props.isReservedRole}
/>
@@ -128,7 +128,7 @@ export class IndexPrivilegeForm extends Component {
selectedOptions={grant.map(toOption)}
onCreateOption={this.onCreateGrantedField}
onChange={this.onGrantedFieldsChange}
- disabled={this.props.isReservedRole}
+ isDisabled={this.props.isReservedRole}
/>
From 63028de17aa58f7a8b7a115277f49664681ef1fa Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Tue, 15 May 2018 15:00:59 -0400
Subject: [PATCH 08/38] Update version of EUI to get disable-able ComboBox
components
---
package.json | 2 +-
x-pack/package.json | 2 +-
x-pack/yarn.lock | 468 +++-----------------------------------------
yarn.lock | 352 ++++++---------------------------
4 files changed, 82 insertions(+), 742 deletions(-)
diff --git a/package.json b/package.json
index 9c6acdfd45264..5bdf13c020631 100644
--- a/package.json
+++ b/package.json
@@ -76,7 +76,7 @@
"url": "https://github.com/elastic/kibana.git"
},
"dependencies": {
- "@elastic/eui": "v0.0.44",
+ "@elastic/eui": "v0.0.47",
"@elastic/filesaver": "1.1.2",
"@elastic/numeral": "2.3.2",
"@elastic/ui-ace": "0.2.3",
diff --git a/x-pack/package.json b/x-pack/package.json
index 95c3ecd15dfb4..bfcb1dd5a9905 100644
--- a/x-pack/package.json
+++ b/x-pack/package.json
@@ -75,7 +75,7 @@
"yargs": "4.7.1"
},
"dependencies": {
- "@elastic/eui": "0.0.44",
+ "@elastic/eui": "0.0.47",
"@elastic/node-crypto": "0.1.2",
"@elastic/node-phantom-simple": "2.2.4",
"@elastic/numeral": "2.3.2",
diff --git a/x-pack/yarn.lock b/x-pack/yarn.lock
index 9747bb69a2f7c..fb4184fbbb632 100644
--- a/x-pack/yarn.lock
+++ b/x-pack/yarn.lock
@@ -10,30 +10,25 @@
esutils "^2.0.2"
js-tokens "^3.0.0"
-"@elastic/eui@0.0.44":
- version "0.0.44"
- resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.44.tgz#b0b58eb1b10d6f8de017f548bb06c5b5f71e3d61"
+"@elastic/eui@0.0.47":
+ version "0.0.47"
+ resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.47.tgz#5bae27966bb1d68bb3106853610a407509053b44"
dependencies:
brace "^0.10.0"
classnames "^2.2.5"
core-js "^2.5.1"
- eslint-config-prettier "^2.9.0"
- eslint-plugin-prettier "^2.6.0"
focus-trap-react "^3.0.4"
highlight.js "^9.12.0"
html "^1.0.0"
- jquery "^3.2.1"
keymirror "^0.1.1"
lodash "^3.10.1"
numeral "^2.0.6"
- prettier "^1.11.1"
prop-types "^15.6.0"
react-ace "^5.5.0"
react-color "^2.13.8"
react-datepicker v1.4.1
react-input-autosize "^2.2.1"
react-virtualized "^9.18.5"
- serve "^6.3.1"
tabbable "^1.1.0"
uuid "^3.1.0"
@@ -97,13 +92,6 @@ accept@2.x.x:
boom "5.x.x"
hoek "4.x.x"
-accepts@~1.3.4:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2"
- dependencies:
- mime-types "~2.1.18"
- negotiator "0.6.1"
-
acorn-globals@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.1.0.tgz#ab716025dbe17c54d3ef81d32ece2b2d99fe2538"
@@ -122,10 +110,6 @@ add-event-listener@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/add-event-listener/-/add-event-listener-0.0.1.tgz#a76229ebc64c8aefae204a16273a2f255abea2d0"
-address@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9"
-
agentkeepalive@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-2.2.0.tgz#c5d1bd4b129008f1163f236f86e5faea2026e2ef"
@@ -185,12 +169,6 @@ angular-ui-bootstrap@1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/angular-ui-bootstrap/-/angular-ui-bootstrap-1.2.5.tgz#b0c1eff0bf3b7a65668984a1b81820a90dc60995"
-ansi-align@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f"
- dependencies:
- string-width "^2.0.0"
-
ansi-cyan@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873"
@@ -276,10 +254,6 @@ aproba@^1.0.3:
version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
-arch@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.0.tgz#3613aa46149064b3c1f0607919bf1d4786e82889"
-
archy@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40"
@@ -304,15 +278,6 @@ argparse@~0.1.15:
underscore "~1.7.0"
underscore.string "~2.4.0"
-args@4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/args/-/args-4.0.0.tgz#5ca24cdba43d4b17111c56616f5f2e9d91933954"
- dependencies:
- camelcase "5.0.0"
- chalk "2.3.2"
- leven "2.1.0"
- mri "1.1.0"
-
argv-split@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/argv-split/-/argv-split-2.0.1.tgz#be264117790dbd5ccd63ec3f449a1804814ac4c5"
@@ -947,12 +912,6 @@ base@^0.11.1:
mixin-deep "^1.2.0"
pascalcase "^0.1.1"
-basic-auth@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.0.tgz#015db3f353e02e56377755f962742e8981e7bbba"
- dependencies:
- safe-buffer "5.1.1"
-
bcrypt-pbkdf@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d"
@@ -979,7 +938,7 @@ bluebird@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.1.1.tgz#7e2e4318d62ae72a674f6aea6357bb4def1a6e41"
-bluebird@3.5.1, bluebird@^3.3.1:
+bluebird@^3.3.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
@@ -1017,18 +976,6 @@ boom@5.x.x:
dependencies:
hoek "4.x.x"
-boxen@1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
- dependencies:
- ansi-align "^2.0.0"
- camelcase "^4.0.0"
- chalk "^2.0.1"
- cli-boxes "^1.0.0"
- string-width "^2.0.0"
- term-size "^1.2.0"
- widest-line "^2.0.0"
-
brace-expansion@^1.0.0, brace-expansion@^1.1.7:
version "1.1.8"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
@@ -1144,10 +1091,6 @@ builtin-modules@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
-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"
@@ -1180,10 +1123,6 @@ camelcase-keys@^2.0.0:
camelcase "^2.0.0"
map-obj "^1.0.0"
-camelcase@5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42"
-
camelcase@^1.0.2:
version "1.2.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
@@ -1196,7 +1135,7 @@ camelcase@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
-camelcase@^4.0.0, camelcase@^4.1.0:
+camelcase@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
@@ -1232,22 +1171,6 @@ chai@~1.9.2:
assertion-error "1.0.0"
deep-eql "0.1.3"
-chalk@2.3.2, chalk@^2.3.2:
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65"
- dependencies:
- ansi-styles "^3.2.1"
- escape-string-regexp "^1.0.5"
- supports-color "^5.3.0"
-
-chalk@2.4.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.0.tgz#a060a297a6b57e15b61ca63ce84995daa0fe6e52"
- dependencies:
- ansi-styles "^3.2.1"
- escape-string-regexp "^1.0.5"
- supports-color "^5.3.0"
-
chalk@^1.0.0, chalk@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
@@ -1266,6 +1189,14 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0:
escape-string-regexp "^1.0.5"
supports-color "^4.0.0"
+chalk@^2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65"
+ dependencies:
+ ansi-styles "^3.2.1"
+ escape-string-regexp "^1.0.5"
+ supports-color "^5.3.0"
+
chance@1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/chance/-/chance-1.0.10.tgz#03500b04ad94e778dd2891b09ec73a6ad87b1996"
@@ -1312,10 +1243,6 @@ classnames@2.2.5, classnames@^2.1.2, classnames@^2.2.3, classnames@^2.2.4, class
version "2.2.5"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d"
-cli-boxes@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143"
-
cli-cursor@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
@@ -1334,13 +1261,6 @@ clipboard@^1.6.1:
select "^1.1.2"
tiny-emitter "^2.0.0"
-clipboardy@1.2.3:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.3.tgz#0526361bf78724c1f20be248d428e365433c07ef"
- dependencies:
- arch "^2.1.0"
- execa "^0.8.0"
-
cliui@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
@@ -1460,24 +1380,6 @@ component-emitter@^1.2.0, component-emitter@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
-compressible@~2.0.13:
- version "2.0.13"
- resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.13.tgz#0d1020ab924b2fdb4d6279875c7d6daba6baa7a9"
- dependencies:
- mime-db ">= 1.33.0 < 2"
-
-compression@^1.6.2:
- version "1.7.2"
- resolved "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz#aaffbcd6aaf854b44ebb280353d5ad1651f59a69"
- dependencies:
- accepts "~1.3.4"
- bytes "3.0.0"
- compressible "~2.0.13"
- debug "2.6.9"
- on-headers "~1.0.1"
- safe-buffer "5.1.1"
- vary "~1.1.2"
-
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -1514,10 +1416,6 @@ content-type-parser@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.2.tgz#caabe80623e63638b2502fd4c7f12ff4ce2352e7"
-content-type@1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
-
content@3.x.x:
version "3.0.6"
resolved "https://registry.yarnpkg.com/content/-/content-3.0.6.tgz#9c2e301e9ae515ed65a4b877d78aa5659bb1b809"
@@ -1789,10 +1687,6 @@ d3@3.5.6:
version "3.5.6"
resolved "https://registry.yarnpkg.com/d3/-/d3-3.5.6.tgz#9451c651ca733fb9672c81fb7f2655164a73a42d"
-dargs@5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/dargs/-/dargs-5.1.0.tgz#ec7ea50c78564cd36c9d5ec18f66329fade27829"
-
dashdash@^1.12.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
@@ -1828,7 +1722,7 @@ debug@2.2.0:
dependencies:
ms "0.7.1"
-debug@2.6.9, debug@2.X, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8:
+debug@2.X, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
dependencies:
@@ -1937,22 +1831,10 @@ delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
-depd@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
-
-depd@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
-
deprecated@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19"
-destroy@~1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
-
detect-file@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
@@ -1971,13 +1853,6 @@ detect-newline@2.X, detect-newline@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
-detect-port@1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.2.2.tgz#57a44533632d8bc74ad255676866ca43f96c7469"
- dependencies:
- address "^1.0.1"
- debug "^2.6.0"
-
dfa@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/dfa/-/dfa-1.1.0.tgz#d30218bd10d030fa421df3ebbc82285463a31781"
@@ -2089,10 +1964,6 @@ ecc-jsbn@~0.1.1:
dependencies:
jsbn "~0.1.0"
-ee-first@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
-
elasticsearch@13.0.1:
version "13.0.1"
resolved "https://registry.yarnpkg.com/elasticsearch/-/elasticsearch-13.0.1.tgz#fa58204233052c4cd221e8721e48f3906b385b32"
@@ -2104,10 +1975,6 @@ elasticsearch@13.0.1:
lodash.isempty "^4.4.0"
lodash.trimend "^4.5.1"
-encodeurl@~1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
-
encoding@^0.1.11:
version "0.1.12"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
@@ -2200,10 +2067,6 @@ es6-promise@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-2.0.1.tgz#ccc4963e679f0ca9fb187c777b9e583d3c7573c2"
-escape-html@~1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
-
escape-string-regexp@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1"
@@ -2252,19 +2115,6 @@ escodegen@~1.3.2:
optionalDependencies:
source-map "~0.1.33"
-eslint-config-prettier@^2.9.0:
- version "2.9.0"
- resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz#5ecd65174d486c22dff389fe036febf502d468a3"
- dependencies:
- get-stdin "^5.0.1"
-
-eslint-plugin-prettier@^2.6.0:
- version "2.6.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.0.tgz#33e4e228bdb06142d03c560ce04ec23f6c767dd7"
- dependencies:
- fast-diff "^1.1.1"
- jest-docblock "^21.0.0"
-
esprima@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
@@ -2301,10 +2151,6 @@ esutils@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570"
-etag@~1.8.1:
- version "1.8.1"
- resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
-
exec-sh@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.1.tgz#163b98a6e89e6b65b47c2a28d215bc1f63989c38"
@@ -2335,18 +2181,6 @@ 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"
-
exit-hook@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
@@ -2488,10 +2322,6 @@ fast-deep-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"
-fast-diff@^1.1.1:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154"
-
fast-json-stable-stringify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
@@ -2550,10 +2380,6 @@ fileset@^2.0.2:
glob "^7.0.3"
minimatch "^3.0.3"
-filesize@3.6.1:
- version "3.6.1"
- resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317"
-
fill-keys@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/fill-keys/-/fill-keys-1.0.2.tgz#9a8fa36f4e8ad634e3bf6b4f3c8882551452eb20"
@@ -2731,22 +2557,10 @@ fragment-cache@^0.2.1:
dependencies:
map-cache "^0.2.2"
-fresh@0.5.2:
- version "0.5.2"
- resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
-
from@^0.1.3:
version "0.1.7"
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
-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-mkdirp-stream@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb"
@@ -2833,10 +2647,6 @@ get-stdin@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
-get-stdin@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398"
-
get-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
@@ -3236,7 +3046,7 @@ gulplog@^1.0.0:
dependencies:
glogg "^1.0.0"
-handlebars@4.0.11, handlebars@^4.0.3:
+handlebars@^4.0.3:
version "4.0.11"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc"
dependencies:
@@ -3475,15 +3285,6 @@ htmlparser2@^3.9.1:
inherits "^2.0.1"
readable-stream "^2.0.2"
-http-errors@1.6.2:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
- dependencies:
- depd "1.1.1"
- inherits "2.0.3"
- setprototypeof "1.0.3"
- statuses ">= 1.3.1 < 2"
-
http-errors@~1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.4.0.tgz#6c0242dea6b3df7afda153c71089b31c6e82aabf"
@@ -3491,15 +3292,6 @@ http-errors@~1.4.0:
inherits "2.0.1"
statuses ">= 1.2.1 < 2"
-http-errors@~1.6.2:
- version "1.6.3"
- resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
- dependencies:
- depd "~1.1.2"
- inherits "2.0.3"
- setprototypeof "1.1.0"
- statuses ">= 1.4.0 < 2"
-
http-signature@~1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
@@ -3566,7 +3358,7 @@ inherits@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b"
-inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
+inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
@@ -3611,10 +3403,6 @@ invert-kv@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
-ip@1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
-
iron@4.x.x:
version "4.0.5"
resolved "https://registry.yarnpkg.com/iron/-/iron-4.0.5.tgz#4f042cceb8b9738f346b59aa734c83a89bc31428"
@@ -3834,7 +3622,7 @@ is-relative@^1.0.0:
dependencies:
is-unc-path "^1.0.0"
-is-stream@1.1.0, is-stream@^1.0.1, is-stream@^1.1.0:
+is-stream@^1.0.1, is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
@@ -3872,10 +3660,6 @@ is-windows@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9"
-is-wsl@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
-
isarray@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
@@ -4065,10 +3849,6 @@ jest-diff@^22.4.3:
jest-get-type "^22.4.3"
pretty-format "^22.4.3"
-jest-docblock@^21.0.0:
- version "21.2.0"
- resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414"
-
jest-docblock@^22.4.3:
version "22.4.3"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-22.4.3.tgz#50886f132b42b280c903c592373bb6e93bb68b19"
@@ -4305,7 +4085,7 @@ jquery@^3.1.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.2.1.tgz#5c4d9de652af6cd0a770154a631bba12b015c787"
-jquery@^3.2.1, jquery@^3.3.1:
+jquery@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
@@ -4383,12 +4163,6 @@ json5@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
-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"
-
jsonify@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
@@ -4476,7 +4250,7 @@ left-pad@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.2.0.tgz#d30a73c6b8201d8f7d8e7956ba9616087a68e0ee"
-leven@2.1.0, leven@^2.1.0:
+leven@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
@@ -4858,21 +4632,6 @@ methods@^1.1.1, methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
-micro-compress@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/micro-compress/-/micro-compress-1.0.0.tgz#53f5a80b4ad0320ca165a559b6e3df145d4f704f"
- dependencies:
- compression "^1.6.2"
-
-micro@9.1.4:
- version "9.1.4"
- resolved "https://registry.yarnpkg.com/micro/-/micro-9.1.4.tgz#dbe655f34bb3390509898ddf3fda12348f5cbaa9"
- dependencies:
- content-type "1.0.4"
- is-stream "1.1.0"
- mri "1.1.0"
- raw-body "2.3.2"
-
micromatch@^2.1.5, micromatch@^2.3.11, micromatch@^2.3.7:
version "2.3.11"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
@@ -4913,30 +4672,16 @@ mime-db@1.x.x:
version "1.32.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.32.0.tgz#485b3848b01a3cda5f968b4882c0771e58e09414"
-"mime-db@>= 1.33.0 < 2", mime-db@~1.33.0:
- version "1.33.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
-
mime-db@~1.30.0:
version "1.30.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01"
-mime-types@2.1.18, mime-types@~2.1.18:
- version "2.1.18"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8"
- dependencies:
- mime-db "~1.33.0"
-
mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7:
version "2.1.17"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a"
dependencies:
mime-db "~1.30.0"
-mime@1.4.1:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
-
mime@^1.4.1:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
@@ -5067,10 +4812,6 @@ moment@2.x.x, "moment@>= 2.9.0", moment@^2.13.0, moment@^2.20.1:
version "2.20.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.20.1.tgz#d6eb1a46cbcc14a2b2f9434112c1ff8907f313fd"
-mri@1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.0.tgz#5c0a3f29c8ccffbbb1ec941dcec09d71fa32f36a"
-
ms@0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
@@ -5141,10 +4882,6 @@ nearley@^2.7.10:
railroad-diagrams "^1.0.0"
randexp "^0.4.2"
-negotiator@0.6.1:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
-
ngreact@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/ngreact/-/ngreact-0.5.1.tgz#2dcccc1541771796689d13e51bb8d5010af41c57"
@@ -5200,10 +4937,6 @@ node-pre-gyp@^0.6.39:
tar "^2.2.1"
tar-pack "^3.4.0"
-node-version@1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.1.3.tgz#1081c87cce6d2dbbd61d0e51e28c287782678496"
-
nomnom@~1.6.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.6.2.tgz#84a66a260174408fc5b77a18f888eccc44fb6971"
@@ -5385,16 +5118,6 @@ object.values@^1.0.4:
function-bind "^1.1.0"
has "^1.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"
- dependencies:
- ee-first "1.1.1"
-
-on-headers@~1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
-
once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.3.3, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -5411,16 +5134,6 @@ onetime@^1.0.0:
version "1.1.0"
resolved "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
-openssl-self-signed-certificate@1.1.6:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/openssl-self-signed-certificate/-/openssl-self-signed-certificate-1.1.6.tgz#9d3a4776b1a57e9847350392114ad2f915a83dd4"
-
-opn@5.3.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c"
- dependencies:
- is-wsl "^1.1.0"
-
optimist@^0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
@@ -5582,7 +5295,7 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
-path-is-inside@1.0.2, path-is-inside@^1.0.1:
+path-is-inside@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
@@ -5617,12 +5330,6 @@ path-to-regexp@^1.0.0, path-to-regexp@^1.7.0:
dependencies:
isarray "0.0.1"
-path-type@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
- dependencies:
- pify "^3.0.0"
-
path-type@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
@@ -5685,10 +5392,6 @@ pify@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
-pify@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
-
pinkie-promise@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
@@ -5793,10 +5496,6 @@ preserve@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
-prettier@^1.11.1:
- version "1.12.1"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.12.1.tgz#c1ad20e803e7749faf905a409d2367e06bbe7325"
-
pretty-format@^22.4.3:
version "22.4.3"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-22.4.3.tgz#f873d780839a9c02e9664c8a082e9ee79eaac16f"
@@ -5969,28 +5668,6 @@ randomatic@^1.1.3:
is-number "^3.0.0"
kind-of "^4.0.0"
-range-parser@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
-
-raw-body@2.3.2:
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89"
- dependencies:
- bytes "3.0.0"
- http-errors "1.6.2"
- iconv-lite "0.4.19"
- unpipe "1.0.0"
-
-rc@^1.0.1, rc@^1.1.6:
- version "1.2.6"
- resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.6.tgz#eb18989c6d4f4f162c399f79ddd29f3835568092"
- dependencies:
- deep-extend "~0.4.0"
- ini "~1.3.0"
- minimist "^1.2.0"
- strip-json-comments "~2.0.1"
-
rc@^1.1.7:
version "1.2.3"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.3.tgz#51575a900f8dd68381c710b4712c2154c3e2035b"
@@ -6376,19 +6053,6 @@ regexpu-core@^2.0.0:
regjsgen "^0.2.0"
regjsparser "^0.1.4"
-registry-auth-token@3.3.2:
- version "3.3.2"
- resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20"
- dependencies:
- rc "^1.1.6"
- safe-buffer "^5.0.1"
-
-registry-url@3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942"
- dependencies:
- rc "^1.0.1"
-
regjsgen@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7"
@@ -6671,7 +6335,7 @@ rxjs@5.3.0:
dependencies:
symbol-observable "^1.0.1"
-safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
@@ -6733,55 +6397,10 @@ semver@^5.4.1, semver@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
-send@0.16.2:
- version "0.16.2"
- resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
- dependencies:
- debug "2.6.9"
- depd "~1.1.2"
- destroy "~1.0.4"
- encodeurl "~1.0.2"
- escape-html "~1.0.3"
- etag "~1.8.1"
- fresh "0.5.2"
- http-errors "~1.6.2"
- mime "1.4.1"
- ms "2.0.0"
- on-finished "~2.3.0"
- range-parser "~1.2.0"
- statuses "~1.4.0"
-
sequencify@~0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/sequencify/-/sequencify-0.0.7.tgz#90cff19d02e07027fd767f5ead3e7b95d1e7380c"
-serve@^6.3.1:
- version "6.5.6"
- resolved "https://registry.yarnpkg.com/serve/-/serve-6.5.6.tgz#579136688f80f6bf4a618ca8e8cba10dfb4d95e3"
- dependencies:
- args "4.0.0"
- basic-auth "2.0.0"
- bluebird "3.5.1"
- boxen "1.3.0"
- chalk "2.4.0"
- clipboardy "1.2.3"
- dargs "5.1.0"
- detect-port "1.2.2"
- filesize "3.6.1"
- fs-extra "5.0.0"
- handlebars "4.0.11"
- ip "1.1.5"
- micro "9.1.4"
- micro-compress "1.0.0"
- mime-types "2.1.18"
- node-version "1.1.3"
- openssl-self-signed-certificate "1.1.6"
- opn "5.3.0"
- path-is-inside "1.0.2"
- path-type "3.0.0"
- send "0.16.2"
- update-check "1.3.2"
-
set-blocking@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-1.0.0.tgz#cd5e5d938048df1ac92dfe92e1f16add656f5ec5"
@@ -6818,14 +6437,6 @@ setimmediate@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
-setprototypeof@1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04"
-
-setprototypeof@1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
-
shallow-copy@~0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170"
@@ -7074,14 +6685,10 @@ static-module@^1.1.0:
static-eval "~0.2.0"
through2 "~0.4.1"
-"statuses@>= 1.2.1 < 2", statuses@~1.4.0:
+"statuses@>= 1.2.1 < 2":
version "1.4.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
-"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2":
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
-
stealthy-require@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
@@ -7339,12 +6946,6 @@ temp@^0.8.3:
os-tmpdir "^1.0.0"
rimraf "~2.2.6"
-term-size@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69"
- dependencies:
- execa "^0.7.0"
-
test-exclude@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26"
@@ -7648,14 +7249,6 @@ unique-stream@^2.0.2:
json-stable-stringify "^1.0.0"
through2-filter "^2.0.0"
-universalify@^0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7"
-
-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"
@@ -7663,13 +7256,6 @@ unset-value@^1.0.0:
has-value "^0.3.1"
isobject "^3.0.0"
-update-check@1.3.2:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/update-check/-/update-check-1.3.2.tgz#460f9e9ab24820367f3edbeb4d4142d9936ff171"
- dependencies:
- registry-auth-token "3.3.2"
- registry-url "3.1.0"
-
urix@^0.1.0, urix@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
@@ -7732,10 +7318,6 @@ value-or-function@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813"
-vary@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
-
venn.js@0.2.9:
version "0.2.9"
resolved "https://registry.yarnpkg.com/venn.js/-/venn.js-0.2.9.tgz#33c29075efa484731d59d884752900cc33033656"
@@ -7934,12 +7516,6 @@ wide-align@^1.1.0:
dependencies:
string-width "^1.0.2"
-widest-line@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.0.tgz#0142a4e8a243f8882c0233aa0e0281aa76152273"
- dependencies:
- string-width "^2.1.1"
-
window-size@0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
diff --git a/yarn.lock b/yarn.lock
index c544a9acbb457..2098dda85233c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -77,30 +77,25 @@
version "0.0.0"
uid ""
-"@elastic/eui@0.0.44", "@elastic/eui@v0.0.44":
- version "0.0.44"
- resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.44.tgz#b0b58eb1b10d6f8de017f548bb06c5b5f71e3d61"
+"@elastic/eui@0.0.47", "@elastic/eui@v0.0.47":
+ version "0.0.47"
+ resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.47.tgz#5bae27966bb1d68bb3106853610a407509053b44"
dependencies:
brace "^0.10.0"
classnames "^2.2.5"
core-js "^2.5.1"
- eslint-config-prettier "^2.9.0"
- eslint-plugin-prettier "^2.6.0"
focus-trap-react "^3.0.4"
highlight.js "^9.12.0"
html "^1.0.0"
- jquery "^3.2.1"
keymirror "^0.1.1"
lodash "^3.10.1"
numeral "^2.0.6"
- prettier "^1.11.1"
prop-types "^15.6.0"
react-ace "^5.5.0"
react-color "^2.13.8"
react-datepicker v1.4.1
react-input-autosize "^2.2.1"
react-virtualized "^9.18.5"
- serve "^6.3.1"
tabbable "^1.1.0"
uuid "^3.1.0"
@@ -181,14 +176,6 @@
version "9.4.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.7.tgz#57d81cd98719df2c9de118f2d5f3b1120dcd7275"
-"@zeit/check-updates@1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@zeit/check-updates/-/check-updates-1.1.0.tgz#d0f65026a36f27cd1fd54c647d8294447c1d2d8b"
- dependencies:
- chalk "2.3.0"
- ms "2.1.1"
- update-notifier "2.3.0"
-
JSONStream@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.1.1.tgz#c98bfd88c8f1e1e8694e53c5baa6c8691553e59a"
@@ -226,13 +213,6 @@ accepts@1.3.3:
mime-types "~2.1.11"
negotiator "0.6.1"
-accepts@~1.3.4:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2"
- dependencies:
- mime-types "~2.1.18"
- negotiator "0.6.1"
-
acorn-dynamic-import@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4"
@@ -281,10 +261,6 @@ add-event-listener@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/add-event-listener/-/add-event-listener-0.0.1.tgz#a76229ebc64c8aefae204a16273a2f255abea2d0"
-address@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9"
-
adm-zip@0.4.7:
version "0.4.7"
resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1"
@@ -506,10 +482,6 @@ aproba@^1.0.3:
version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
-arch@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.0.tgz#3613aa46149064b3c1f0607919bf1d4786e82889"
-
are-we-there-yet@~1.1.2:
version "1.1.4"
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d"
@@ -530,16 +502,6 @@ argparse@~0.1.15:
underscore "~1.7.0"
underscore.string "~2.4.0"
-args@3.0.8:
- version "3.0.8"
- resolved "https://registry.yarnpkg.com/args/-/args-3.0.8.tgz#2f425ab639c69d74ff728f3d7c6e93b97b91af7c"
- dependencies:
- camelcase "4.1.0"
- chalk "2.1.0"
- mri "1.1.0"
- pkginfo "0.4.1"
- string-similarity "1.2.0"
-
arr-diff@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
@@ -1560,12 +1522,6 @@ base@^0.11.1:
mixin-deep "^1.2.0"
pascalcase "^0.1.1"
-basic-auth@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.0.tgz#015db3f353e02e56377755f962742e8981e7bbba"
- dependencies:
- safe-buffer "5.1.1"
-
batch-processor@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/batch-processor/-/batch-processor-1.0.0.tgz#75c95c32b748e0850d10c2b168f6bdbe9891ace8"
@@ -1622,14 +1578,14 @@ bluebird@3.4.6:
version "3.4.6"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.6.tgz#01da8d821d87813d158967e743d5fe6c62cf8c0f"
-bluebird@3.5.1, bluebird@^3.3.0:
- version "3.5.1"
- resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
-
bluebird@^2.10.0, bluebird@^2.9.24:
version "2.11.0"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
+bluebird@^3.3.0:
+ version "3.5.1"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
+
bmp-js@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.0.3.tgz#64113e9c7cf1202b376ed607bf30626ebe57b18a"
@@ -1716,7 +1672,7 @@ boom@5.2.0, boom@5.x.x:
dependencies:
hoek "4.x.x"
-boxen@1.3.0, boxen@^1.2.1, boxen@^1.2.2:
+boxen@^1.2.1, boxen@^1.2.2:
version "1.3.0"
resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
dependencies:
@@ -2064,10 +2020,6 @@ camelcase-keys@^3.0.0:
camelcase "^3.0.0"
map-obj "^1.0.0"
-camelcase@4.1.0, camelcase@^4.0.0, camelcase@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
-
camelcase@^1.0.2:
version "1.2.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
@@ -2080,6 +2032,10 @@ camelcase@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
+camelcase@^4.0.0, camelcase@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
+
caniuse-api@^1.5.2:
version "1.6.1"
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c"
@@ -2139,14 +2095,6 @@ chai@3.5.0, "chai@>=1.9.2 <4.0.0":
deep-eql "^0.1.3"
type-detect "^1.0.0"
-chalk@2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e"
- dependencies:
- ansi-styles "^3.1.0"
- escape-string-regexp "^1.0.5"
- supports-color "^4.0.0"
-
chalk@2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba"
@@ -2155,14 +2103,6 @@ chalk@2.3.0:
escape-string-regexp "^1.0.5"
supports-color "^4.0.0"
-chalk@2.3.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2:
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65"
- dependencies:
- ansi-styles "^3.2.1"
- escape-string-regexp "^1.0.5"
- supports-color "^5.3.0"
-
chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3, chalk@~1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
@@ -2173,6 +2113,14 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3, chalk@~1.1.1:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
+chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65"
+ dependencies:
+ ansi-styles "^3.2.1"
+ escape-string-regexp "^1.0.5"
+ supports-color "^5.3.0"
+
chalk@~0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174"
@@ -2389,13 +2337,6 @@ clipboard@^1.6.1:
select "^1.1.2"
tiny-emitter "^2.0.0"
-clipboardy@1.2.3:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.3.tgz#0526361bf78724c1f20be248d428e365433c07ef"
- dependencies:
- arch "^2.1.0"
- execa "^0.8.0"
-
cliui@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
@@ -2607,24 +2548,6 @@ component-inherit@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
-compressible@~2.0.13:
- version "2.0.13"
- resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.13.tgz#0d1020ab924b2fdb4d6279875c7d6daba6baa7a9"
- dependencies:
- mime-db ">= 1.33.0 < 2"
-
-compression@^1.6.2:
- version "1.7.2"
- resolved "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz#aaffbcd6aaf854b44ebb280353d5ad1651f59a69"
- dependencies:
- accepts "~1.3.4"
- bytes "3.0.0"
- compressible "~2.0.13"
- debug "2.6.9"
- on-headers "~1.0.1"
- safe-buffer "5.1.1"
- vary "~1.1.2"
-
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -2739,7 +2662,7 @@ content-type-parser@^1.0.1, content-type-parser@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.2.tgz#caabe80623e63638b2502fd4c7f12ff4ce2352e7"
-content-type@1.0.4, content-type@~1.0.1, content-type@~1.0.4:
+content-type@~1.0.1, content-type@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
@@ -3301,10 +3224,6 @@ d@1:
dependencies:
es5-ext "^0.10.9"
-dargs@5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/dargs/-/dargs-5.1.0.tgz#ec7ea50c78564cd36c9d5ec18f66329fade27829"
-
dashdash@^1.12.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
@@ -3352,7 +3271,7 @@ debug@2.6.0:
dependencies:
ms "0.7.2"
-debug@2.6.9, debug@2.X, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9:
+debug@2.6.9, debug@2.X, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
dependencies:
@@ -3531,7 +3450,7 @@ depd@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.0.1.tgz#80aec64c9d6d97e65cc2a9caa93c0aa6abf73aaa"
-depd@~1.1.0, depd@~1.1.1, depd@~1.1.2:
+depd@~1.1.0, depd@~1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
@@ -3542,10 +3461,6 @@ des.js@^1.0.0:
inherits "^2.0.1"
minimalistic-assert "^1.0.0"
-destroy@~1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
-
detect-indent@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
@@ -3560,13 +3475,6 @@ detect-newline@2.X, detect-newline@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
-detect-port@1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.2.2.tgz#57a44533632d8bc74ad255676866ca43f96c7469"
- dependencies:
- address "^1.0.1"
- debug "^2.6.0"
-
dezalgo@^1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456"
@@ -3845,7 +3753,7 @@ encode-uri-query@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/encode-uri-query/-/encode-uri-query-1.0.0.tgz#d632be4aafe8316c6145007ffb2844c5312b194c"
-encodeurl@~1.0.1, encodeurl@~1.0.2:
+encodeurl@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
@@ -4364,10 +4272,6 @@ esutils@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570"
-etag@~1.8.1:
- version "1.8.1"
- resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
-
even-better@7.0.2:
version "7.0.2"
resolved "https://registry.yarnpkg.com/even-better/-/even-better-7.0.2.tgz#d056f429c90ecc20ee9494aca0a751f743504d2e"
@@ -4446,18 +4350,6 @@ 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"
-
execa@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.9.0.tgz#adb7ce62cf985071f60580deb4a88b9e34712d01"
@@ -4773,10 +4665,6 @@ fileset@^2.0.2:
glob "^7.0.3"
minimatch "^3.0.3"
-filesize@3.6.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.0.tgz#22d079615624bb6fd3c04026120628a41b3f4efa"
-
fill-keys@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/fill-keys/-/fill-keys-1.0.2.tgz#9a8fa36f4e8ad634e3bf6b4f3c8882551452eb20"
@@ -4971,10 +4859,6 @@ fragment-cache@^0.2.1:
dependencies:
map-cache "^0.2.2"
-fresh@0.5.2:
- version "0.5.2"
- resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
-
from@^0.1.3, from@~0:
version "0.1.7"
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
@@ -4997,14 +4881,6 @@ fs-extra@4.0.3, fs-extra@^4.0.1:
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-extra@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291"
@@ -5630,9 +5506,9 @@ h2o2@5.1.1:
joi "9.X.X"
wreck "9.X.X"
-handlebars@4.0.11, handlebars@^4.0.1, handlebars@^4.0.3:
- version "4.0.11"
- resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc"
+handlebars@4.0.5:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.5.tgz#92c6ed6bb164110c50d4d8d0fbddc70806c6f8e7"
dependencies:
async "^1.4.0"
optimist "^0.6.1"
@@ -5640,9 +5516,9 @@ handlebars@4.0.11, handlebars@^4.0.1, handlebars@^4.0.3:
optionalDependencies:
uglify-js "^2.6"
-handlebars@4.0.5:
- version "4.0.5"
- resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.5.tgz#92c6ed6bb164110c50d4d8d0fbddc70806c6f8e7"
+handlebars@^4.0.1, handlebars@^4.0.3:
+ version "4.0.11"
+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc"
dependencies:
async "^1.4.0"
optimist "^0.6.1"
@@ -6250,10 +6126,6 @@ ip-regex@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd"
-ip@1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
-
iron@4.x.x:
version "4.0.5"
resolved "https://registry.yarnpkg.com/iron/-/iron-4.0.5.tgz#4f042cceb8b9738f346b59aa734c83a89bc31428"
@@ -6600,7 +6472,7 @@ is-retry-allowed@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
-is-stream@1.1.0, is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0:
+is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
@@ -6658,10 +6530,6 @@ is-word-character@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.1.tgz#5a03fa1ea91ace8a6eb0c7cd770eb86d65c8befb"
-is-wsl@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
-
isarray@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
@@ -7336,7 +7204,7 @@ jpeg-js@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.2.0.tgz#53e448ec9d263e683266467e9442d2c5a2ef5482"
-jquery@^3.1.1, jquery@^3.2.1, jquery@^3.3.1:
+jquery@^3.1.1, jquery@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
@@ -8421,21 +8289,6 @@ methods@^1.1.1, methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
-micro-compress@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/micro-compress/-/micro-compress-1.0.0.tgz#53f5a80b4ad0320ca165a559b6e3df145d4f704f"
- dependencies:
- compression "^1.6.2"
-
-micro@9.1.0:
- version "9.1.0"
- resolved "https://registry.yarnpkg.com/micro/-/micro-9.1.0.tgz#f2effba306639076e994c007c327dfc36a5185e9"
- dependencies:
- content-type "1.0.4"
- is-stream "1.1.0"
- mri "1.1.0"
- raw-body "2.3.2"
-
micromatch@^2.1.5, micromatch@^2.3.11:
version "2.3.11"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
@@ -8479,11 +8332,11 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
-mime-db@1.x.x, "mime-db@>= 1.33.0 < 2", mime-db@~1.33.0:
+mime-db@1.x.x, mime-db@~1.33.0:
version "1.33.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
-mime-types@2.1.18, mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7:
+mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7:
version "2.1.18"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8"
dependencies:
@@ -8493,10 +8346,6 @@ mime@1.3.x:
version "1.3.6"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.6.tgz#591d84d3653a6b0b4a3b9df8de5aa8108e72e5e0"
-mime@1.4.1:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
-
mime@^1.2.11, mime@^1.3.4, mime@^1.4.1:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
@@ -8656,10 +8505,6 @@ moment@2.x.x, "moment@>= 2.9.0", moment@^2.10.6, moment@^2.13.0, moment@^2.20.1:
version "2.21.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a"
-mri@1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.0.tgz#5c0a3f29c8ccffbbb1ec941dcec09d71fa32f36a"
-
ms@0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.0.tgz#865be94c2e7397ad8a57da6a633a6e2f30798b83"
@@ -8676,7 +8521,7 @@ ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
-ms@2.1.1, ms@^2.0.0:
+ms@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
@@ -8879,10 +8724,6 @@ node-status-codes@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/node-status-codes/-/node-status-codes-1.0.0.tgz#5ae5541d024645d32a58fcddc9ceecea7ae3ac2f"
-node-version@1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.1.0.tgz#f437d7ba407e65e2c4eaef8887b1718ba523d4f0"
-
nomnom@~1.6.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.6.2.tgz#84a66a260174408fc5b77a18f888eccc44fb6971"
@@ -9106,10 +8947,6 @@ on-finished@~2.3.0:
dependencies:
ee-first "1.1.1"
-on-headers@~1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
-
once@1.x, once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.3.3, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -9126,16 +8963,6 @@ onetime@^2.0.0:
dependencies:
mimic-fn "^1.0.0"
-openssl-self-signed-certificate@1.1.6:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/openssl-self-signed-certificate/-/openssl-self-signed-certificate-1.1.6.tgz#9d3a4776b1a57e9847350392114ad2f915a83dd4"
-
-opn@5.2.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/opn/-/opn-5.2.0.tgz#71fdf934d6827d676cecbea1531f95d354641225"
- dependencies:
- is-wsl "^1.1.0"
-
optimist@^0.6.1, optimist@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
@@ -9387,7 +9214,7 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1, path-is-absolute@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
-path-is-inside@1.0.2, path-is-inside@^1.0.1, path-is-inside@^1.0.2:
+path-is-inside@^1.0.1, path-is-inside@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
@@ -9412,12 +9239,6 @@ path-to-regexp@^1.0.0, path-to-regexp@^1.7.0:
dependencies:
isarray "0.0.1"
-path-type@3.0.0, path-type@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
- dependencies:
- pify "^3.0.0"
-
path-type@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
@@ -9432,6 +9253,12 @@ path-type@^2.0.0:
dependencies:
pify "^2.0.0"
+path-type@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
+ dependencies:
+ pify "^3.0.0"
+
pause-stream@0.0.11:
version "0.0.11"
resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
@@ -9564,10 +9391,6 @@ pkg-up@^2.0.0:
dependencies:
find-up "^2.1.0"
-pkginfo@0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff"
-
plugin-error@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-1.0.1.tgz#77016bd8919d0ac377fdcdd0322328953ca5781c"
@@ -9903,10 +9726,6 @@ preserve@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
-prettier@^1.11.1:
- version "1.11.1"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.11.1.tgz#61e43fc4cd44e68f2b0dfc2c38cd4bb0fccdcc75"
-
prettier@^1.12.1:
version "1.12.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.12.1.tgz#c1ad20e803e7749faf905a409d2367e06bbe7325"
@@ -10181,7 +10000,7 @@ randomfill@^1.0.3:
randombytes "^2.0.5"
safe-buffer "^5.1.0"
-range-parser@^1.2.0, range-parser@~1.2.0:
+range-parser@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
@@ -11109,7 +10928,7 @@ rxjs@5.4.3:
dependencies:
symbol-observable "^1.0.1"
-safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
@@ -11226,51 +11045,6 @@ semver@~4.3.3:
version "4.3.6"
resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
-send@0.16.2:
- version "0.16.2"
- resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
- dependencies:
- debug "2.6.9"
- depd "~1.1.2"
- destroy "~1.0.4"
- encodeurl "~1.0.2"
- escape-html "~1.0.3"
- etag "~1.8.1"
- fresh "0.5.2"
- http-errors "~1.6.2"
- mime "1.4.1"
- ms "2.0.0"
- on-finished "~2.3.0"
- range-parser "~1.2.0"
- statuses "~1.4.0"
-
-serve@^6.3.1:
- version "6.5.3"
- resolved "https://registry.yarnpkg.com/serve/-/serve-6.5.3.tgz#39ae7b7ff5934a9ca93ba7235344eb34b726cc48"
- dependencies:
- "@zeit/check-updates" "1.1.0"
- args "3.0.8"
- basic-auth "2.0.0"
- bluebird "3.5.1"
- boxen "1.3.0"
- chalk "2.3.2"
- clipboardy "1.2.3"
- dargs "5.1.0"
- detect-port "1.2.2"
- filesize "3.6.0"
- fs-extra "5.0.0"
- handlebars "4.0.11"
- ip "1.1.5"
- micro "9.1.0"
- micro-compress "1.0.0"
- mime-types "2.1.18"
- node-version "1.1.0"
- openssl-self-signed-certificate "1.1.6"
- opn "5.2.0"
- path-is-inside "1.0.2"
- path-type "3.0.0"
- send "0.16.2"
-
set-blocking@^2.0.0, set-blocking@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
@@ -11745,7 +11519,7 @@ static-module@^2.2.0:
static-eval "^2.0.0"
through2 "~2.0.3"
-statuses@1, "statuses@>= 1.2.1 < 2", "statuses@>= 1.3.1 < 2", statuses@~1.4.0:
+statuses@1, "statuses@>= 1.2.1 < 2", "statuses@>= 1.3.1 < 2":
version "1.4.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
@@ -11817,12 +11591,6 @@ string-length@^2.0.0:
astral-regex "^1.0.0"
strip-ansi "^4.0.0"
-string-similarity@1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-1.2.0.tgz#d75153cb383846318b7a39a8d9292bb4db4e9c30"
- dependencies:
- lodash "^4.13.1"
-
string-width@^1.0.1, string-width@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
@@ -12720,7 +12488,19 @@ upath@^1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/upath/-/upath-1.0.4.tgz#ee2321ba0a786c50973db043a50b7bcba822361d"
-update-notifier@2.3.0, update-notifier@^2.2.0:
+update-notifier@^0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-0.5.0.tgz#07b5dc2066b3627ab3b4f530130f7eddda07a4cc"
+ dependencies:
+ chalk "^1.0.0"
+ configstore "^1.0.0"
+ is-npm "^1.0.0"
+ latest-version "^1.0.0"
+ repeating "^1.1.2"
+ semver-diff "^2.0.0"
+ string-length "^1.0.0"
+
+update-notifier@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.3.0.tgz#4e8827a6bb915140ab093559d7014e3ebb837451"
dependencies:
@@ -12734,18 +12514,6 @@ update-notifier@2.3.0, update-notifier@^2.2.0:
semver-diff "^2.0.0"
xdg-basedir "^3.0.0"
-update-notifier@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-0.5.0.tgz#07b5dc2066b3627ab3b4f530130f7eddda07a4cc"
- dependencies:
- chalk "^1.0.0"
- configstore "^1.0.0"
- is-npm "^1.0.0"
- latest-version "^1.0.0"
- repeating "^1.1.2"
- semver-diff "^2.0.0"
- string-length "^1.0.0"
-
urix@^0.1.0, urix@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
@@ -12857,10 +12625,6 @@ value-or-function@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813"
-vary@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
-
vega-canvas@1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/vega-canvas/-/vega-canvas-1.0.1.tgz#22cfa510af0cfbd920fc6af8b6111d3de5e63c44"
From 3984c2b31a76aed72629fe1f5e525665e6111b7f Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Wed, 16 May 2018 13:53:19 -0400
Subject: [PATCH 09/38] working port from rbac-phase-1
---
.../public/views/management/edit_role.js | 27 +-----
.../edit_role/components/edit_role_page.js | 40 +++++----
.../{ => privileges}/cluster_privileges.js | 8 +-
.../{ => privileges}/index_privilege_form.js | 2 +-
.../privileges/kibana_privileges.js | 83 +++++++++++++++++++
.../lib/get_application_privileges.js | 26 ++++++
.../lib/set_application_privileges.js | 20 +++++
7 files changed, 164 insertions(+), 42 deletions(-)
rename x-pack/plugins/security/public/views/management/edit_role/components/{ => privileges}/cluster_privileges.js (88%)
rename x-pack/plugins/security/public/views/management/edit_role/components/{ => privileges}/index_privilege_form.js (98%)
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/lib/get_application_privileges.js
diff --git a/x-pack/plugins/security/public/views/management/edit_role.js b/x-pack/plugins/security/public/views/management/edit_role.js
index de26a66847dee..9c19ccacaf824 100644
--- a/x-pack/plugins/security/public/views/management/edit_role.js
+++ b/x-pack/plugins/security/public/views/management/edit_role.js
@@ -26,26 +26,6 @@ import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
-const getKibanaPrivileges = (kibanaApplicationPrivilege, role, application) => {
- const kibanaPrivileges = kibanaApplicationPrivilege.reduce((acc, p) => {
- acc[p.name] = false;
- return acc;
- }, {});
-
- if (!role.applications || role.applications.length === 0) {
- return kibanaPrivileges;
- }
-
- const applications = role.applications.filter(x => x.application === application);
-
- const assigned = _.uniq(_.flatten(_.pluck(applications, 'privileges')));
- assigned.forEach(a => {
- kibanaPrivileges[a] = true;
- });
-
- return kibanaPrivileges;
-};
-
const getOtherApplications = (kibanaPrivileges, role, application) => {
if (!role.applications || role.applications.length === 0) {
return [];
@@ -82,6 +62,7 @@ routes.when(`${EDIT_ROLES_PATH}/:name?`, {
},
kibanaApplicationPrivilege(ApplicationPrivilege, kbnUrl, Promise, Private) {
return ApplicationPrivilege.query().$promise
+ .then(privileges => privileges.map(p => p.toJSON()))
.catch(checkLicenseError(kbnUrl, Promise, Private));
},
users(ShieldUser, kbnUrl, Promise, Private) {
@@ -109,7 +90,7 @@ routes.when(`${EDIT_ROLES_PATH}/:name?`, {
$scope.rbacEnabled = rbacEnabled;
const kibanaApplicationPrivilege = $route.current.locals.kibanaApplicationPrivilege;
const role = $route.current.locals.role;
- $scope.kibanaPrivileges = getKibanaPrivileges(kibanaApplicationPrivilege, role, rbacApplication);
+ $scope.kibanaPrivileges = {};// getKibanaPrivileges(kibanaApplicationPrivilege, role, rbacApplication);
$scope.otherApplications = getOtherApplications(kibanaApplicationPrivilege, role, rbacApplication);
$scope.rolesHref = `#${ROLES_PATH}`;
@@ -144,10 +125,10 @@ routes.when(`${EDIT_ROLES_PATH}/:name?`, {
render( {
- if (!this.props.kibanaPrivilegesEnabled) {
+ if (!this.props.rbacEnabled) {
return null;
}
return (
-
- Cluster Privileges}
- >
-
- { }} />
-
-
+
+ Kibana
+
+
+
+
+
);
};
+ onKibanaPrivilegesChange = (applications) => {
+ this.setState({
+ role: {
+ ...this.state.role,
+ applications
+ }
+ });
+ }
+
editingExistingRole = () => {
return !!this.props.role.name;
};
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/cluster_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/cluster_privileges.js
similarity index 88%
rename from x-pack/plugins/security/public/views/management/edit_role/components/cluster_privileges.js
rename to x-pack/plugins/security/public/views/management/edit_role/components/privileges/cluster_privileges.js
index 8ed97e8aad5c1..8193b73e022bf 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/cluster_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/cluster_privileges.js
@@ -6,15 +6,15 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
-import { getClusterPrivileges } from '../../../../services/role_privileges';
-import { isReservedRole } from '../lib/is_reserved_role';
+import { getClusterPrivileges } from '../../../../../services/role_privileges';
+import { isReservedRole } from '../../lib/is_reserved_role';
import {
EuiCheckboxGroup,
EuiText,
EuiSpacer,
EuiLink,
} from '@elastic/eui';
-import { CLUSTER_PRIVS_DOC_LINK } from '../lib/constants';
+import { CLUSTER_PRIVS_DOC_LINK } from '../../lib/constants';
export class ClusterPrivileges extends Component {
static propTypes = {
@@ -42,7 +42,7 @@ export class ClusterPrivileges extends Component {
Learn more
-
+
option.label;
const toOption = (value) => ({ label: value });
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
new file mode 100644
index 0000000000000..4f26e847ab84c
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
@@ -0,0 +1,83 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { Component, Fragment } from 'react';
+import PropTypes from 'prop-types';
+import { isReservedRole } from '../../lib/is_reserved_role';
+import { getKibanaPrivileges } from '../../lib/get_application_privileges';
+import { togglePrivilege } from '../../lib/set_application_privileges';
+import {
+ EuiCheckboxGroup,
+ EuiText,
+ EuiSpacer,
+} from '@elastic/eui';
+
+
+export class KibanaPrivileges extends Component {
+ static propTypes = {
+ role: PropTypes.object.isRequired,
+ kibanaAppPrivileges: PropTypes.array.isRequired,
+ onChange: PropTypes.func.isRequired,
+ };
+
+ idPrefix = () => `${this.props.rbacApplication}_`;
+
+ privilegeToId = (privilege) => `${this.idPrefix()}${privilege}`;
+
+ idToPrivilege = (id) => id.split(this.idPrefix())[1];
+
+ render() {
+
+ const {
+ kibanaAppPrivileges,
+ role,
+ rbacApplication
+ } = this.props;
+
+ const kibanaPrivileges = getKibanaPrivileges(kibanaAppPrivileges, role, rbacApplication);
+
+ const checkboxes = Object.keys(kibanaPrivileges).map(p => ({
+ id: this.privilegeToId(p),
+ label: p
+ }));
+
+ const selectionMap = Object.keys(kibanaPrivileges).reduce((acc, p) => {
+ return {
+ ...acc,
+ [this.privilegeToId(p)]: kibanaPrivileges[p]
+ };
+ }, {});
+
+ return (
+
+
+
+ Manage the actions this role can perform against Kibana.
+
+
+
+
+
+ );
+ }
+
+ onKibanaPrivilegesChange = (privilege) => {
+ console.log('kib priv change', privilege);
+ const role = {
+ ...this.props.role,
+ applications: [...this.props.role.applications]
+ };
+
+ togglePrivilege(role, this.props.rbacApplication, this.idToPrivilege(privilege));
+
+ this.props.onChange(role.applications);
+ }
+}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/lib/get_application_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/lib/get_application_privileges.js
new file mode 100644
index 0000000000000..1ee8d201806b6
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/lib/get_application_privileges.js
@@ -0,0 +1,26 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import _ from 'lodash';
+
+export function getKibanaPrivileges(kibanaApplicationPrivilege, role, application) {
+ const kibanaPrivileges = kibanaApplicationPrivilege.reduce((acc, p) => {
+ acc[p.name] = false;
+ return acc;
+ }, {});
+
+ if (!role.applications || role.applications.length === 0) {
+ return kibanaPrivileges;
+ }
+
+ const applications = role.applications.filter(x => x.application === application);
+
+ const assigned = _.uniq(_.flatten(_.pluck(applications, 'privileges')));
+ assigned.forEach(a => {
+ kibanaPrivileges[a] = true;
+ });
+
+ return kibanaPrivileges;
+}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/lib/set_application_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/lib/set_application_privileges.js
index e14aad01f6807..e6e133fbf69bd 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/lib/set_application_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/lib/set_application_privileges.js
@@ -27,3 +27,23 @@ export function setApplicationPrivileges(kibanaPrivileges, role, application) {
}];
}
}
+
+export function togglePrivilege(role, application, permission) {
+ const appPermissions = role.applications
+ .find(a => a.application === application && a.resources[0] === DEFAULT_RESOURCE);
+
+ if (!appPermissions) {
+ role.applications.push({
+ application,
+ privileges: [permission],
+ resources: [DEFAULT_RESOURCE]
+ });
+ } else {
+ const indexOfExisting = appPermissions.privileges.indexOf(permission);
+ if (indexOfExisting >= 0) {
+ appPermissions.privileges.splice(indexOfExisting, 1);
+ } else {
+ appPermissions.privileges.push(permission);
+ }
+ }
+}
From 4f39d2b273223b1b2da2c2dc5956d0a1f2a06e73 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Wed, 16 May 2018 15:09:00 -0400
Subject: [PATCH 10/38] refactor permission components
---
.../public/views/management/edit_role.html | 197 +---------
.../public/views/management/edit_role.js | 20 -
.../edit_role/components/edit_role_page.js | 359 ++++--------------
.../privileges/elasticsearch_privileges.js | 135 +++++++
.../edit_role/components/privileges/index.js | 8 +
.../components/privileges/index_privileges.js | 172 +++++++++
.../privileges/kibana_privileges.js | 12 +-
7 files changed, 395 insertions(+), 508 deletions(-)
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/privileges/index.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
diff --git a/x-pack/plugins/security/public/views/management/edit_role.html b/x-pack/plugins/security/public/views/management/edit_role.html
index 198dae71b4485..2e8134b17d29f 100644
--- a/x-pack/plugins/security/public/views/management/edit_role.html
+++ b/x-pack/plugins/security/public/views/management/edit_role.html
@@ -1,196 +1 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- New Role
-
-
- “{{ role.name }}” Role
-
-
-
-
-
-
-
-
-
- Delete role
-
-
-
-
- Reserved
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/x-pack/plugins/security/public/views/management/edit_role.js b/x-pack/plugins/security/public/views/management/edit_role.js
index 9c19ccacaf824..27dc0a63141c2 100644
--- a/x-pack/plugins/security/public/views/management/edit_role.js
+++ b/x-pack/plugins/security/public/views/management/edit_role.js
@@ -25,15 +25,6 @@ import { EditRolePage } from './edit_role/components/edit_role_page';
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
-
-const getOtherApplications = (kibanaPrivileges, role, application) => {
- if (!role.applications || role.applications.length === 0) {
- return [];
- }
-
- return role.applications.map(x => x.application).filter(x => x !== application);
-};
-
routes.when(`${EDIT_ROLES_PATH}/:name?`, {
template,
resolve: {
@@ -83,17 +74,8 @@ routes.when(`${EDIT_ROLES_PATH}/:name?`, {
const Notifier = $injector.get('Notifier');
- $scope.role = $route.current.locals.role;
- $scope.users = $route.current.locals.users;
- $scope.indexPatterns = $route.current.locals.indexPatterns;
-
- $scope.rbacEnabled = rbacEnabled;
const kibanaApplicationPrivilege = $route.current.locals.kibanaApplicationPrivilege;
const role = $route.current.locals.role;
- $scope.kibanaPrivileges = {};// getKibanaPrivileges(kibanaApplicationPrivilege, role, rbacApplication);
- $scope.otherApplications = getOtherApplications(kibanaApplicationPrivilege, role, rbacApplication);
-
- $scope.rolesHref = `#${ROLES_PATH}`;
this.isNewRole = $route.current.params.name == null;
this.fieldOptions = {};
@@ -141,7 +123,5 @@ routes.when(`${EDIT_ROLES_PATH}/:name?`, {
$scope.$on('$destroy', () => {
unmountComponentAtNode(domNode);
});
-
- $scope.union = _.flow(_.union, _.compact);
}
});
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
index a276688eca4f3..cf8b77a77f72f 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
@@ -3,38 +3,31 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { Component, Fragment } from 'react';
+import React, { Component } from 'react';
import PropTypes from 'prop-types';
-import { difference, get } from 'lodash';
+import { get } from 'lodash';
import { Notifier, toastNotifications } from 'ui/notify';
import {
EuiText,
EuiSpacer,
- EuiIcon,
- EuiAccordion,
- EuiComboBox,
EuiPage,
EuiPageContent,
- EuiPanel,
EuiForm,
EuiFormRow,
EuiFieldText,
EuiFlexGroup,
EuiFlexItem,
EuiButton,
- EuiTitle,
} from '@elastic/eui';
import { PageHeader } from './page_header';
-import { IndexPrivilegeForm } from './privileges/index_privilege_form';
-import { ClusterPrivileges } from './privileges/cluster_privileges';
-import { getFields, saveRole, deleteRole } from '../../../../objects';
+import { saveRole, deleteRole } from '../../../../objects';
import { isReservedRole } from '../lib/is_reserved_role';
import { RoleValidator } from '../lib/validate_role';
import { ReservedRoleBadge } from './reserved_role_badge';
import { ROLES_PATH } from '../../management_urls';
import { DeleteRoleButton } from './delete_role_button';
import { setApplicationPrivileges } from '../lib/set_application_privileges';
-import { KibanaPrivileges } from './privileges/kibana_privileges';
+import { ElasticsearchPrivileges, KibanaPrivileges } from './privileges';
const notifier = new Notifier();
@@ -56,112 +49,52 @@ export class EditRolePage extends Component {
super(props);
this.state = {
role: props.role,
- availableFields: {},
formError: null
};
this.validator = new RoleValidator({ shouldValidate: false });
}
- componentDidMount() {
- this.loadAvailableFields(this.state.role.indices);
- }
-
- loadAvailableFields(indices) {
- const patterns = indices.map(index => index.names.join(','));
-
- const cachedPatterns = Object.keys(this.state.availableFields);
- const patternsToFetch = difference(patterns, cachedPatterns);
-
- const fetchRequests = patternsToFetch.map(this.loadFieldsForPattern);
-
- Promise.all(fetchRequests)
- .then(response => {
-
- this.setState({
- availableFields: {
- ...this.state.availableFields,
- ...response.reduce((acc, o) => ({ ...acc, ...o }), {})
- }
- });
- });
- }
-
- loadFieldsForPattern = async (pattern) => {
- if (!pattern) return { [pattern]: [] };
-
- try {
- return {
- [pattern]: await getFields(this.props.httpClient, pattern)
- };
-
- } catch (e) {
- return {
- [pattern]: []
- };
- }
- }
-
render() {
- const {
- validator
- } = this;
-
return (
-
-
- {this.getTitle()}
-
- {this.getActionButton()}
-
-
-
-
-
-
-
-
-
+
+ {this.getRoleName()}
{this.getElasticsearchPrivileges()}
+
+
{this.getKibanaPrivileges()}
-
-
- Save
-
-
-
- Cancel
-
-
-
+ {this.getFormButtons()}
);
}
- getTitle = () => {
- if (this.editingExistingRole()) {
- return `Edit role`;
- }
- return `New Role`;
+ getFormTitle = () => {
+ const titleText = this.editingExistingRole()
+ ? 'Edit Role'
+ : 'New Role';
+
+ return (
+
+
+ {titleText}
+
+ {this.getActionButton()}
+
+ );
};
getActionButton = () => {
@@ -176,6 +109,24 @@ export class EditRolePage extends Component {
return null;
};
+ getRoleName = () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+ }
+
onNameChange = (e) => {
const rawValue = e.target.value;
const name = rawValue.replace(/\s/g, '-');
@@ -188,190 +139,24 @@ export class EditRolePage extends Component {
});
}
- getElasticsearchPrivileges = () => {
- const {
- role
- } = this.state;
-
+ getElasticsearchPrivileges() {
return (
-
-
- Elasticsearch
-
-
-
-
-
- Cluster Privileges ({role.cluster.length})}
- >
-
-
-
-
-
-
-
- Index Privileges (
- {role.indices.filter(i => i.names.length).length})
-
- }
- >
-
-
- Index Privileges allow you to foo the bar while baring the baz
-
-
-
- {this.getIndexPrivileges()}
-
-
-
-
-
- Run As Privileges ({role.run_as.length})}
- >
-
-
- Run As Privileges allow you to foo the bar while baring the baz
-
-
-
- ({ id: username, label: username }))}
- selectedOptions={this.state.role.run_as.map(u => ({ label: u }))}
- onChange={this.onRunAsUserChange}
- isDisabled={isReservedRole(this.props.role)}
- />
-
-
-
- );
- };
-
- getIndexPrivileges = () => {
- const { indices = [] } = this.state.role;
-
- const {
- indexPatterns,
- allowDocumentLevelSecurity,
- allowFieldLevelSecurity
- } = this.props;
-
- const props = {
- indexPatterns,
- allowDocumentLevelSecurity,
- allowFieldLevelSecurity,
- isReservedRole: isReservedRole(this.props.role)
- };
-
- const forms = indices.map((indexPrivilege, idx) => (
-
- ));
-
- const button = isReservedRole(this.props.role)
- ? null
- : (
-
-
-
- New Index Privilege
-
-
-
- );
-
- return (
-
- {forms}
- {button}
-
);
- };
-
- addIndexPrivilege = () => {
- const { role } = this.state;
-
- this.setState({
- role: {
- ...role,
- indices: [...role.indices, {
- names: [],
- privileges: [],
- field_security: {
- grant: ['*']
- }
- }]
- }
- });
- };
-
- onIndexPrivilegeChange = (index) => {
- return (updatedPrivilege) => {
- const { role } = this.state;
- const { indices } = role;
-
- const newIndicesState = [...indices];
- newIndicesState[index] = updatedPrivilege;
-
- this.setState({
- role: {
- ...role,
- indices: newIndicesState
- }
- });
-
- this.loadAvailableFields(newIndicesState);
- };
- };
-
- onIndexPrivilegeDelete = (privilegeIndex) => {
- return () => {
- const { role } = this.state;
-
- const newIndicesState = [...role.indices];
- newIndicesState.splice(privilegeIndex, 1);
-
- this.setState({
- role: {
- ...role,
- indices: newIndicesState
- }
- });
- };
}
- onClusterPrivilegesChange = (cluster) => {
+ onRoleChange = (role) => {
this.setState({
- role: {
- ...this.state.role,
- cluster
- }
- });
- }
-
- onRunAsUserChange = (users) => {
- this.setState({
- role: {
- ...this.state.role,
- run_as: users.map(u => u.label)
- }
+ role
});
}
@@ -381,31 +166,29 @@ export class EditRolePage extends Component {
}
return (
-
-
- Kibana
-
-
-
-
-
-
+
);
};
- onKibanaPrivilegesChange = (applications) => {
- this.setState({
- role: {
- ...this.state.role,
- applications
- }
- });
- }
+ getFormButtons = () => {
+ return (
+
+
+ Save
+
+
+
+ Cancel
+
+
+
+ );
+ };
editingExistingRole = () => {
return !!this.props.role.name;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
new file mode 100644
index 0000000000000..ef1c09bf70095
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
@@ -0,0 +1,135 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { Component, Fragment } from 'react';
+import PropTypes from 'prop-types';
+import {
+ EuiText,
+ EuiSpacer,
+ EuiIcon,
+ EuiAccordion,
+ EuiComboBox,
+ EuiPanel,
+ EuiTitle,
+} from '@elastic/eui';
+import { isReservedRole } from '../../lib/is_reserved_role';
+import { ClusterPrivileges } from './cluster_privileges';
+import { IndexPrivileges } from './index_privileges';
+
+export class ElasticsearchPrivileges extends Component {
+ static propTypes = {
+ role: PropTypes.object.isRequired,
+ httpClient: PropTypes.func.isRequired,
+ onChange: PropTypes.func.isRequired,
+ runAsUsers: PropTypes.array.isRequired,
+ validator: PropTypes.object.isRequired,
+ };
+
+ render() {
+ const {
+ role,
+ httpClient,
+ validator,
+ onChange,
+ indexPatterns,
+ allowDocumentLevelSecurity,
+ allowFieldLevelSecurity,
+ } = this.props;
+
+ const indexProps = {
+ role,
+ httpClient,
+ validator,
+ indexPatterns,
+ allowDocumentLevelSecurity,
+ allowFieldLevelSecurity,
+ onChange,
+ };
+
+ return (
+
+
+ Elasticsearch
+
+
+
+
+
+ Cluster Privileges ({role.cluster.length})}
+ >
+
+
+
+
+
+
+
+ Index Privileges (
+ {role.indices.filter(i => i.names.length).length})
+
+ }
+ >
+
+
+ Index Privileges allow you to foo the bar while baring the baz
+
+
+
+
+
+
+
+
+
+
+
+
+ Run As Privileges ({role.run_as.length})}
+ >
+
+
+ Run As Privileges allow you to foo the bar while baring the baz
+
+
+
+ ({ id: username, label: username }))}
+ selectedOptions={this.props.role.run_as.map(u => ({ label: u }))}
+ onChange={this.onRunAsUserChange}
+ isDisabled={isReservedRole(this.props.role)}
+ />
+
+
+
+ );
+ }
+
+ onClusterPrivilegesChange = (cluster) => {
+ const role = {
+ ...this.props.role,
+ cluster
+ };
+
+ this.props.onChange(role);
+ }
+
+ onRunAsUserChange = (users) => {
+ const role = {
+ ...this.props.role,
+ run_as: users.map(u => u.label)
+ };
+
+ this.props.onChange(role);
+ }
+}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index.js
new file mode 100644
index 0000000000000..d142af394b155
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index.js
@@ -0,0 +1,8 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { ElasticsearchPrivileges } from './elasticsearch_privileges';
+export { KibanaPrivileges } from './kibana_privileges';
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
new file mode 100644
index 0000000000000..4f52be678e7f0
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
@@ -0,0 +1,172 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React, { Component, Fragment } from 'react';
+import PropTypes from 'prop-types';
+import _ from 'lodash';
+import { isReservedRole } from '../../lib/is_reserved_role';
+import { IndexPrivilegeForm } from './index_privilege_form';
+import { getFields } from '../../../../../objects';
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiButton
+} from '@elastic/eui';
+
+export class IndexPrivileges extends Component {
+ static propTypes = {
+ role: PropTypes.object.isRequired,
+ indexPatterns: PropTypes.array.isRequired,
+ allowDocumentLevelSecurity: PropTypes.bool.isRequired,
+ allowFieldLevelSecurity: PropTypes.bool.isRequired,
+ httpClient: PropTypes.func.isRequired,
+ onChange: PropTypes.func.isRequired,
+ validator: PropTypes.object.isRequired,
+ }
+
+ state = {
+ availableFields: {}
+ }
+
+ componentDidMount() {
+ this.loadAvailableFields(this.props.role.indices);
+ }
+
+ render() {
+ const { indices = [] } = this.props.role;
+
+ const {
+ indexPatterns,
+ allowDocumentLevelSecurity,
+ allowFieldLevelSecurity
+ } = this.props;
+
+ const props = {
+ indexPatterns,
+ allowDocumentLevelSecurity,
+ allowFieldLevelSecurity,
+ isReservedRole: isReservedRole(this.props.role)
+ };
+
+ const forms = indices.map((indexPrivilege, idx) => (
+
+ ));
+
+ const button = isReservedRole(this.props.role)
+ ? null
+ : (
+
+
+
+ New Index Privilege
+
+
+
+ );
+
+ return (
+
+ {forms}
+ {button}
+
+ );
+ }
+
+ addIndexPrivilege = () => {
+ const { role } = this.props;
+
+ const newIndices = [...role.indices, {
+ names: [],
+ privileges: [],
+ field_security: {
+ grant: ['*']
+ }
+ }];
+
+ this.props.onChange({
+ ...this.props.role,
+ indices: newIndices
+ });
+ };
+
+ onIndexPrivilegeChange = (privilegeIndex) => {
+ return (updatedPrivilege) => {
+ const { role } = this.props;
+ const { indices } = role;
+
+ const newIndices = [...indices];
+ newIndices[privilegeIndex] = updatedPrivilege;
+
+ this.props.onChange({
+ ...this.props.role,
+ indices: newIndices
+ });
+
+ this.loadAvailableFields(newIndices);
+ };
+ };
+
+ onIndexPrivilegeDelete = (privilegeIndex) => {
+ return () => {
+ const { role } = this.state;
+
+ const newIndices = [...role.indices];
+ newIndices.splice(privilegeIndex, 1);
+
+ this.props.onChange({
+ ...this.props.role,
+ indices: newIndices
+ });
+ };
+ }
+
+ isPlaceholderPrivilege = (indexPrivilege) => {
+ return indexPrivilege.names.length === 0;
+ };
+
+ loadAvailableFields(indices) {
+ const patterns = indices.map(index => index.names.join(','));
+
+ const cachedPatterns = Object.keys(this.state.availableFields);
+ const patternsToFetch = _.difference(patterns, cachedPatterns);
+
+ const fetchRequests = patternsToFetch.map(this.loadFieldsForPattern);
+
+ Promise.all(fetchRequests)
+ .then(response => {
+
+ this.setState({
+ availableFields: {
+ ...this.state.availableFields,
+ ...response.reduce((acc, o) => ({ ...acc, ...o }), {})
+ }
+ });
+ });
+ }
+
+ loadFieldsForPattern = async (pattern) => {
+ if (!pattern) return { [pattern]: [] };
+
+ try {
+ return {
+ [pattern]: await getFields(this.props.httpClient, pattern)
+ };
+
+ } catch (e) {
+ return {
+ [pattern]: []
+ };
+ }
+ }
+}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
index 4f26e847ab84c..32005aafa04ce 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
@@ -13,9 +13,8 @@ import {
EuiCheckboxGroup,
EuiText,
EuiSpacer,
+ EuiTitle,
} from '@elastic/eui';
-
-
export class KibanaPrivileges extends Component {
static propTypes = {
role: PropTypes.object.isRequired,
@@ -53,6 +52,12 @@ export class KibanaPrivileges extends Component {
return (
+
+ Kibana
+
+
+
+
Manage the actions this role can perform against Kibana.
@@ -70,7 +75,6 @@ export class KibanaPrivileges extends Component {
}
onKibanaPrivilegesChange = (privilege) => {
- console.log('kib priv change', privilege);
const role = {
...this.props.role,
applications: [...this.props.role.applications]
@@ -78,6 +82,6 @@ export class KibanaPrivileges extends Component {
togglePrivilege(role, this.props.rbacApplication, this.idToPrivilege(privilege));
- this.props.onChange(role.applications);
+ this.props.onChange(role);
}
}
From 918cca4a6b5367ceaecd2de9c5b556331263ca24 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Wed, 16 May 2018 15:44:15 -0400
Subject: [PATCH 11/38] combine role utils into a single file
---
x-pack/plugins/security/public/lib/role.js | 11 ++++++++++-
.../management/edit_role/components/edit_role_page.js | 2 +-
.../components/privileges/cluster_privileges.js | 2 +-
.../components/privileges/elasticsearch_privileges.js | 2 +-
.../components/privileges/index_privileges.js | 2 +-
.../components/privileges/kibana_privileges.js | 2 +-
.../edit_role/components/reserved_role_badge.js | 2 +-
.../management/edit_role/lib/is_reserved_role.js | 9 ---------
8 files changed, 16 insertions(+), 16 deletions(-)
delete mode 100644 x-pack/plugins/security/public/views/management/edit_role/lib/is_reserved_role.js
diff --git a/x-pack/plugins/security/public/lib/role.js b/x-pack/plugins/security/public/lib/role.js
index 89eade0f0584e..96057aa55f595 100644
--- a/x-pack/plugins/security/public/lib/role.js
+++ b/x-pack/plugins/security/public/lib/role.js
@@ -14,4 +14,13 @@ import { get } from 'lodash';
*/
export function isRoleEnabled(role) {
return get(role, 'transient_metadata.enabled', true);
-}
\ No newline at end of file
+}
+
+/**
+ * Returns whether given role is reserved or not.
+ *
+ * @param {role} the Role as returned by roles API
+ */
+export function isReservedRole(role) {
+ return get(role, 'metadata._reserved', false);
+}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
index cf8b77a77f72f..3564d66221ac0 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
@@ -21,7 +21,7 @@ import {
} from '@elastic/eui';
import { PageHeader } from './page_header';
import { saveRole, deleteRole } from '../../../../objects';
-import { isReservedRole } from '../lib/is_reserved_role';
+import { isReservedRole } from '../../../../lib/role';
import { RoleValidator } from '../lib/validate_role';
import { ReservedRoleBadge } from './reserved_role_badge';
import { ROLES_PATH } from '../../management_urls';
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/cluster_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/cluster_privileges.js
index 8193b73e022bf..f0bd225db61e5 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/cluster_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/cluster_privileges.js
@@ -7,7 +7,7 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { getClusterPrivileges } from '../../../../../services/role_privileges';
-import { isReservedRole } from '../../lib/is_reserved_role';
+import { isReservedRole } from '../../../../../lib/role';
import {
EuiCheckboxGroup,
EuiText,
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
index ef1c09bf70095..39345f8461b2a 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
@@ -15,9 +15,9 @@ import {
EuiPanel,
EuiTitle,
} from '@elastic/eui';
-import { isReservedRole } from '../../lib/is_reserved_role';
import { ClusterPrivileges } from './cluster_privileges';
import { IndexPrivileges } from './index_privileges';
+import { isReservedRole } from '../../../../../lib/role';
export class ElasticsearchPrivileges extends Component {
static propTypes = {
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
index 4f52be678e7f0..ef9800eb416f4 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
@@ -6,7 +6,7 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
-import { isReservedRole } from '../../lib/is_reserved_role';
+import { isReservedRole } from '../../../../../lib/role';
import { IndexPrivilegeForm } from './index_privilege_form';
import { getFields } from '../../../../../objects';
import {
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
index 32005aafa04ce..b8b81afdf5d34 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
@@ -6,7 +6,7 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
-import { isReservedRole } from '../../lib/is_reserved_role';
+import { isReservedRole } from '../../../../../lib/role';
import { getKibanaPrivileges } from '../../lib/get_application_privileges';
import { togglePrivilege } from '../../lib/set_application_privileges';
import {
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.js b/x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.js
index bebc146f602ff..8d0c17bd062ab 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.js
@@ -7,7 +7,7 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { isReservedRole } from '../lib/is_reserved_role';
+import { isReservedRole } from '../../../../lib/role';
import {
EuiBadge,
EuiToolTip,
diff --git a/x-pack/plugins/security/public/views/management/edit_role/lib/is_reserved_role.js b/x-pack/plugins/security/public/views/management/edit_role/lib/is_reserved_role.js
deleted file mode 100644
index 84d003e1b6033..0000000000000
--- a/x-pack/plugins/security/public/views/management/edit_role/lib/is_reserved_role.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-export function isReservedRole(role) {
- return (role && role.metadata && role.metadata._reserved) || false;
-}
From fcc74323b2cd518cf455acaeaaf5393cb7726047 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Wed, 16 May 2018 15:59:25 -0400
Subject: [PATCH 12/38] add index.js to components directory
---
.../plugins/security/public/views/management/edit_role.js | 2 +-
.../public/views/management/edit_role/components/index.js | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/index.js
diff --git a/x-pack/plugins/security/public/views/management/edit_role.js b/x-pack/plugins/security/public/views/management/edit_role.js
index 27dc0a63141c2..8a3423ea8ccae 100644
--- a/x-pack/plugins/security/public/views/management/edit_role.js
+++ b/x-pack/plugins/security/public/views/management/edit_role.js
@@ -20,7 +20,7 @@ import { XPackInfoProvider } from 'plugins/xpack_main/services/xpack_info';
import { checkLicenseError } from 'plugins/security/lib/check_license_error';
import { EDIT_ROLES_PATH, ROLES_PATH } from './management_urls';
-import { EditRolePage } from './edit_role/components/edit_role_page';
+import { EditRolePage } from './edit_role/components';
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/index.js b/x-pack/plugins/security/public/views/management/edit_role/components/index.js
new file mode 100644
index 0000000000000..1a0afb37c4791
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { EditRolePage } from './edit_role_page';
From 74e1d4a8b9bf67b7dddae8119b322a7d4a239058 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Thu, 17 May 2018 08:48:01 -0400
Subject: [PATCH 13/38] Improve form validation
---
.../privileges/elasticsearch_privileges.js | 30 +++++++++++++++----
.../privileges/kibana_privileges.js | 3 +-
.../management/edit_role/lib/validate_role.js | 4 +--
.../edit_role/lib/validate_role.test.js | 9 +++---
4 files changed, 33 insertions(+), 13 deletions(-)
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
index 39345f8461b2a..e8e40ba3fc4ae 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
@@ -8,6 +8,7 @@ import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import {
EuiText,
+ EuiTextColor,
EuiSpacer,
EuiIcon,
EuiAccordion,
@@ -49,10 +50,16 @@ export class ElasticsearchPrivileges extends Component {
onChange,
};
+ const {
+ isInvalid
+ } = validator.validateIndexPrivileges(role);
+
+ const indexTextColor = isInvalid ? 'danger' : 'default';
+
return (
- Elasticsearch
+ Elasticsearch
@@ -60,8 +67,13 @@ export class ElasticsearchPrivileges extends Component {
Cluster Privileges ({role.cluster.length})}
+ buttonContent={
+
+ Cluster Privileges ({role.cluster.length})
+
+ }
>
+
@@ -72,14 +84,18 @@ export class ElasticsearchPrivileges extends Component {
id={'indexPrivilegesAccordion'}
buttonContent={
- Index Privileges (
- {role.indices.filter(i => i.names.length).length})
+
+ Index Privileges (
+ {role.indices.filter(i => i.names.length).length})
+
}
>
+
+
- Index Privileges allow you to foo the bar while baring the baz
+ Control access to the data in your cluster.
@@ -96,9 +112,11 @@ export class ElasticsearchPrivileges extends Component {
id={'runAsPrivilegesAccordion'}
buttonContent={ Run As Privileges ({role.run_as.length})
}
>
+
+
- Run As Privileges allow you to foo the bar while baring the baz
+ Allow requests to be submitted on behalf of other users.
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
index b8b81afdf5d34..3c222800108b1 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
@@ -18,6 +18,7 @@ import {
export class KibanaPrivileges extends Component {
static propTypes = {
role: PropTypes.object.isRequired,
+ spaces: PropTypes.array,
kibanaAppPrivileges: PropTypes.array.isRequired,
onChange: PropTypes.func.isRequired,
};
@@ -53,7 +54,7 @@ export class KibanaPrivileges extends Component {
return (
- Kibana
+ Kibana
diff --git a/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.js b/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.js
index 3c7ffa0b667eb..0179c4bb2d40e 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.js
@@ -23,8 +23,8 @@ export class RoleValidator {
if (!role.name) {
return invalid(`Please provide a role name`);
}
- if (role.name.length > 30) {
- return invalid(`Name must not exceed 30 characters`);
+ if (role.name.length > 1024) {
+ return invalid(`Name must not exceed 1024 characters`);
}
if (!role.name.match(/^[a-zA-Z_][a-zA-Z0-9_@\-\$\.]*$/)) {
return invalid(`Name must begin with a letter or underscore and contain only letters, underscores, and numbers.`);
diff --git a/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.test.js b/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.test.js
index eea22c4d75fb0..795e681be5d59 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.test.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.test.js
@@ -28,12 +28,12 @@ describe('validateRoleName', () => {
expect(validator.validateRoleName(role)).toEqual({ isInvalid: true, error: `Please provide a role name` });
});
- test('it cannot exceed 30 characters', () => {
+ test('it cannot exceed 1024 characters', () => {
const role = {
- name: 'This-is-a31-character-role-name'
+ name: new Array(1026).join('A')
};
- expect(validator.validateRoleName(role)).toEqual({ isInvalid: true, error: `Name must not exceed 30 characters` });
+ expect(validator.validateRoleName(role)).toEqual({ isInvalid: true, error: `Name must not exceed 1024 characters` });
});
const charList = `!#%^&*()+=[]{}\|';:"/,<>?`.split('');
@@ -44,7 +44,8 @@ describe('validateRoleName', () => {
};
expect(validator.validateRoleName(role)).toEqual(
- { isInvalid: true,
+ {
+ isInvalid: true,
error: `Name must begin with a letter or underscore and contain only letters, underscores, and numbers.`
}
);
From 92812e54ded619745b915236ddcf2e50cae1883b Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Fri, 18 May 2018 14:48:59 -0400
Subject: [PATCH 14/38] Fixes #18166 : warn when no fields are granted
---
.../privileges/index_privilege_form.js | 36 ++++++++++++++-----
.../components/privileges/index_privileges.js | 2 +-
2 files changed, 29 insertions(+), 9 deletions(-)
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
index 3d69531880807..f5059ccef160f 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
@@ -6,6 +6,7 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import {
+ EuiCallOut,
EuiComboBox,
EuiTextArea,
EuiFormRow,
@@ -116,20 +117,39 @@ export class IndexPrivilegeForm extends Component {
));
}
+ let grantedFieldsWarning = null;
+
if (allowFieldLevelSecurity) {
const { grant = [] } = indexPrivilege.field_security || {};
+ if (grant.length === 0) {
+ grantedFieldsWarning = (
+
+
+
+
+ If no fields are granted, then users assigned to this role will not be able to
+ see any data for this index. Is this really what you want?
+
+
+
+ );
+ }
+
features.push((
-
-
+
+
+
+ {grantedFieldsWarning}
+
));
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
index ef9800eb416f4..58a1834974e56 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
@@ -119,7 +119,7 @@ export class IndexPrivileges extends Component {
onIndexPrivilegeDelete = (privilegeIndex) => {
return () => {
- const { role } = this.state;
+ const { role } = this.props;
const newIndices = [...role.indices];
newIndices.splice(privilegeIndex, 1);
From b6d1b9aa7f91d6240408e4c4f9020f0335f31fd3 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Mon, 21 May 2018 13:23:56 -0400
Subject: [PATCH 15/38] Disable certain edits for Reserved Spaces
---
x-pack/plugins/spaces/common/index.js | 7 ++++
.../components/manage_space_page.js | 28 ++++++++++----
.../components/reserved_space_badge.js | 37 +++++++++++++++++++
.../components/reserved_space_badge.test.js | 30 +++++++++++++++
.../management/components/url_context.js | 6 ++-
5 files changed, 99 insertions(+), 9 deletions(-)
create mode 100644 x-pack/plugins/spaces/common/index.js
create mode 100644 x-pack/plugins/spaces/public/views/management/components/reserved_space_badge.js
create mode 100644 x-pack/plugins/spaces/public/views/management/components/reserved_space_badge.test.js
diff --git a/x-pack/plugins/spaces/common/index.js b/x-pack/plugins/spaces/common/index.js
new file mode 100644
index 0000000000000..1cd6907d3d64c
--- /dev/null
+++ b/x-pack/plugins/spaces/common/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { isReservedSpace } from './is_reserved_space';
\ No newline at end of file
diff --git a/x-pack/plugins/spaces/public/views/management/components/manage_space_page.js b/x-pack/plugins/spaces/public/views/management/components/manage_space_page.js
index 2262e597fb433..2207076c3e695 100644
--- a/x-pack/plugins/spaces/public/views/management/components/manage_space_page.js
+++ b/x-pack/plugins/spaces/public/views/management/components/manage_space_page.js
@@ -25,6 +25,8 @@ import { DeleteSpacesButton } from './delete_spaces_button';
import { Notifier, toastNotifications } from 'ui/notify';
import { UrlContext } from './url_context';
import { toUrlContext, isValidUrlContext } from '../lib/url_context_utils';
+import { isReservedSpace } from '../../../../common';
+import { ReservedSpaceBadge } from './reserved_space_badge';
export class ManageSpacePage extends React.Component {
state = {
@@ -71,12 +73,7 @@ export class ManageSpacePage extends React.Component {
-
-
- {this.getTitle()}
-
- {this.getActionButton()}
-
+ {this.getFormHeading()}
@@ -108,7 +105,7 @@ export class ManageSpacePage extends React.Component {
@@ -128,6 +125,19 @@ export class ManageSpacePage extends React.Component {
);
}
+ getFormHeading = () => {
+ const isReserved = isReservedSpace(this.state.space);
+
+ return (
+
+
+ {this.getTitle()}
+
+ {isReserved ? this.getReservedBadge() : this.getActionButton()}
+
+ );
+ };
+
getTitle = () => {
if (this.editingExistingSpace()) {
return `Edit space`;
@@ -135,8 +145,10 @@ export class ManageSpacePage extends React.Component {
return `Create a space`;
};
+ getReservedBadge = () => ;
+
getActionButton = () => {
- if (this.editingExistingSpace()) {
+ if (this.editingExistingSpace() && !isReservedSpace(this.state.space)) {
return (
{
+ const {
+ space
+ } = props;
+
+ if (isReservedSpace(space)) {
+ return (
+
+
+ Reserved Space
+
+
+ );
+ }
+ return null;
+};
+
+ReservedSpaceBadge.propTypes = {
+ space: PropTypes.object.isRequired
+};
diff --git a/x-pack/plugins/spaces/public/views/management/components/reserved_space_badge.test.js b/x-pack/plugins/spaces/public/views/management/components/reserved_space_badge.test.js
new file mode 100644
index 0000000000000..e45926b859824
--- /dev/null
+++ b/x-pack/plugins/spaces/public/views/management/components/reserved_space_badge.test.js
@@ -0,0 +1,30 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import {
+ EuiBadge
+} from '@elastic/eui';
+import { ReservedSpaceBadge } from './reserved_space_badge';
+import {
+ shallow
+} from 'enzyme';
+
+const reservedSpace = {
+ _reserved: true
+};
+
+const unreservedSpace = {};
+
+test('it renders without crashing', () => {
+ const wrapper = shallow( );
+ expect(wrapper.find(EuiBadge)).toHaveLength(1);
+});
+
+test('it renders nothing for an unreserved space', () => {
+ const wrapper = shallow( );
+ expect(wrapper.find('*')).toHaveLength(0);
+});
diff --git a/x-pack/plugins/spaces/public/views/management/components/url_context.js b/x-pack/plugins/spaces/public/views/management/components/url_context.js
index 418a51b29347e..6253e36d0f9e2 100644
--- a/x-pack/plugins/spaces/public/views/management/components/url_context.js
+++ b/x-pack/plugins/spaces/public/views/management/components/url_context.js
@@ -35,7 +35,7 @@ export class UrlContext extends Component {
this.textFieldRef = ref}
@@ -48,6 +48,10 @@ export class UrlContext extends Component {
}
getLabel = () => {
+ if (!this.props.editable) {
+ return (URL Context
);
+ }
+
const editLinkText = this.state.editing ? `[stop editing]` : `[edit]`;
return (URL Context {editLinkText}
);
};
From 36e7a67b5e6822ad9670f3b0c8a56d844bb7e963 Mon Sep 17 00:00:00 2001
From: Brandon Kobel
Date: Tue, 22 May 2018 11:05:20 -0400
Subject: [PATCH 16/38] Adding built-in types and alphabetizing (#19306)
---
x-pack/plugins/security/server/lib/privileges/privileges.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/x-pack/plugins/security/server/lib/privileges/privileges.js b/x-pack/plugins/security/server/lib/privileges/privileges.js
index e05be3117f934..129d4b3abfb3e 100644
--- a/x-pack/plugins/security/server/lib/privileges/privileges.js
+++ b/x-pack/plugins/security/server/lib/privileges/privileges.js
@@ -45,7 +45,7 @@ function buildSavedObjectsReadPrivileges() {
}
function buildSavedObjectsPrivileges(actions) {
- const objectTypes = ['config', 'dashboard', 'index-pattern', 'search', 'visualization', 'graph-workspace'];
+ const objectTypes = ['config', 'dashboard', 'graph-workspace', 'index-pattern', 'search', 'timelion-sheet', 'url', 'visualization'];
return objectTypes
.map(type => actions.map(action => `action:saved-objects/${type}/${action}`))
.reduce((acc, types) => [...acc, ...types], []);
From 06eb78422cd3c600a15ee691b3be440da3373f38 Mon Sep 17 00:00:00 2001
From: Brandon Kobel
Date: Tue, 22 May 2018 14:56:02 -0400
Subject: [PATCH 17/38] Filtering out non-default resource Kibana privileges
(#19321)
---
x-pack/plugins/security/public/views/management/edit_role.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/x-pack/plugins/security/public/views/management/edit_role.js b/x-pack/plugins/security/public/views/management/edit_role.js
index 3f0ab02129dbb..ba159bc0c95d9 100644
--- a/x-pack/plugins/security/public/views/management/edit_role.js
+++ b/x-pack/plugins/security/public/views/management/edit_role.js
@@ -33,7 +33,10 @@ const getKibanaPrivileges = (kibanaApplicationPrivilege, role, application) => {
return kibanaPrivileges;
}
- const applications = role.applications.filter(x => x.application === application);
+ // we're filtering out privileges for non-default resources as well incase
+ // the roles were created in a future version
+ const applications = role.applications
+ .filter(x => x.application === application && x.application.resources.all(r => r === DEFAULT_RESOURCE));
const assigned = _.uniq(_.flatten(_.pluck(applications, 'privileges')));
assigned.forEach(a => {
From 74891fda0e5c23900f5aade0d32b0b6fff205eba Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Fri, 25 May 2018 10:28:05 -0400
Subject: [PATCH 18/38] Initial design refactor of edit roles screen
---
.../public/views/management/edit_role.js | 1 +
.../edit_role/components/edit_role_page.js | 60 +++---
.../privileges/cluster_privileges.js | 44 +++--
.../privileges/elasticsearch_privileges.js | 176 +++++++++++-------
.../privileges/elasticsearch_privileges.less | 3 +
.../privileges/index_privilege_form.js | 118 +++++++++++-
.../components/privileges/index_privileges.js | 26 +--
.../views/management/edit_role/edit_role.less | 8 +
.../views/management/manage_spaces.less | 4 +-
9 files changed, 291 insertions(+), 149 deletions(-)
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.less
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/edit_role.less
diff --git a/x-pack/plugins/security/public/views/management/edit_role.js b/x-pack/plugins/security/public/views/management/edit_role.js
index 8a3423ea8ccae..d05e519b4e24d 100644
--- a/x-pack/plugins/security/public/views/management/edit_role.js
+++ b/x-pack/plugins/security/public/views/management/edit_role.js
@@ -8,6 +8,7 @@ import _ from 'lodash';
import routes from 'ui/routes';
import { fatalError } from 'ui/notify';
import template from 'plugins/security/views/management/edit_role.html';
+import 'plugins/security/views/management/edit_role/edit_role.less';
import 'angular-ui-select';
import 'plugins/security/services/application_privilege';
import 'plugins/security/services/shield_user';
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
index 3564d66221ac0..332d1d853cfe0 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
@@ -8,6 +8,7 @@ import PropTypes from 'prop-types';
import { get } from 'lodash';
import { Notifier, toastNotifications } from 'ui/notify';
import {
+ EuiPanel,
EuiText,
EuiSpacer,
EuiPage,
@@ -56,29 +57,32 @@ export class EditRolePage extends Component {
render() {
return (
-
+
-
-
+
+
+
+ {this.getFormTitle()}
-
+
- {this.getRoleName()}
+ {this.getRoleName()}
-
+
- {this.getElasticsearchPrivileges()}
+ {this.getElasticsearchPrivileges()}
-
+
- {this.getKibanaPrivileges()}
+ {this.getKibanaPrivileges()}
-
+
- {this.getFormButtons()}
-
-
-
+ {this.getFormButtons()}
+
+
+
+
);
}
@@ -111,19 +115,21 @@ export class EditRolePage extends Component {
getRoleName = () => {
return (
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
);
}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/cluster_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/cluster_privileges.js
index f0bd225db61e5..e67ddd16a7fb3 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/cluster_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/cluster_privileges.js
@@ -4,17 +4,16 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { Component, Fragment } from 'react';
+import React, { Component } from 'react';
+import _ from 'lodash';
import PropTypes from 'prop-types';
import { getClusterPrivileges } from '../../../../../services/role_privileges';
import { isReservedRole } from '../../../../../lib/role';
import {
EuiCheckboxGroup,
- EuiText,
- EuiSpacer,
- EuiLink,
+ EuiFlexGroup,
+ EuiFlexItem,
} from '@elastic/eui';
-import { CLUSTER_PRIVS_DOC_LINK } from '../../lib/constants';
export class ClusterPrivileges extends Component {
static propTypes = {
@@ -23,35 +22,40 @@ export class ClusterPrivileges extends Component {
};
render() {
- const checkboxes = getClusterPrivileges().map(p => ({
- id: p,
- label: p
- }));
- const { role } = this.props;
+ const clusterPrivileges = getClusterPrivileges();
+ const privilegeGroups = _.chunk(clusterPrivileges, clusterPrivileges.length / 2);
+
+ return (
+
+ {privilegeGroups.map(this.buildCheckboxGroup)}
+
+ );
+ }
+
+ buildCheckboxGroup = (items, key) => {
+ const role = this.props.role;
+
+ const checkboxes = items.map(i => ({
+ id: i,
+ label: i
+ }));
const selectionMap = (role.cluster || [])
.map(k => ({ [k]: true }))
.reduce((acc, o) => ({ ...acc, ...o }), {});
return (
-
-
-
- Manage the actions this role can perform against your cluster.
- Learn more
-
-
-
+
-
+
);
- }
+ };
onClusterPrivilegesChange = (privilege) => {
const { cluster } = this.props.role;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
index e8e40ba3fc4ae..5e47a82148367 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
@@ -8,17 +8,23 @@ import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import {
EuiText,
- EuiTextColor,
EuiSpacer,
EuiIcon,
- EuiAccordion,
EuiComboBox,
EuiPanel,
+ EuiFormRow,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiButton,
+ EuiDescribedFormGroup,
EuiTitle,
+ EuiHorizontalRule,
+ EuiLink,
} from '@elastic/eui';
import { ClusterPrivileges } from './cluster_privileges';
import { IndexPrivileges } from './index_privileges';
import { isReservedRole } from '../../../../../lib/role';
+import './elasticsearch_privileges.less';
export class ElasticsearchPrivileges extends Component {
static propTypes = {
@@ -29,7 +35,43 @@ export class ElasticsearchPrivileges extends Component {
validator: PropTypes.object.isRequired,
};
+ state = {
+ collapsed: false
+ };
+
render() {
+
+
+ return (
+
+ {this.getTitle()}
+ {this.getForm()}
+
+ );
+ }
+
+ getTitle = () => {
+ return (
+
+
+
+
+ Elasticsearch
+
+
+
+
+ {this.state.collapsed ? 'show' : 'hide'}
+
+
+ );
+ };
+
+ getForm = () => {
+ if (this.state.collapsed) {
+ return null;
+ }
+
const {
role,
httpClient,
@@ -50,76 +92,33 @@ export class ElasticsearchPrivileges extends Component {
onChange,
};
- const {
- isInvalid
- } = validator.validateIndexPrivileges(role);
-
- const indexTextColor = isInvalid ? 'danger' : 'default';
-
return (
-
- Elasticsearch
-
-
-
-
-
- Cluster Privileges ({role.cluster.length})
-
- }
- >
-
+ Cluster privileges
}
+ description={
+
+ Manage the actions this role can perform against your cluster.
+
+ }
+ >
+
-
-
-
+
+
-
-
-
- Index Privileges (
- {role.indices.filter(i => i.names.length).length})
-
-
- }
- >
-
-
-
-
- Control access to the data in your cluster.
-
-
-
-
-
-
-
-
-
-
- Run As Privileges ({role.run_as.length})}
- >
-
-
-
-
- Allow requests to be submitted on behalf of other users.
-
-
-
+ Run As privileges}
+ description={
+
+ Allow requests to be submitted on behalf of other users.
+
+ }
+ >
+
({ id: username, label: username }))}
@@ -127,12 +126,55 @@ export class ElasticsearchPrivileges extends Component {
onChange={this.onRunAsUserChange}
isDisabled={isReservedRole(this.props.role)}
/>
-
-
+
+
+
+
+
+
+
+
+
+ Index privileges
+ Control access to the data in your cluster.
+
+
+ Add Index Privilege
+
+
+
+
+
+
+
+
);
}
+ toggleCollapsed = () => {
+ this.setState({
+ collapsed: !this.state.collapsed
+ });
+ }
+
+ addIndexPrivilege = () => {
+ const { role } = this.props;
+
+ const newIndices = [...role.indices, {
+ names: [],
+ privileges: [],
+ field_security: {
+ grant: ['*']
+ }
+ }];
+
+ this.props.onChange({
+ ...this.props.role,
+ indices: newIndices
+ });
+ };
+
onClusterPrivilegesChange = (cluster) => {
const role = {
...this.props.role,
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.less b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.less
new file mode 100644
index 0000000000000..9bbe1380ea15d
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.less
@@ -0,0 +1,3 @@
+.manageRoles__esLogo {
+ margin-right: 10px;
+}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
index f5059ccef160f..e52dec02de291 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
@@ -12,9 +12,11 @@ import {
EuiFormRow,
EuiFlexGroup,
EuiFlexItem,
- EuiButton,
+ EuiSwitch,
EuiSpacer,
EuiHorizontalRule,
+ EuiLink,
+ EuiIcon,
} from '@elastic/eui';
import { getIndexPrivileges } from '../../../../../services/role_privileges';
@@ -34,21 +36,24 @@ export class IndexPrivilegeForm extends Component {
validator: PropTypes.object.isRequired,
};
+ constructor(props) {
+ super(props);
+ this.state = {
+ queryExanded: !!props.indexPrivilege.query,
+ documentQuery: props.indexPrivilege.query
+ };
+ }
+
render() {
return (
-
+
{this.getPrivilegeForm()}
{this.props.allowDelete && (
-
+
)}
@@ -82,13 +87,108 @@ export class IndexPrivilegeForm extends Component {
/>
+ {this.getGrantedFieldsControl()}
- {this.getConditionalFeatures()}
+ {this.getGrantedDocumentsControl()}
);
};
+ getGrantedFieldsControl = () => {
+ const {
+ allowFieldLevelSecurity,
+ availableFields,
+ indexPrivilege,
+ } = this.props;
+
+ if (!allowFieldLevelSecurity) {
+ return null;
+ }
+
+ const { grant = [] } = indexPrivilege.field_security || {};
+
+ return (
+
+
+
+
+
+
+
+ );
+ };
+
+ getGrantedDocumentsControl = () => {
+ const {
+ allowDocumentLevelSecurity,
+ indexPrivilege,
+ } = this.props;
+
+ if (!allowDocumentLevelSecurity) {
+ return null;
+ }
+
+ return (
+
+
+
+
+ {this.state.queryExpanded &&
+
+
+
+
+
+ }
+
+ );
+ };
+
+ toggleDocumentQuery = () => {
+ const willToggleOff = this.state.queryExanded;
+ const willToggleOn = !willToggleOff;
+
+ // If turning off, then save the current query in state so that we can restore it if the user changes their mind.
+ this.setState({
+ queryExpanded: !this.state.queryExpanded,
+ documentQuery: willToggleOff ? this.props.indexPrivilege.query : this.state.documentQuery
+ });
+
+ // If turning off, then remove the query from the Index Privilege
+ if (willToggleOff) {
+ this.props.onChange({
+ ...this.props.indexPrivilege,
+ query: '',
+ });
+ }
+
+ // If turning on, then restore the saved query if available
+ if (willToggleOn && !this.props.indexPrivilege.query && this.state.documentQuery) {
+ this.props.onChange({
+ ...this.props.indexPrivilege,
+ query: this.state.documentQuery,
+ });
+ }
+ };
+
getConditionalFeatures = () => {
const {
allowDocumentLevelSecurity,
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
index 58a1834974e56..2837d1927dc56 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
@@ -3,17 +3,12 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { Component, Fragment } from 'react';
+import React, { Component } from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import { isReservedRole } from '../../../../../lib/role';
import { IndexPrivilegeForm } from './index_privilege_form';
import { getFields } from '../../../../../objects';
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiButton
-} from '@elastic/eui';
export class IndexPrivileges extends Component {
static propTypes = {
@@ -63,24 +58,7 @@ export class IndexPrivileges extends Component {
/>
));
- const button = isReservedRole(this.props.role)
- ? null
- : (
-
-
-
- New Index Privilege
-
-
-
- );
-
- return (
-
- {forms}
- {button}
-
- );
+ return forms;
}
addIndexPrivilege = () => {
diff --git a/x-pack/plugins/security/public/views/management/edit_role/edit_role.less b/x-pack/plugins/security/public/views/management/edit_role/edit_role.less
new file mode 100644
index 0000000000000..7b6b150c0444e
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/edit_role.less
@@ -0,0 +1,8 @@
+#editRoleReactRoot, .editRolePage, .editRolePage__content {
+ background: #f5f5f5;
+}
+
+.editRolePage__content {
+ border: none;
+ box-shadow: none;
+}
diff --git a/x-pack/plugins/spaces/public/views/management/manage_spaces.less b/x-pack/plugins/spaces/public/views/management/manage_spaces.less
index a9696d0c2f824..ae515cbb829fa 100644
--- a/x-pack/plugins/spaces/public/views/management/manage_spaces.less
+++ b/x-pack/plugins/spaces/public/views/management/manage_spaces.less
@@ -1,7 +1,7 @@
-.application, .euiPanel {
+.manageSpaces__application, .manageSpaces__.euiPanel {
background: #f5f5f5
}
-.euiPage {
+.manageSpaces__euiPage {
padding: 0;
}
From ad0ec049856ba8be2f1c9b9d3c7c243316161c61 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Fri, 25 May 2018 10:42:25 -0400
Subject: [PATCH 19/38] improved ui for reserved roles
---
.../edit_role/components/edit_role_page.js | 27 ++++++++++++++++---
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
index 332d1d853cfe0..34c2178831878 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
@@ -87,9 +87,14 @@ export class EditRolePage extends Component {
}
getFormTitle = () => {
- const titleText = this.editingExistingRole()
- ? 'Edit Role'
- : 'New Role';
+ let titleText;
+ if (isReservedRole(this.props.role)) {
+ titleText = 'Reserved role';
+ } else if (this.editingExistingRole()) {
+ titleText = 'Edit role';
+ } else {
+ titleText = 'New role';
+ }
return (
@@ -182,10 +187,24 @@ export class EditRolePage extends Component {
};
getFormButtons = () => {
+ if (isReservedRole(this.props.role)) {
+ return (
+
+
+
+ Return to role list
+
+
+
+ );
+ }
+
+ const saveText = this.editingExistingRole() ? 'Update role' : 'Create role';
+
return (
- Save
+ {saveText}
From ebf85d84f6631165af350aa3e3e69e7bc463efef Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Fri, 25 May 2018 11:42:30 -0400
Subject: [PATCH 20/38] create CollapsiblePanel component for roles screen
---
.../collapsible_panel.test.js.snap | 59 +++++++++++++++
.../edit_role/components/collapsible_panel.js | 74 +++++++++++++++++++
.../components/collapsible_panel.less | 3 +
.../components/collapsible_panel.test.js | 57 ++++++++++++++
.../privileges/elasticsearch_privileges.js | 44 +----------
.../privileges/elasticsearch_privileges.less | 3 -
.../privileges/kibana_privileges.js | 34 ++++-----
7 files changed, 212 insertions(+), 62 deletions(-)
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/collapsible_panel.test.js.snap
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.less
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.test.js
delete mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.less
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/collapsible_panel.test.js.snap b/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/collapsible_panel.test.js.snap
new file mode 100644
index 0000000000000..d94f2f4c47bab
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/collapsible_panel.test.js.snap
@@ -0,0 +1,59 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`it renders without blowing up 1`] = `
+
+
+
+
+
+
+
+ Elasticsearch
+
+
+
+
+
+ hide
+
+
+
+
+
+
+ child
+
+
+
+`;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.js b/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.js
new file mode 100644
index 0000000000000..e39b25e8e522b
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.js
@@ -0,0 +1,74 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { Component, Fragment } from 'react';
+import PropTypes from 'prop-types';
+import './collapsible_panel.less';
+import {
+ EuiPanel,
+ EuiLink,
+ EuiIcon,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiTitle,
+ EuiSpacer,
+} from '@elastic/eui';
+
+export class CollapsiblePanel extends Component {
+ static propTypes = {
+ iconType: PropTypes.string.isRequired,
+ title: PropTypes.string.isRequired,
+ }
+
+ state = {
+ collapsed: false
+ }
+
+ render() {
+ return (
+
+ {this.getTitle()}
+ {this.getForm()}
+
+ );
+ }
+
+ getTitle = () => {
+ return (
+
+
+
+
+ {this.props.title}
+
+
+
+
+ {this.state.collapsed ? 'show' : 'hide'}
+
+
+ );
+ };
+
+ getForm = () => {
+ if (this.state.collapsed) {
+ return null;
+ }
+
+ return (
+
+
+ {this.props.children}
+
+ );
+ }
+
+ toggleCollapsed = () => {
+ this.setState({
+ collapsed: !this.state.collapsed
+ });
+ }
+}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.less b/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.less
new file mode 100644
index 0000000000000..cc56943ffcda9
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.less
@@ -0,0 +1,3 @@
+.collapsiblePanel__logo {
+ margin-right: 10px;
+}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.test.js b/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.test.js
new file mode 100644
index 0000000000000..ec0182101653a
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.test.js
@@ -0,0 +1,57 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { shallow, mount } from 'enzyme';
+import { CollapsiblePanel } from './collapsible_panel';
+import { EuiLink } from '@elastic/eui';
+
+test('it renders without blowing up', () => {
+ const wrapper = shallow(
+
+ child
+
+ );
+
+ expect(wrapper).toMatchSnapshot();
+});
+
+test('it renders children by default', () => {
+ const wrapper = mount(
+
+ child 1
+ child 2
+
+ );
+
+ expect(wrapper.find(CollapsiblePanel)).toHaveLength(1);
+ expect(wrapper.find('.child')).toHaveLength(2);
+});
+
+test('it hides children when the "hide" link is clicked', () => {
+ const wrapper = mount(
+
+ child 1
+ child 2
+
+ );
+
+ expect(wrapper.find(CollapsiblePanel)).toHaveLength(1);
+ expect(wrapper.find('.child')).toHaveLength(2);
+
+ wrapper.find(EuiLink).simulate('click');
+
+ expect(wrapper.find('.child')).toHaveLength(0);
+});
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
index 5e47a82148367..e6a8aa6c60e03 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
@@ -9,9 +9,7 @@ import PropTypes from 'prop-types';
import {
EuiText,
EuiSpacer,
- EuiIcon,
EuiComboBox,
- EuiPanel,
EuiFormRow,
EuiFlexGroup,
EuiFlexItem,
@@ -19,12 +17,11 @@ import {
EuiDescribedFormGroup,
EuiTitle,
EuiHorizontalRule,
- EuiLink,
} from '@elastic/eui';
import { ClusterPrivileges } from './cluster_privileges';
import { IndexPrivileges } from './index_privileges';
import { isReservedRole } from '../../../../../lib/role';
-import './elasticsearch_privileges.less';
+import { CollapsiblePanel } from '../collapsible_panel';
export class ElasticsearchPrivileges extends Component {
static propTypes = {
@@ -35,43 +32,15 @@ export class ElasticsearchPrivileges extends Component {
validator: PropTypes.object.isRequired,
};
- state = {
- collapsed: false
- };
-
render() {
-
-
return (
-
- {this.getTitle()}
+
{this.getForm()}
-
+
);
}
- getTitle = () => {
- return (
-
-
-
-
- Elasticsearch
-
-
-
-
- {this.state.collapsed ? 'show' : 'hide'}
-
-
- );
- };
-
getForm = () => {
- if (this.state.collapsed) {
- return null;
- }
-
const {
role,
httpClient,
@@ -94,7 +63,6 @@ export class ElasticsearchPrivileges extends Component {
return (
-
Cluster privileges}
description={
@@ -152,12 +120,6 @@ export class ElasticsearchPrivileges extends Component {
);
}
- toggleCollapsed = () => {
- this.setState({
- collapsed: !this.state.collapsed
- });
- }
-
addIndexPrivilege = () => {
const { role } = this.props;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.less b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.less
deleted file mode 100644
index 9bbe1380ea15d..0000000000000
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.less
+++ /dev/null
@@ -1,3 +0,0 @@
-.manageRoles__esLogo {
- margin-right: 10px;
-}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
index 3c222800108b1..b13002feae003 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
@@ -4,16 +4,16 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { Component, Fragment } from 'react';
+import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { isReservedRole } from '../../../../../lib/role';
import { getKibanaPrivileges } from '../../lib/get_application_privileges';
import { togglePrivilege } from '../../lib/set_application_privileges';
+
+import { CollapsiblePanel } from '../collapsible_panel';
import {
EuiCheckboxGroup,
- EuiText,
- EuiSpacer,
- EuiTitle,
+ EuiDescribedFormGroup,
} from '@elastic/eui';
export class KibanaPrivileges extends Component {
static propTypes = {
@@ -30,7 +30,14 @@ export class KibanaPrivileges extends Component {
idToPrivilege = (id) => id.split(this.idPrefix())[1];
render() {
+ return (
+
+ {this.getForm()}
+
+ );
+ }
+ getForm = () => {
const {
kibanaAppPrivileges,
role,
@@ -52,26 +59,17 @@ export class KibanaPrivileges extends Component {
}, {});
return (
-
-
- Kibana
-
-
-
-
-
-
- Manage the actions this role can perform against Kibana.
-
-
-
+ Application privileges}
+ description={Manage the actions this role can perform within Kibana.
}
+ >
-
+
);
}
From a826ee5d19c6c9c345c11f07e48b57a553bf22c7 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Tue, 29 May 2018 09:09:43 -0400
Subject: [PATCH 21/38] Improve readonly view
---
.../edit_role/components/edit_role_page.js | 1 +
.../privileges/elasticsearch_privileges.js | 14 ++++++++------
.../privileges/index_privilege_form.js | 18 ++++++++++--------
x-pack/plugins/spaces/index.js | 2 +-
4 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
index 34c2178831878..da42fdf681332 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
@@ -154,6 +154,7 @@ export class EditRolePage extends Component {
return (
({ id: username, label: username }))}
selectedOptions={this.props.role.run_as.map(u => ({ label: u }))}
onChange={this.onRunAsUserChange}
- isDisabled={isReservedRole(this.props.role)}
+ isDisabled={!this.props.editable}
/>
@@ -106,9 +106,11 @@ export class ElasticsearchPrivileges extends Component {
Index privileges
Control access to the data in your cluster.
-
- Add Index Privilege
-
+ {this.props.editable && (
+
+ Add Index Privilege
+
+ )}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
index e52dec02de291..95f013fbb004b 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
@@ -137,14 +137,16 @@ export class IndexPrivilegeForm extends Component {
return (
-
-
-
+ {!this.props.isReservedRole &&
+
+
+
+ }
{this.state.queryExpanded &&
diff --git a/x-pack/plugins/spaces/index.js b/x-pack/plugins/spaces/index.js
index 603b8ddb22e11..38d2e84cc992f 100644
--- a/x-pack/plugins/spaces/index.js
+++ b/x-pack/plugins/spaces/index.js
@@ -52,7 +52,7 @@ export const spaces = (kibana) => new kibana.Plugin({
valid: true,
space: await getActiveSpace(request.getSavedObjectsClient(), request.getBasePath())
};
- } catch(e) {
+ } catch (e) {
vars.activeSpace = {
valid: false,
error: wrapError(e).output.payload
From d188dc825ba8370ab7a321ce7c363e94651e71bc Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Tue, 29 May 2018 09:17:05 -0400
Subject: [PATCH 22/38] Fix save logic
---
.../views/management/edit_role/components/edit_role_page.js | 3 ---
1 file changed, 3 deletions(-)
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
index da42fdf681332..2e8e956ef9352 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
@@ -27,7 +27,6 @@ import { RoleValidator } from '../lib/validate_role';
import { ReservedRoleBadge } from './reserved_role_badge';
import { ROLES_PATH } from '../../management_urls';
import { DeleteRoleButton } from './delete_role_button';
-import { setApplicationPrivileges } from '../lib/set_application_privileges';
import { ElasticsearchPrivileges, KibanaPrivileges } from './privileges';
const notifier = new Notifier();
@@ -248,8 +247,6 @@ export class EditRolePage extends Component {
role.indices = role.indices.filter(i => !this.isPlaceholderPrivilege(i));
role.indices.forEach((index) => index.query || delete index.query);
- setApplicationPrivileges(this.props.kibanaPrivileges, role, this.props.rbacApplication);
-
saveRole(httpClient, role)
.then(() => {
toastNotifications.addSuccess('Saved role');
From 4464482f9b19800d4d066f72a056804d7cea9e4a Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Tue, 29 May 2018 09:33:21 -0400
Subject: [PATCH 23/38] Re-add granted fields warning
---
.../privileges/index_privilege_form.js | 126 +++++-------------
1 file changed, 36 insertions(+), 90 deletions(-)
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
index 95f013fbb004b..b807f41f4b3c8 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
@@ -108,22 +108,44 @@ export class IndexPrivilegeForm extends Component {
const { grant = [] } = indexPrivilege.field_security || {};
- return (
-
-
+ let grantedFieldsWarning = null;
+
+ if (allowFieldLevelSecurity) {
+
+ if (grant.length === 0) {
+ grantedFieldsWarning = (
-
+
+
+
+ If no fields are granted, then users assigned to this role will not be able to
+ see any data for this index. Is this really what you want?
+
+
-
-
- );
- };
+ );
+ }
+
+ return (
+
+
+
+
+ {grantedFieldsWarning}
+
+
+
+ );
+ }
+
+ return null;
+ }
getGrantedDocumentsControl = () => {
const {
@@ -191,82 +213,6 @@ export class IndexPrivilegeForm extends Component {
}
};
- getConditionalFeatures = () => {
- const {
- allowDocumentLevelSecurity,
- allowFieldLevelSecurity,
- indexPrivilege,
- availableFields,
- } = this.props;
-
- if (!allowFieldLevelSecurity && !allowDocumentLevelSecurity) {
- return null;
- }
-
- const features = [];
- if (allowDocumentLevelSecurity) {
- features.push((
-
-
-
-
-
- ));
- }
-
- let grantedFieldsWarning = null;
-
- if (allowFieldLevelSecurity) {
-
- const { grant = [] } = indexPrivilege.field_security || {};
-
- if (grant.length === 0) {
- grantedFieldsWarning = (
-
-
-
-
- If no fields are granted, then users assigned to this role will not be able to
- see any data for this index. Is this really what you want?
-
-
-
- );
- }
-
- features.push((
-
-
-
-
- {grantedFieldsWarning}
-
-
-
- ));
- }
-
- return (
-
-
-
- {features}
-
-
- );
- };
-
onCreateIndexPatternOption = (option) => {
const newIndexPatterns = this.props.indexPrivilege.names.concat([option]);
From 767fb277a4b35db977f14c6355e6b3bac8519ee6 Mon Sep 17 00:00:00 2001
From: kobelb
Date: Tue, 29 May 2018 10:41:58 -0400
Subject: [PATCH 24/38] Removing unused file
---
.../security/server/lib/check_user_permission.js | 14 --------------
1 file changed, 14 deletions(-)
delete mode 100644 x-pack/plugins/security/server/lib/check_user_permission.js
diff --git a/x-pack/plugins/security/server/lib/check_user_permission.js b/x-pack/plugins/security/server/lib/check_user_permission.js
deleted file mode 100644
index 6890a6fc79092..0000000000000
--- a/x-pack/plugins/security/server/lib/check_user_permission.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-/*! Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one or more contributor license agreements.
- * Licensed under the Elastic License; you may not use this file except in compliance with the Elastic License. */
-
-
-export async function checkUserPermission(permission, hasPermission) {
- // POC Stub. TODO: Use ES Permissions API once implemented.
- return Promise.resolve(hasPermission);
-}
From ebd09d1159ebf22a11243e6b660dcf72ec8b73a0 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Tue, 29 May 2018 15:32:37 -0400
Subject: [PATCH 25/38] additional tests
---
.../__snapshots__/page_header.test.js.snap | 11 ++
.../edit_role/components/page_header.js | 4 +-
.../edit_role/components/page_header.test.js | 36 ++++
.../cluster_privileges.test.js.snap | 92 ++++++++++
.../elasticsearch_privileges.test.js.snap | 164 ++++++++++++++++++
.../index_privileges.test.js.snap | 3 +
.../privileges/cluster_privileges.test.js | 20 +++
.../privileges/elasticsearch_privileges.js | 3 +
.../elasticsearch_privileges.test.js | 72 ++++++++
.../privileges/index_privileges.test.js | 54 ++++++
10 files changed, 456 insertions(+), 3 deletions(-)
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/page_header.test.js.snap
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/page_header.test.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/cluster_privileges.test.js.snap
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/elasticsearch_privileges.test.js.snap
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/index_privileges.test.js.snap
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/privileges/cluster_privileges.test.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.test.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.test.js
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/page_header.test.js.snap b/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/page_header.test.js.snap
new file mode 100644
index 0000000000000..7dddfa8c5cdef
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/page_header.test.js.snap
@@ -0,0 +1,11 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`it renders without crashing 1`] = `
+
+
+
+
+
+`;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/page_header.js b/x-pack/plugins/security/public/views/management/edit_role/components/page_header.js
index 956c2809b325f..ffbab9d0921a7 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/page_header.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/page_header.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { Component } from 'react';
+import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
@@ -36,8 +36,6 @@ export class PageHeader extends Component {
}
}
-
-
PageHeader.propTypes = {
breadcrumbs: PropTypes.array.isRequired
};
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/page_header.test.js b/x-pack/plugins/security/public/views/management/edit_role/components/page_header.test.js
new file mode 100644
index 0000000000000..89151673b9911
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/page_header.test.js
@@ -0,0 +1,36 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { shallow, mount } from 'enzyme';
+import { PageHeader } from './page_header';
+import { EuiHeaderBreadcrumbs, EuiHeaderBreadcrumb } from '@elastic/eui';
+
+test('it renders without crashing', () => {
+ const wrapper = shallow( );
+ expect(wrapper.find(EuiHeaderBreadcrumbs)).toHaveLength(1);
+ expect(wrapper).toMatchSnapshot();
+});
+
+test('it renders breadcrumbs', () => {
+ const breadcrumbs = [{
+ id: 'item-1',
+ href: '#item-1',
+ current: false
+ }, {
+ id: 'item-2',
+ href: '#item-2',
+ current: false
+ }, {
+ id: 'item-3',
+ href: '#item-3',
+ current: true
+ }];
+
+ const wrapper = mount( );
+ expect(wrapper.find(EuiHeaderBreadcrumbs)).toHaveLength(1);
+ expect(wrapper.find(EuiHeaderBreadcrumb)).toHaveLength(breadcrumbs.length);
+});
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/cluster_privileges.test.js.snap b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/cluster_privileges.test.js.snap
new file mode 100644
index 0000000000000..5315e277468ed
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/cluster_privileges.test.js.snap
@@ -0,0 +1,92 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`it renders without crashing 1`] = `
+
+
+
+
+
+
+
+
+`;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/elasticsearch_privileges.test.js.snap b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/elasticsearch_privileges.test.js.snap
new file mode 100644
index 0000000000000..b01cbf77668e0
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/elasticsearch_privileges.test.js.snap
@@ -0,0 +1,164 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`it renders without crashing 1`] = `
+
+
+
+ Manage the actions this role can perform against your cluster.
+
+ }
+ fullWidth={false}
+ gutterSize="l"
+ title={
+
+ Cluster privileges
+
+ }
+ titleSize="xs"
+ >
+
+
+
+
+
+
+ Allow requests to be submitted on behalf of other users.
+
+ }
+ fullWidth={false}
+ gutterSize="l"
+ title={
+
+ Run As privileges
+
+ }
+ titleSize="xs"
+ >
+
+
+
+
+
+
+
+
+
+
+
+ Index privileges
+
+
+
+
+ Control access to the data in your cluster.
+
+
+
+
+
+ Add Index Privilege
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/index_privileges.test.js.snap b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/index_privileges.test.js.snap
new file mode 100644
index 0000000000000..189c4766c29f9
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/index_privileges.test.js.snap
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`it renders without crashing 1`] = `Array []`;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/cluster_privileges.test.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/cluster_privileges.test.js
new file mode 100644
index 0000000000000..f75cf0ade71a9
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/cluster_privileges.test.js
@@ -0,0 +1,20 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { shallow, mount } from 'enzyme';
+import { ClusterPrivileges } from './cluster_privileges';
+import { EuiCheckboxGroup } from '@elastic/eui';
+
+test('it renders without crashing', () => {
+ const wrapper = shallow( );
+ expect(wrapper).toMatchSnapshot();
+});
+
+test('it renders 2 checkbox groups of privileges', () => {
+ const wrapper = mount( );
+ expect(wrapper.find(EuiCheckboxGroup)).toHaveLength(2);
+});
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
index f827523d9ccbf..b473d318b2f45 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
@@ -30,6 +30,9 @@ export class ElasticsearchPrivileges extends Component {
onChange: PropTypes.func.isRequired,
runAsUsers: PropTypes.array.isRequired,
validator: PropTypes.object.isRequired,
+ indexPatterns: PropTypes.array.isRequired,
+ allowDocumentLevelSecurity: PropTypes.bool.isRequired,
+ allowFieldLevelSecurity: PropTypes.bool.isRequired,
};
render() {
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.test.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.test.js
new file mode 100644
index 0000000000000..7a2af5723e543
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.test.js
@@ -0,0 +1,72 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { shallow, mount } from 'enzyme';
+import { IndexPrivileges } from './index_privileges';
+import { ClusterPrivileges } from './cluster_privileges';
+import { ElasticsearchPrivileges } from './elasticsearch_privileges';
+import { RoleValidator } from '../../lib/validate_role';
+
+test('it renders without crashing', () => {
+ const props = {
+ role: {
+ cluster: [],
+ indices: [],
+ run_as: []
+ },
+ editable: true,
+ httpClient: jest.fn(),
+ onChange: jest.fn(),
+ runAsUsers: [],
+ indexPatterns: [],
+ allowDocumentLevelSecurity: true,
+ allowFieldLevelSecurity: true,
+ validator: new RoleValidator(),
+ };
+ const wrapper = shallow( );
+ expect(wrapper).toMatchSnapshot();
+});
+
+test('it renders ClusterPrivileges', () => {
+ const props = {
+ role: {
+ cluster: [],
+ indices: [],
+ run_as: []
+ },
+ editable: true,
+ httpClient: jest.fn(),
+ onChange: jest.fn(),
+ runAsUsers: [],
+ indexPatterns: [],
+ allowDocumentLevelSecurity: true,
+ allowFieldLevelSecurity: true,
+ validator: new RoleValidator(),
+ };
+ const wrapper = mount( );
+ expect(wrapper.find(ClusterPrivileges)).toHaveLength(1);
+});
+
+test('it renders IndexPrivileges', () => {
+ const props = {
+ role: {
+ cluster: [],
+ indices: [],
+ run_as: []
+ },
+ editable: true,
+ httpClient: jest.fn(),
+ onChange: jest.fn(),
+ runAsUsers: [],
+ indexPatterns: [],
+ allowDocumentLevelSecurity: true,
+ allowFieldLevelSecurity: true,
+ validator: new RoleValidator(),
+ };
+ const wrapper = mount( );
+ expect(wrapper.find(IndexPrivileges)).toHaveLength(1);
+});
\ No newline at end of file
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.test.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.test.js
new file mode 100644
index 0000000000000..221d301ceef0f
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.test.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { shallow, mount } from 'enzyme';
+import { IndexPrivileges } from './index_privileges';
+import { IndexPrivilegeForm } from './index_privilege_form';
+import { RoleValidator } from '../../lib/validate_role';
+
+test('it renders without crashing', () => {
+ const props = {
+ role: {
+ cluster: [],
+ indices: [],
+ run_as: []
+ },
+ httpClient: jest.fn(),
+ onChange: jest.fn(),
+ indexPatterns: [],
+ allowDocumentLevelSecurity: true,
+ allowFieldLevelSecurity: true,
+ validator: new RoleValidator(),
+ };
+ const wrapper = shallow( );
+ expect(wrapper).toMatchSnapshot();
+});
+
+test('it renders a IndexPrivilegeForm for each privilege on the role', () => {
+ const props = {
+ role: {
+ cluster: [],
+ indices: [{
+ names: ['foo*'],
+ privileges: ['all'],
+ query: '*',
+ field_security: {
+ grant: ['some_field']
+ }
+ }],
+ run_as: []
+ },
+ httpClient: jest.fn(),
+ onChange: jest.fn(),
+ indexPatterns: [],
+ allowDocumentLevelSecurity: true,
+ allowFieldLevelSecurity: true,
+ validator: new RoleValidator(),
+ };
+ const wrapper = mount( );
+ expect(wrapper.find(IndexPrivilegeForm)).toHaveLength(1);
+});
\ No newline at end of file
From 642eaae1f4ba2c2cb09a9c18196e7b14922a96c3 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Tue, 29 May 2018 15:46:00 -0400
Subject: [PATCH 26/38] port remainder of index privs logic, and remove angular
version of that form
---
.../components/privileges/index_privileges.js | 9 +-
.../index_privileges_form.html | 128 ------------------
.../index_privileges_form.js | 60 --------
.../index_privileges_form.less | 7 -
4 files changed, 6 insertions(+), 198 deletions(-)
delete mode 100644 x-pack/plugins/security/public/views/management/index_privileges_form/index_privileges_form.html
delete mode 100644 x-pack/plugins/security/public/views/management/index_privileges_form/index_privileges_form.js
delete mode 100644 x-pack/plugins/security/public/views/management/index_privileges_form/index_privileges_form.less
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
index 2837d1927dc56..cf04718c3e475 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
@@ -6,7 +6,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
-import { isReservedRole } from '../../../../../lib/role';
+import { isReservedRole, isRoleEnabled } from '../../../../../lib/role';
import { IndexPrivilegeForm } from './index_privilege_form';
import { getFields } from '../../../../../objects';
@@ -40,8 +40,11 @@ export class IndexPrivileges extends Component {
const props = {
indexPatterns,
- allowDocumentLevelSecurity,
- allowFieldLevelSecurity,
+ // If editing an existing role while that has been disabled, always show the FLS/DLS fields because currently
+ // a role is only marked as disabled if it has FLS/DLS setup (usually before the user changed to a license that
+ // doesn't permit FLS/DLS).
+ allowDocumentLevelSecurity: allowDocumentLevelSecurity || !isRoleEnabled(this.props.role),
+ allowFieldLevelSecurity: allowFieldLevelSecurity || !isRoleEnabled(this.props.role),
isReservedRole: isReservedRole(this.props.role)
};
diff --git a/x-pack/plugins/security/public/views/management/index_privileges_form/index_privileges_form.html b/x-pack/plugins/security/public/views/management/index_privileges_form/index_privileges_form.html
deleted file mode 100644
index 829b0dfaefa92..0000000000000
--- a/x-pack/plugins/security/public/views/management/index_privileges_form/index_privileges_form.html
+++ /dev/null
@@ -1,128 +0,0 @@
-
diff --git a/x-pack/plugins/security/public/views/management/index_privileges_form/index_privileges_form.js b/x-pack/plugins/security/public/views/management/index_privileges_form/index_privileges_form.js
deleted file mode 100644
index 1bb058f56d096..0000000000000
--- a/x-pack/plugins/security/public/views/management/index_privileges_form/index_privileges_form.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import _ from 'lodash';
-import { uiModules } from 'ui/modules';
-import template from './index_privileges_form.html';
-
-const module = uiModules.get('security', ['kibana']);
-module.directive('kbnIndexPrivilegesForm', function () {
- return {
- template,
- scope: {
- isNewRole: '=',
- indices: '=',
- indexPatterns: '=',
- privileges: '=',
- fieldOptions: '=',
- isReserved: '=',
- isEnabled: '=',
- allowDocumentLevelSecurity: '=',
- allowFieldLevelSecurity: '=',
- addIndex: '&',
- removeIndex: '&',
- },
- restrict: 'E',
- replace: true,
- controllerAs: 'indexPrivilegesController',
- controller: function ($scope) {
- this.addIndex = function addIndex() {
- $scope.addIndex({ indices: $scope.indices });
- };
-
- this.removeIndex = function removeIndex(index) {
- $scope.removeIndex({ indices: $scope.indices, index });
- };
-
- this.getIndexTitle = function getIndexTitle(index) {
- const indices = index.names.length ? index.names.join(', ') : 'No indices';
- const privileges = index.privileges.length ? index.privileges.join(', ') : 'No privileges';
- return `${indices} (${privileges})`;
- };
-
- this.union = _.flow(_.union, _.compact);
-
- // If editing an existing role while that has been disabled, always show the FLS/DLS fields because currently
- // a role is only marked as disabled if it has FLS/DLS setup (usually before the user changed to a license that
- // doesn't permit FLS/DLS).
- if (!$scope.isNewRole && !$scope.isEnabled) {
- this.showDocumentLevelSecurity = true;
- this.showFieldLevelSecurity = true;
- } else {
- this.showDocumentLevelSecurity = $scope.allowDocumentLevelSecurity;
- this.showFieldLevelSecurity = $scope.allowFieldLevelSecurity;
- }
- },
- };
-});
diff --git a/x-pack/plugins/security/public/views/management/index_privileges_form/index_privileges_form.less b/x-pack/plugins/security/public/views/management/index_privileges_form/index_privileges_form.less
deleted file mode 100644
index edd7a4898f45a..0000000000000
--- a/x-pack/plugins/security/public/views/management/index_privileges_form/index_privileges_form.less
+++ /dev/null
@@ -1,7 +0,0 @@
-.indexPrivilegesForm {
- height: 550px;
-}
-
-.indexPrivilegesList {
- flex: 0 0 400px;
-}
From 009c29fb415ef3c095b38d9ada84ecd8209ccb60 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Wed, 30 May 2018 08:23:18 -0400
Subject: [PATCH 27/38] additional tests and a bugfix
---
.../security/public/lib/__tests__/role.js | 35 ---
.../plugins/security/public/lib/role.test.js | 59 +++++
.../index_privilege_form.test.js.snap | 192 ++++++++++++++++
.../privileges/index_privilege_form.js | 4 +-
.../privileges/index_privilege_form.test.js | 206 ++++++++++++++++++
5 files changed, 459 insertions(+), 37 deletions(-)
delete mode 100644 x-pack/plugins/security/public/lib/__tests__/role.js
create mode 100644 x-pack/plugins/security/public/lib/role.test.js
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/index_privilege_form.test.js.snap
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.test.js
diff --git a/x-pack/plugins/security/public/lib/__tests__/role.js b/x-pack/plugins/security/public/lib/__tests__/role.js
deleted file mode 100644
index efb22152ef7b1..0000000000000
--- a/x-pack/plugins/security/public/lib/__tests__/role.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import expect from 'expect.js';
-import { isRoleEnabled } from '../role';
-
-describe('role', () => {
- describe('isRoleEnabled', () => {
- it('should return false if role is explicitly not enabled', () => {
- const testRole = {
- transient_metadata: {
- enabled: false
- }
- };
- expect(isRoleEnabled(testRole)).to.be(false);
- });
-
- it('should return true if role is explicitly enabled', () => {
- const testRole = {
- transient_metadata: {
- enabled: true
- }
- };
- expect(isRoleEnabled(testRole)).to.be(true);
- });
-
- it('should return true if role is NOT explicitly enabled or disabled', () => {
- const testRole = {};
- expect(isRoleEnabled(testRole)).to.be(true);
- });
- });
-});
diff --git a/x-pack/plugins/security/public/lib/role.test.js b/x-pack/plugins/security/public/lib/role.test.js
new file mode 100644
index 0000000000000..4c6e9fb896dcf
--- /dev/null
+++ b/x-pack/plugins/security/public/lib/role.test.js
@@ -0,0 +1,59 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { isRoleEnabled, isReservedRole } from './role';
+
+describe('role', () => {
+ describe('isRoleEnabled', () => {
+ test('should return false if role is explicitly not enabled', () => {
+ const testRole = {
+ transient_metadata: {
+ enabled: false
+ }
+ };
+ expect(isRoleEnabled(testRole)).toBe(false);
+ });
+
+ test('should return true if role is explicitly enabled', () => {
+ const testRole = {
+ transient_metadata: {
+ enabled: true
+ }
+ };
+ expect(isRoleEnabled(testRole)).toBe(true);
+ });
+
+ test('should return true if role is NOT explicitly enabled or disabled', () => {
+ const testRole = {};
+ expect(isRoleEnabled(testRole)).toBe(true);
+ });
+ });
+
+ describe('isReservedRole', () => {
+ test('should return false if role is explicitly not reserved', () => {
+ const testRole = {
+ metadata: {
+ _reserved: false
+ }
+ };
+ expect(isReservedRole(testRole)).toBe(false);
+ });
+
+ test('should return true if role is explicitly reserved', () => {
+ const testRole = {
+ metadata: {
+ _reserved: true
+ }
+ };
+ expect(isReservedRole(testRole)).toBe(true);
+ });
+
+ test('should return false if role is NOT explicitly reserved or not reserved', () => {
+ const testRole = {};
+ expect(isReservedRole(testRole)).toBe(false);
+ });
+ });
+});
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/index_privilege_form.test.js.snap b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/index_privilege_form.test.js.snap
new file mode 100644
index 0000000000000..440bc8f832bbe
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/index_privilege_form.test.js.snap
@@ -0,0 +1,192 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`it renders without crashing 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ If no fields are granted, then users assigned to this role will not be able to see any data for this index. Is this really what you want?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
index b807f41f4b3c8..615edfa032188 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
@@ -39,7 +39,7 @@ export class IndexPrivilegeForm extends Component {
constructor(props) {
super(props);
this.state = {
- queryExanded: !!props.indexPrivilege.query,
+ queryExpanded: !!props.indexPrivilege.query,
documentQuery: props.indexPrivilege.query
};
}
@@ -128,7 +128,7 @@ export class IndexPrivilegeForm extends Component {
return (
-
+
{
+ const props = {
+ indexPrivilege: {
+ names: [],
+ privileges: [],
+ query: null,
+ field_security: {
+ grant: []
+ }
+ },
+ indexPatterns: [],
+ availableFields: [],
+ isReservedRole: false,
+ allowDelete: true,
+ allowDocumentLevelSecurity: true,
+ allowFieldLevelSecurity: true,
+ validator: new RoleValidator(),
+ onChange: jest.fn()
+ };
+
+ const wrapper = shallow( );
+ expect(wrapper).toMatchSnapshot();
+});
+
+describe('delete button', () => {
+ const props = {
+ indexPrivilege: {
+ names: [],
+ privileges: [],
+ query: null,
+ field_security: {
+ grant: []
+ }
+ },
+ indexPatterns: [],
+ availableFields: [],
+ isReservedRole: false,
+ allowDelete: true,
+ allowDocumentLevelSecurity: true,
+ allowFieldLevelSecurity: true,
+ validator: new RoleValidator(),
+ onChange: jest.fn(),
+ onDelete: jest.fn()
+ };
+
+ test('it is hidden when allowDelete is false', () => {
+ const testProps = {
+ ...props,
+ allowDelete: false
+ };
+ const wrapper = mount( );
+ expect(wrapper.find(EuiLink)).toHaveLength(0);
+ });
+
+ test('it is shown when allowDelete is true', () => {
+ const testProps = {
+ ...props,
+ allowDelete: true
+ };
+ const wrapper = mount( );
+ expect(wrapper.find(EuiLink)).toHaveLength(1);
+ });
+
+ test('it invokes onDelete when clicked', () => {
+ const testProps = {
+ ...props,
+ allowDelete: true
+ };
+ const wrapper = mount( );
+ wrapper.find(EuiLink).simulate('click');
+ expect(testProps.onDelete).toHaveBeenCalledTimes(1);
+ });
+});
+
+describe(`document level security`, () => {
+ const props = {
+ indexPrivilege: {
+ names: [],
+ privileges: [],
+ query: "some query",
+ field_security: {
+ grant: []
+ }
+ },
+ indexPatterns: [],
+ availableFields: [],
+ isReservedRole: false,
+ allowDelete: true,
+ allowDocumentLevelSecurity: true,
+ allowFieldLevelSecurity: true,
+ validator: new RoleValidator(),
+ onChange: jest.fn()
+ };
+
+ test(`inputs are hidden when DLS is not allowed`, () => {
+ const testProps = {
+ ...props,
+ allowDocumentLevelSecurity: false
+ };
+
+ const wrapper = mount( );
+ expect(wrapper.find(EuiSwitch)).toHaveLength(0);
+ expect(wrapper.find(EuiTextArea)).toHaveLength(0);
+ });
+
+ test('only the switch is shown when allowed, and query is empty', () => {
+ const testProps = {
+ ...props,
+ indexPrivilege: {
+ ...props.indexPrivilege,
+ query: null
+ }
+ };
+
+ const wrapper = mount( );
+ expect(wrapper.find(EuiSwitch)).toHaveLength(1);
+ expect(wrapper.find(EuiTextArea)).toHaveLength(0);
+ });
+
+ test('both inputs are shown when allowed, and query is not empty', () => {
+ const testProps = {
+ ...props,
+ };
+
+ const wrapper = mount( );
+ expect(wrapper.find(EuiSwitch)).toHaveLength(1);
+ expect(wrapper.find(EuiTextArea)).toHaveLength(1);
+ });
+});
+
+describe('field level security', () => {
+ const props = {
+ indexPrivilege: {
+ names: [],
+ privileges: [],
+ query: null,
+ field_security: {
+ grant: ["foo*"]
+ }
+ },
+ indexPatterns: [],
+ availableFields: [],
+ isReservedRole: false,
+ allowDelete: true,
+ allowDocumentLevelSecurity: true,
+ allowFieldLevelSecurity: true,
+ validator: new RoleValidator(),
+ onChange: jest.fn()
+ };
+
+ test(`input is hidden when FLS is not allowed`, () => {
+ const testProps = {
+ ...props,
+ allowFieldLevelSecurity: false
+ };
+
+ const wrapper = mount( );
+ expect(wrapper.find(".indexPrivilegeForm__grantedFieldsRow")).toHaveLength(0);
+ });
+
+ test('input is shown when allowed', () => {
+ const testProps = {
+ ...props,
+ };
+
+ const wrapper = mount( );
+ expect(wrapper.find("div.indexPrivilegeForm__grantedFieldsRow")).toHaveLength(1);
+ });
+
+ test('it displays a warning when no fields are granted', () => {
+ const testProps = {
+ ...props,
+ indexPrivilege: {
+ ...props.indexPrivilege,
+ field_security: {
+ grant: []
+ }
+ }
+ };
+
+ const wrapper = mount( );
+ expect(wrapper.find("div.indexPrivilegeForm__grantedFieldsRow")).toHaveLength(1);
+ expect(wrapper.find(EuiCallOut)).toHaveLength(1);
+ });
+
+ test('it does not display a warning when fields are granted', () => {
+ const testProps = {
+ ...props
+ };
+
+ const wrapper = mount( );
+ expect(wrapper.find("div.indexPrivilegeForm__grantedFieldsRow")).toHaveLength(1);
+ expect(wrapper.find(EuiCallOut)).toHaveLength(0);
+ });
+});
From d0c44e98939162b05fff3fee38d8aa7171986387 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Wed, 30 May 2018 08:51:52 -0400
Subject: [PATCH 28/38] remove unused code
---
x-pack/plugins/security/public/objects/index.js | 4 +---
.../security/public/objects/lib/get_users.js | 14 --------------
.../plugins/security/public/objects/lib/roles.js | 11 -----------
.../security/public/views/management/edit_role.js | 8 +-------
.../edit_role/components/edit_role_page.js | 8 ++++----
.../security/public/views/management/management.js | 1 -
.../public/views/management/management.less | 1 -
7 files changed, 6 insertions(+), 41 deletions(-)
delete mode 100644 x-pack/plugins/security/public/objects/lib/get_users.js
diff --git a/x-pack/plugins/security/public/objects/index.js b/x-pack/plugins/security/public/objects/index.js
index 88575e4e24677..a6238ca879901 100644
--- a/x-pack/plugins/security/public/objects/index.js
+++ b/x-pack/plugins/security/public/objects/index.js
@@ -4,8 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { getRole, saveRole, deleteRole } from './lib/roles';
-
-export { getUsers } from './lib/get_users';
+export { saveRole, deleteRole } from './lib/roles';
export { getFields } from './lib/get_fields';
diff --git a/x-pack/plugins/security/public/objects/lib/get_users.js b/x-pack/plugins/security/public/objects/lib/get_users.js
deleted file mode 100644
index fd82b62d0f928..0000000000000
--- a/x-pack/plugins/security/public/objects/lib/get_users.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-import chrome from 'ui/chrome';
-
-const apiBase = chrome.addBasePath(`/api/security/v1/users`);
-
-export async function getUsers($http) {
- return await $http
- .get(apiBase)
- .then(response => response.data || []);
-}
diff --git a/x-pack/plugins/security/public/objects/lib/roles.js b/x-pack/plugins/security/public/objects/lib/roles.js
index c6b68d283569c..5fdd95a7ccb64 100644
--- a/x-pack/plugins/security/public/objects/lib/roles.js
+++ b/x-pack/plugins/security/public/objects/lib/roles.js
@@ -11,17 +11,6 @@ export async function saveRole($http, role) {
return await $http.post(`${apiBase}/${role.name}`, role);
}
-export async function getRole($http, name) {
- try {
- return await $http.get(`${apiBase}/${name}`);
- } catch (response) {
- if (response.status === 404) {
- return null;
- }
- throw response;
- }
-}
-
export async function deleteRole($http, name) {
return await $http.delete(`${apiBase}/${name}`);
}
diff --git a/x-pack/plugins/security/public/views/management/edit_role.js b/x-pack/plugins/security/public/views/management/edit_role.js
index d05e519b4e24d..6c5c88f717cd0 100644
--- a/x-pack/plugins/security/public/views/management/edit_role.js
+++ b/x-pack/plugins/security/public/views/management/edit_role.js
@@ -78,9 +78,6 @@ routes.when(`${EDIT_ROLES_PATH}/:name?`, {
const kibanaApplicationPrivilege = $route.current.locals.kibanaApplicationPrivilege;
const role = $route.current.locals.role;
- this.isNewRole = $route.current.params.name == null;
- this.fieldOptions = {};
-
const xpackInfo = Private(XPackInfoProvider);
const allowDocumentLevelSecurity = xpackInfo.get('features.security.allowRoleDocumentLevelSecurity');
const allowFieldLevelSecurity = xpackInfo.get('features.security.allowRoleFieldLevelSecurity');
@@ -92,8 +89,6 @@ routes.when(`${EDIT_ROLES_PATH}/:name?`, {
indexPatterns,
} = $route.current.locals;
- this.fieldOptions = {};
-
const roleToEdit = role.toJSON();
if (roleToEdit.indices.length === 0) {
roleToEdit.indices.push({
@@ -107,12 +102,11 @@ routes.when(`${EDIT_ROLES_PATH}/:name?`, {
render(
Date: Wed, 30 May 2018 16:43:52 -0400
Subject: [PATCH 29/38] address PR feedback
---
.../security/public/documentation_links.js | 5 +-
.../elasticsearch_privileges.test.js.snap | 42 +++++-
.../privileges/elasticsearch_privileges.js | 16 ++-
.../privileges/elasticsearch_privileges.less | 3 +
.../management/{ => edit_role}/edit_role.html | 0
.../views/management/edit_role/index.js | 130 ++++++++++++++++++
.../management/edit_role/lib/constants.js | 7 -
.../public/views/management/management.js | 2 +-
8 files changed, 190 insertions(+), 15 deletions(-)
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.less
rename x-pack/plugins/security/public/views/management/{ => edit_role}/edit_role.html (100%)
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/index.js
delete mode 100644 x-pack/plugins/security/public/views/management/edit_role/lib/constants.js
diff --git a/x-pack/plugins/security/public/documentation_links.js b/x-pack/plugins/security/public/documentation_links.js
index 8d9bb3c2256b4..d60092ea945e6 100644
--- a/x-pack/plugins/security/public/documentation_links.js
+++ b/x-pack/plugins/security/public/documentation_links.js
@@ -7,5 +7,8 @@
import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links';
export const documentationLinks = {
- dashboardViewMode: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/xpack-view-modes.html`
+ dashboardViewMode: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/xpack-view-modes.html`,
+ esClusterPrivileges: `${ELASTIC_WEBSITE_URL}guide/en/x-pack/current/security-privileges.html#security-privileges`,
+ esIndicesPrivileges: `${ELASTIC_WEBSITE_URL}guide/en/x-pack/current/security-privileges.html#privileges-list-indices`,
+ esRunAsPrivileges: `${ELASTIC_WEBSITE_URL}guide/en/x-pack/current/security-privileges.html#_run_as_privilege`,
};
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/elasticsearch_privileges.test.js.snap b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/elasticsearch_privileges.test.js.snap
index b01cbf77668e0..f0fe2a5c630f5 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/elasticsearch_privileges.test.js.snap
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/elasticsearch_privileges.test.js.snap
@@ -16,7 +16,19 @@ exports[`it renders without crashing 1`] = `
gutterSize="l"
title={
- Cluster privileges
+ Cluster privileges
+
+
+
}
titleSize="xs"
@@ -51,7 +63,19 @@ exports[`it renders without crashing 1`] = `
gutterSize="l"
title={
- Run As privileges
+ Run As privileges
+
+
+
}
titleSize="xs"
@@ -98,7 +122,19 @@ exports[`it renders without crashing 1`] = `
size="xs"
>
- Index privileges
+ Index privileges
+
+
+
Cluster privileges}
+ title={Cluster privileges {this.learnMore(documentationLinks.esClusterPrivileges)}
}
description={
Manage the actions this role can perform against your cluster.
@@ -82,7 +86,7 @@ export class ElasticsearchPrivileges extends Component {
Run As privileges
}
+ title={Run As privileges {this.learnMore(documentationLinks.esRunAsPrivileges)}
}
description={
Allow requests to be submitted on behalf of other users.
@@ -106,7 +110,7 @@ export class ElasticsearchPrivileges extends Component {
- Index privileges
+ Index privileges {this.learnMore(documentationLinks.esIndicesPrivileges)}
Control access to the data in your cluster.
{this.props.editable && (
@@ -125,6 +129,12 @@ export class ElasticsearchPrivileges extends Component {
);
}
+ learnMore = (href) => (
+
+
+
+ );
+
addIndexPrivilege = () => {
const { role } = this.props;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.less b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.less
new file mode 100644
index 0000000000000..776ef72a4627e
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.less
@@ -0,0 +1,3 @@
+.editRole__learnMore {
+ margin-left: 5px;
+}
\ No newline at end of file
diff --git a/x-pack/plugins/security/public/views/management/edit_role.html b/x-pack/plugins/security/public/views/management/edit_role/edit_role.html
similarity index 100%
rename from x-pack/plugins/security/public/views/management/edit_role.html
rename to x-pack/plugins/security/public/views/management/edit_role/edit_role.html
diff --git a/x-pack/plugins/security/public/views/management/edit_role/index.js b/x-pack/plugins/security/public/views/management/edit_role/index.js
new file mode 100644
index 0000000000000..9d3e10b75dba4
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/index.js
@@ -0,0 +1,130 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import _ from 'lodash';
+import routes from 'ui/routes';
+import { fatalError } from 'ui/notify';
+import template from 'plugins/security/views/management/edit_role/edit_role.html';
+import 'plugins/security/views/management/edit_role/edit_role.less';
+import 'angular-ui-select';
+import 'plugins/security/services/application_privilege';
+import 'plugins/security/services/shield_user';
+import 'plugins/security/services/shield_role';
+import 'plugins/security/services/shield_privileges';
+import 'plugins/security/services/shield_indices';
+
+import { IndexPatternsProvider } from 'ui/index_patterns/index_patterns';
+import { XPackInfoProvider } from 'plugins/xpack_main/services/xpack_info';
+import { checkLicenseError } from 'plugins/security/lib/check_license_error';
+import { EDIT_ROLES_PATH, ROLES_PATH } from '../management_urls';
+
+import { EditRolePage } from './components';
+
+import React from 'react';
+import { render, unmountComponentAtNode } from 'react-dom';
+
+routes.when(`${EDIT_ROLES_PATH}/:name?`, {
+ template,
+ resolve: {
+ role($route, ShieldRole, kbnUrl, Promise, Notifier) {
+ const name = $route.current.params.name;
+
+ let role;
+
+ if (name != null) {
+ role = ShieldRole.get({ name }).$promise
+ .catch((response) => {
+
+ if (response.status !== 404) {
+ return fatalError(response);
+ }
+
+ const notifier = new Notifier();
+ notifier.error(`No "${name}" role found.`);
+ kbnUrl.redirect(ROLES_PATH);
+ return Promise.halt();
+ });
+
+ } else {
+ role = Promise.resolve(new ShieldRole({
+ cluster: [],
+ indices: [],
+ run_as: [],
+ applications: []
+ }));
+ }
+
+ return role.then(roleToEdit => {
+ if (roleToEdit.indices.length === 0) {
+ roleToEdit.indices.push({
+ names: [],
+ privileges: [],
+ field_security: {
+ grant: ['*']
+ }
+ });
+ }
+ return roleToEdit;
+ });
+
+ },
+ kibanaApplicationPrivilege(ApplicationPrivilege, kbnUrl, Promise, Private) {
+ return ApplicationPrivilege.query().$promise
+ .then(privileges => privileges.map(p => p.toJSON()))
+ .catch(checkLicenseError(kbnUrl, Promise, Private));
+ },
+ users(ShieldUser, kbnUrl, Promise, Private) {
+ // $promise is used here because the result is an ngResource, not a promise itself
+ return ShieldUser.query().$promise
+ .then(users => _.map(users, 'username'))
+ .catch(checkLicenseError(kbnUrl, Promise, Private));
+ },
+ indexPatterns(Private) {
+ const indexPatterns = Private(IndexPatternsProvider);
+ return indexPatterns.getTitles();
+ }
+ },
+ controllerAs: 'editRole',
+ controller($injector, $scope, $http, rbacEnabled, rbacApplication) {
+ const $route = $injector.get('$route');
+ const Private = $injector.get('Private');
+
+ const Notifier = $injector.get('Notifier');
+
+ const kibanaApplicationPrivilege = $route.current.locals.kibanaApplicationPrivilege;
+ const role = $route.current.locals.role;
+
+ const xpackInfo = Private(XPackInfoProvider);
+ const allowDocumentLevelSecurity = xpackInfo.get('features.security.allowRoleDocumentLevelSecurity');
+ const allowFieldLevelSecurity = xpackInfo.get('features.security.allowRoleFieldLevelSecurity');
+
+ const domNode = document.getElementById('editRoleReactRoot');
+
+ const {
+ users,
+ indexPatterns,
+ } = $route.current.locals;
+
+ render( , domNode);
+
+ // unmount react on controller destroy
+ $scope.$on('$destroy', () => {
+ unmountComponentAtNode(domNode);
+ });
+ }
+});
diff --git a/x-pack/plugins/security/public/views/management/edit_role/lib/constants.js b/x-pack/plugins/security/public/views/management/edit_role/lib/constants.js
deleted file mode 100644
index 6518df48847e9..0000000000000
--- a/x-pack/plugins/security/public/views/management/edit_role/lib/constants.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-export const CLUSTER_PRIVS_DOC_LINK = `https://www.elastic.co/guide/en/x-pack/current/security-privileges.html#security-privileges`;
diff --git a/x-pack/plugins/security/public/views/management/management.js b/x-pack/plugins/security/public/views/management/management.js
index 06866c226ce90..f7000478cbfc7 100644
--- a/x-pack/plugins/security/public/views/management/management.js
+++ b/x-pack/plugins/security/public/views/management/management.js
@@ -9,7 +9,7 @@ import 'plugins/security/views/management/password_form/password_form';
import 'plugins/security/views/management/users';
import 'plugins/security/views/management/roles';
import 'plugins/security/views/management/edit_user';
-import 'plugins/security/views/management/edit_role';
+import 'plugins/security/views/management/edit_role/index';
import 'plugins/security/views/management/management.less';
import routes from 'ui/routes';
import { XPackInfoProvider } from 'plugins/xpack_main/services/xpack_info';
From abb55d71452397a95ae45278d9d7572287f27a8c Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Wed, 30 May 2018 16:47:26 -0400
Subject: [PATCH 30/38] improve role validation
---
.../__snapshots__/validate_role.test.js.snap | 3 +++
.../management/edit_role/lib/validate_role.js | 20 ++++++++++---------
.../edit_role/lib/validate_role.test.js | 8 ++++++++
3 files changed, 22 insertions(+), 9 deletions(-)
create mode 100644 x-pack/plugins/security/public/views/management/edit_role/lib/__snapshots__/validate_role.test.js.snap
diff --git a/x-pack/plugins/security/public/views/management/edit_role/lib/__snapshots__/validate_role.test.js.snap b/x-pack/plugins/security/public/views/management/edit_role/lib/__snapshots__/validate_role.test.js.snap
new file mode 100644
index 0000000000000..20b4280b7f493
--- /dev/null
+++ b/x-pack/plugins/security/public/views/management/edit_role/lib/__snapshots__/validate_role.test.js.snap
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`validateIndexPrivileges it throws when indices is not an array 1`] = `"Expected role.indices to be an array"`;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.js b/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.js
index 0179c4bb2d40e..3fc638a83782c 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.js
@@ -35,16 +35,18 @@ export class RoleValidator {
validateIndexPrivileges(role) {
if (!this._shouldValidate) return valid();
- if (Array.isArray(role.indices)) {
- const areIndicesValid = role.indices
- .map(this.validateIndexPrivilege.bind(this))
- .find((result) => result.isInvalid) == null;
-
- if (areIndicesValid) {
- return valid();
- }
- return invalid();
+ if (!Array.isArray(role.indices)) {
+ throw new TypeError(`Expected role.indices to be an array`);
+ }
+
+ const areIndicesValid = role.indices
+ .map(this.validateIndexPrivilege.bind(this))
+ .find((result) => result.isInvalid) == null;
+
+ if (areIndicesValid) {
+ return valid();
}
+ return invalid();
}
validateIndexPrivilege(indexPrivilege) {
diff --git a/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.test.js b/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.test.js
index 795e681be5d59..47d2bfe59a37e 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.test.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/lib/validate_role.test.js
@@ -83,4 +83,12 @@ describe('validateIndexPrivileges', () => {
isInvalid: true
});
});
+
+ test('it throws when indices is not an array', () => {
+ const role = {
+ indices: null
+ };
+
+ expect(() => validator.validateIndexPrivileges(role)).toThrowErrorMatchingSnapshot();
+ });
});
From cb02fe1dec8d1fa8608783943893b1f78d7aec13 Mon Sep 17 00:00:00 2001
From: chorn
Date: Thu, 31 May 2018 18:02:34 -0400
Subject: [PATCH 31/38] Design edits
- played with spacing
- moved some buttons around
- moved the reserved lock icon to title
- moved links to docs to description and make it a text link
- fixed some responsive layouts
---
.../kbn-ui-framework/dist/ui_framework.css | 206 ------------------
.../edit_role/components/collapsible_panel.js | 8 +-
.../components/collapsible_panel.less | 3 +-
.../edit_role/components/edit_role_page.js | 122 +++++------
.../privileges/elasticsearch_privileges.js | 49 ++---
.../privileges/index_privilege_form.js | 68 +++---
.../privileges/kibana_privileges.js | 15 +-
.../components/reserved_role_badge.js | 11 +-
.../views/management/edit_role/edit_role.less | 10 +-
9 files changed, 143 insertions(+), 349 deletions(-)
diff --git a/packages/kbn-ui-framework/dist/ui_framework.css b/packages/kbn-ui-framework/dist/ui_framework.css
index 0d013535e3555..101f718149647 100644
--- a/packages/kbn-ui-framework/dist/ui_framework.css
+++ b/packages/kbn-ui-framework/dist/ui_framework.css
@@ -78,15 +78,12 @@ main {
overflow: hidden; }
.kuiActionItem {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between; }
@@ -105,15 +102,12 @@ main {
background-color: rgba(0, 0, 0, 0.1); }
.kuiBar {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
@@ -121,22 +115,18 @@ main {
/* 1 */ }
.kuiBarSection {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
margin-left: 25px;
margin-right: 25px; }
.kuiBarSection:not(:first-child):not(:last-child):not(:only-child) {
- -webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
@@ -145,12 +135,10 @@ main {
margin-left: 0; }
.kuiBarSection:last-child {
margin-right: 0;
- -webkit-box-flex: 0;
-webkit-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
/* 4 */
- -webkit-box-pack: end;
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end;
@@ -201,12 +189,10 @@ main {
* 1. Solves whitespace problems introduced by inline elements.
*/
.kuiButton__inner {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
/* 1 */
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
@@ -513,11 +499,9 @@ main {
background-color: rgba(165, 231, 255, 0.5); }
.kuiButtonGroup {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center; }
@@ -545,24 +529,19 @@ main {
margin-left: 2px; }
.kuiButtonGroup--fullWidth {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex; }
.kuiButtonGroup--fullWidth > .kuiButton {
- -webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
text-align: center; }
.kuiCard {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
@@ -572,20 +551,15 @@ main {
line-height: 1.5; }
.kuiCard__description {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-pack: start;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
@@ -613,7 +587,6 @@ main {
* 2. Offset the spacing between wrapped cards.
*/
.kuiCardGroup {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
@@ -628,7 +601,6 @@ main {
* 2. Use an even margin all around the card so that the spacing is still even when wrapped.
*/ }
.kuiCardGroup .kuiCard {
- -webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
@@ -636,7 +608,6 @@ main {
margin: 15px;
/* 2 */ }
.kuiCardGroup .kuiCard .kuiCard__description {
- -webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto; }
@@ -687,20 +658,15 @@ main {
right: 0;
left: 0;
background: rgba(255, 255, 255, 0.7);
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
- -webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
@@ -736,11 +702,9 @@ main {
cursor: pointer; }
.kuiColorPicker__preview {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center; }
@@ -890,11 +854,9 @@ main {
margin-right: 8px; }
.kuiContextMenu__itemLayout {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center; }
@@ -1071,13 +1033,11 @@ main {
color: #ffffff; }
.kuiContextMenuItem__inner {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex; }
.kuiContextMenuItem__text {
- -webkit-box-flex: 1;
-webkit-flex-grow: 1;
-ms-flex-positive: 1;
flex-grow: 1; }
@@ -1096,13 +1056,11 @@ main {
text-decoration: none; }
.kuiEvent {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex; }
.kuiEventSymbol {
- -webkit-box-flex: 0;
-webkit-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
@@ -1111,7 +1069,6 @@ main {
padding-right: 8px; }
.kuiEventBody {
- -webkit-box-flex: 1;
-webkit-flex: 1 1 0%;
-ms-flex: 1 1 0%;
flex: 1 1 0%; }
@@ -1150,16 +1107,13 @@ main {
border-bottom: solid 2px #00A69B; }
.kuiFlexGroup {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch; }
.kuiFlexGroup .kuiFlexItem {
- -webkit-box-flex: 1;
-webkit-flex-grow: 1;
-ms-flex-positive: 1;
flex-grow: 1; }
@@ -1185,13 +1139,11 @@ main {
margin: 20px; }
.kuiFlexGroup--justifyContentSpaceEvenly {
- -webkit-box-pack: space-evenly;
-webkit-justify-content: space-evenly;
-ms-flex-pack: space-evenly;
justify-content: space-evenly; }
.kuiFlexGroup--justifyContentSpaceBetween {
- -webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between; }
@@ -1202,31 +1154,26 @@ main {
justify-content: space-around; }
.kuiFlexGroup--justifyContentCenter {
- -webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center; }
.kuiFlexGroup--justifyContentFlexEnd {
- -webkit-box-pack: end;
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end; }
.kuiFlexGroup--alignItemsStart {
- -webkit-box-align: start;
-webkit-align-items: flex-start;
-ms-flex-align: start;
align-items: flex-start; }
.kuiFlexGroup--alignItemsCenter {
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center; }
.kuiFlexGroup--alignItemsEnd {
- -webkit-box-align: end;
-webkit-align-items: flex-end;
-ms-flex-align: end;
align-items: flex-end; }
@@ -1243,7 +1190,6 @@ main {
flex-wrap: wrap; } }
.kuiFlexGrid {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
@@ -1252,12 +1198,10 @@ main {
flex-wrap: wrap;
margin-bottom: 0; }
.kuiFlexGrid > .kuiFlexItem {
- -webkit-box-flex: 0;
-webkit-flex-grow: 0;
-ms-flex-positive: 0;
flex-grow: 0; }
.kuiFlexGrid > .kuiFlexItem.kuiFlexItem--flexGrowZero {
- -webkit-box-flex: 0 !important;
-webkit-flex-grow: 0 !important;
-ms-flex-positive: 0 !important;
flex-grow: 0 !important;
@@ -1274,7 +1218,6 @@ main {
.kuiFlexGrid--gutterSmall {
margin: -4px;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch; }
@@ -1285,7 +1228,6 @@ main {
.kuiFlexGrid--gutterSmall {
margin: -4px;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch; }
@@ -1296,7 +1238,6 @@ main {
.kuiFlexGrid--gutterSmall {
margin: -4px;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch; }
@@ -1314,7 +1255,6 @@ main {
.kuiFlexGrid--gutterMedium {
margin: -8px;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch; }
@@ -1325,7 +1265,6 @@ main {
.kuiFlexGrid--gutterMedium {
margin: -8px;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch; }
@@ -1336,7 +1275,6 @@ main {
.kuiFlexGrid--gutterMedium {
margin: -8px;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch; }
@@ -1354,7 +1292,6 @@ main {
.kuiFlexGrid--gutterLarge {
margin: -12px;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch; }
@@ -1365,7 +1302,6 @@ main {
.kuiFlexGrid--gutterLarge {
margin: -12px;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch; }
@@ -1376,7 +1312,6 @@ main {
.kuiFlexGrid--gutterLarge {
margin: -12px;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch; }
@@ -1394,7 +1329,6 @@ main {
.kuiFlexGrid--gutterXLarge {
margin: -16px;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch; }
@@ -1405,7 +1339,6 @@ main {
.kuiFlexGrid--gutterXLarge {
margin: -16px;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch; }
@@ -1416,7 +1349,6 @@ main {
.kuiFlexGrid--gutterXLarge {
margin: -16px;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch; }
@@ -1429,13 +1361,10 @@ main {
* 1. Allow KuiPanels to expand to fill the item.
*/
.kuiFlexItem {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
/* 1 */
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
@@ -1446,7 +1375,6 @@ main {
*/ }
.kuiFlexItem.kuiFlexItem--flexGrowZero {
/* 1 */
- -webkit-box-flex: 0;
-webkit-flex-grow: 0;
-ms-flex-positive: 0;
flex-grow: 0;
@@ -1456,52 +1384,42 @@ main {
flex-basis: auto;
/* 2 */ }
.kuiFlexItem.kuiFlexItem--flexGrow1 {
- -webkit-box-flex: 1;
-webkit-flex-grow: 1;
-ms-flex-positive: 1;
flex-grow: 1; }
.kuiFlexItem.kuiFlexItem--flexGrow2 {
- -webkit-box-flex: 2;
-webkit-flex-grow: 2;
-ms-flex-positive: 2;
flex-grow: 2; }
.kuiFlexItem.kuiFlexItem--flexGrow3 {
- -webkit-box-flex: 3;
-webkit-flex-grow: 3;
-ms-flex-positive: 3;
flex-grow: 3; }
.kuiFlexItem.kuiFlexItem--flexGrow4 {
- -webkit-box-flex: 4;
-webkit-flex-grow: 4;
-ms-flex-positive: 4;
flex-grow: 4; }
.kuiFlexItem.kuiFlexItem--flexGrow5 {
- -webkit-box-flex: 5;
-webkit-flex-grow: 5;
-ms-flex-positive: 5;
flex-grow: 5; }
.kuiFlexItem.kuiFlexItem--flexGrow6 {
- -webkit-box-flex: 6;
-webkit-flex-grow: 6;
-ms-flex-positive: 6;
flex-grow: 6; }
.kuiFlexItem.kuiFlexItem--flexGrow7 {
- -webkit-box-flex: 7;
-webkit-flex-grow: 7;
-ms-flex-positive: 7;
flex-grow: 7; }
.kuiFlexItem.kuiFlexItem--flexGrow8 {
- -webkit-box-flex: 8;
-webkit-flex-grow: 8;
-ms-flex-positive: 8;
flex-grow: 8; }
.kuiFlexItem.kuiFlexItem--flexGrow9 {
- -webkit-box-flex: 9;
-webkit-flex-grow: 9;
-ms-flex-positive: 9;
flex-grow: 9; }
.kuiFlexItem.kuiFlexItem--flexGrow10 {
- -webkit-box-flex: 10;
-webkit-flex-grow: 10;
-ms-flex-positive: 10;
flex-grow: 10; }
@@ -1592,11 +1510,9 @@ main {
background-color: #0079a5; }
.kuiCheckBoxLabel {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
@@ -1860,18 +1776,15 @@ main {
* 1. We may want to put elements in here which have different heights.
*/
.kuiFieldGroup {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
/* 1 */ }
.kuiFieldGroup--alignTop {
- -webkit-box-align: start;
-webkit-align-items: flex-start;
-ms-flex-align: start;
align-items: flex-start; }
@@ -1882,7 +1795,6 @@ main {
margin-left: 10px; }
.kuiFieldGroupSection--wide {
- -webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto; }
@@ -1890,7 +1802,6 @@ main {
width: 100%; }
.kuiGallery {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
@@ -1899,20 +1810,15 @@ main {
flex-wrap: wrap; }
.kuiGalleryItem {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
@@ -1931,15 +1837,12 @@ main {
border-color: #00A6FF; }
.kuiGalleryItem__image {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
@@ -1970,15 +1873,12 @@ main {
color: #666; }
.kuiHeaderBar {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
@@ -1990,22 +1890,18 @@ main {
* 1. Align a single section to the left by default.
*/
.kuiHeaderBarSection {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
margin-left: 25px;
margin-right: 25px; }
.kuiHeaderBarSection:not(:first-child):not(:last-child):not(:only-child) {
- -webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
@@ -2014,12 +1910,10 @@ main {
margin-left: 0; }
.kuiHeaderBarSection:last-child {
margin-right: 0;
- -webkit-box-flex: 0;
-webkit-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
/* 4 */
- -webkit-box-pack: end;
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end;
@@ -2118,11 +2012,9 @@ main {
* 1. Align with first line of title text if it wraps.
*/
.kuiInfoPanelHeader {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: baseline;
-webkit-align-items: baseline;
-ms-flex-align: baseline;
align-items: baseline;
@@ -2179,11 +2071,9 @@ main {
* a bit.
*/
.kuiLocalBreadcrumbs {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
@@ -2253,15 +2143,12 @@ main {
padding: 0; }
.kuiDatePickerNavigation {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
@@ -2425,13 +2312,11 @@ main {
/* 1 */ }
.kuiLocalDropdownPanels {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex; }
.kuiLocalDropdownPanel {
- -webkit-box-flex: 1;
-webkit-flex: 1 1 0%;
-ms-flex: 1 1 0%;
flex: 1 1 0%; }
@@ -2460,15 +2345,12 @@ main {
margin-bottom: 0; }
.kuiLocalDropdownHeader {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
@@ -2487,7 +2369,6 @@ main {
color: #cecece; }
.kuiLocalDropdownHeader__actions {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex; }
@@ -2549,21 +2430,17 @@ main {
color: #9e9e9e; }
.kuiLocalMenu {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch; }
.kuiLocalMenuItem {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
@@ -2615,16 +2492,12 @@ main {
* dropdown.
*/
.kuiLocalNav {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
- -webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
@@ -2643,15 +2516,12 @@ main {
* 1. Allow row to expand if the content is so long that it wraps.
*/
.kuiLocalNavRow {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch;
- -webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
@@ -2659,11 +2529,9 @@ main {
/* 1 */ }
.kuiLocalNavRow__section {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch; }
@@ -2678,14 +2546,12 @@ main {
.kuiLocalNavRow--secondary {
padding: 0 10px;
/* 1 */
- -webkit-box-align: start;
-webkit-align-items: flex-start;
-ms-flex-align: start;
align-items: flex-start;
/* 1 */ }
.kuiLocalSearch {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
@@ -2708,7 +2574,6 @@ main {
transition: border-color 0.1s linear;
min-height: 30px;
/* 1 */
- -webkit-box-flex: 1;
-webkit-flex: 1 1 100%;
-ms-flex: 1 1 100%;
flex: 1 1 100%;
@@ -2738,7 +2603,6 @@ main {
.kuiLocalSearchInput--secondary {
height: 30px;
- -webkit-box-flex: 0;
-webkit-flex: 0 0 auto;
-ms-flex: 0 0 auto;
flex: 0 0 auto;
@@ -2750,11 +2614,9 @@ main {
border-right-color: #333333; }
.kuiLocalSearchAssistedInput {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-flex: 1;
-webkit-flex: 1 1 100%;
-ms-flex: 1 1 100%;
flex: 1 1 100%;
@@ -2857,11 +2719,9 @@ main {
* 1. We want the bottom border on selected tabs to be flush with the bottom of the container.
*/
.kuiLocalTabs {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: end;
-webkit-align-items: flex-end;
-ms-flex-align: end;
align-items: flex-end;
@@ -2906,11 +2766,9 @@ main {
color: #dedede; }
.kuiLocalTitle {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
@@ -3042,7 +2900,6 @@ main {
/* 3 */ }
.kuiMenuButtonGroup {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex; }
@@ -3050,7 +2907,6 @@ main {
margin-left: 4px; }
.kuiMenuButtonGroup--alignRight {
- -webkit-box-pack: end;
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end; }
@@ -3073,7 +2929,6 @@ main {
color: #191E23; }
.kuiMicroButtonGroup {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex; }
@@ -3087,15 +2942,12 @@ main {
left: 0;
right: 0;
bottom: 0;
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
@@ -3121,15 +2973,12 @@ main {
min-width: auto; }
.kuiModalHeader {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
@@ -3170,11 +3019,9 @@ main {
color: #cecece; }
.kuiModalFooter {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-pack: end;
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end;
@@ -3213,11 +3060,9 @@ main {
* 1. Put 10px of space between each child.
*/
.kuiPager {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center; }
@@ -3237,21 +3082,16 @@ main {
border-radius: 4px; }
.kuiPanel--prompt {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
text-align: center;
- -webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
@@ -3268,29 +3108,23 @@ main {
border-radius: 0; }
.kuiPanel--centered {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center; }
.kuiPanelHeader {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
@@ -3352,22 +3186,18 @@ main {
* 1. Undo what barSection mixin does.
*/
.kuiPanelHeaderSection {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
margin-left: 25px;
margin-right: 25px; }
.kuiPanelHeaderSection:not(:first-child):not(:last-child):not(:only-child) {
- -webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
@@ -3376,12 +3206,10 @@ main {
margin-left: 0; }
.kuiPanelHeaderSection:last-child {
margin-right: 0;
- -webkit-box-flex: 0;
-webkit-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
/* 4 */
- -webkit-box-pack: end;
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end;
@@ -3406,7 +3234,6 @@ main {
background-color: #FFF;
border: 1px solid #D9D9D9;
border-radius: 4px;
- -webkit-box-flex: 1;
-webkit-flex-grow: 1;
-ms-flex-positive: 1;
flex-grow: 1; }
@@ -3419,7 +3246,6 @@ main {
.kuiPanelSimple.kuiPanelSimple--shadow {
box-shadow: 0 16px 16px -8px rgba(0, 0, 0, 0.1); }
.kuiPanelSimple.kuiPanelSimple--flexGrowZero {
- -webkit-box-flex: 0;
-webkit-flex-grow: 0;
-ms-flex-positive: 0;
flex-grow: 0; }
@@ -3513,16 +3339,12 @@ main {
color: #ffffff; }
.kuiEmptyTablePrompt {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
@@ -3537,11 +3359,9 @@ main {
margin-top: 10px; }
.kuiStatusText {
- display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
- -webkit-box-align: baseline;
-webkit-align-items: baseline;
-ms-flex-align: baseline;
align-items: baseline; }
@@ -3657,11 +3477,9 @@ main {
display: block;
opacity: 1; }
.kuiTableHeaderCellButton .kuiTableHeaderCell__liner {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center; }
@@ -3762,7 +3580,6 @@ main {
line-height: 1.5; }
.kuiTabs {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
@@ -3886,15 +3703,12 @@ main {
/* 1 */ }
.kuiToolBar {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
@@ -3945,22 +3759,18 @@ main {
border-color: #0079a5; }
.kuiToolBarSection {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
margin-left: 25px;
margin-right: 25px; }
.kuiToolBarSection:not(:first-child):not(:last-child):not(:only-child) {
- -webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
@@ -3969,12 +3779,10 @@ main {
margin-left: 0; }
.kuiToolBarSection:last-child {
margin-right: 0;
- -webkit-box-flex: 0;
-webkit-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
/* 4 */
- -webkit-box-pack: end;
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end;
@@ -3994,15 +3802,12 @@ main {
/* 1 */ }
.kuiToolBarFooter {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
@@ -4014,22 +3819,18 @@ main {
border: 1px solid #D9D9D9; }
.kuiToolBarFooterSection {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
- -webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
margin-left: 25px;
margin-right: 25px; }
.kuiToolBarFooterSection:not(:first-child):not(:last-child):not(:only-child) {
- -webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
@@ -4038,12 +3839,10 @@ main {
margin-left: 0; }
.kuiToolBarFooterSection:last-child {
margin-right: 0;
- -webkit-box-flex: 0;
-webkit-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
/* 4 */
- -webkit-box-pack: end;
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end;
@@ -4061,17 +3860,14 @@ main {
* kuiToolBarSection sibling.
*/
.kuiToolBarSearch {
- display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
- -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
margin-left: 25px;
margin-right: 25px;
- -webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
@@ -4087,7 +3883,6 @@ main {
/* 1 */ }
.kuiToolBarSearchBox {
- -webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
@@ -4210,7 +4005,6 @@ main {
.kuiView {
background-color: #FFF;
- -webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto; }
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.js b/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.js
index e39b25e8e522b..f2bac7a02b99c 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.js
@@ -38,12 +38,12 @@ export class CollapsiblePanel extends Component {
getTitle = () => {
return (
-
+
-
- {this.props.title}
-
+
+ {this.props.title}
+
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.less b/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.less
index cc56943ffcda9..ffb065880c560 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.less
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/collapsible_panel.less
@@ -1,3 +1,4 @@
.collapsiblePanel__logo {
- margin-right: 10px;
+ margin-right: 8px;
+ vertical-align: text-bottom;
}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
index 38f3389ccace6..8b50c3b19e5fa 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
@@ -9,10 +9,10 @@ import { get } from 'lodash';
import { toastNotifications } from 'ui/notify';
import {
EuiPanel,
- EuiText,
+ EuiTitle,
EuiSpacer,
EuiPage,
- EuiPageContent,
+ EuiButtonEmpty,
EuiForm,
EuiFormRow,
EuiFieldText,
@@ -57,27 +57,21 @@ export class EditRolePage extends Component {
-
-
- {this.getFormTitle()}
+
+ {this.getFormTitle()}
-
+
- {this.getRoleName()}
+ {this.getRoleName()}
-
+ {this.getElasticsearchPrivileges()}
- {this.getElasticsearchPrivileges()}
+ {this.getKibanaPrivileges()}
-
+
- {this.getKibanaPrivileges()}
-
-
-
- {this.getFormButtons()}
-
-
+ {this.getFormButtons()}
+
);
@@ -94,12 +88,7 @@ export class EditRolePage extends Component {
}
return (
-
-
- {titleText}
-
- {this.getActionButton()}
-
+ {titleText}
);
};
@@ -118,19 +107,22 @@ export class EditRolePage extends Component {
getRoleName = () => {
return (
-
-
-
-
-
-
-
-
+
+
+
+
);
}
@@ -149,17 +141,20 @@ export class EditRolePage extends Component {
getElasticsearchPrivileges() {
return (
-
+
+
+
+
);
}
@@ -175,40 +170,41 @@ export class EditRolePage extends Component {
}
return (
-
+
+
+
+
);
};
getFormButtons = () => {
if (isReservedRole(this.props.role)) {
return (
-
-
-
- Return to role list
-
-
-
+
+ Return to role list
+
);
}
const saveText = this.editingExistingRole() ? 'Update role' : 'Create role';
return (
-
+
{saveText}
-
+
Cancel
-
+
+
+ {this.getActionButton()}
);
};
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
index 49be5cfc83c4e..a0c6eca6f0c6e 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/elasticsearch_privileges.js
@@ -11,14 +11,11 @@ import {
EuiSpacer,
EuiComboBox,
EuiFormRow,
- EuiFlexGroup,
- EuiFlexItem,
EuiButton,
EuiDescribedFormGroup,
EuiTitle,
EuiHorizontalRule,
EuiLink,
- EuiIcon,
} from '@elastic/eui';
import './elasticsearch_privileges.less';
import { ClusterPrivileges } from './cluster_privileges';
@@ -71,14 +68,14 @@ export class ElasticsearchPrivileges extends Component {
return (
Cluster privileges {this.learnMore(documentationLinks.esClusterPrivileges)}}
+ title={Cluster privileges }
description={
- Manage the actions this role can perform against your cluster.
+ Manage the actions this role can perform against your cluster. {this.learnMore(documentationLinks.esClusterPrivileges)}
}
>
-
+
@@ -86,14 +83,14 @@ export class ElasticsearchPrivileges extends Component {
Run As privileges {this.learnMore(documentationLinks.esRunAsPrivileges)}}
+ title={Run As privileges }
description={
- Allow requests to be submitted on behalf of other users.
+ Allow requests to be submitted on the behalf of other users. {this.learnMore(documentationLinks.esRunAsPrivileges)}
}
>
-
+
({ id: username, label: username }))}
@@ -106,32 +103,26 @@ export class ElasticsearchPrivileges extends Component {
-
-
-
-
- Index privileges {this.learnMore(documentationLinks.esIndicesPrivileges)}
- Control access to the data in your cluster.
-
- {this.props.editable && (
-
- Add Index Privilege
-
- )}
-
-
-
-
-
-
-
+ Index privileges
+
+
+ Control access to the data in your cluster. {this.learnMore(documentationLinks.esIndicesPrivileges)}
+
+
+
+
+
+
+ {this.props.editable && (
+ Add index privilege
+ )}
);
}
learnMore = (href) => (
-
+ Learn more
);
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
index 615edfa032188..479762770fce6 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
@@ -6,7 +6,6 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import {
- EuiCallOut,
EuiComboBox,
EuiTextArea,
EuiFormRow,
@@ -15,8 +14,7 @@ import {
EuiSwitch,
EuiSpacer,
EuiHorizontalRule,
- EuiLink,
- EuiIcon,
+ EuiButtonIcon,
} from '@elastic/eui';
import { getIndexPrivileges } from '../../../../../services/role_privileges';
@@ -46,19 +44,21 @@ export class IndexPrivilegeForm extends Component {
render() {
return (
-
-
+
+
+
{this.getPrivilegeForm()}
{this.props.allowDelete && (
-
+
+
+
)}
-
-
+
);
}
@@ -90,6 +90,8 @@ export class IndexPrivilegeForm extends Component {
{this.getGrantedFieldsControl()}
+
+
{this.getGrantedDocumentsControl()}
);
@@ -108,27 +110,36 @@ export class IndexPrivilegeForm extends Component {
const { grant = [] } = indexPrivilege.field_security || {};
- let grantedFieldsWarning = null;
+ // TODO: Remove this completely, if ok with just putting the text in the helptext
+ // let grantedFieldsWarning = null;
if (allowFieldLevelSecurity) {
- if (grant.length === 0) {
- grantedFieldsWarning = (
-
-
-
-
- If no fields are granted, then users assigned to this role will not be able to
- see any data for this index. Is this really what you want?
-
-
-
- );
- }
+ // if (grant.length === 0) {
+ // grantedFieldsWarning = (
+ //
+ //
+ //
+ //
+ // If no fields are granted, then users assigned to this role will not be able to
+ // see any data for this index. Is this really what you want?
+ //
+ //
+ //
+ // );
+ // }
return (
-
+
- {grantedFieldsWarning}
@@ -158,9 +168,9 @@ export class IndexPrivilegeForm extends Component {
}
return (
-
+
{!this.props.isReservedRole &&
-
+
}
{this.state.queryExpanded &&
-
-
+
+
Application privileges}
description={Manage the actions this role can perform within Kibana.
}
>
-
+
+
+
);
}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.js b/x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.js
index 8d0c17bd062ab..8b750b19338ed 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.js
@@ -9,9 +9,8 @@ import PropTypes from 'prop-types';
import { isReservedRole } from '../../../../lib/role';
import {
- EuiBadge,
+ EuiIcon,
EuiToolTip,
- EuiFlexItem,
} from '@elastic/eui';
@@ -22,11 +21,9 @@ export const ReservedRoleBadge = (props) => {
if (isReservedRole(role)) {
return (
-
-
- Reserved Role
-
-
+
+
+
);
}
return null;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/edit_role.less b/x-pack/plugins/security/public/views/management/edit_role/edit_role.less
index 7b6b150c0444e..d4f7ac04880d6 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/edit_role.less
+++ b/x-pack/plugins/security/public/views/management/edit_role/edit_role.less
@@ -1,8 +1,10 @@
-#editRoleReactRoot, .editRolePage, .editRolePage__content {
+#editRoleReactRoot {
background: #f5f5f5;
+ flex-grow: 1;
}
-.editRolePage__content {
- border: none;
- box-shadow: none;
+.editRolePage {
+ max-width: 1000px;
+ margin-left: auto;
+ margin-right: auto;
}
From 87f8cd8f6539e60f1e9ba400efa7a5b6d1c5d269 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Fri, 1 Jun 2018 08:23:50 -0400
Subject: [PATCH 32/38] start addressing design feedback
---
.../public/views/management/edit_role.js | 122 ------------------
.../edit_role/components/edit_role_page.js | 4 +-
.../components/privileges/index_privileges.js | 5 +
.../views/management/edit_role/index.js | 14 +-
4 files changed, 8 insertions(+), 137 deletions(-)
delete mode 100644 x-pack/plugins/security/public/views/management/edit_role.js
diff --git a/x-pack/plugins/security/public/views/management/edit_role.js b/x-pack/plugins/security/public/views/management/edit_role.js
deleted file mode 100644
index 6c5c88f717cd0..0000000000000
--- a/x-pack/plugins/security/public/views/management/edit_role.js
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import _ from 'lodash';
-import routes from 'ui/routes';
-import { fatalError } from 'ui/notify';
-import template from 'plugins/security/views/management/edit_role.html';
-import 'plugins/security/views/management/edit_role/edit_role.less';
-import 'angular-ui-select';
-import 'plugins/security/services/application_privilege';
-import 'plugins/security/services/shield_user';
-import 'plugins/security/services/shield_role';
-import 'plugins/security/services/shield_privileges';
-import 'plugins/security/services/shield_indices';
-
-import { IndexPatternsProvider } from 'ui/index_patterns/index_patterns';
-import { XPackInfoProvider } from 'plugins/xpack_main/services/xpack_info';
-import { checkLicenseError } from 'plugins/security/lib/check_license_error';
-import { EDIT_ROLES_PATH, ROLES_PATH } from './management_urls';
-
-import { EditRolePage } from './edit_role/components';
-
-import React from 'react';
-import { render, unmountComponentAtNode } from 'react-dom';
-
-routes.when(`${EDIT_ROLES_PATH}/:name?`, {
- template,
- resolve: {
- role($route, ShieldRole, kbnUrl, Promise, Notifier) {
- const name = $route.current.params.name;
- if (name != null) {
- return ShieldRole.get({ name }).$promise
- .catch((response) => {
-
- if (response.status !== 404) {
- return fatalError(response);
- }
-
- const notifier = new Notifier();
- notifier.error(`No "${name}" role found.`);
- kbnUrl.redirect(ROLES_PATH);
- return Promise.halt();
- });
- }
- return new ShieldRole({
- cluster: [],
- indices: [],
- run_as: [],
- applications: []
- });
- },
- kibanaApplicationPrivilege(ApplicationPrivilege, kbnUrl, Promise, Private) {
- return ApplicationPrivilege.query().$promise
- .then(privileges => privileges.map(p => p.toJSON()))
- .catch(checkLicenseError(kbnUrl, Promise, Private));
- },
- users(ShieldUser, kbnUrl, Promise, Private) {
- // $promise is used here because the result is an ngResource, not a promise itself
- return ShieldUser.query().$promise
- .then(users => _.map(users, 'username'))
- .catch(checkLicenseError(kbnUrl, Promise, Private));
- },
- indexPatterns(Private) {
- const indexPatterns = Private(IndexPatternsProvider);
- return indexPatterns.getTitles();
- }
- },
- controllerAs: 'editRole',
- controller($injector, $scope, $http, rbacEnabled, rbacApplication) {
- const $route = $injector.get('$route');
- const Private = $injector.get('Private');
-
- const Notifier = $injector.get('Notifier');
-
- const kibanaApplicationPrivilege = $route.current.locals.kibanaApplicationPrivilege;
- const role = $route.current.locals.role;
-
- const xpackInfo = Private(XPackInfoProvider);
- const allowDocumentLevelSecurity = xpackInfo.get('features.security.allowRoleDocumentLevelSecurity');
- const allowFieldLevelSecurity = xpackInfo.get('features.security.allowRoleFieldLevelSecurity');
-
- const domNode = document.getElementById('editRoleReactRoot');
-
- const {
- users,
- indexPatterns,
- } = $route.current.locals;
-
- const roleToEdit = role.toJSON();
- if (roleToEdit.indices.length === 0) {
- roleToEdit.indices.push({
- names: [],
- privileges: [],
- field_security: {
- grant: ['*']
- }
- });
- }
-
- render( , domNode);
-
- // unmount react on controller destroy
- $scope.$on('$destroy', () => {
- unmountComponentAtNode(domNode);
- });
- }
-});
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
index 38f3389ccace6..0d7b89e4f2563 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
@@ -86,11 +86,11 @@ export class EditRolePage extends Component {
getFormTitle = () => {
let titleText;
if (isReservedRole(this.props.role)) {
- titleText = 'Reserved role';
+ titleText = 'Viewing role';
} else if (this.editingExistingRole()) {
titleText = 'Edit role';
} else {
- titleText = 'New role';
+ titleText = 'Create role';
}
return (
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
index cf04718c3e475..c4b961e60cd05 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
@@ -117,6 +117,11 @@ export class IndexPrivileges extends Component {
};
loadAvailableFields(indices) {
+ // Reserved roles cannot be edited, and therefore do not need to fetch available fields.
+ if (isReservedRole(this.props.role)) {
+ return;
+ }
+
const patterns = indices.map(index => index.names.join(','));
const cachedPatterns = Object.keys(this.state.availableFields);
diff --git a/x-pack/plugins/security/public/views/management/edit_role/index.js b/x-pack/plugins/security/public/views/management/edit_role/index.js
index 9d3e10b75dba4..385fe444e0422 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/index.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/index.js
@@ -57,19 +57,7 @@ routes.when(`${EDIT_ROLES_PATH}/:name?`, {
}));
}
- return role.then(roleToEdit => {
- if (roleToEdit.indices.length === 0) {
- roleToEdit.indices.push({
- names: [],
- privileges: [],
- field_security: {
- grant: ['*']
- }
- });
- }
- return roleToEdit;
- });
-
+ return role.then(res => res.toJSON());
},
kibanaApplicationPrivilege(ApplicationPrivilege, kbnUrl, Promise, Private) {
return ApplicationPrivilege.query().$promise
From bb1c129f247cf75ced21f8c4f18630fe611db8ed Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Fri, 1 Jun 2018 10:02:21 -0400
Subject: [PATCH 33/38] Don't hide delete button for placeholder privileges
---
.../edit_role/components/privileges/index_privileges.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
index c4b961e60cd05..cb72ecd7aa4bf 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privileges.js
@@ -53,7 +53,7 @@ export class IndexPrivileges extends Component {
key={idx}
{...props}
validator={this.props.validator}
- allowDelete={!props.isReservedRole && !(this.isPlaceholderPrivilege(indexPrivilege) && indices.length === 1)}
+ allowDelete={!props.isReservedRole}
indexPrivilege={indexPrivilege}
availableFields={this.state.availableFields[indexPrivilege.names.join(',')]}
onChange={this.onIndexPrivilegeChange(idx)}
From 829a6e763aeee78a19441b0f7ee3921304b63df5 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Fri, 1 Jun 2018 10:28:47 -0400
Subject: [PATCH 34/38] change Kibana Privileges to use a select instead of
checkboxes
---
.../privileges/kibana_privileges.js | 46 ++++++++++++-------
1 file changed, 29 insertions(+), 17 deletions(-)
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
index b13002feae003..41537bd27f7a2 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana_privileges.js
@@ -8,13 +8,16 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { isReservedRole } from '../../../../../lib/role';
import { getKibanaPrivileges } from '../../lib/get_application_privileges';
-import { togglePrivilege } from '../../lib/set_application_privileges';
+import { setApplicationPrivileges } from '../../lib/set_application_privileges';
import { CollapsiblePanel } from '../collapsible_panel';
import {
- EuiCheckboxGroup,
+ EuiSelect,
EuiDescribedFormGroup,
} from '@elastic/eui';
+
+const noPrivilegeValue = '-none-';
+
export class KibanaPrivileges extends Component {
static propTypes = {
role: PropTypes.object.isRequired,
@@ -46,26 +49,24 @@ export class KibanaPrivileges extends Component {
const kibanaPrivileges = getKibanaPrivileges(kibanaAppPrivileges, role, rbacApplication);
- const checkboxes = Object.keys(kibanaPrivileges).map(p => ({
- id: this.privilegeToId(p),
- label: p
- }));
+ const options = [
+ { value: noPrivilegeValue, text: 'none' },
+ ...Object.keys(kibanaPrivileges).map(p => ({
+ value: p,
+ text: p
+ }))
+ ];
- const selectionMap = Object.keys(kibanaPrivileges).reduce((acc, p) => {
- return {
- ...acc,
- [this.privilegeToId(p)]: kibanaPrivileges[p]
- };
- }, {});
+ const value = Object.keys(kibanaPrivileges).find(p => kibanaPrivileges[p]) || noPrivilegeValue;
return (
Application privileges}
description={Manage the actions this role can perform within Kibana.
}
>
-
@@ -73,13 +74,24 @@ export class KibanaPrivileges extends Component {
);
}
- onKibanaPrivilegesChange = (privilege) => {
+ onKibanaPrivilegesChange = (e) => {
const role = {
...this.props.role,
applications: [...this.props.role.applications]
};
- togglePrivilege(role, this.props.rbacApplication, this.idToPrivilege(privilege));
+ const privilege = e.target.value;
+
+ if (privilege === noPrivilegeValue) {
+ // unsetting all privileges -- only necessary until RBAC Phase 3
+ const noPrivileges = {};
+ setApplicationPrivileges(noPrivileges, role, this.props.rbacApplication);
+ } else {
+ const newPrivileges = {
+ [privilege]: true
+ };
+ setApplicationPrivileges(newPrivileges, role, this.props.rbacApplication);
+ }
this.props.onChange(role);
}
From c7776709ea0f63c1b70be000b7d84ab0c2aea928 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Fri, 1 Jun 2018 11:34:27 -0400
Subject: [PATCH 35/38] upgrade to EUI 0.0.51, and fix Role breadcrumbs
---
package.json | 4 +-
x-pack/package.json | 2 +-
.../__snapshots__/page_header.test.js.snap | 4 +-
.../edit_role/components/page_header.js | 14 +--
.../edit_role/components/page_header.test.js | 12 +-
.../views/management/edit_role/edit_role.html | 2 +-
.../views/management/edit_role/index.js | 18 ++-
.../__snapshots__/page_header.test.js.snap | 16 ++-
.../management/components/page_header.js | 20 ++--
.../management/components/page_header.test.js | 16 ++-
x-pack/yarn.lock | 112 +++++++++++++-----
yarn.lock | 103 +++++++++++++---
12 files changed, 224 insertions(+), 99 deletions(-)
diff --git a/package.json b/package.json
index 5bdf13c020631..d6f2bffd002e8 100644
--- a/package.json
+++ b/package.json
@@ -76,7 +76,7 @@
"url": "https://github.com/elastic/kibana.git"
},
"dependencies": {
- "@elastic/eui": "v0.0.47",
+ "@elastic/eui": "v0.0.51",
"@elastic/filesaver": "1.1.2",
"@elastic/numeral": "2.3.2",
"@elastic/ui-ace": "0.2.3",
@@ -205,8 +205,8 @@
"validate-npm-package-name": "2.2.2",
"vega-lib": "^3.3.1",
"vega-lite": "^2.4.0",
- "vega-tooltip": "^0.9.14",
"vega-schema-url-parser": "1.0.0",
+ "vega-tooltip": "^0.9.14",
"vision": "4.1.0",
"webpack": "3.6.0",
"webpack-merge": "4.1.0",
diff --git a/x-pack/package.json b/x-pack/package.json
index bfcb1dd5a9905..95aa06158b637 100644
--- a/x-pack/package.json
+++ b/x-pack/package.json
@@ -75,7 +75,7 @@
"yargs": "4.7.1"
},
"dependencies": {
- "@elastic/eui": "0.0.47",
+ "@elastic/eui": "v0.0.51",
"@elastic/node-crypto": "0.1.2",
"@elastic/node-phantom-simple": "2.2.4",
"@elastic/numeral": "2.3.2",
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/page_header.test.js.snap b/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/page_header.test.js.snap
index 7dddfa8c5cdef..c7cbfdb53fd73 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/page_header.test.js.snap
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/page_header.test.js.snap
@@ -5,7 +5,9 @@ exports[`it renders without crashing 1`] = `
-
+
`;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/page_header.js b/x-pack/plugins/security/public/views/management/edit_role/components/page_header.js
index ffbab9d0921a7..03347a01ec0fa 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/page_header.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/page_header.js
@@ -10,7 +10,6 @@ import PropTypes from 'prop-types';
import {
EuiHeader,
EuiHeaderSection,
- EuiHeaderBreadcrumb,
EuiHeaderBreadcrumbs
} from '@elastic/eui';
@@ -19,20 +18,17 @@ export class PageHeader extends Component {
return (
-
- {this.props.breadcrumbs.map(this.buildBreadcrumb)}
-
+
);
}
buildBreadcrumb = (breadcrumb) => {
- return (
-
- {breadcrumb.display}
-
- );
+ return {
+ text: breadcrumb.display,
+ href: breadcrumb.href,
+ };
}
}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/page_header.test.js b/x-pack/plugins/security/public/views/management/edit_role/components/page_header.test.js
index 89151673b9911..80248b4e75b83 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/page_header.test.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/page_header.test.js
@@ -7,7 +7,7 @@
import React from 'react';
import { shallow, mount } from 'enzyme';
import { PageHeader } from './page_header';
-import { EuiHeaderBreadcrumbs, EuiHeaderBreadcrumb } from '@elastic/eui';
+import { EuiHeaderBreadcrumbs } from '@elastic/eui';
test('it renders without crashing', () => {
const wrapper = shallow( );
@@ -17,20 +17,16 @@ test('it renders without crashing', () => {
test('it renders breadcrumbs', () => {
const breadcrumbs = [{
- id: 'item-1',
+ display: 'item-1',
href: '#item-1',
- current: false
}, {
- id: 'item-2',
+ display: 'item-2',
href: '#item-2',
- current: false
}, {
- id: 'item-3',
+ display: 'item-3',
href: '#item-3',
- current: true
}];
const wrapper = mount( );
expect(wrapper.find(EuiHeaderBreadcrumbs)).toHaveLength(1);
- expect(wrapper.find(EuiHeaderBreadcrumb)).toHaveLength(breadcrumbs.length);
});
diff --git a/x-pack/plugins/security/public/views/management/edit_role/edit_role.html b/x-pack/plugins/security/public/views/management/edit_role/edit_role.html
index 2e8134b17d29f..5539f0521dd79 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/edit_role.html
+++ b/x-pack/plugins/security/public/views/management/edit_role/edit_role.html
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/x-pack/plugins/security/public/views/management/edit_role/index.js b/x-pack/plugins/security/public/views/management/edit_role/index.js
index 385fe444e0422..e356b9d7c01b6 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/index.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/index.js
@@ -96,6 +96,8 @@ routes.when(`${EDIT_ROLES_PATH}/:name?`, {
indexPatterns,
} = $route.current.locals;
+ const routeBreadcrumbs = routes.getBreadcrumbs();
+
render( b.id === 'edit');
+
+ const hasEntryAfterEdit = indexOfEdit >= 0 && indexOfEdit < (routeBreadcrumbs.length - 1);
+
+ if (hasEntryAfterEdit) {
+ // The entry after 'edit' is the name of the role being edited (if any). We don't want to use the "humanized" version of the role name here
+ const roleName = routeBreadcrumbs[indexOfEdit + 1];
+ roleName.display = roleName.id;
+ }
+
+ return routeBreadcrumbs.filter(b => b.id !== 'edit');
+}
diff --git a/x-pack/plugins/spaces/public/views/management/components/__snapshots__/page_header.test.js.snap b/x-pack/plugins/spaces/public/views/management/components/__snapshots__/page_header.test.js.snap
index 936f678055d41..c7cbfdb53fd73 100644
--- a/x-pack/plugins/spaces/public/views/management/components/__snapshots__/page_header.test.js.snap
+++ b/x-pack/plugins/spaces/public/views/management/components/__snapshots__/page_header.test.js.snap
@@ -1,15 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`it renders without crashing 1`] = `
-
+
+
`;
diff --git a/x-pack/plugins/spaces/public/views/management/components/page_header.js b/x-pack/plugins/spaces/public/views/management/components/page_header.js
index 956c2809b325f..19a76b3d6ccf5 100644
--- a/x-pack/plugins/spaces/public/views/management/components/page_header.js
+++ b/x-pack/plugins/spaces/public/views/management/components/page_header.js
@@ -4,13 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { Component } from 'react';
+import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
EuiHeader,
EuiHeaderSection,
- EuiHeaderBreadcrumb,
EuiHeaderBreadcrumbs
} from '@elastic/eui';
@@ -19,25 +18,20 @@ export class PageHeader extends Component {
return (
-
- {this.props.breadcrumbs.map(this.buildBreadcrumb)}
-
+
);
}
buildBreadcrumb = (breadcrumb) => {
- return (
-
- {breadcrumb.display}
-
- );
+ return {
+ text: breadcrumb.display,
+ href: breadcrumb.href,
+ };
}
}
-
-
PageHeader.propTypes = {
breadcrumbs: PropTypes.array.isRequired
-};
+};
\ No newline at end of file
diff --git a/x-pack/plugins/spaces/public/views/management/components/page_header.test.js b/x-pack/plugins/spaces/public/views/management/components/page_header.test.js
index b960175b38deb..706a6de4a0abc 100644
--- a/x-pack/plugins/spaces/public/views/management/components/page_header.test.js
+++ b/x-pack/plugins/spaces/public/views/management/components/page_header.test.js
@@ -6,30 +6,28 @@
import React from 'react';
import { PageHeader } from './page_header';
-import { render } from 'enzyme';
-import renderer from 'react-test-renderer';
+import { mount, shallow } from 'enzyme';
test('it renders without crashing', () => {
- const component = renderer.create(
+ const component = shallow(
);
expect(component).toMatchSnapshot();
});
test('it renders breadcrumbs', () => {
- const component = render(
+ const component = mount(
);
- expect(component.find('a')).toHaveLength(2);
+ expect(component.find('a.euiBreadcrumb')).toHaveLength(1);
+ expect(component.find('span.euiBreadcrumb')).toHaveLength(1);
});
diff --git a/x-pack/yarn.lock b/x-pack/yarn.lock
index fb4184fbbb632..7c39d6e8fae06 100644
--- a/x-pack/yarn.lock
+++ b/x-pack/yarn.lock
@@ -10,9 +10,9 @@
esutils "^2.0.2"
js-tokens "^3.0.0"
-"@elastic/eui@0.0.47":
- version "0.0.47"
- resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.47.tgz#5bae27966bb1d68bb3106853610a407509053b44"
+"@elastic/eui@v0.0.51":
+ version "0.0.51"
+ resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.51.tgz#5d809af270dd9994a609fd01eaa84e21a62fff98"
dependencies:
brace "^0.10.0"
classnames "^2.2.5"
@@ -990,8 +990,8 @@ brace@0.10.0, brace@^0.10.0:
w3c-blob "0.0.1"
brace@^0.11.0:
- version "0.11.0"
- resolved "https://registry.yarnpkg.com/brace/-/brace-0.11.0.tgz#155cd80607687dc8cb908f0df94e62a033c1d563"
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/brace/-/brace-0.11.1.tgz#4896fcc9d544eef45f4bb7660db320d3b379fe58"
braces@^1.8.2:
version "1.8.5"
@@ -1072,6 +1072,10 @@ buffer-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe"
+buffer-from@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.0.tgz#87fcaa3a298358e0ade6e442cfce840740d1ad04"
+
buffer@^3.0.1:
version "3.6.0"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb"
@@ -1400,7 +1404,16 @@ concat-stream@1.5.1:
readable-stream "~2.0.0"
typedarray "~0.0.5"
-concat-stream@^1.4.7, concat-stream@~1.6.0:
+concat-stream@^1.4.7:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
+ dependencies:
+ buffer-from "^1.0.0"
+ inherits "^2.0.3"
+ readable-stream "^2.2.2"
+ typedarray "^0.0.6"
+
+concat-stream@~1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
dependencies:
@@ -1443,8 +1456,8 @@ core-js@^2.4.0, core-js@^2.5.0:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e"
core-js@^2.5.1:
- version "2.5.5"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.5.tgz#b14dde936c640c0579a6b50cabcc132dd6127e3b"
+ version "2.5.7"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
@@ -2470,8 +2483,8 @@ focus-trap-react@^3.0.4, focus-trap-react@^3.1.1:
focus-trap "^2.0.1"
focus-trap@^2.0.1:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-2.4.2.tgz#44ea1c55a9c22c2b6529dcebbde6390eb2ee4c88"
+ version "2.4.5"
+ resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-2.4.5.tgz#91c9c9ffb907f8f4446d80202dda9c12c2853ddb"
dependencies:
tabbable "^1.0.3"
@@ -3316,10 +3329,16 @@ icalendar@0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/icalendar/-/icalendar-0.7.1.tgz#d0d3486795f8f1c5cf4f8cafac081b4b4e7a32ae"
-iconv-lite@0.4.19, iconv-lite@^0.4.19, iconv-lite@~0.4.13:
+iconv-lite@0.4.19, iconv-lite@^0.4.19:
version "0.4.19"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
+iconv-lite@~0.4.13:
+ version "0.4.23"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
+ dependencies:
+ safer-buffer ">= 2.1.2 < 3"
+
ieee754@^1.1.4:
version "1.1.8"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
@@ -4513,7 +4532,11 @@ lodash@3.10.1, lodash@^3.10.0, lodash@^3.10.1:
version "3.10.1"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
-lodash@^4.0.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1:
+lodash@^4.0.1:
+ version "4.17.10"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
+
+lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
@@ -5539,7 +5562,7 @@ prop-types@15.5.8:
dependencies:
fbjs "^0.8.9"
-prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.0:
+prop-types@^15.5.0, prop-types@^15.5.4, prop-types@^15.6.0:
version "15.6.0"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856"
dependencies:
@@ -5547,7 +5570,7 @@ prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8,
loose-envify "^1.3.1"
object-assign "^4.1.1"
-prop-types@^15.6.1:
+prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.1:
version "15.6.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca"
dependencies:
@@ -5710,8 +5733,8 @@ react-clipboard.js@^1.1.2:
prop-types "^15.5.0"
react-color@^2.13.8:
- version "2.13.8"
- resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.13.8.tgz#bcc58f79a722b9bfc37c402e68cd18f26970aee4"
+ version "2.14.1"
+ resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.14.1.tgz#db8ad4f45d81e74896fc2e1c99508927c6d084e0"
dependencies:
lodash "^4.0.1"
material-colors "^1.2.1"
@@ -5743,6 +5766,10 @@ react-input-autosize@^2.1.2, react-input-autosize@^2.2.1:
dependencies:
prop-types "^15.5.8"
+react-lifecycles-compat@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
+
react-markdown-renderer@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/react-markdown-renderer/-/react-markdown-renderer-1.4.0.tgz#f3b95bd9fc7f7bf8ab3f0150aa696b41740e7d01"
@@ -5855,14 +5882,15 @@ react-test-renderer@^16.0.0-0, react-test-renderer@^16.2.0:
prop-types "^15.6.0"
react-virtualized@^9.18.5:
- version "9.18.5"
- resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.18.5.tgz#42dd390ebaa7ea809bfcaf775d39872641679b89"
+ version "9.19.1"
+ resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.19.1.tgz#84b53253df2d9df61c85ce037141edccc70a73fd"
dependencies:
babel-runtime "^6.26.0"
classnames "^2.2.3"
dom-helpers "^2.4.0 || ^3.0.0"
loose-envify "^1.3.0"
prop-types "^15.6.0"
+ react-lifecycles-compat "^3.0.4"
react-vis@^1.8.1:
version "1.8.2"
@@ -5924,7 +5952,7 @@ read-pkg@^1.0.0:
isarray "0.0.1"
string_decoder "~0.10.x"
-readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2:
+readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5:
version "2.3.3"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
dependencies:
@@ -5936,6 +5964,18 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable
string_decoder "~1.0.3"
util-deprecate "~1.0.1"
+readable-stream@^2.2.2:
+ version "2.3.6"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.3"
+ isarray "~1.0.0"
+ process-nextick-args "~2.0.0"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.1.1"
+ util-deprecate "~1.0.1"
+
readable-stream@^2.3.3, readable-stream@^2.3.5:
version "2.3.5"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.5.tgz#b4f85003a938cbb6ecbce2a124fb1012bd1a838d"
@@ -6335,10 +6375,18 @@ rxjs@5.3.0:
dependencies:
symbol-observable "^1.0.1"
-safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
+safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+
+"safer-buffer@>= 2.1.2 < 3":
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+
samsam@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567"
@@ -6739,6 +6787,12 @@ string_decoder@~1.0.3:
dependencies:
safe-buffer "~5.1.0"
+string_decoder@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+ dependencies:
+ safe-buffer "~5.1.0"
+
stringstream@~0.0.4, stringstream@~0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
@@ -6898,8 +6952,8 @@ tabbable@1.1.0:
resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-1.1.0.tgz#2c9a9c9f09db5bb0659f587d532548dd6ef2067b"
tabbable@^1.0.3, tabbable@^1.1.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-1.1.2.tgz#b171680aea6e0a3e9281ff23532e2e5de11c0d94"
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-1.1.3.tgz#0e4ee376f3631e42d7977a074dbd2b3827843081"
tar-fs@1.13.0:
version "1.13.0"
@@ -7160,8 +7214,8 @@ typedarray@^0.0.6, typedarray@~0.0.5:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
ua-parser-js@^0.7.9:
- version "0.7.17"
- resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac"
+ version "0.7.18"
+ resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed"
uglify-js@^2.6:
version "2.8.29"
@@ -7293,10 +7347,14 @@ uuid@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1"
-uuid@^3.0.0, uuid@^3.1.0:
+uuid@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
+uuid@^3.1.0:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14"
+
v8flags@^2.0.2:
version "2.1.1"
resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4"
@@ -7489,8 +7547,8 @@ whatwg-encoding@^1.0.1:
iconv-lite "0.4.19"
whatwg-fetch@>=0.10.0:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84"
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f"
whatwg-url@^6.3.0:
version "6.4.0"
diff --git a/yarn.lock b/yarn.lock
index 2098dda85233c..459cd99a1d3ea 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -77,9 +77,9 @@
version "0.0.0"
uid ""
-"@elastic/eui@0.0.47", "@elastic/eui@v0.0.47":
- version "0.0.47"
- resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.47.tgz#5bae27966bb1d68bb3106853610a407509053b44"
+"@elastic/eui@v0.0.51":
+ version "0.0.51"
+ resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.51.tgz#5d809af270dd9994a609fd01eaa84e21a62fff98"
dependencies:
brace "^0.10.0"
classnames "^2.2.5"
@@ -1860,6 +1860,10 @@ buffer-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe"
+buffer-from@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.0.tgz#87fcaa3a298358e0ade6e442cfce840740d1ad04"
+
buffer-xor@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
@@ -2576,7 +2580,16 @@ concat-stream@1.6.0:
readable-stream "^2.2.2"
typedarray "^0.0.6"
-concat-stream@^1.4.7, concat-stream@^1.5.2, concat-stream@^1.6.0, concat-stream@~1.6.0:
+concat-stream@^1.4.7:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
+ dependencies:
+ buffer-from "^1.0.0"
+ inherits "^2.0.3"
+ readable-stream "^2.2.2"
+ typedarray "^0.0.6"
+
+concat-stream@^1.5.2, concat-stream@^1.6.0, concat-stream@~1.6.0:
version "1.6.1"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.1.tgz#261b8f518301f1d834e36342b9fea095d2620a26"
dependencies:
@@ -2699,10 +2712,14 @@ core-js@^1.0.0:
version "1.2.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
-core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.0, core-js@^2.5.1:
+core-js@^2.2.0, core-js@^2.5.0:
version "2.5.3"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e"
+core-js@^2.4.0, core-js@^2.5.1:
+ version "2.5.7"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
+
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -4772,8 +4789,8 @@ focus-trap-react@^3.0.4, focus-trap-react@^3.1.1:
focus-trap "^2.0.1"
focus-trap@^2.0.1:
- version "2.4.3"
- resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-2.4.3.tgz#95edc23e77829b7772cb2486d61fd6371ce112f9"
+ version "2.4.5"
+ resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-2.4.5.tgz#91c9c9ffb907f8f4446d80202dda9c12c2853ddb"
dependencies:
tabbable "^1.0.3"
@@ -5905,7 +5922,7 @@ icalendar@0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/icalendar/-/icalendar-0.7.1.tgz#d0d3486795f8f1c5cf4f8cafac081b4b4e7a32ae"
-iconv-lite@0.4, iconv-lite@0.4.19, iconv-lite@^0.4.13, iconv-lite@^0.4.17, iconv-lite@^0.4.19, iconv-lite@~0.4.13:
+iconv-lite@0.4, iconv-lite@0.4.19, iconv-lite@^0.4.13, iconv-lite@^0.4.17, iconv-lite@^0.4.19:
version "0.4.19"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
@@ -5917,6 +5934,12 @@ iconv-lite@0.4.7:
version "0.4.7"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.7.tgz#89d32fec821bf8597f44609b4bc09bed5c209a23"
+iconv-lite@~0.4.13:
+ version "0.4.23"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
+ dependencies:
+ safer-buffer ">= 2.1.2 < 3"
+
icss-replace-symbols@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
@@ -10041,7 +10064,16 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.1.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
-react-ace@^5.5.0, react-ace@^5.9.0:
+react-ace@^5.5.0:
+ version "5.10.0"
+ resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-5.10.0.tgz#e328b37ac52759f700be5afdb86ada2f5ec84c5e"
+ dependencies:
+ brace "^0.11.0"
+ lodash.get "^4.4.2"
+ lodash.isequal "^4.1.1"
+ prop-types "^15.5.8"
+
+react-ace@^5.9.0:
version "5.9.0"
resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-5.9.0.tgz#427a1cc4869b960a6f9748aa7eb169a9269fc336"
dependencies:
@@ -10129,6 +10161,10 @@ react-input-range@^1.3.0:
autobind-decorator "^1.3.4"
prop-types "^15.5.8"
+react-lifecycles-compat@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
+
react-markdown-renderer@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/react-markdown-renderer/-/react-markdown-renderer-1.4.0.tgz#f3b95bd9fc7f7bf8ab3f0150aa696b41740e7d01"
@@ -10271,14 +10307,15 @@ react-toggle@4.0.2:
classnames "^2.2.5"
react-virtualized@^9.18.5:
- version "9.18.5"
- resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.18.5.tgz#42dd390ebaa7ea809bfcaf775d39872641679b89"
+ version "9.19.1"
+ resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.19.1.tgz#84b53253df2d9df61c85ce037141edccc70a73fd"
dependencies:
babel-runtime "^6.26.0"
classnames "^2.2.3"
dom-helpers "^2.4.0 || ^3.0.0"
loose-envify "^1.3.0"
prop-types "^15.6.0"
+ react-lifecycles-compat "^3.0.4"
react-vis@^1.8.1:
version "1.9.2"
@@ -10381,7 +10418,7 @@ read-pkg@^2.0.0:
normalize-package-data "^2.3.2"
path-type "^2.0.0"
-readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@~2.3.3:
+readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@~2.3.3:
version "2.3.5"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.5.tgz#b4f85003a938cbb6ecbce2a124fb1012bd1a838d"
dependencies:
@@ -10393,6 +10430,18 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable
string_decoder "~1.0.3"
util-deprecate "~1.0.1"
+readable-stream@^2.2.2:
+ version "2.3.6"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.3"
+ isarray "~1.0.0"
+ process-nextick-args "~2.0.0"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.1.1"
+ util-deprecate "~1.0.1"
+
readable-stream@~1.0.2:
version "1.0.34"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
@@ -10928,10 +10977,14 @@ rxjs@5.4.3:
dependencies:
symbol-observable "^1.0.1"
-safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
+safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+
safe-json-stringify@~1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.1.0.tgz#bd2b6dad1ebafab3c24672a395527f01804b7e19"
@@ -10949,6 +11002,10 @@ safefs@^4.0.0:
editions "^1.1.1"
graceful-fs "^4.1.4"
+"safer-buffer@>= 2.1.2 < 3":
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+
samsam@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567"
@@ -11622,6 +11679,12 @@ string_decoder@~1.0.3:
dependencies:
safe-buffer "~5.1.0"
+string_decoder@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+ dependencies:
+ safe-buffer "~5.1.0"
+
stringstream@~0.0.4, stringstream@~0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
@@ -11820,8 +11883,8 @@ tabbable@1.1.0:
resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-1.1.0.tgz#2c9a9c9f09db5bb0659f587d532548dd6ef2067b"
tabbable@^1.0.3, tabbable@^1.1.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-1.1.2.tgz#b171680aea6e0a3e9281ff23532e2e5de11c0d94"
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-1.1.3.tgz#0e4ee376f3631e42d7977a074dbd2b3827843081"
table@^3.7.8:
version "3.8.3"
@@ -12276,8 +12339,8 @@ typescript@^2.8.1:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.1.tgz#6160e4f8f195d5ba81d4876f9c0cc1fbc0820624"
ua-parser-js@^0.7.9:
- version "0.7.17"
- resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac"
+ version "0.7.18"
+ resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed"
uc.micro@^1.0.1, uc.micro@^1.0.3:
version "1.0.5"
@@ -13116,7 +13179,11 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
dependencies:
iconv-lite "0.4.19"
-whatwg-fetch@>=0.10.0, whatwg-fetch@^2.0.3:
+whatwg-fetch@>=0.10.0:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f"
+
+whatwg-fetch@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84"
From b05d9376a8ea5eb7811f6634887e05bfd459713a Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Tue, 5 Jun 2018 13:16:42 -0400
Subject: [PATCH 36/38] fix doc links
---
x-pack/plugins/security/public/documentation_links.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/x-pack/plugins/security/public/documentation_links.js b/x-pack/plugins/security/public/documentation_links.js
index d60092ea945e6..d357451d48ac7 100644
--- a/x-pack/plugins/security/public/documentation_links.js
+++ b/x-pack/plugins/security/public/documentation_links.js
@@ -8,7 +8,7 @@ import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links';
export const documentationLinks = {
dashboardViewMode: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/xpack-view-modes.html`,
- esClusterPrivileges: `${ELASTIC_WEBSITE_URL}guide/en/x-pack/current/security-privileges.html#security-privileges`,
- esIndicesPrivileges: `${ELASTIC_WEBSITE_URL}guide/en/x-pack/current/security-privileges.html#privileges-list-indices`,
- esRunAsPrivileges: `${ELASTIC_WEBSITE_URL}guide/en/x-pack/current/security-privileges.html#_run_as_privilege`,
+ esClusterPrivileges: `${ELASTIC_WEBSITE_URL}guide/en/x-pack/${DOC_LINK_VERSION}/security-privileges.html#security-privileges`,
+ esIndicesPrivileges: `${ELASTIC_WEBSITE_URL}guide/en/x-pack/${DOC_LINK_VERSION}/security-privileges.html#privileges-list-indices`,
+ esRunAsPrivileges: `${ELASTIC_WEBSITE_URL}guide/en/x-pack/${DOC_LINK_VERSION}/security-privileges.html#_run_as_privilege`,
};
From 6adfe2af3cd6408d352f2171af61eb1c1cd36a74 Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Tue, 5 Jun 2018 16:54:05 -0400
Subject: [PATCH 37/38] Fix tests and cleanup unused code
---
.../collapsible_panel.test.js.snap | 10 +-
.../elasticsearch_privileges.test.js.snap | 200 +++++++-----------
.../index_privilege_form.test.js.snap | 56 +++--
.../privileges/index_privilege_form.js | 18 --
.../privileges/index_privilege_form.test.js | 12 +-
.../components/reserved_role_badge.test.js | 4 +-
6 files changed, 117 insertions(+), 183 deletions(-)
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/collapsible_panel.test.js.snap b/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/collapsible_panel.test.js.snap
index d94f2f4c47bab..d946357354fe2 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/collapsible_panel.test.js.snap
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/collapsible_panel.test.js.snap
@@ -10,9 +10,9 @@ exports[`it renders without blowing up 1`] = `
alignItems="baseline"
component="div"
direction="row"
- gutterSize="l"
+ gutterSize="s"
justifyContent="flexStart"
- responsive={true}
+ responsive={false}
wrap={false}
>
-
+
Elasticsearch
-
+
- Manage the actions this role can perform against your cluster.
-
- }
- fullWidth={false}
- gutterSize="l"
- title={
-
- Cluster privileges
+ Manage the actions this role can perform against your cluster.
-
+ Learn more
}
+ fullWidth={false}
+ gutterSize="l"
+ title={
+
+ Cluster privileges
+
+ }
titleSize="xs"
>
- Allow requests to be submitted on behalf of other users.
-
- }
- fullWidth={false}
- gutterSize="l"
- title={
-
- Run As privileges
+ Allow requests to be submitted on the behalf of other users.
-
+ Learn more
}
+ fullWidth={false}
+ gutterSize="l"
+ title={
+
+ Run As privileges
+
+ }
titleSize="xs"
>
-
-
-
-
-
-
- Index privileges
-
-
-
-
-
-
-
- Control access to the data in your cluster.
-
-
-
-
-
- Add Index Privilege
-
-
-
-
-
-
-
+ Index privileges
+
+
+
+
-
+ Control access to the data in your cluster.
+
+ Learn more
+
+
+
+
-
+ }
+ />
+
+
+ Add index privilege
+
`;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/index_privilege_form.test.js.snap b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/index_privilege_form.test.js.snap
index 440bc8f832bbe..b84dcc659d5f9 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/index_privilege_form.test.js.snap
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/__snapshots__/index_privilege_form.test.js.snap
@@ -1,9 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`it renders without crashing 1`] = `
-
+
+
-
-
-
-
- If no fields are granted, then users assigned to this role will not be able to see any data for this index. Is this really what you want?
-
-
-
+
-
-
-
+
-
-
+
`;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
index 479762770fce6..e5fafd0798f87 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
@@ -110,25 +110,7 @@ export class IndexPrivilegeForm extends Component {
const { grant = [] } = indexPrivilege.field_security || {};
- // TODO: Remove this completely, if ok with just putting the text in the helptext
- // let grantedFieldsWarning = null;
-
if (allowFieldLevelSecurity) {
-
- // if (grant.length === 0) {
- // grantedFieldsWarning = (
- //
- //
- //
- //
- // If no fields are granted, then users assigned to this role will not be able to
- // see any data for this index. Is this really what you want?
- //
- //
- //
- // );
- // }
-
return (
{
const props = {
@@ -60,7 +60,7 @@ describe('delete button', () => {
allowDelete: false
};
const wrapper = mount( );
- expect(wrapper.find(EuiLink)).toHaveLength(0);
+ expect(wrapper.find(EuiButtonIcon)).toHaveLength(0);
});
test('it is shown when allowDelete is true', () => {
@@ -69,7 +69,7 @@ describe('delete button', () => {
allowDelete: true
};
const wrapper = mount( );
- expect(wrapper.find(EuiLink)).toHaveLength(1);
+ expect(wrapper.find(EuiButtonIcon)).toHaveLength(1);
});
test('it invokes onDelete when clicked', () => {
@@ -78,7 +78,7 @@ describe('delete button', () => {
allowDelete: true
};
const wrapper = mount( );
- wrapper.find(EuiLink).simulate('click');
+ wrapper.find(EuiButtonIcon).simulate('click');
expect(testProps.onDelete).toHaveBeenCalledTimes(1);
});
});
@@ -191,7 +191,7 @@ describe('field level security', () => {
const wrapper = mount( );
expect(wrapper.find("div.indexPrivilegeForm__grantedFieldsRow")).toHaveLength(1);
- expect(wrapper.find(EuiCallOut)).toHaveLength(1);
+ expect(wrapper.find(".euiFormHelpText")).toHaveLength(1);
});
test('it does not display a warning when fields are granted', () => {
@@ -201,6 +201,6 @@ describe('field level security', () => {
const wrapper = mount( );
expect(wrapper.find("div.indexPrivilegeForm__grantedFieldsRow")).toHaveLength(1);
- expect(wrapper.find(EuiCallOut)).toHaveLength(0);
+ expect(wrapper.find(".euiFormHelpText")).toHaveLength(0);
});
});
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.test.js b/x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.test.js
index c9227a415f9ff..939348661a741 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.test.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/reserved_role_badge.test.js
@@ -6,7 +6,7 @@
import React from 'react';
import {
- EuiBadge
+ EuiIcon
} from '@elastic/eui';
import { ReservedRoleBadge } from './reserved_role_badge';
import {
@@ -23,7 +23,7 @@ const unreservedRole = {};
test('it renders without crashing', () => {
const wrapper = shallow( );
- expect(wrapper.find(EuiBadge)).toHaveLength(1);
+ expect(wrapper.find(EuiIcon)).toHaveLength(1);
});
test('it renders nothing for an unreserved role', () => {
From e739e5c640cace21695e784c269d972d1b9be70f Mon Sep 17 00:00:00 2001
From: Larry Gregory
Date: Thu, 7 Jun 2018 14:57:42 -0400
Subject: [PATCH 38/38] design updates
---
.../__snapshots__/page_header.test.js.snap | 20 +++++++++-------
.../edit_role/components/edit_role_page.js | 24 +++++++++----------
.../edit_role/components/page_header.js | 14 +++++------
.../edit_role/components/page_header.test.js | 6 ++---
.../privileges/index_privilege_form.js | 3 ++-
5 files changed, 33 insertions(+), 34 deletions(-)
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/page_header.test.js.snap b/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/page_header.test.js.snap
index c7cbfdb53fd73..628a5c068f83a 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/page_header.test.js.snap
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/__snapshots__/page_header.test.js.snap
@@ -1,13 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`it renders without crashing 1`] = `
-
-
-
-
-
+
+
+
+
`;
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
index 5843ece2ee3e2..13cd7a4f1823b 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/edit_role_page.js
@@ -54,26 +54,24 @@ export class EditRolePage extends Component {
render() {
return (
-
+
-
-
- {this.getFormTitle()}
+
+ {this.getFormTitle()}
-
+
- {this.getRoleName()}
+ {this.getRoleName()}
- {this.getElasticsearchPrivileges()}
+ {this.getElasticsearchPrivileges()}
- {this.getKibanaPrivileges()}
+ {this.getKibanaPrivileges()}
-
+
- {this.getFormButtons()}
-
-
-
+ {this.getFormButtons()}
+
+
);
}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/page_header.js b/x-pack/plugins/security/public/views/management/edit_role/components/page_header.js
index 03347a01ec0fa..87aac82490817 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/page_header.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/page_header.js
@@ -8,19 +8,17 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
- EuiHeader,
- EuiHeaderSection,
- EuiHeaderBreadcrumbs
+ EuiBreadcrumbs,
+ EuiSpacer,
} from '@elastic/eui';
export class PageHeader extends Component {
render() {
return (
-
-
-
-
-
+
+
+
+
);
}
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/page_header.test.js b/x-pack/plugins/security/public/views/management/edit_role/components/page_header.test.js
index 80248b4e75b83..99f6994ea9898 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/page_header.test.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/page_header.test.js
@@ -7,11 +7,11 @@
import React from 'react';
import { shallow, mount } from 'enzyme';
import { PageHeader } from './page_header';
-import { EuiHeaderBreadcrumbs } from '@elastic/eui';
+import { EuiBreadcrumbs } from '@elastic/eui';
test('it renders without crashing', () => {
const wrapper = shallow( );
- expect(wrapper.find(EuiHeaderBreadcrumbs)).toHaveLength(1);
+ expect(wrapper.find(EuiBreadcrumbs)).toHaveLength(1);
expect(wrapper).toMatchSnapshot();
});
@@ -28,5 +28,5 @@ test('it renders breadcrumbs', () => {
}];
const wrapper = mount( );
- expect(wrapper.find(EuiHeaderBreadcrumbs)).toHaveLength(1);
+ expect(wrapper.find(EuiBreadcrumbs)).toHaveLength(1);
});
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
index e5fafd0798f87..ee62b80c5e282 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/index_privilege_form.js
@@ -102,6 +102,7 @@ export class IndexPrivilegeForm extends Component {
allowFieldLevelSecurity,
availableFields,
indexPrivilege,
+ isReservedRole,
} = this.props;
if (!allowFieldLevelSecurity) {
@@ -118,7 +119,7 @@ export class IndexPrivilegeForm extends Component {
fullWidth={true}
className="indexPrivilegeForm__grantedFieldsRow"
helpText={
- grant.length === 0 ?
+ !isReservedRole && grant.length === 0 ?
'If no fields are granted, then users assigned to this role will not be able to see any data for this index.' : undefined
}
>