From 9d3d3cdc67e692c90d3bc959984114f007156615 Mon Sep 17 00:00:00 2001
From: Aleh Zasypkin
Date: Tue, 21 Jan 2020 13:40:39 +0100
Subject: [PATCH] Migrate Management views to Kibana Platform plugin (#53880)
---
.../saved_objects_client.test.ts | 19 -
.../saved_objects/saved_objects_client.ts | 6 +-
src/plugins/management/public/index.ts | 7 +-
.../legacy/plugins/security/common/model.ts | 28 -
x-pack/legacy/plugins/security/index.d.ts | 2 +-
x-pack/legacy/plugins/security/index.js | 3 -
.../security/public/documentation_links.js | 16 -
.../plugins/security/public/images/logout.svg | 3 -
.../plugins/security/public/images/person.svg | 3 -
.../legacy/plugins/security/public/index.scss | 3 +
.../security/public/lib/__tests__/util.js | 49 --
.../legacy/plugins/security/public/lib/api.ts | 56 --
.../security/public/lib/api_keys_api.ts | 47 --
.../plugins/security/public/lib/role_utils.ts | 58 --
.../plugins/security/public/lib/roles_api.ts | 25 -
.../public/lib/transform_role_for_save.ts | 41 -
.../plugins/security/public/lib/util.js | 19 -
.../security/public/objects/lib/get_fields.ts | 15 -
.../security/public/objects/lib/roles.ts | 21 -
.../security/public/register_feature.js | 29 -
.../public/services/shield_indices.js | 18 -
.../security/public/services/shield_role.js | 30 -
.../plugins/security/public/views/_index.scss | 3 -
.../public/views/account/account.html | 1 -
.../security/public/views/account/account.js | 27 +-
.../security/public/views/login/_index.scss | 3 +-
.../public/views/login/components/_index.scss | 1 +
.../basic_login_form.test.tsx | 2 +-
.../basic_login_form/basic_login_form.tsx | 2 +-
.../login/components/login_page/_index.scss | 1 +
.../login_page/_login_page.scss} | 5 -
.../components/login_page/login_page.test.tsx | 2 +-
.../components/login_page/login_page.tsx | 2 +-
.../security/public/views/login/login.html | 1 -
.../security/public/views/login/login.tsx | 8 +-
.../views/login}/login_state.ts | 0
.../login/parse_next.test.ts} | 47 +-
.../public/{lib => views/login}/parse_next.ts | 0
.../public/views/management/_index.scss | 4 -
.../management/api_keys_grid/api_keys.html | 3 -
.../management/api_keys_grid/api_keys.js | 35 -
.../public/views/management/breadcrumbs.ts | 115 ---
.../_change_password_form.scss | 17 -
.../change_password_form/_index.scss | 1 -
.../change_password_form.html | 141 ----
.../change_password_form.js | 48 --
.../views/management/edit_role/_index.scss | 1 -
.../edit_role/components/_index.scss | 9 -
.../components/edit_role_page.test.tsx | 716 ------------------
.../edit_role/components/edit_role_page.tsx | 409 ----------
.../es/elasticsearch_privileges.test.tsx | 96 ---
.../views/management/edit_role/edit_role.html | 3 -
.../views/management/edit_role/index.js | 176 -----
.../views/management/edit_user/_index.scss | 1 -
.../views/management/edit_user/edit_user.html | 3 -
.../views/management/edit_user/edit_user.js | 58 --
.../public/views/management/management.js | 134 ----
.../password_form/password_form.html | 53 --
.../management/password_form/password_form.js | 24 -
.../edit_role_mapping/_index.scss | 1 -
.../edit_role_mapping_page.test.tsx | 341 ---------
.../edit_role_mapping/edit_role_mapping.html | 3 -
.../role_mappings/edit_role_mapping/index.tsx | 45 --
.../role_mappings_grid_page.test.tsx | 182 -----
.../role_mappings_grid/index.tsx | 40 -
.../role_mappings_grid/role_mappings.html | 3 -
.../views/management/roles_grid/roles.html | 3 -
.../views/management/roles_grid/roles.js | 35 -
.../views/management/users_grid/users.html | 3 -
.../views/management/users_grid/users.js | 47 --
.../overwritten_session.tsx | 3 +-
x-pack/plugins/security/common/model/index.ts | 11 +-
.../security/common/model/role.test.ts} | 9 +-
x-pack/plugins/security/common/model/role.ts | 51 ++
x-pack/plugins/security/kibana.json | 3 +-
x-pack/plugins/security/public/_index.scss | 2 +
.../account_management_page.test.tsx | 37 +-
.../account_management_page.tsx | 18 +-
.../change_password/change_password.tsx | 19 +-
.../change_password/index.ts | 0
.../public/account_management}/index.ts | 0
.../personal_info/index.ts | 0
.../personal_info/personal_info.tsx | 11 +-
.../security/public/management/_index.scss | 3 +
.../api_keys/api_keys_api_client.mock.ts | 13 +
.../api_keys/api_keys_api_client.test.ts | 86 +++
.../api_keys/api_keys_api_client.ts | 42 +
.../api_keys_grid_page.test.tsx.snap | 20 +-
.../api_keys_grid_page.test.tsx | 124 +--
.../api_keys_grid}/api_keys_grid_page.tsx | 50 +-
.../empty_prompt/empty_prompt.tsx | 7 +-
.../api_keys_grid}/empty_prompt/index.ts | 0
.../api_keys/api_keys_grid}/index.ts | 2 +-
.../invalidate_provider/index.ts | 0
.../invalidate_provider.tsx | 21 +-
.../api_keys_grid}/not_enabled/index.ts | 0
.../not_enabled/not_enabled.tsx | 10 +-
.../api_keys_grid}/permission_denied/index.ts | 0
.../permission_denied/permission_denied.tsx | 0
.../api_keys/api_keys_management_app.test.tsx | 54 ++
.../api_keys/api_keys_management_app.tsx | 58 ++
.../api_keys}/documentation_links.ts | 16 +-
.../public/management/api_keys/index.mock.ts | 7 +
.../public/management/api_keys/index.ts | 7 +
.../security/public/management/index.ts | 8 +
.../management/management_service.test.ts | 226 ++++++
.../public/management/management_service.ts | 95 +++
.../public}/management/management_urls.ts | 9 +-
.../management/role_mappings/_index.scss | 1 +
.../delete_provider/delete_provider.test.tsx | 152 ++--
.../delete_provider/delete_provider.tsx | 21 +-
.../components/delete_provider/index.ts | 0
.../role_mappings/components/index.ts | 0
.../components/no_compatible_realms/index.ts | 0
.../no_compatible_realms.tsx | 10 +-
.../components/permission_denied/index.ts | 0
.../permission_denied/permission_denied.tsx | 0
.../components/section_loading/index.ts | 0
.../section_loading/section_loading.test.tsx | 0
.../section_loading/section_loading.tsx | 0
.../role_mappings}/documentation_links.ts | 12 +-
.../edit_role_mapping/_index.scss | 1 +
.../edit_role_mapping_page.test.tsx | 399 ++++++++++
.../edit_role_mapping_page.tsx | 44 +-
.../role_mappings/edit_role_mapping}/index.ts | 0
.../mapping_info_panel/index.ts | 0
.../mapping_info_panel.test.tsx | 36 +-
.../mapping_info_panel/mapping_info_panel.tsx | 13 +-
.../add_role_template_button.test.tsx | 0
.../add_role_template_button.tsx | 0
.../role_selector/index.tsx | 0
.../role_selector/role_selector.test.tsx | 25 +-
.../role_selector/role_selector.tsx | 7 +-
.../role_template_editor.test.tsx | 0
.../role_selector/role_template_editor.tsx | 4 +-
.../role_template_type_select.tsx | 4 +-
.../rule_editor_panel/_index.scss | 1 +
.../_rule_editor_group.scss} | 0
.../add_rule_button.test.tsx | 2 +-
.../rule_editor_panel/add_rule_button.tsx | 2 +-
.../field_rule_editor.test.tsx | 2 +-
.../rule_editor_panel/field_rule_editor.tsx | 2 +-
.../rule_editor_panel/index.tsx | 0
.../json_rule_editor.test.tsx | 10 +-
.../rule_editor_panel/json_rule_editor.tsx | 7 +-
.../rule_editor_panel.test.tsx | 9 +-
.../rule_editor_panel/rule_editor_panel.tsx | 14 +-
.../rule_group_editor.test.tsx | 2 +-
.../rule_editor_panel/rule_group_editor.tsx | 4 +-
.../rule_editor_panel/rule_group_title.tsx | 9 +-
.../visual_rule_editor.test.tsx | 2 +-
.../rule_editor_panel/visual_rule_editor.tsx | 6 +-
.../services/is_rule_group.ts | 0
.../services/role_mapping_constants.ts | 0
.../services/role_mapping_validation.test.ts | 2 +-
.../services/role_mapping_validation.ts | 2 +-
.../services/role_template_type.test.ts | 2 +-
.../services/role_template_type.ts | 2 +-
.../management/role_mappings/index.mock.ts | 7 +
.../public/management/role_mappings/index.ts | 7 +
.../__snapshots__/rule_builder.test.ts.snap | 0
.../role_mappings/model/all_rule.test.ts | 0
.../role_mappings/model/all_rule.ts | 0
.../role_mappings/model/any_rule.test.ts | 0
.../role_mappings/model/any_rule.ts | 0
.../model/except_all_rule.test.ts | 0
.../role_mappings/model/except_all_rule.ts | 0
.../model/except_any_rule.test.ts | 0
.../role_mappings/model/except_any_rule.ts | 0
.../role_mappings/model/field_rule.test.ts | 0
.../role_mappings/model/field_rule.ts | 0
.../management/role_mappings/model/index.ts | 0
.../management/role_mappings/model/rule.ts | 0
.../role_mappings/model/rule_builder.test.ts | 2 +-
.../role_mappings/model/rule_builder.ts | 2 +-
.../role_mappings/model/rule_builder_error.ts | 0
.../role_mappings/model/rule_group.ts | 2 +-
.../role_mappings_api_client.mock.ts | 15 +
.../role_mappings_api_client.ts} | 8 +-
.../create_role_mapping_button.tsx | 2 +-
.../create_role_mapping_button/index.ts | 0
.../empty_prompt/empty_prompt.tsx | 0
.../role_mappings_grid}/empty_prompt/index.ts | 0
.../role_mappings_grid}/index.ts | 0
.../role_mappings_grid_page.test.tsx | 219 ++++++
.../role_mappings_grid_page.tsx | 29 +-
.../role_mappings_management_app.test.tsx | 127 ++++
.../role_mappings_management_app.tsx | 104 +++
.../public/management/roles/_index.scss | 1 +
.../management/roles/documentation_links.ts | 27 +
.../__snapshots__/validate_role.test.ts.snap | 0
.../management/roles/edit_role/_index.scss | 3 +
.../collapsible_panel.test.tsx.snap | 0
.../collapsible_panel/_collapsible_panel.scss | 0
.../edit_role/collapsible_panel/_index.scss | 1 +
.../collapsible_panel.test.tsx | 0
.../collapsible_panel/collapsible_panel.tsx | 1 -
.../edit_role}/collapsible_panel/index.ts | 0
.../edit_role}/delete_role_button.test.tsx | 6 +-
.../roles/edit_role}/delete_role_button.tsx | 8 +-
.../roles/edit_role/edit_role_page.test.tsx | 552 ++++++++++++++
.../roles/edit_role/edit_role_page.tsx | 594 +++++++++++++++
.../management/roles/edit_role}/index.ts | 0
.../roles/edit_role}/privilege_utils.test.ts | 0
.../roles/edit_role}/privilege_utils.ts | 2 +-
.../roles/edit_role/privileges/_index.scss | 2 +
.../privileges/_privilege_feature_icon.scss | 4 +
.../cluster_privileges.test.tsx.snap | 0
.../elasticsearch_privileges.test.tsx.snap | 24 +-
.../index_privilege_form.test.tsx.snap | 0
.../index_privileges.test.tsx.snap | 0
.../privileges/es/cluster_privileges.test.tsx | 2 +-
.../privileges/es/cluster_privileges.tsx | 3 +-
.../es/elasticsearch_privileges.test.tsx | 67 ++
.../es/elasticsearch_privileges.tsx | 34 +-
.../es/index_privilege_form.test.tsx | 2 +-
.../privileges/es/index_privilege_form.tsx | 7 +-
.../privileges/es/index_privileges.test.tsx | 27 +-
.../privileges/es/index_privileges.tsx | 32 +-
.../roles/edit_role}/privileges/index.ts | 0
.../kibana_privileges_region.test.tsx.snap | 0
.../edit_role/privileges/kibana/_index.scss | 2 +
.../edit_role/privileges/kibana}/constants.ts | 0
.../__snapshots__/feature_table.test.tsx.snap | 0
.../_change_all_privileges.scss} | 0
.../kibana/feature_table/_index.scss | 1 +
.../feature_table/change_all_privileges.tsx | 0
.../feature_table/feature_table.test.tsx | 7 +-
.../kibana/feature_table/feature_table.tsx | 32 +-
.../privileges/kibana/feature_table/index.ts | 0
.../__fixtures__/build_role.ts | 2 +-
.../__fixtures__/common_allowed_privileges.ts | 0
.../default_privilege_definition.ts | 2 +-
.../__fixtures__/index.ts | 0
.../kibana_privilege_calculator/index.ts | 0
...bana_allowed_privileges_calculator.test.ts | 2 +-
.../kibana_allowed_privileges_calculator.ts | 11 +-
.../kibana_base_privilege_calculator.test.ts | 6 +-
.../kibana_base_privilege_calculator.ts | 9 +-
...ibana_feature_privilege_calculator.test.ts | 6 +-
.../kibana_feature_privilege_calculator.ts | 13 +-
.../kibana_privilege_calculator.test.ts | 4 +-
.../kibana_privilege_calculator.ts | 5 +-
.../kibana_privilege_calculator_types.ts | 0
.../kibana_privileges_calculator_factory.ts | 12 +-
.../kibana/kibana_privileges_region.test.tsx | 4 +-
.../kibana/kibana_privileges_region.tsx | 17 +-
.../simple_privilege_section.test.tsx.snap | 0
.../kibana/simple_privilege_section/index.ts | 0
.../privilege_selector.tsx | 2 +-
.../simple_privilege_section.test.tsx | 8 +-
.../simple_privilege_section.tsx | 21 +-
.../unsupported_space_privileges_warning.tsx | 0
.../__fixtures__/index.ts | 0
.../__fixtures__/raw_kibana_privileges.ts | 2 +-
.../privilege_display.test.tsx.snap | 0
.../privilege_space_form.test.tsx.snap | 102 ---
...pace_aware_privilege_section.test.tsx.snap | 0
.../space_aware_privilege_section/_index.scss | 0
.../_privilege_matrix.scss | 2 +-
.../space_aware_privilege_section/index.ts | 0
.../privilege_display.test.tsx | 2 +-
.../privilege_display.tsx | 7 +-
.../privilege_matrix.test.tsx | 10 +-
.../privilege_matrix.tsx | 17 +-
.../privilege_space_form.test.tsx | 4 +-
.../privilege_space_form.tsx | 14 +-
.../privilege_space_table.test.tsx | 4 +-
.../privilege_space_table.tsx | 15 +-
.../space_aware_privilege_section.test.tsx | 6 +-
.../space_aware_privilege_section.tsx | 15 +-
.../space_selector.tsx | 4 +-
.../kibana/transform_error_section/index.ts | 0
.../transform_error_section.tsx | 0
.../edit_role}/reserved_role_badge.test.tsx | 2 +-
.../roles/edit_role}/reserved_role_badge.tsx | 3 +-
.../edit_role/spaces_popover_list/_index.scss | 1 +
.../_spaces_popover_list.scss | 0
.../edit_role}/spaces_popover_list/index.ts | 0
.../spaces_popover_list.tsx | 7 +-
.../roles/edit_role}/validate_role.test.ts | 2 +-
.../roles/edit_role}/validate_role.ts | 2 +-
.../public/management/roles/index.mock.ts | 9 +
.../security/public/management/roles/index.ts | 8 +
.../roles/indices_api_client.mock.ts | 11 +
.../management/roles/indices_api_client.ts | 18 +
.../roles/privileges_api_client.mock.ts | 12 +
.../management/roles/privileges_api_client.ts | 22 +
.../management/roles/roles_api_client.mock.ts | 14 +
.../roles/roles_api_client.test.ts} | 73 +-
.../management/roles/roles_api_client.ts | 62 ++
.../roles_grid_page.test.tsx.snap | 0
.../confirm_delete/confirm_delete.tsx | 57 +-
.../roles/roles_grid}/confirm_delete/index.ts | 0
.../management/roles/roles_grid}/index.ts | 0
.../roles_grid}/permission_denied/index.ts | 0
.../permission_denied/permission_denied.tsx | 0
.../roles_grid}/roles_grid_page.test.tsx | 89 ++-
.../roles/roles_grid}/roles_grid_page.tsx | 89 +--
.../roles/roles_management_app.test.tsx | 160 ++++
.../management/roles/roles_management_app.tsx | 116 +++
.../public/management/users/_index.scss | 1 +
.../change_password_form.test.tsx | 24 +-
.../change_password_form.tsx | 16 +-
.../components}/change_password_form/index.ts | 0
.../confirm_delete_users.test.tsx} | 53 +-
.../confirm_delete_users.tsx} | 81 +-
.../components/confirm_delete_users}/index.ts | 2 +-
.../management/users/components/index.ts | 8 +
.../users/edit_user/_edit_user_page.scss} | 0
.../management/users/edit_user/_index.scss | 1 +
.../users/edit_user}/edit_user_page.test.tsx | 55 +-
.../users/edit_user}/edit_user_page.tsx | 175 ++---
.../management/users/edit_user}/index.ts | 0
.../users/edit_user}/validate_user.test.ts | 2 +-
.../users/edit_user}/validate_user.ts | 2 +-
.../public/management/users/index.mock.ts} | 2 +-
.../public/management/users}/index.ts | 5 +-
.../management/users/user_api_client.mock.ts | 15 +
.../management/users/user_api_client.ts | 45 ++
.../management/users/users_grid}/index.ts | 2 +-
.../users_grid/users_grid_page.test.tsx} | 34 +-
.../users/users_grid/users_grid_page.tsx} | 52 +-
.../users/users_management_app.test.tsx | 131 ++++
.../management/users/users_management_app.tsx | 94 +++
x-pack/plugins/security/public/plugin.ts | 74 --
x-pack/plugins/security/public/plugin.tsx | 147 ++++
.../server/routes/role_mapping/get.ts | 2 +-
x-pack/plugins/spaces/common/index.ts | 2 +-
.../translations/translations/ja-JP.json | 15 -
.../translations/translations/zh-CN.json | 15 -
.../functional/apps/security/management.js | 2 +-
.../functional/apps/security/role_mappings.ts | 2 +-
333 files changed, 4797 insertions(+), 4496 deletions(-)
delete mode 100644 x-pack/legacy/plugins/security/common/model.ts
delete mode 100644 x-pack/legacy/plugins/security/public/documentation_links.js
delete mode 100644 x-pack/legacy/plugins/security/public/images/logout.svg
delete mode 100644 x-pack/legacy/plugins/security/public/images/person.svg
delete mode 100644 x-pack/legacy/plugins/security/public/lib/__tests__/util.js
delete mode 100644 x-pack/legacy/plugins/security/public/lib/api.ts
delete mode 100644 x-pack/legacy/plugins/security/public/lib/api_keys_api.ts
delete mode 100644 x-pack/legacy/plugins/security/public/lib/role_utils.ts
delete mode 100644 x-pack/legacy/plugins/security/public/lib/roles_api.ts
delete mode 100644 x-pack/legacy/plugins/security/public/lib/transform_role_for_save.ts
delete mode 100644 x-pack/legacy/plugins/security/public/lib/util.js
delete mode 100644 x-pack/legacy/plugins/security/public/objects/lib/get_fields.ts
delete mode 100644 x-pack/legacy/plugins/security/public/objects/lib/roles.ts
delete mode 100644 x-pack/legacy/plugins/security/public/register_feature.js
delete mode 100644 x-pack/legacy/plugins/security/public/services/shield_indices.js
delete mode 100644 x-pack/legacy/plugins/security/public/services/shield_role.js
delete mode 100644 x-pack/legacy/plugins/security/public/views/account/account.html
create mode 100644 x-pack/legacy/plugins/security/public/views/login/components/_index.scss
create mode 100644 x-pack/legacy/plugins/security/public/views/login/components/login_page/_index.scss
rename x-pack/legacy/plugins/security/public/views/login/{_login.scss => components/login_page/_login_page.scss} (88%)
delete mode 100644 x-pack/legacy/plugins/security/public/views/login/login.html
rename x-pack/legacy/plugins/security/{common => public/views/login}/login_state.ts (100%)
rename x-pack/legacy/plugins/security/public/{lib/__tests__/parse_next.js => views/login/parse_next.test.ts} (80%)
rename x-pack/legacy/plugins/security/public/{lib => views/login}/parse_next.ts (100%)
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/_index.scss
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/api_keys_grid/api_keys.html
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/api_keys_grid/api_keys.js
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/breadcrumbs.ts
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/change_password_form/_change_password_form.scss
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/change_password_form/_index.scss
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/change_password_form/change_password_form.html
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/change_password_form/change_password_form.js
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/edit_role/_index.scss
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/edit_role/components/_index.scss
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/edit_role/components/edit_role_page.test.tsx
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/edit_role/components/edit_role_page.tsx
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/elasticsearch_privileges.test.tsx
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/edit_role/edit_role.html
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/edit_role/index.js
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/edit_user/_index.scss
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/edit_user/edit_user.html
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/edit_user/edit_user.js
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/management.js
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/password_form/password_form.html
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/password_form/password_form.js
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/_index.scss
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/edit_role_mapping_page.test.tsx
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/edit_role_mapping.html
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/index.tsx
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/role_mappings_grid_page.test.tsx
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/index.tsx
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/role_mappings.html
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/roles_grid/roles.html
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/roles_grid/roles.js
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/users_grid/users.html
delete mode 100644 x-pack/legacy/plugins/security/public/views/management/users_grid/users.js
rename x-pack/{legacy/plugins/security/public/lib/role_utils.test.ts => plugins/security/common/model/role.test.ts} (96%)
create mode 100644 x-pack/plugins/security/public/_index.scss
rename x-pack/{legacy/plugins/security/public/views/account/components => plugins/security/public/account_management}/account_management_page.test.tsx (72%)
rename x-pack/{legacy/plugins/security/public/views/account/components => plugins/security/public/account_management}/account_management_page.tsx (62%)
rename x-pack/{legacy/plugins/security/public/views/account/components => plugins/security/public/account_management}/change_password/change_password.tsx (81%)
rename x-pack/{legacy/plugins/security/public/views/account/components => plugins/security/public/account_management}/change_password/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/account/components => plugins/security/public/account_management}/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/account/components => plugins/security/public/account_management}/personal_info/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/account/components => plugins/security/public/account_management}/personal_info/personal_info.tsx (89%)
create mode 100644 x-pack/plugins/security/public/management/_index.scss
create mode 100644 x-pack/plugins/security/public/management/api_keys/api_keys_api_client.mock.ts
create mode 100644 x-pack/plugins/security/public/management/api_keys/api_keys_api_client.test.ts
create mode 100644 x-pack/plugins/security/public/management/api_keys/api_keys_api_client.ts
rename x-pack/{legacy/plugins/security/public/views/management/api_keys_grid/components => plugins/security/public/management/api_keys/api_keys_grid}/__snapshots__/api_keys_grid_page.test.tsx.snap (91%)
rename x-pack/{legacy/plugins/security/public/views/management/api_keys_grid/components => plugins/security/public/management/api_keys/api_keys_grid}/api_keys_grid_page.test.tsx (65%)
rename x-pack/{legacy/plugins/security/public/views/management/api_keys_grid/components => plugins/security/public/management/api_keys/api_keys_grid}/api_keys_grid_page.tsx (90%)
rename x-pack/{legacy/plugins/security/public/views/management/api_keys_grid/components => plugins/security/public/management/api_keys/api_keys_grid}/empty_prompt/empty_prompt.tsx (89%)
rename x-pack/{legacy/plugins/security/public/views/management/api_keys_grid/components => plugins/security/public/management/api_keys/api_keys_grid}/empty_prompt/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/api_keys_grid/components => plugins/security/public/management/api_keys/api_keys_grid}/index.ts (81%)
rename x-pack/{legacy/plugins/security/public/views/management/api_keys_grid/components => plugins/security/public/management/api_keys/api_keys_grid}/invalidate_provider/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/api_keys_grid/components => plugins/security/public/management/api_keys/api_keys_grid}/invalidate_provider/invalidate_provider.tsx (91%)
rename x-pack/{legacy/plugins/security/public/views/management/api_keys_grid/components => plugins/security/public/management/api_keys/api_keys_grid}/not_enabled/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/api_keys_grid/components => plugins/security/public/management/api_keys/api_keys_grid}/not_enabled/not_enabled.tsx (78%)
rename x-pack/{legacy/plugins/security/public/views/management/api_keys_grid/components => plugins/security/public/management/api_keys/api_keys_grid}/permission_denied/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/api_keys_grid/components => plugins/security/public/management/api_keys/api_keys_grid}/permission_denied/permission_denied.tsx (100%)
create mode 100644 x-pack/plugins/security/public/management/api_keys/api_keys_management_app.test.tsx
create mode 100644 x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx
rename x-pack/{legacy/plugins/security/public/views/management/api_keys_grid/services => plugins/security/public/management/api_keys}/documentation_links.ts (51%)
create mode 100644 x-pack/plugins/security/public/management/api_keys/index.mock.ts
create mode 100644 x-pack/plugins/security/public/management/api_keys/index.ts
create mode 100644 x-pack/plugins/security/public/management/index.ts
create mode 100644 x-pack/plugins/security/public/management/management_service.test.ts
create mode 100644 x-pack/plugins/security/public/management/management_service.ts
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/management_urls.ts (74%)
create mode 100644 x-pack/plugins/security/public/management/role_mappings/_index.scss
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/components/delete_provider/delete_provider.test.tsx (64%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/components/delete_provider/delete_provider.tsx (93%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/components/delete_provider/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/components/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/components/no_compatible_realms/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/components/no_compatible_realms/no_compatible_realms.tsx (78%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/components/permission_denied/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/components/permission_denied/permission_denied.tsx (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/components/section_loading/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/components/section_loading/section_loading.test.tsx (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/components/section_loading/section_loading.tsx (100%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/services => plugins/security/public/management/role_mappings}/documentation_links.ts (70%)
create mode 100644 x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/_index.scss
create mode 100644 x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.test.tsx
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/edit_role_mapping_page.tsx (87%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/mapping_info_panel/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/mapping_info_panel/mapping_info_panel.test.tsx (82%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/mapping_info_panel/mapping_info_panel.tsx (95%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/role_selector/add_role_template_button.test.tsx (100%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/role_selector/add_role_template_button.tsx (100%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/role_selector/index.tsx (100%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/role_selector/role_selector.test.tsx (85%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/role_selector/role_selector.tsx (94%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/role_selector/role_template_editor.test.tsx (100%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/role_selector/role_template_editor.tsx (98%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/role_selector/role_template_type_select.tsx (92%)
create mode 100644 x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/_index.scss
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/_index.scss => plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/_rule_editor_group.scss} (100%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/rule_editor_panel/add_rule_button.test.tsx (97%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/rule_editor_panel/add_rule_button.tsx (97%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/rule_editor_panel/field_rule_editor.test.tsx (99%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/rule_editor_panel/field_rule_editor.tsx (99%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/rule_editor_panel/index.tsx (100%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/rule_editor_panel/json_rule_editor.test.tsx (89%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/rule_editor_panel/json_rule_editor.tsx (95%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/rule_editor_panel/rule_editor_panel.test.tsx (88%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/rule_editor_panel/rule_editor_panel.tsx (94%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/rule_editor_panel/rule_group_editor.test.tsx (99%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/rule_editor_panel/rule_group_editor.tsx (97%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/rule_editor_panel/rule_group_title.tsx (97%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/rule_editor_panel/visual_rule_editor.test.tsx (99%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components => plugins/security/public/management/role_mappings/edit_role_mapping}/rule_editor_panel/visual_rule_editor.tsx (95%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/edit_role_mapping/services/is_rule_group.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/edit_role_mapping/services/role_mapping_constants.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/edit_role_mapping/services/role_mapping_validation.test.ts (98%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/edit_role_mapping/services/role_mapping_validation.ts (97%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/edit_role_mapping/services/role_template_type.test.ts (96%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/edit_role_mapping/services/role_template_type.ts (96%)
create mode 100644 x-pack/plugins/security/public/management/role_mappings/index.mock.ts
create mode 100644 x-pack/plugins/security/public/management/role_mappings/index.ts
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/__snapshots__/rule_builder.test.ts.snap (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/all_rule.test.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/all_rule.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/any_rule.test.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/any_rule.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/except_all_rule.test.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/except_all_rule.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/except_any_rule.test.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/except_any_rule.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/field_rule.test.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/field_rule.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/rule.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/rule_builder.test.ts (99%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/rule_builder.ts (99%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/rule_builder_error.ts (100%)
rename x-pack/{legacy/plugins/security/public/views => plugins/security/public}/management/role_mappings/model/rule_group.ts (94%)
create mode 100644 x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.mock.ts
rename x-pack/{legacy/plugins/security/public/lib/role_mappings_api.ts => plugins/security/public/management/role_mappings/role_mappings_api_client.ts} (89%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components => plugins/security/public/management/role_mappings/role_mappings_grid}/create_role_mapping_button/create_role_mapping_button.tsx (90%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components => plugins/security/public/management/role_mappings/role_mappings_grid}/create_role_mapping_button/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components => plugins/security/public/management/role_mappings/role_mappings_grid}/empty_prompt/empty_prompt.tsx (100%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components => plugins/security/public/management/role_mappings/role_mappings_grid}/empty_prompt/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components => plugins/security/public/management/role_mappings/role_mappings_grid}/index.ts (100%)
create mode 100644 x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx
rename x-pack/{legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components => plugins/security/public/management/role_mappings/role_mappings_grid}/role_mappings_grid_page.tsx (93%)
create mode 100644 x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx
create mode 100644 x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx
create mode 100644 x-pack/plugins/security/public/management/roles/_index.scss
create mode 100644 x-pack/plugins/security/public/management/roles/documentation_links.ts
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/lib => plugins/security/public/management/roles/edit_role}/__snapshots__/validate_role.test.ts.snap (100%)
create mode 100644 x-pack/plugins/security/public/management/roles/edit_role/_index.scss
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/collapsible_panel/__snapshots__/collapsible_panel.test.tsx.snap (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/collapsible_panel/_collapsible_panel.scss (100%)
create mode 100644 x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/_index.scss
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/collapsible_panel/collapsible_panel.test.tsx (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/collapsible_panel/collapsible_panel.tsx (99%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/collapsible_panel/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/delete_role_button.test.tsx (94%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/delete_role_button.tsx (95%)
create mode 100644 x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx
create mode 100644 x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role}/privilege_utils.test.ts (100%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role}/privilege_utils.ts (93%)
create mode 100644 x-pack/plugins/security/public/management/roles/edit_role/privileges/_index.scss
create mode 100644 x-pack/plugins/security/public/management/roles/edit_role/privileges/_privilege_feature_icon.scss
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/es/__snapshots__/cluster_privileges.test.tsx.snap (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap (87%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/es/__snapshots__/index_privilege_form.test.tsx.snap (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/es/__snapshots__/index_privileges.test.tsx.snap (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/es/cluster_privileges.test.tsx (96%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/es/cluster_privileges.tsx (93%)
create mode 100644 x-pack/plugins/security/public/management/roles/edit_role/privileges/es/elasticsearch_privileges.test.tsx
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/es/elasticsearch_privileges.tsx (89%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/es/index_privilege_form.test.tsx (99%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/es/index_privilege_form.tsx (98%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/es/index_privileges.test.tsx (74%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/es/index_privileges.tsx (84%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/__snapshots__/kibana_privileges_region.test.tsx.snap (100%)
create mode 100644 x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/_index.scss
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/constants.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/feature_table/__snapshots__/feature_table.test.tsx.snap (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/_index.scss => plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/_change_all_privileges.scss} (100%)
create mode 100644 x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/_index.scss
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/feature_table/change_all_privileges.tsx (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/feature_table/feature_table.test.tsx (94%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/feature_table/feature_table.tsx (91%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/feature_table/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/kibana_privilege_calculator/__fixtures__/build_role.ts (90%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/kibana_privilege_calculator/__fixtures__/common_allowed_privileges.ts (100%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/kibana_privilege_calculator/__fixtures__/default_privilege_definition.ts (94%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/kibana_privilege_calculator/__fixtures__/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/kibana_privilege_calculator/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/kibana_privilege_calculator/kibana_allowed_privileges_calculator.test.ts (99%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/kibana_privilege_calculator/kibana_allowed_privileges_calculator.ts (94%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/kibana_privilege_calculator/kibana_base_privilege_calculator.test.ts (98%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/kibana_privilege_calculator/kibana_base_privilege_calculator.ts (91%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/kibana_privilege_calculator/kibana_feature_privilege_calculator.test.ts (99%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/kibana_privilege_calculator/kibana_feature_privilege_calculator.ts (94%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/kibana_privilege_calculator/kibana_privilege_calculator.test.ts (99%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/kibana_privilege_calculator/kibana_privilege_calculator.ts (96%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/kibana_privilege_calculator/kibana_privilege_calculator_types.ts (100%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/roles/edit_role/privileges/kibana}/kibana_privilege_calculator/kibana_privileges_calculator_factory.ts (90%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/kibana_privileges_region.test.tsx (95%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/kibana_privileges_region.tsx (79%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/simple_privilege_section/__snapshots__/simple_privilege_section.test.tsx.snap (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/simple_privilege_section/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/simple_privilege_section/privilege_selector.tsx (95%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/simple_privilege_section/simple_privilege_section.test.tsx (95%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx (94%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/simple_privilege_section/unsupported_space_privileges_warning.tsx (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/__fixtures__/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/__fixtures__/raw_kibana_privileges.ts (94%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_display.test.tsx.snap (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_space_form.test.tsx.snap (82%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/__snapshots__/space_aware_privilege_section.test.tsx.snap (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/_index.scss (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/_privilege_matrix.scss (87%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/privilege_display.test.tsx (96%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/privilege_display.tsx (96%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/privilege_matrix.test.tsx (89%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/privilege_matrix.tsx (93%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx (95%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx (96%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx (99%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx (94%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.test.tsx (95%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx (93%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/space_aware_privilege_section/space_selector.tsx (93%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/transform_error_section/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/privileges/kibana/transform_error_section/transform_error_section.tsx (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/reserved_role_badge.test.tsx (96%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/reserved_role_badge.tsx (89%)
create mode 100644 x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/_index.scss
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/spaces_popover_list/_spaces_popover_list.scss (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/spaces_popover_list/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/components => plugins/security/public/management/roles/edit_role}/spaces_popover_list/spaces_popover_list.tsx (95%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/lib => plugins/security/public/management/roles/edit_role}/validate_role.test.ts (99%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_role/lib => plugins/security/public/management/roles/edit_role}/validate_role.ts (98%)
create mode 100644 x-pack/plugins/security/public/management/roles/index.mock.ts
create mode 100644 x-pack/plugins/security/public/management/roles/index.ts
create mode 100644 x-pack/plugins/security/public/management/roles/indices_api_client.mock.ts
create mode 100644 x-pack/plugins/security/public/management/roles/indices_api_client.ts
create mode 100644 x-pack/plugins/security/public/management/roles/privileges_api_client.mock.ts
create mode 100644 x-pack/plugins/security/public/management/roles/privileges_api_client.ts
create mode 100644 x-pack/plugins/security/public/management/roles/roles_api_client.mock.ts
rename x-pack/{legacy/plugins/security/public/lib/transform_role_for_save.test.ts => plugins/security/public/management/roles/roles_api_client.test.ts} (82%)
create mode 100644 x-pack/plugins/security/public/management/roles/roles_api_client.ts
rename x-pack/{legacy/plugins/security/public/views/management/roles_grid/components => plugins/security/public/management/roles/roles_grid}/__snapshots__/roles_grid_page.test.tsx.snap (100%)
rename x-pack/{legacy/plugins/security/public/views/management/roles_grid/components => plugins/security/public/management/roles/roles_grid}/confirm_delete/confirm_delete.tsx (72%)
rename x-pack/{legacy/plugins/security/public/views/management/roles_grid/components => plugins/security/public/management/roles/roles_grid}/confirm_delete/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/roles_grid/components => plugins/security/public/management/roles/roles_grid}/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/roles_grid/components => plugins/security/public/management/roles/roles_grid}/permission_denied/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/views/management/roles_grid/components => plugins/security/public/management/roles/roles_grid}/permission_denied/permission_denied.tsx (100%)
rename x-pack/{legacy/plugins/security/public/views/management/roles_grid/components => plugins/security/public/management/roles/roles_grid}/roles_grid_page.test.tsx (63%)
rename x-pack/{legacy/plugins/security/public/views/management/roles_grid/components => plugins/security/public/management/roles/roles_grid}/roles_grid_page.tsx (78%)
create mode 100644 x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx
create mode 100644 x-pack/plugins/security/public/management/roles/roles_management_app.tsx
create mode 100644 x-pack/plugins/security/public/management/users/_index.scss
rename x-pack/{legacy/plugins/security/public/components/management => plugins/security/public/management/users/components}/change_password_form/change_password_form.test.tsx (82%)
rename x-pack/{legacy/plugins/security/public/components/management => plugins/security/public/management/users/components}/change_password_form/change_password_form.tsx (96%)
rename x-pack/{legacy/plugins/security/public/components/management => plugins/security/public/management/users/components}/change_password_form/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/components/management/users/confirm_delete.test.tsx => plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.test.tsx} (58%)
rename x-pack/{legacy/plugins/security/public/components/management/users/confirm_delete.tsx => plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.tsx} (50%)
rename x-pack/{legacy/plugins/security/public/components/management/users => plugins/security/public/management/users/components/confirm_delete_users}/index.ts (79%)
create mode 100644 x-pack/plugins/security/public/management/users/components/index.ts
rename x-pack/{legacy/plugins/security/public/views/management/edit_user/_users.scss => plugins/security/public/management/users/edit_user/_edit_user_page.scss} (100%)
create mode 100644 x-pack/plugins/security/public/management/users/edit_user/_index.scss
rename x-pack/{legacy/plugins/security/public/views/management/edit_user/components => plugins/security/public/management/users/edit_user}/edit_user_page.test.tsx (70%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_user/components => plugins/security/public/management/users/edit_user}/edit_user_page.tsx (77%)
rename x-pack/{legacy/plugins/security/public/views/management/edit_user/components => plugins/security/public/management/users/edit_user}/index.ts (100%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/users/edit_user}/validate_user.test.ts (98%)
rename x-pack/{legacy/plugins/security/public/lib => plugins/security/public/management/users/edit_user}/validate_user.ts (98%)
rename x-pack/{legacy/plugins/security/public/views/management/index.js => plugins/security/public/management/users/index.mock.ts} (80%)
rename x-pack/{legacy/plugins/security/public/objects => plugins/security/public/management/users}/index.ts (68%)
create mode 100644 x-pack/plugins/security/public/management/users/user_api_client.mock.ts
create mode 100644 x-pack/plugins/security/public/management/users/user_api_client.ts
rename x-pack/{legacy/plugins/security/public/views/management/users_grid/components => plugins/security/public/management/users/users_grid}/index.ts (82%)
rename x-pack/{legacy/plugins/security/public/views/management/users_grid/components/users_list_page.test.tsx => plugins/security/public/management/users/users_grid/users_grid_page.test.tsx} (63%)
rename x-pack/{legacy/plugins/security/public/views/management/users_grid/components/users_list_page.tsx => plugins/security/public/management/users/users_grid/users_grid_page.tsx} (85%)
create mode 100644 x-pack/plugins/security/public/management/users/users_management_app.test.tsx
create mode 100644 x-pack/plugins/security/public/management/users/users_management_app.tsx
delete mode 100644 x-pack/plugins/security/public/plugin.ts
create mode 100644 x-pack/plugins/security/public/plugin.tsx
diff --git a/src/core/public/saved_objects/saved_objects_client.test.ts b/src/core/public/saved_objects/saved_objects_client.test.ts
index e633e00965c6a..0c34a16c68e99 100644
--- a/src/core/public/saved_objects/saved_objects_client.test.ts
+++ b/src/core/public/saved_objects/saved_objects_client.test.ts
@@ -448,23 +448,4 @@ describe('SavedObjectsClient', () => {
`);
});
});
-
- it('maintains backwards compatibility by transforming http.fetch errors to be compatible with kfetch errors', () => {
- const err = {
- response: { ok: false, redirected: false, status: 409, statusText: 'Conflict' },
- body: 'response body',
- };
- http.fetch.mockRejectedValue(err);
- return expect(savedObjectsClient.get(doc.type, doc.id)).rejects.toMatchInlineSnapshot(`
- Object {
- "body": "response body",
- "res": Object {
- "ok": false,
- "redirected": false,
- "status": 409,
- "statusText": "Conflict",
- },
- }
- `);
- });
});
diff --git a/src/core/public/saved_objects/saved_objects_client.ts b/src/core/public/saved_objects/saved_objects_client.ts
index dab98ee66cdb1..ccb23793a8534 100644
--- a/src/core/public/saved_objects/saved_objects_client.ts
+++ b/src/core/public/saved_objects/saved_objects_client.ts
@@ -465,11 +465,7 @@ export class SavedObjectsClient {
* uses `{response: {status: number}}`.
*/
private savedObjectsFetch(path: string, { method, query, body }: HttpFetchOptions) {
- return this.http.fetch(path, { method, query, body }).catch(err => {
- const kfetchError = Object.assign(err, { res: err.response });
- delete kfetchError.response;
- return Promise.reject(kfetchError);
- });
+ return this.http.fetch(path, { method, query, body });
}
}
diff --git a/src/plugins/management/public/index.ts b/src/plugins/management/public/index.ts
index faec466dbd671..4ece75bbf36da 100644
--- a/src/plugins/management/public/index.ts
+++ b/src/plugins/management/public/index.ts
@@ -24,7 +24,12 @@ export function plugin(initializerContext: PluginInitializerContext) {
return new ManagementPlugin();
}
-export { ManagementSetup, ManagementStart, RegisterManagementApp } from './types';
+export {
+ ManagementSetup,
+ ManagementStart,
+ RegisterManagementApp,
+ RegisterManagementAppArgs,
+} from './types';
export { ManagementApp } from './management_app';
export { ManagementSection } from './management_section';
export { ManagementSidebarNav } from './components'; // for use in legacy management apps
diff --git a/x-pack/legacy/plugins/security/common/model.ts b/x-pack/legacy/plugins/security/common/model.ts
deleted file mode 100644
index 733e89f774db8..0000000000000
--- a/x-pack/legacy/plugins/security/common/model.ts
+++ /dev/null
@@ -1,28 +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 {
- ApiKey,
- ApiKeyToInvalidate,
- AuthenticatedUser,
- BuiltinESPrivileges,
- EditUser,
- FeaturesPrivileges,
- InlineRoleTemplate,
- InvalidRoleTemplate,
- KibanaPrivileges,
- RawKibanaFeaturePrivileges,
- RawKibanaPrivileges,
- Role,
- RoleIndexPrivilege,
- RoleKibanaPrivilege,
- RoleMapping,
- RoleTemplate,
- StoredRoleTemplate,
- User,
- canUserChangePassword,
- getUserDisplayName,
-} from '../../../../plugins/security/common/model';
diff --git a/x-pack/legacy/plugins/security/index.d.ts b/x-pack/legacy/plugins/security/index.d.ts
index 18284c8be689a..d453415f73376 100644
--- a/x-pack/legacy/plugins/security/index.d.ts
+++ b/x-pack/legacy/plugins/security/index.d.ts
@@ -5,7 +5,7 @@
*/
import { Legacy } from 'kibana';
-import { AuthenticatedUser } from './common/model';
+import { AuthenticatedUser } from '../../../plugins/security/public';
/**
* Public interface of the security plugin.
diff --git a/x-pack/legacy/plugins/security/index.js b/x-pack/legacy/plugins/security/index.js
index bc403b803b8df..4988c30a1398b 100644
--- a/x-pack/legacy/plugins/security/index.js
+++ b/x-pack/legacy/plugins/security/index.js
@@ -40,8 +40,6 @@ export const security = kibana =>
},
uiExports: {
- chromeNavControls: [],
- managementSections: ['plugins/security/views/management'],
styleSheetPaths: resolve(__dirname, 'public/index.scss'),
apps: [
{
@@ -76,7 +74,6 @@ export const security = kibana =>
'plugins/security/hacks/on_unauthorized_response',
'plugins/security/hacks/register_account_management_app',
],
- home: ['plugins/security/register_feature'],
injectDefaultVars: server => {
const securityPlugin = server.newPlatform.setup.plugins.security;
if (!securityPlugin) {
diff --git a/x-pack/legacy/plugins/security/public/documentation_links.js b/x-pack/legacy/plugins/security/public/documentation_links.js
deleted file mode 100644
index 8050289b95e9d..0000000000000
--- a/x-pack/legacy/plugins/security/public/documentation_links.js
+++ /dev/null
@@ -1,16 +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 { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links';
-
-const ES_REF_URL = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}`;
-
-export const documentationLinks = {
- dashboardViewMode: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/xpack-view-modes.html`,
- esClusterPrivileges: `${ES_REF_URL}/security-privileges.html#privileges-list-cluster`,
- esIndicesPrivileges: `${ES_REF_URL}/security-privileges.html#privileges-list-indices`,
- esRunAsPrivileges: `${ES_REF_URL}/security-privileges.html#_run_as_privilege`,
-};
diff --git a/x-pack/legacy/plugins/security/public/images/logout.svg b/x-pack/legacy/plugins/security/public/images/logout.svg
deleted file mode 100644
index d6533c0719904..0000000000000
--- a/x-pack/legacy/plugins/security/public/images/logout.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
\ No newline at end of file
diff --git a/x-pack/legacy/plugins/security/public/images/person.svg b/x-pack/legacy/plugins/security/public/images/person.svg
deleted file mode 100644
index 988ddac8859d7..0000000000000
--- a/x-pack/legacy/plugins/security/public/images/person.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
\ No newline at end of file
diff --git a/x-pack/legacy/plugins/security/public/index.scss b/x-pack/legacy/plugins/security/public/index.scss
index 2d7696bed3989..187ad5231534d 100644
--- a/x-pack/legacy/plugins/security/public/index.scss
+++ b/x-pack/legacy/plugins/security/public/index.scss
@@ -15,3 +15,6 @@ $secFormWidth: 460px;
// Public views
@import './views/index';
+// Styles of Kibana Platform plugin
+@import '../../../../plugins/security/public/index';
+
diff --git a/x-pack/legacy/plugins/security/public/lib/__tests__/util.js b/x-pack/legacy/plugins/security/public/lib/__tests__/util.js
deleted file mode 100644
index 3f7d8aea53a85..0000000000000
--- a/x-pack/legacy/plugins/security/public/lib/__tests__/util.js
+++ /dev/null
@@ -1,49 +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 '@kbn/expect';
-import { toggle, toggleSort } from '../../../public/lib/util';
-
-describe('util', () => {
- describe('toggle', () => {
- it('should add an item to a collection if not already included', () => {
- const collection = [1, 2, 3, 4, 5];
- toggle(collection, 6);
- expect(collection.indexOf(6)).to.be.above(0);
- });
-
- it('should remove an item from a collection if already included', () => {
- const collection = [1, 2, 3, 4, 5];
- toggle(collection, 3);
- expect(collection.indexOf(3)).to.be.below(0);
- });
- });
-
- describe('toggleSort', () => {
- it('should toggle reverse if called with the same orderBy', () => {
- const sort = { orderBy: 'foo', reverse: false };
-
- toggleSort(sort, 'foo');
- expect(sort.reverse).to.be.true;
-
- toggleSort(sort, 'foo');
- expect(sort.reverse).to.be.false;
- });
-
- it('should change orderBy and set reverse to false when called with a different orderBy', () => {
- const sort = { orderBy: 'foo', reverse: false };
-
- toggleSort(sort, 'bar');
- expect(sort.orderBy).to.equal('bar');
- expect(sort.reverse).to.be.false;
-
- sort.reverse = true;
- toggleSort(sort, 'foo');
- expect(sort.orderBy).to.equal('foo');
- expect(sort.reverse).to.be.false;
- });
- });
-});
diff --git a/x-pack/legacy/plugins/security/public/lib/api.ts b/x-pack/legacy/plugins/security/public/lib/api.ts
deleted file mode 100644
index c5c6994bf4be3..0000000000000
--- a/x-pack/legacy/plugins/security/public/lib/api.ts
+++ /dev/null
@@ -1,56 +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 { kfetch } from 'ui/kfetch';
-import { Role, User, EditUser } from '../../common/model';
-
-const usersUrl = '/internal/security/users';
-const rolesUrl = '/api/security/role';
-
-export class UserAPIClient {
- public async getUsers(): Promise {
- return await kfetch({ pathname: usersUrl });
- }
-
- public async getUser(username: string): Promise {
- const url = `${usersUrl}/${encodeURIComponent(username)}`;
- return await kfetch({ pathname: url });
- }
-
- public async deleteUser(username: string) {
- const url = `${usersUrl}/${encodeURIComponent(username)}`;
- await kfetch({ pathname: url, method: 'DELETE' }, {});
- }
-
- public async saveUser(user: EditUser) {
- const url = `${usersUrl}/${encodeURIComponent(user.username)}`;
-
- await kfetch({ pathname: url, body: JSON.stringify(user), method: 'POST' });
- }
-
- public async getRoles(): Promise {
- return await kfetch({ pathname: rolesUrl });
- }
-
- public async getRole(name: string): Promise {
- const url = `${rolesUrl}/${encodeURIComponent(name)}`;
- return await kfetch({ pathname: url });
- }
-
- public async changePassword(username: string, password: string, currentPassword: string) {
- const data: Record = {
- newPassword: password,
- };
- if (currentPassword) {
- data.password = currentPassword;
- }
- await kfetch({
- pathname: `${usersUrl}/${encodeURIComponent(username)}/password`,
- method: 'POST',
- body: JSON.stringify(data),
- });
- }
-}
diff --git a/x-pack/legacy/plugins/security/public/lib/api_keys_api.ts b/x-pack/legacy/plugins/security/public/lib/api_keys_api.ts
deleted file mode 100644
index fbc0460c5908a..0000000000000
--- a/x-pack/legacy/plugins/security/public/lib/api_keys_api.ts
+++ /dev/null
@@ -1,47 +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 { kfetch } from 'ui/kfetch';
-import { ApiKey, ApiKeyToInvalidate } from '../../common/model';
-
-interface CheckPrivilegesResponse {
- areApiKeysEnabled: boolean;
- isAdmin: boolean;
-}
-
-interface InvalidateApiKeysResponse {
- itemsInvalidated: ApiKeyToInvalidate[];
- errors: any[];
-}
-
-interface GetApiKeysResponse {
- apiKeys: ApiKey[];
-}
-
-const apiKeysUrl = `/internal/security/api_key`;
-
-export class ApiKeysApi {
- public static async checkPrivileges(): Promise {
- return kfetch({ pathname: `${apiKeysUrl}/privileges` });
- }
-
- public static async getApiKeys(isAdmin: boolean = false): Promise {
- const query = {
- isAdmin,
- };
-
- return kfetch({ pathname: apiKeysUrl, query });
- }
-
- public static async invalidateApiKeys(
- apiKeys: ApiKeyToInvalidate[],
- isAdmin: boolean = false
- ): Promise {
- const pathname = `${apiKeysUrl}/invalidate`;
- const body = JSON.stringify({ apiKeys, isAdmin });
- return kfetch({ pathname, method: 'POST', body });
- }
-}
diff --git a/x-pack/legacy/plugins/security/public/lib/role_utils.ts b/x-pack/legacy/plugins/security/public/lib/role_utils.ts
deleted file mode 100644
index c33b7385306fb..0000000000000
--- a/x-pack/legacy/plugins/security/public/lib/role_utils.ts
+++ /dev/null
@@ -1,58 +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 { cloneDeep, get } from 'lodash';
-import { Role } from '../../common/model';
-
-/**
- * Returns whether given role is enabled or not
- *
- * @param role Object Role JSON, as returned by roles API
- * @return Boolean true if role is enabled; false otherwise
- */
-export function isRoleEnabled(role: Partial) {
- return get(role, 'transient_metadata.enabled', true);
-}
-
-/**
- * Returns whether given role is reserved or not.
- *
- * @param {role} the Role as returned by roles API
- */
-export function isReservedRole(role: Partial) {
- return get(role, 'metadata._reserved', false);
-}
-
-/**
- * Returns whether given role is editable through the UI or not.
- *
- * @param role the Role as returned by roles API
- */
-export function isReadOnlyRole(role: Partial): boolean {
- return isReservedRole(role) || !!(role._transform_error && role._transform_error.length > 0);
-}
-
-/**
- * Returns a deep copy of the role.
- *
- * @param role the Role to copy.
- */
-export function copyRole(role: Role) {
- return cloneDeep(role);
-}
-
-/**
- * Creates a deep copy of the role suitable for cloning.
- *
- * @param role the Role to clone.
- */
-export function prepareRoleClone(role: Role): Role {
- const clone = copyRole(role);
-
- clone.name = '';
-
- return clone;
-}
diff --git a/x-pack/legacy/plugins/security/public/lib/roles_api.ts b/x-pack/legacy/plugins/security/public/lib/roles_api.ts
deleted file mode 100644
index 20c1491ccaac6..0000000000000
--- a/x-pack/legacy/plugins/security/public/lib/roles_api.ts
+++ /dev/null
@@ -1,25 +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 { kfetch } from 'ui/kfetch';
-import { Role } from '../../common/model';
-
-export class RolesApi {
- public static async getRoles(): Promise {
- return kfetch({ pathname: '/api/security/role' });
- }
-
- public static async getRole(roleName: string): Promise {
- return kfetch({ pathname: `/api/security/role/${encodeURIComponent(roleName)}` });
- }
-
- public static async deleteRole(roleName: string) {
- return kfetch({
- pathname: `/api/security/role/${encodeURIComponent(roleName)}`,
- method: 'DELETE',
- });
- }
-}
diff --git a/x-pack/legacy/plugins/security/public/lib/transform_role_for_save.ts b/x-pack/legacy/plugins/security/public/lib/transform_role_for_save.ts
deleted file mode 100644
index 861ba530050a1..0000000000000
--- a/x-pack/legacy/plugins/security/public/lib/transform_role_for_save.ts
+++ /dev/null
@@ -1,41 +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 { Role, RoleIndexPrivilege } from '../../common/model';
-import { isGlobalPrivilegeDefinition } from './privilege_utils';
-
-export function transformRoleForSave(role: Role, spacesEnabled: boolean) {
- // Remove any placeholder index privileges
- role.elasticsearch.indices = role.elasticsearch.indices.filter(
- indexPrivilege => !isPlaceholderPrivilege(indexPrivilege)
- );
-
- // Remove any placeholder query entries
- role.elasticsearch.indices.forEach(index => index.query || delete index.query);
-
- // If spaces are disabled, then do not persist any space privileges
- if (!spacesEnabled) {
- role.kibana = role.kibana.filter(isGlobalPrivilegeDefinition);
- }
-
- role.kibana.forEach(kibanaPrivilege => {
- // If a base privilege is defined, then do not persist feature privileges
- if (kibanaPrivilege.base.length > 0) {
- kibanaPrivilege.feature = {};
- }
- });
-
- delete role.name;
- delete role.transient_metadata;
- delete role._unrecognized_applications;
- delete role._transform_error;
-
- return role;
-}
-
-function isPlaceholderPrivilege(indexPrivilege: RoleIndexPrivilege) {
- return indexPrivilege.names.length === 0;
-}
diff --git a/x-pack/legacy/plugins/security/public/lib/util.js b/x-pack/legacy/plugins/security/public/lib/util.js
deleted file mode 100644
index bdf44aa3f10bb..0000000000000
--- a/x-pack/legacy/plugins/security/public/lib/util.js
+++ /dev/null
@@ -1,19 +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 toggle(collection, item) {
- const i = collection.indexOf(item);
- if (i >= 0) collection.splice(i, 1);
- else collection.push(item);
-}
-
-export function toggleSort(sort, orderBy) {
- if (sort.orderBy === orderBy) sort.reverse = !sort.reverse;
- else {
- sort.orderBy = orderBy;
- sort.reverse = false;
- }
-}
diff --git a/x-pack/legacy/plugins/security/public/objects/lib/get_fields.ts b/x-pack/legacy/plugins/security/public/objects/lib/get_fields.ts
deleted file mode 100644
index 91d98782dab42..0000000000000
--- a/x-pack/legacy/plugins/security/public/objects/lib/get_fields.ts
+++ /dev/null
@@ -1,15 +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 { IHttpResponse } from 'angular';
-import chrome from 'ui/chrome';
-
-const apiBase = chrome.addBasePath(`/internal/security/fields`);
-
-export async function getFields($http: any, query: string): Promise {
- return await $http
- .get(`${apiBase}/${query}`)
- .then((response: IHttpResponse) => response.data || []);
-}
diff --git a/x-pack/legacy/plugins/security/public/objects/lib/roles.ts b/x-pack/legacy/plugins/security/public/objects/lib/roles.ts
deleted file mode 100644
index e33cbe4c6c031..0000000000000
--- a/x-pack/legacy/plugins/security/public/objects/lib/roles.ts
+++ /dev/null
@@ -1,21 +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';
-import { Role } from '../../../common/model';
-import { copyRole } from '../../lib/role_utils';
-import { transformRoleForSave } from '../../lib/transform_role_for_save';
-
-const apiBase = chrome.addBasePath(`/api/security/role`);
-
-export async function saveRole($http: any, role: Role, spacesEnabled: boolean) {
- const data = transformRoleForSave(copyRole(role), spacesEnabled);
-
- return await $http.put(`${apiBase}/${role.name}`, data);
-}
-
-export async function deleteRole($http: any, name: string) {
- return await $http.delete(`${apiBase}/${name}`);
-}
diff --git a/x-pack/legacy/plugins/security/public/register_feature.js b/x-pack/legacy/plugins/security/public/register_feature.js
deleted file mode 100644
index c0bd42690b6fd..0000000000000
--- a/x-pack/legacy/plugins/security/public/register_feature.js
+++ /dev/null
@@ -1,29 +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 {
- FeatureCatalogueRegistryProvider,
- FeatureCatalogueCategory,
-} from 'ui/registry/feature_catalogue';
-
-import { i18n } from '@kbn/i18n';
-
-FeatureCatalogueRegistryProvider.register(() => {
- return {
- id: 'security',
- title: i18n.translate('xpack.security.registerFeature.securitySettingsTitle', {
- defaultMessage: 'Security Settings',
- }),
- description: i18n.translate('xpack.security.registerFeature.securitySettingsDescription', {
- defaultMessage:
- 'Protect your data and easily manage who has access to what with users and roles.',
- }),
- icon: 'securityApp',
- path: '/app/kibana#/management/security',
- showOnHomePage: true,
- category: FeatureCatalogueCategory.ADMIN,
- };
-});
diff --git a/x-pack/legacy/plugins/security/public/services/shield_indices.js b/x-pack/legacy/plugins/security/public/services/shield_indices.js
deleted file mode 100644
index 791fa6cb59648..0000000000000
--- a/x-pack/legacy/plugins/security/public/services/shield_indices.js
+++ /dev/null
@@ -1,18 +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 { uiModules } from 'ui/modules';
-
-const module = uiModules.get('security', []);
-module.service('shieldIndices', ($http, chrome) => {
- return {
- getFields: query => {
- return $http
- .get(chrome.addBasePath(`/internal/security/fields/${query}`))
- .then(response => response.data);
- },
- };
-});
diff --git a/x-pack/legacy/plugins/security/public/services/shield_role.js b/x-pack/legacy/plugins/security/public/services/shield_role.js
deleted file mode 100644
index 261d3449a7a2d..0000000000000
--- a/x-pack/legacy/plugins/security/public/services/shield_role.js
+++ /dev/null
@@ -1,30 +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 'angular-resource';
-import { omit } from 'lodash';
-import angular from 'angular';
-import { uiModules } from 'ui/modules';
-
-const module = uiModules.get('security', ['ngResource']);
-module.service('ShieldRole', ($resource, chrome) => {
- return $resource(
- chrome.addBasePath('/api/security/role/:name'),
- {
- name: '@name',
- },
- {
- save: {
- method: 'PUT',
- transformRequest(data) {
- return angular.toJson(
- omit(data, 'name', 'transient_metadata', '_unrecognized_applications')
- );
- },
- },
- }
- );
-});
diff --git a/x-pack/legacy/plugins/security/public/views/_index.scss b/x-pack/legacy/plugins/security/public/views/_index.scss
index b85a7e1997390..6c2a091adf536 100644
--- a/x-pack/legacy/plugins/security/public/views/_index.scss
+++ b/x-pack/legacy/plugins/security/public/views/_index.scss
@@ -1,5 +1,2 @@
// Login styles
@import './login/index';
-
-// Management styles
-@import './management/index';
diff --git a/x-pack/legacy/plugins/security/public/views/account/account.html b/x-pack/legacy/plugins/security/public/views/account/account.html
deleted file mode 100644
index 0935c415b1829..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/account/account.html
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/x-pack/legacy/plugins/security/public/views/account/account.js b/x-pack/legacy/plugins/security/public/views/account/account.js
index 70a7b8dce727e..13abc44e08f96 100644
--- a/x-pack/legacy/plugins/security/public/views/account/account.js
+++ b/x-pack/legacy/plugins/security/public/views/account/account.js
@@ -4,17 +4,14 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import routes from 'ui/routes';
-import template from './account.html';
-import { i18n } from '@kbn/i18n';
-import { I18nContext } from 'ui/i18n';
-import { npSetup } from 'ui/new_platform';
-import { AccountManagementPage } from './components';
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
+import { i18n } from '@kbn/i18n';
+import { npStart } from 'ui/new_platform';
+import routes from 'ui/routes';
routes.when('/account', {
- template,
+ template: '',
k7Breadcrumbs: () => [
{
text: i18n.translate('xpack.security.account.breadcrumb', {
@@ -24,19 +21,15 @@ routes.when('/account', {
],
controllerAs: 'accountController',
controller($scope) {
- $scope.$on('$destroy', () => {
- const elem = document.getElementById('userProfileReactRoot');
- if (elem) {
- unmountComponentAtNode(elem);
- }
- });
$scope.$$postDigest(() => {
+ const domNode = document.getElementById('userProfileReactRoot');
+
render(
-
-
- ,
- document.getElementById('userProfileReactRoot')
+ ,
+ domNode
);
+
+ $scope.$on('$destroy', () => unmountComponentAtNode(domNode));
});
},
});
diff --git a/x-pack/legacy/plugins/security/public/views/login/_index.scss b/x-pack/legacy/plugins/security/public/views/login/_index.scss
index 9f133940f7977..9083c8dc3b775 100644
--- a/x-pack/legacy/plugins/security/public/views/login/_index.scss
+++ b/x-pack/legacy/plugins/security/public/views/login/_index.scss
@@ -5,5 +5,4 @@
// loginChart__legend--small
// loginChart__legend-isLoading
-@import 'login';
-
+@import './components/index';
diff --git a/x-pack/legacy/plugins/security/public/views/login/components/_index.scss b/x-pack/legacy/plugins/security/public/views/login/components/_index.scss
new file mode 100644
index 0000000000000..a6f9598b9cc04
--- /dev/null
+++ b/x-pack/legacy/plugins/security/public/views/login/components/_index.scss
@@ -0,0 +1 @@
+@import './login_page/index';
diff --git a/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.test.tsx b/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.test.tsx
index 93451453a523a..3a970d582bdc8 100644
--- a/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.test.tsx
+++ b/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.test.tsx
@@ -7,7 +7,7 @@
import { EuiButton, EuiCallOut } from '@elastic/eui';
import React from 'react';
import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
-import { LoginState } from '../../../../../common/login_state';
+import { LoginState } from '../../login_state';
import { BasicLoginForm } from './basic_login_form';
const createMockHttp = ({ simulateError = false } = {}) => {
diff --git a/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.tsx b/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.tsx
index e6d3b5b7536b6..c263381fbdb56 100644
--- a/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.tsx
+++ b/x-pack/legacy/plugins/security/public/views/login/components/basic_login_form/basic_login_form.tsx
@@ -9,7 +9,7 @@ import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react';
import React, { ChangeEvent, Component, FormEvent, Fragment, MouseEvent } from 'react';
import ReactMarkdown from 'react-markdown';
import { EuiText } from '@elastic/eui';
-import { LoginState } from '../../../../../common/login_state';
+import { LoginState } from '../../login_state';
interface Props {
http: any;
diff --git a/x-pack/legacy/plugins/security/public/views/login/components/login_page/_index.scss b/x-pack/legacy/plugins/security/public/views/login/components/login_page/_index.scss
new file mode 100644
index 0000000000000..4dd2c0cabfb5e
--- /dev/null
+++ b/x-pack/legacy/plugins/security/public/views/login/components/login_page/_index.scss
@@ -0,0 +1 @@
+@import './login_page';
diff --git a/x-pack/legacy/plugins/security/public/views/login/_login.scss b/x-pack/legacy/plugins/security/public/views/login/components/login_page/_login_page.scss
similarity index 88%
rename from x-pack/legacy/plugins/security/public/views/login/_login.scss
rename to x-pack/legacy/plugins/security/public/views/login/components/login_page/_login_page.scss
index 607e9e6ec5e3f..cdfad55ee064a 100644
--- a/x-pack/legacy/plugins/security/public/views/login/_login.scss
+++ b/x-pack/legacy/plugins/security/public/views/login/components/login_page/_login_page.scss
@@ -1,4 +1,3 @@
-
.loginWelcome {
@include kibanaFullScreenGraphics;
}
@@ -16,10 +15,6 @@
margin-bottom: $euiSizeXL;
}
-.loginWelcome__footerAction {
- margin-right: $euiSizeS;
-}
-
.loginWelcome__content {
position: relative;
margin: auto;
diff --git a/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.test.tsx b/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.test.tsx
index c16db007bdbdc..a0318d50a45e5 100644
--- a/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.test.tsx
+++ b/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.test.tsx
@@ -6,7 +6,7 @@
import { shallow } from 'enzyme';
import React from 'react';
-import { LoginLayout, LoginState } from '../../../../../common/login_state';
+import { LoginLayout, LoginState } from '../../login_state';
import { LoginPage } from './login_page';
const createMockHttp = ({ simulateError = false } = {}) => {
diff --git a/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.tsx b/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.tsx
index e7e56947ca58f..8035789a30e9d 100644
--- a/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.tsx
+++ b/x-pack/legacy/plugins/security/public/views/login/components/login_page/login_page.tsx
@@ -19,7 +19,7 @@ import {
EuiTitle,
} from '@elastic/eui';
import classNames from 'classnames';
-import { LoginState } from '../../../../../common/login_state';
+import { LoginState } from '../../login_state';
import { BasicLoginForm } from '../basic_login_form';
import { DisabledLoginForm } from '../disabled_login_form';
diff --git a/x-pack/legacy/plugins/security/public/views/login/login.html b/x-pack/legacy/plugins/security/public/views/login/login.html
deleted file mode 100644
index 2695fabdd6367..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/login/login.html
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/x-pack/legacy/plugins/security/public/views/login/login.tsx b/x-pack/legacy/plugins/security/public/views/login/login.tsx
index d9daf2d1f4d0d..0b89ac553c9a8 100644
--- a/x-pack/legacy/plugins/security/public/views/login/login.tsx
+++ b/x-pack/legacy/plugins/security/public/views/login/login.tsx
@@ -6,16 +6,14 @@
import { i18n } from '@kbn/i18n';
import { get } from 'lodash';
-import { parseNext } from 'plugins/security/lib/parse_next';
import { LoginPage } from 'plugins/security/views/login/components';
-// @ts-ignore
-import template from 'plugins/security/views/login/login.html';
import React from 'react';
import { render } from 'react-dom';
import chrome from 'ui/chrome';
import { I18nContext } from 'ui/i18n';
import { parse } from 'url';
-import { LoginState } from '../../../common/login_state';
+import { parseNext } from './parse_next';
+import { LoginState } from './login_state';
const messageMap = {
SESSION_EXPIRED: i18n.translate('xpack.security.login.sessionExpiredDescription', {
defaultMessage: 'Your session has timed out. Please log in again.',
@@ -31,7 +29,7 @@ interface AnyObject {
(chrome as AnyObject)
.setVisible(false)
- .setRootTemplate(template)
+ .setRootTemplate('')
.setRootController(
'login',
(
diff --git a/x-pack/legacy/plugins/security/common/login_state.ts b/x-pack/legacy/plugins/security/public/views/login/login_state.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/common/login_state.ts
rename to x-pack/legacy/plugins/security/public/views/login/login_state.ts
diff --git a/x-pack/legacy/plugins/security/public/lib/__tests__/parse_next.js b/x-pack/legacy/plugins/security/public/views/login/parse_next.test.ts
similarity index 80%
rename from x-pack/legacy/plugins/security/public/lib/__tests__/parse_next.js
rename to x-pack/legacy/plugins/security/public/views/login/parse_next.test.ts
index 7516433c77f83..b5e6c7dca41d8 100644
--- a/x-pack/legacy/plugins/security/public/lib/__tests__/parse_next.js
+++ b/x-pack/legacy/plugins/security/public/views/login/parse_next.test.ts
@@ -4,12 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from '@kbn/expect';
-import { parseNext } from '../parse_next';
+import { parseNext } from './parse_next';
describe('parseNext', () => {
it('should return a function', () => {
- expect(parseNext).to.be.a('function');
+ expect(parseNext).toBeInstanceOf(Function);
});
describe('with basePath defined', () => {
@@ -17,14 +16,14 @@ describe('parseNext', () => {
it('should return basePath with a trailing slash when next is not specified', () => {
const basePath = '/iqf';
const href = `${basePath}/login`;
- expect(parseNext(href, basePath)).to.equal(`${basePath}/`);
+ expect(parseNext(href, basePath)).toEqual(`${basePath}/`);
});
it('should properly handle next without hash', () => {
const basePath = '/iqf';
const next = `${basePath}/app/kibana`;
const href = `${basePath}/login?next=${next}`;
- expect(parseNext(href, basePath)).to.equal(next);
+ expect(parseNext(href, basePath)).toEqual(next);
});
it('should properly handle next with hash', () => {
@@ -32,7 +31,7 @@ describe('parseNext', () => {
const next = `${basePath}/app/kibana`;
const hash = '/discover/New-Saved-Search';
const href = `${basePath}/login?next=${next}#${hash}`;
- expect(parseNext(href, basePath)).to.equal(`${next}#${hash}`);
+ expect(parseNext(href, basePath)).toEqual(`${next}#${hash}`);
});
it('should properly decode special characters', () => {
@@ -40,7 +39,7 @@ describe('parseNext', () => {
const next = `${encodeURIComponent(basePath)}%2Fapp%2Fkibana`;
const hash = '/discover/New-Saved-Search';
const href = `${basePath}/login?next=${next}#${hash}`;
- expect(parseNext(href, basePath)).to.equal(decodeURIComponent(`${next}#${hash}`));
+ expect(parseNext(href, basePath)).toEqual(decodeURIComponent(`${next}#${hash}`));
});
// to help prevent open redirect to a different url
@@ -48,7 +47,7 @@ describe('parseNext', () => {
const basePath = '/iqf';
const next = `https://example.com${basePath}/app/kibana`;
const href = `${basePath}/login?next=${next}`;
- expect(parseNext(href, basePath)).to.equal(`${basePath}/`);
+ expect(parseNext(href, basePath)).toEqual(`${basePath}/`);
});
// to help prevent open redirect to a different url by abusing encodings
@@ -58,7 +57,7 @@ describe('parseNext', () => {
const next = `${encodeURIComponent(baseUrl)}%2Fapp%2Fkibana`;
const hash = '/discover/New-Saved-Search';
const href = `${basePath}/login?next=${next}#${hash}`;
- expect(parseNext(href, basePath)).to.equal(`${basePath}/`);
+ expect(parseNext(href, basePath)).toEqual(`${basePath}/`);
});
// to help prevent open redirect to a different port
@@ -66,7 +65,7 @@ describe('parseNext', () => {
const basePath = '/iqf';
const next = `http://localhost:5601${basePath}/app/kibana`;
const href = `${basePath}/login?next=${next}`;
- expect(parseNext(href, basePath)).to.equal(`${basePath}/`);
+ expect(parseNext(href, basePath)).toEqual(`${basePath}/`);
});
// to help prevent open redirect to a different port by abusing encodings
@@ -76,7 +75,7 @@ describe('parseNext', () => {
const next = `${encodeURIComponent(baseUrl)}%2Fapp%2Fkibana`;
const hash = '/discover/New-Saved-Search';
const href = `${basePath}/login?next=${next}#${hash}`;
- expect(parseNext(href, basePath)).to.equal(`${basePath}/`);
+ expect(parseNext(href, basePath)).toEqual(`${basePath}/`);
});
// to help prevent open redirect to a different base path
@@ -84,18 +83,18 @@ describe('parseNext', () => {
const basePath = '/iqf';
const next = '/notbasepath/app/kibana';
const href = `${basePath}/login?next=${next}`;
- expect(parseNext(href, basePath)).to.equal(`${basePath}/`);
+ expect(parseNext(href, basePath)).toEqual(`${basePath}/`);
});
// disallow network-path references
it('should return / if next is url without protocol', () => {
const nextWithTwoSlashes = '//example.com';
const hrefWithTwoSlashes = `/login?next=${nextWithTwoSlashes}`;
- expect(parseNext(hrefWithTwoSlashes)).to.equal('/');
+ expect(parseNext(hrefWithTwoSlashes)).toEqual('/');
const nextWithThreeSlashes = '///example.com';
const hrefWithThreeSlashes = `/login?next=${nextWithThreeSlashes}`;
- expect(parseNext(hrefWithThreeSlashes)).to.equal('/');
+ expect(parseNext(hrefWithThreeSlashes)).toEqual('/');
});
});
@@ -103,34 +102,34 @@ describe('parseNext', () => {
// trailing slash is important since it must match the cookie path exactly
it('should return / with a trailing slash when next is not specified', () => {
const href = '/login';
- expect(parseNext(href)).to.equal('/');
+ expect(parseNext(href)).toEqual('/');
});
it('should properly handle next without hash', () => {
const next = '/app/kibana';
const href = `/login?next=${next}`;
- expect(parseNext(href)).to.equal(next);
+ expect(parseNext(href)).toEqual(next);
});
it('should properly handle next with hash', () => {
const next = '/app/kibana';
const hash = '/discover/New-Saved-Search';
const href = `/login?next=${next}#${hash}`;
- expect(parseNext(href)).to.equal(`${next}#${hash}`);
+ expect(parseNext(href)).toEqual(`${next}#${hash}`);
});
it('should properly decode special characters', () => {
const next = '%2Fapp%2Fkibana';
const hash = '/discover/New-Saved-Search';
const href = `/login?next=${next}#${hash}`;
- expect(parseNext(href)).to.equal(decodeURIComponent(`${next}#${hash}`));
+ expect(parseNext(href)).toEqual(decodeURIComponent(`${next}#${hash}`));
});
// to help prevent open redirect to a different url
it('should return / if next includes a protocol/hostname', () => {
const next = 'https://example.com/app/kibana';
const href = `/login?next=${next}`;
- expect(parseNext(href)).to.equal('/');
+ expect(parseNext(href)).toEqual('/');
});
// to help prevent open redirect to a different url by abusing encodings
@@ -139,14 +138,14 @@ describe('parseNext', () => {
const next = `${encodeURIComponent(baseUrl)}%2Fapp%2Fkibana`;
const hash = '/discover/New-Saved-Search';
const href = `/login?next=${next}#${hash}`;
- expect(parseNext(href)).to.equal('/');
+ expect(parseNext(href)).toEqual('/');
});
// to help prevent open redirect to a different port
it('should return / if next includes a port', () => {
const next = 'http://localhost:5601/app/kibana';
const href = `/login?next=${next}`;
- expect(parseNext(href)).to.equal('/');
+ expect(parseNext(href)).toEqual('/');
});
// to help prevent open redirect to a different port by abusing encodings
@@ -155,18 +154,18 @@ describe('parseNext', () => {
const next = `${encodeURIComponent(baseUrl)}%2Fapp%2Fkibana`;
const hash = '/discover/New-Saved-Search';
const href = `/login?next=${next}#${hash}`;
- expect(parseNext(href)).to.equal('/');
+ expect(parseNext(href)).toEqual('/');
});
// disallow network-path references
it('should return / if next is url without protocol', () => {
const nextWithTwoSlashes = '//example.com';
const hrefWithTwoSlashes = `/login?next=${nextWithTwoSlashes}`;
- expect(parseNext(hrefWithTwoSlashes)).to.equal('/');
+ expect(parseNext(hrefWithTwoSlashes)).toEqual('/');
const nextWithThreeSlashes = '///example.com';
const hrefWithThreeSlashes = `/login?next=${nextWithThreeSlashes}`;
- expect(parseNext(hrefWithThreeSlashes)).to.equal('/');
+ expect(parseNext(hrefWithThreeSlashes)).toEqual('/');
});
});
});
diff --git a/x-pack/legacy/plugins/security/public/lib/parse_next.ts b/x-pack/legacy/plugins/security/public/views/login/parse_next.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/lib/parse_next.ts
rename to x-pack/legacy/plugins/security/public/views/login/parse_next.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/_index.scss b/x-pack/legacy/plugins/security/public/views/management/_index.scss
deleted file mode 100644
index 78b53845071e4..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/_index.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-@import './change_password_form/index';
-@import './edit_role/index';
-@import './edit_user/index';
-@import './role_mappings/edit_role_mapping/index';
\ No newline at end of file
diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/api_keys.html b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/api_keys.html
deleted file mode 100644
index e46c6f72b5d20..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/api_keys.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/api_keys.js b/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/api_keys.js
deleted file mode 100644
index e7143b1020814..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/api_keys.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 React from 'react';
-import { render, unmountComponentAtNode } from 'react-dom';
-import routes from 'ui/routes';
-import template from './api_keys.html';
-import { API_KEYS_PATH } from '../management_urls';
-import { getApiKeysBreadcrumbs } from '../breadcrumbs';
-import { I18nContext } from 'ui/i18n';
-import { ApiKeysGridPage } from './components';
-
-routes.when(API_KEYS_PATH, {
- template,
- k7Breadcrumbs: getApiKeysBreadcrumbs,
- controller($scope) {
- $scope.$$postDigest(() => {
- const domNode = document.getElementById('apiKeysGridReactRoot');
-
- render(
-
-
- ,
- domNode
- );
-
- // unmount react on controller destroy
- $scope.$on('$destroy', () => {
- unmountComponentAtNode(domNode);
- });
- });
- },
-});
diff --git a/x-pack/legacy/plugins/security/public/views/management/breadcrumbs.ts b/x-pack/legacy/plugins/security/public/views/management/breadcrumbs.ts
deleted file mode 100644
index 4ab7e45e84849..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/breadcrumbs.ts
+++ /dev/null
@@ -1,115 +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 { i18n } from '@kbn/i18n';
-import { MANAGEMENT_BREADCRUMB } from 'ui/management/breadcrumbs';
-
-export function getUsersBreadcrumbs() {
- return [
- MANAGEMENT_BREADCRUMB,
- {
- text: i18n.translate('xpack.security.users.breadcrumb', {
- defaultMessage: 'Users',
- }),
- href: '#/management/security/users',
- },
- ];
-}
-
-export function getEditUserBreadcrumbs($route: Record) {
- const { username } = $route.current.params;
- return [
- ...getUsersBreadcrumbs(),
- {
- text: username,
- href: `#/management/security/users/edit/${username}`,
- },
- ];
-}
-
-export function getCreateUserBreadcrumbs() {
- return [
- ...getUsersBreadcrumbs(),
- {
- text: i18n.translate('xpack.security.users.createBreadcrumb', {
- defaultMessage: 'Create',
- }),
- },
- ];
-}
-
-export function getRolesBreadcrumbs() {
- return [
- MANAGEMENT_BREADCRUMB,
- {
- text: i18n.translate('xpack.security.roles.breadcrumb', {
- defaultMessage: 'Roles',
- }),
- href: '#/management/security/roles',
- },
- ];
-}
-
-export function getEditRoleBreadcrumbs($route: Record) {
- const { name } = $route.current.params;
- return [
- ...getRolesBreadcrumbs(),
- {
- text: name,
- href: `#/management/security/roles/edit/${name}`,
- },
- ];
-}
-
-export function getCreateRoleBreadcrumbs() {
- return [
- ...getUsersBreadcrumbs(),
- {
- text: i18n.translate('xpack.security.roles.createBreadcrumb', {
- defaultMessage: 'Create',
- }),
- },
- ];
-}
-
-export function getApiKeysBreadcrumbs() {
- return [
- MANAGEMENT_BREADCRUMB,
- {
- text: i18n.translate('xpack.security.apiKeys.breadcrumb', {
- defaultMessage: 'API Keys',
- }),
- href: '#/management/security/api_keys',
- },
- ];
-}
-
-export function getRoleMappingBreadcrumbs() {
- return [
- MANAGEMENT_BREADCRUMB,
- {
- text: i18n.translate('xpack.security.roleMapping.breadcrumb', {
- defaultMessage: 'Role Mappings',
- }),
- href: '#/management/security/role_mappings',
- },
- ];
-}
-
-export function getEditRoleMappingBreadcrumbs($route: Record) {
- const { name } = $route.current.params;
- return [
- ...getRoleMappingBreadcrumbs(),
- {
- text:
- name ||
- i18n.translate('xpack.security.roleMappings.createBreadcrumb', {
- defaultMessage: 'Create',
- }),
- href: `#/management/security/role_mappings/edit/${name}`,
- },
- ];
-}
diff --git a/x-pack/legacy/plugins/security/public/views/management/change_password_form/_change_password_form.scss b/x-pack/legacy/plugins/security/public/views/management/change_password_form/_change_password_form.scss
deleted file mode 100644
index 98331c2070a31..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/change_password_form/_change_password_form.scss
+++ /dev/null
@@ -1,17 +0,0 @@
-.secChangePasswordForm__panel {
- max-width: $secFormWidth;
-}
-
-.secChangePasswordForm__subLabel {
- margin-bottom: $euiSizeS;
-}
-
-.secChangePasswordForm__footer {
- display: flex;
- justify-content: flex-start;
- align-items: center;
-
- .kuiButton + .kuiButton {
- margin-left: $euiSizeS;
- }
-}
diff --git a/x-pack/legacy/plugins/security/public/views/management/change_password_form/_index.scss b/x-pack/legacy/plugins/security/public/views/management/change_password_form/_index.scss
deleted file mode 100644
index a6058b5ddebbf..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/change_password_form/_index.scss
+++ /dev/null
@@ -1 +0,0 @@
-@import './change_password_form';
diff --git a/x-pack/legacy/plugins/security/public/views/management/change_password_form/change_password_form.html b/x-pack/legacy/plugins/security/public/views/management/change_password_form/change_password_form.html
deleted file mode 100644
index 92fb95861a6f8..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/change_password_form/change_password_form.html
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
diff --git a/x-pack/legacy/plugins/security/public/views/management/change_password_form/change_password_form.js b/x-pack/legacy/plugins/security/public/views/management/change_password_form/change_password_form.js
deleted file mode 100644
index d9aa59f6df142..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/change_password_form/change_password_form.js
+++ /dev/null
@@ -1,48 +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 { uiModules } from 'ui/modules';
-import template from './change_password_form.html';
-
-const module = uiModules.get('security', ['kibana']);
-module.directive('kbnChangePasswordForm', function() {
- return {
- template,
- scope: {
- requireCurrentPassword: '=',
- showKibanaWarning: '=',
- onChangePassword: '&',
- },
- restrict: 'E',
- replace: true,
- controllerAs: 'changePasswordController',
- controller: function($scope) {
- this.currentPassword = null;
- this.newPassword = null;
- this.newPasswordConfirmation = null;
- this.isFormVisible = false;
- this.isIncorrectPassword = false;
-
- this.showForm = () => {
- this.isFormVisible = true;
- };
-
- this.hideForm = () => {
- $scope.changePasswordForm.$setPristine();
- $scope.changePasswordForm.$setUntouched();
- this.currentPassword = null;
- this.newPassword = null;
- this.newPasswordConfirmation = null;
- this.isFormVisible = false;
- this.isIncorrectPassword = false;
- };
-
- this.onIncorrectPassword = () => {
- this.isIncorrectPassword = true;
- };
- },
- };
-});
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/_index.scss b/x-pack/legacy/plugins/security/public/views/management/edit_role/_index.scss
deleted file mode 100644
index 192091fb04e3c..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/_index.scss
+++ /dev/null
@@ -1 +0,0 @@
-@import './components/index';
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/_index.scss b/x-pack/legacy/plugins/security/public/views/management/edit_role/components/_index.scss
deleted file mode 100644
index 32b3832e7a9fa..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/_index.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-@import './collapsible_panel/collapsible_panel';
-@import './privileges/kibana/space_aware_privilege_section/index';
-@import './privileges/kibana/feature_table/index';
-@import './spaces_popover_list/spaces_popover_list';
-
-.secPrivilegeFeatureIcon {
- flex-shrink: 0;
- margin-right: $euiSizeS;
-}
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/edit_role_page.test.tsx b/x-pack/legacy/plugins/security/public/views/management/edit_role/components/edit_role_page.test.tsx
deleted file mode 100644
index 67c32c8393171..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/edit_role_page.test.tsx
+++ /dev/null
@@ -1,716 +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 { ReactWrapper } from 'enzyme';
-import React from 'react';
-import { mountWithIntl } from 'test_utils/enzyme_helpers';
-import { UICapabilities } from 'ui/capabilities';
-import { Space } from '../../../../../../spaces/common/model/space';
-import { Feature } from '../../../../../../../../plugins/features/public';
-// These modules should be moved into a common directory
-// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import { Actions } from '../../../../../../../../plugins/security/server/authorization/actions';
-// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import { privilegesFactory } from '../../../../../../../../plugins/security/server/authorization/privileges';
-import { RawKibanaPrivileges, Role } from '../../../../../common/model';
-import { EditRolePage } from './edit_role_page';
-import { SimplePrivilegeSection } from './privileges/kibana/simple_privilege_section';
-import { SpaceAwarePrivilegeSection } from './privileges/kibana/space_aware_privilege_section';
-import { TransformErrorSection } from './privileges/kibana/transform_error_section';
-
-const buildFeatures = () => {
- return [
- {
- id: 'feature1',
- name: 'Feature 1',
- icon: 'addDataApp',
- app: ['feature1App'],
- privileges: {
- all: {
- app: ['feature1App'],
- ui: ['feature1-ui'],
- savedObject: {
- all: [],
- read: [],
- },
- },
- },
- },
- {
- id: 'feature2',
- name: 'Feature 2',
- icon: 'addDataApp',
- app: ['feature2App'],
- privileges: {
- all: {
- app: ['feature2App'],
- ui: ['feature2-ui'],
- savedObject: {
- all: ['feature2'],
- read: ['config'],
- },
- },
- },
- },
- ] as Feature[];
-};
-
-const buildRawKibanaPrivileges = () => {
- return privilegesFactory(new Actions('unit_test_version'), {
- getFeatures: () => buildFeatures(),
- }).get();
-};
-
-const buildBuiltinESPrivileges = () => {
- return {
- cluster: ['all', 'manage', 'monitor'],
- index: ['all', 'read', 'write', 'index'],
- };
-};
-
-const buildUICapabilities = (canManageSpaces = true) => {
- return {
- catalogue: {},
- management: {},
- navLinks: {},
- spaces: {
- manage: canManageSpaces,
- },
- } as UICapabilities;
-};
-
-const buildSpaces = () => {
- return [
- {
- id: 'default',
- name: 'Default',
- disabledFeatures: [],
- _reserved: true,
- },
- {
- id: 'space_1',
- name: 'Space 1',
- disabledFeatures: [],
- },
- {
- id: 'space_2',
- name: 'Space 2',
- disabledFeatures: ['feature2'],
- },
- ] as Space[];
-};
-
-const expectReadOnlyFormButtons = (wrapper: ReactWrapper) => {
- expect(wrapper.find('button[data-test-subj="roleFormReturnButton"]')).toHaveLength(1);
- expect(wrapper.find('button[data-test-subj="roleFormSaveButton"]')).toHaveLength(0);
-};
-
-const expectSaveFormButtons = (wrapper: ReactWrapper) => {
- expect(wrapper.find('button[data-test-subj="roleFormReturnButton"]')).toHaveLength(0);
- expect(wrapper.find('button[data-test-subj="roleFormSaveButton"]')).toHaveLength(1);
-};
-
-describe('', () => {
- describe('with spaces enabled', () => {
- it('can render a reserved role', () => {
- const role: Role = {
- name: 'superuser',
- metadata: {
- _reserved: true,
- },
- elasticsearch: {
- cluster: ['all'],
- indices: [],
- run_as: ['*'],
- },
- kibana: [
- {
- spaces: ['*'],
- base: ['all'],
- feature: {},
- },
- ],
- };
-
- const features: Feature[] = buildFeatures();
- const mockHttpClient = jest.fn();
- const indexPatterns: string[] = ['foo*', 'bar*'];
- const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
- const builtinESPrivileges = buildBuiltinESPrivileges();
- const spaces: Space[] = buildSpaces();
- const uiCapabilities: UICapabilities = buildUICapabilities();
-
- const wrapper = mountWithIntl(
-
- );
-
- expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(1);
- expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1);
- expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
- expectReadOnlyFormButtons(wrapper);
- });
-
- it('can render a user defined role', () => {
- const role: Role = {
- name: 'my custom role',
- metadata: {},
- elasticsearch: {
- cluster: ['all'],
- indices: [],
- run_as: ['*'],
- },
- kibana: [
- {
- spaces: ['*'],
- base: ['all'],
- feature: {},
- },
- ],
- };
-
- const features: Feature[] = buildFeatures();
- const mockHttpClient = jest.fn();
- const indexPatterns: string[] = ['foo*', 'bar*'];
- const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
- const builtinESPrivileges = buildBuiltinESPrivileges();
- const spaces: Space[] = buildSpaces();
- const uiCapabilities: UICapabilities = buildUICapabilities();
-
- const wrapper = mountWithIntl(
-
- );
-
- expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0);
- expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1);
- expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
- expectSaveFormButtons(wrapper);
- });
-
- it('can render when creating a new role', () => {
- // @ts-ignore
- const role: Role = {
- metadata: {},
- elasticsearch: {
- cluster: [],
- indices: [],
- run_as: [],
- },
- kibana: [],
- };
-
- const features: Feature[] = buildFeatures();
- const mockHttpClient = jest.fn();
- const indexPatterns: string[] = ['foo*', 'bar*'];
- const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
- const builtinESPrivileges = buildBuiltinESPrivileges();
- const spaces: Space[] = buildSpaces();
- const uiCapabilities: UICapabilities = buildUICapabilities();
-
- const wrapper = mountWithIntl(
-
- );
-
- expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1);
- expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
- expectSaveFormButtons(wrapper);
- });
-
- it('can render when cloning an existing role', () => {
- const role: Role = {
- metadata: {
- _reserved: false,
- },
- name: '',
- elasticsearch: {
- cluster: ['all', 'manage'],
- indices: [
- {
- names: ['foo*'],
- privileges: ['all'],
- field_security: {
- except: ['f'],
- grant: ['b*'],
- },
- },
- ],
- run_as: ['elastic'],
- },
- kibana: [
- {
- spaces: ['*'],
- base: ['all'],
- feature: {},
- },
- ],
- };
-
- const features: Feature[] = buildFeatures();
- const mockHttpClient = jest.fn();
- const indexPatterns: string[] = ['foo*', 'bar*'];
- const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
- const builtinESPrivileges = buildBuiltinESPrivileges();
- const spaces: Space[] = buildSpaces();
- const uiCapabilities: UICapabilities = buildUICapabilities();
-
- const wrapper = mountWithIntl(
-
- );
-
- expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1);
- expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
- expectSaveFormButtons(wrapper);
- });
-
- it('renders an auth error when not authorized to manage spaces', () => {
- const role: Role = {
- name: 'my custom role',
- metadata: {},
- elasticsearch: {
- cluster: ['all'],
- indices: [],
- run_as: ['*'],
- },
- kibana: [
- {
- spaces: ['*'],
- base: ['all'],
- feature: {},
- },
- ],
- };
-
- const features: Feature[] = buildFeatures();
- const mockHttpClient = jest.fn();
- const indexPatterns: string[] = ['foo*', 'bar*'];
- const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
- const builtinESPrivileges = buildBuiltinESPrivileges();
- const spaces: Space[] = buildSpaces();
- const uiCapabilities: UICapabilities = buildUICapabilities(false);
-
- const wrapper = mountWithIntl(
-
- );
-
- expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0);
-
- expect(
- wrapper.find('EuiCallOut[data-test-subj="userCannotManageSpacesCallout"]')
- ).toHaveLength(1);
-
- expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1);
- expectSaveFormButtons(wrapper);
- });
-
- it('renders a partial read-only view when there is a transform error', () => {
- const role: Role = {
- name: 'my custom role',
- metadata: {},
- elasticsearch: {
- cluster: ['all'],
- indices: [],
- run_as: ['*'],
- },
- kibana: [],
- _transform_error: ['kibana'],
- };
-
- const features: Feature[] = buildFeatures();
- const mockHttpClient = jest.fn();
- const indexPatterns: string[] = ['foo*', 'bar*'];
- const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
- const builtinESPrivileges = buildBuiltinESPrivileges();
- const spaces: Space[] = buildSpaces();
- const uiCapabilities: UICapabilities = buildUICapabilities(false);
-
- const wrapper = mountWithIntl(
-
- );
-
- expect(wrapper.find(TransformErrorSection)).toHaveLength(1);
- expectReadOnlyFormButtons(wrapper);
- });
- });
-
- describe('with spaces disabled', () => {
- it('can render a reserved role', () => {
- const role: Role = {
- name: 'superuser',
- metadata: {
- _reserved: true,
- },
- elasticsearch: {
- cluster: ['all'],
- indices: [],
- run_as: ['*'],
- },
- kibana: [
- {
- spaces: ['*'],
- base: ['all'],
- feature: {},
- },
- ],
- };
-
- const features: Feature[] = buildFeatures();
- const mockHttpClient = jest.fn();
- const indexPatterns: string[] = ['foo*', 'bar*'];
- const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
- const builtinESPrivileges = buildBuiltinESPrivileges();
- const uiCapabilities: UICapabilities = buildUICapabilities();
-
- const wrapper = mountWithIntl(
-
- );
-
- expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(1);
- expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1);
- expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
- expectReadOnlyFormButtons(wrapper);
- });
-
- it('can render a user defined role', () => {
- const role: Role = {
- name: 'my custom role',
- metadata: {},
- elasticsearch: {
- cluster: ['all'],
- indices: [],
- run_as: ['*'],
- },
- kibana: [
- {
- spaces: ['*'],
- base: ['all'],
- feature: {},
- },
- ],
- };
-
- const features: Feature[] = buildFeatures();
- const mockHttpClient = jest.fn();
- const indexPatterns: string[] = ['foo*', 'bar*'];
- const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
- const builtinESPrivileges = buildBuiltinESPrivileges();
- const uiCapabilities: UICapabilities = buildUICapabilities();
-
- const wrapper = mountWithIntl(
-
- );
-
- expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0);
- expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1);
- expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
- expectSaveFormButtons(wrapper);
- });
-
- it('can render when creating a new role', () => {
- // @ts-ignore
- const role: Role = {
- metadata: {},
- elasticsearch: {
- cluster: [],
- indices: [],
- run_as: [],
- },
- kibana: [],
- };
-
- const features: Feature[] = buildFeatures();
- const mockHttpClient = jest.fn();
- const indexPatterns: string[] = ['foo*', 'bar*'];
- const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
- const builtinESPrivileges = buildBuiltinESPrivileges();
- const uiCapabilities: UICapabilities = buildUICapabilities();
-
- const wrapper = mountWithIntl(
-
- );
-
- expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1);
- expectSaveFormButtons(wrapper);
- });
-
- it('can render when cloning an existing role', () => {
- const role: Role = {
- metadata: {
- _reserved: false,
- },
- name: '',
- elasticsearch: {
- cluster: ['all', 'manage'],
- indices: [
- {
- names: ['foo*'],
- privileges: ['all'],
- field_security: {
- except: ['f'],
- grant: ['b*'],
- },
- },
- ],
- run_as: ['elastic'],
- },
- kibana: [
- {
- spaces: ['*'],
- base: ['all'],
- feature: {},
- },
- ],
- };
-
- const features: Feature[] = buildFeatures();
- const mockHttpClient = jest.fn();
- const indexPatterns: string[] = ['foo*', 'bar*'];
- const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
- const builtinESPrivileges = buildBuiltinESPrivileges();
- const uiCapabilities: UICapabilities = buildUICapabilities();
-
- const wrapper = mountWithIntl(
-
- );
-
- expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1);
- expectSaveFormButtons(wrapper);
- });
-
- it('does not care if user cannot manage spaces', () => {
- const role: Role = {
- name: 'my custom role',
- metadata: {},
- elasticsearch: {
- cluster: ['all'],
- indices: [],
- run_as: ['*'],
- },
- kibana: [
- {
- spaces: ['*'],
- base: ['all'],
- feature: {},
- },
- ],
- };
-
- const features: Feature[] = buildFeatures();
- const mockHttpClient = jest.fn();
- const indexPatterns: string[] = ['foo*', 'bar*'];
- const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
- const builtinESPrivileges = buildBuiltinESPrivileges();
- const uiCapabilities: UICapabilities = buildUICapabilities(false);
-
- const wrapper = mountWithIntl(
-
- );
-
- expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0);
-
- expect(
- wrapper.find('EuiCallOut[data-test-subj="userCannotManageSpacesCallout"]')
- ).toHaveLength(0);
-
- expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1);
- expectSaveFormButtons(wrapper);
- });
-
- it('renders a partial read-only view when there is a transform error', () => {
- const role: Role = {
- name: 'my custom role',
- metadata: {},
- elasticsearch: {
- cluster: ['all'],
- indices: [],
- run_as: ['*'],
- },
- kibana: [],
- _transform_error: ['kibana'],
- };
-
- const features: Feature[] = buildFeatures();
- const mockHttpClient = jest.fn();
- const indexPatterns: string[] = ['foo*', 'bar*'];
- const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
- const builtinESPrivileges = buildBuiltinESPrivileges();
- const uiCapabilities: UICapabilities = buildUICapabilities(false);
-
- const wrapper = mountWithIntl(
-
- );
-
- expect(wrapper.find(TransformErrorSection)).toHaveLength(1);
- expectReadOnlyFormButtons(wrapper);
- });
- });
-});
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/edit_role_page.tsx b/x-pack/legacy/plugins/security/public/views/management/edit_role/components/edit_role_page.tsx
deleted file mode 100644
index 2ba012afa689d..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/edit_role_page.tsx
+++ /dev/null
@@ -1,409 +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 {
- EuiButton,
- EuiButtonEmpty,
- EuiFieldText,
- EuiFlexGroup,
- EuiFlexItem,
- EuiForm,
- EuiFormRow,
- EuiPanel,
- EuiSpacer,
- EuiText,
- EuiTitle,
-} from '@elastic/eui';
-import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react';
-import { get } from 'lodash';
-import React, { ChangeEvent, Component, Fragment, HTMLProps } from 'react';
-import { UICapabilities } from 'ui/capabilities';
-import { toastNotifications } from 'ui/notify';
-import { Space } from '../../../../../../spaces/common/model/space';
-import { Feature } from '../../../../../../../../plugins/features/public';
-import {
- KibanaPrivileges,
- RawKibanaPrivileges,
- Role,
- BuiltinESPrivileges,
-} from '../../../../../common/model';
-import {
- isReadOnlyRole,
- isReservedRole,
- copyRole,
- prepareRoleClone,
-} from '../../../../lib/role_utils';
-import { deleteRole, saveRole } from '../../../../objects';
-import { ROLES_PATH } from '../../management_urls';
-import { RoleValidationResult, RoleValidator } from '../lib/validate_role';
-import { DeleteRoleButton } from './delete_role_button';
-import { ElasticsearchPrivileges, KibanaPrivilegesRegion } from './privileges';
-import { ReservedRoleBadge } from './reserved_role_badge';
-
-interface Props {
- action: 'edit' | 'clone';
- role: Role;
- runAsUsers: string[];
- indexPatterns: string[];
- httpClient: any;
- allowDocumentLevelSecurity: boolean;
- allowFieldLevelSecurity: boolean;
- kibanaPrivileges: RawKibanaPrivileges;
- builtinESPrivileges: BuiltinESPrivileges;
- spaces?: Space[];
- spacesEnabled: boolean;
- intl: InjectedIntl;
- uiCapabilities: UICapabilities;
- features: Feature[];
-}
-
-interface State {
- role: Role;
- formError: RoleValidationResult | null;
-}
-
-class EditRolePageUI extends Component {
- private validator: RoleValidator;
-
- constructor(props: Props) {
- super(props);
-
- this.validator = new RoleValidator({ shouldValidate: false });
-
- let role: Role;
- if (props.action === 'clone') {
- role = prepareRoleClone(props.role);
- } else {
- role = copyRole(props.role);
- }
-
- this.state = {
- role,
- formError: null,
- };
- }
-
- public componentDidMount() {
- if (this.props.action === 'clone' && isReservedRole(this.props.role)) {
- this.backToRoleList();
- }
- }
-
- public render() {
- const description = this.props.spacesEnabled ? (
-
- ) : (
-
- );
-
- return (
-
-
- {this.getFormTitle()}
-
-
-
- {description}
-
- {isReservedRole(this.state.role) && (
-
-
-
-
-
-
-
-
- )}
-
-
-
- {this.getRoleName()}
-
- {this.getElasticsearchPrivileges()}
-
- {this.getKibanaPrivileges()}
-
-
-
- {this.getFormButtons()}
-
-
- );
- }
-
- private getFormTitle = () => {
- let titleText;
- const props: HTMLProps = {
- tabIndex: 0,
- };
- if (isReservedRole(this.state.role)) {
- titleText = (
-
- );
- props['aria-describedby'] = 'reservedRoleDescription';
- } else if (this.editingExistingRole()) {
- titleText = (
-
- );
- } else {
- titleText = (
-
- );
- }
-
- return (
-
-
- {titleText}
-
-
- );
- };
-
- private getActionButton = () => {
- if (this.editingExistingRole() && !isReadOnlyRole(this.state.role)) {
- return (
-
-
-
- );
- }
-
- return null;
- };
-
- private getRoleName = () => {
- return (
-
-
- }
- helpText={
- !isReservedRole(this.state.role) && this.editingExistingRole() ? (
-
- ) : (
- undefined
- )
- }
- {...this.validator.validateRoleName(this.state.role)}
- >
-
-
-
- );
- };
-
- private onNameChange = (e: ChangeEvent) => {
- const rawValue = e.target.value;
- const name = rawValue.replace(/\s/g, '_');
-
- this.setState({
- role: {
- ...this.state.role,
- name,
- },
- });
- };
-
- private getElasticsearchPrivileges() {
- return (
-
-
-
-
- );
- }
-
- private onRoleChange = (role: Role) => {
- this.setState({
- role,
- });
- };
-
- private getKibanaPrivileges = () => {
- return (
-
-
-
-
- );
- };
-
- private getFormButtons = () => {
- if (isReadOnlyRole(this.state.role)) {
- return this.getReturnToRoleListButton();
- }
-
- return (
-
- {this.getSaveButton()}
- {this.getCancelButton()}
-
- {this.getActionButton()}
-
- );
- };
-
- private getReturnToRoleListButton = () => {
- return (
-
-
-
- );
- };
-
- private getSaveButton = () => {
- const saveText = this.editingExistingRole() ? (
-
- ) : (
-
- );
-
- return (
-
- {saveText}
-
- );
- };
-
- private getCancelButton = () => {
- return (
-
-
-
- );
- };
-
- private editingExistingRole = () => {
- return !!this.props.role.name && this.props.action === 'edit';
- };
-
- private saveRole = () => {
- this.validator.enableValidation();
-
- const result = this.validator.validateForSave(this.state.role);
- if (result.isInvalid) {
- this.setState({
- formError: result,
- });
- } else {
- this.setState({
- formError: null,
- });
-
- const { httpClient, intl, spacesEnabled } = this.props;
-
- saveRole(httpClient, this.state.role, spacesEnabled)
- .then(() => {
- toastNotifications.addSuccess(
- intl.formatMessage({
- id: 'xpack.security.management.editRole.roleSuccessfullySavedNotificationMessage',
- defaultMessage: 'Saved role',
- })
- );
- this.backToRoleList();
- })
- .catch((error: any) => {
- toastNotifications.addDanger(get(error, 'data.message'));
- });
- }
- };
-
- private handleDeleteRole = () => {
- const { httpClient, role, intl } = this.props;
-
- deleteRole(httpClient, role.name)
- .then(() => {
- toastNotifications.addSuccess(
- intl.formatMessage({
- id: 'xpack.security.management.editRole.roleSuccessfullyDeletedNotificationMessage',
- defaultMessage: 'Deleted role',
- })
- );
- this.backToRoleList();
- })
- .catch((error: any) => {
- toastNotifications.addDanger(get(error, 'data.message'));
- });
- };
-
- private backToRoleList = () => {
- window.location.hash = ROLES_PATH;
- };
-}
-
-export const EditRolePage = injectI18n(EditRolePageUI);
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/elasticsearch_privileges.test.tsx b/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/elasticsearch_privileges.test.tsx
deleted file mode 100644
index 5ba3d1daf61ac..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/elasticsearch_privileges.test.tsx
+++ /dev/null
@@ -1,96 +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 React from 'react';
-import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
-import { RoleValidator } from '../../../lib/validate_role';
-import { ClusterPrivileges } from './cluster_privileges';
-import { ElasticsearchPrivileges } from './elasticsearch_privileges';
-import { IndexPrivileges } from './index_privileges';
-
-test('it renders without crashing', () => {
- const props = {
- role: {
- name: '',
- elasticsearch: {
- cluster: [],
- indices: [],
- run_as: [],
- },
- kibana: [],
- },
- editable: true,
- httpClient: jest.fn(),
- onChange: jest.fn(),
- runAsUsers: [],
- indexPatterns: [],
- allowDocumentLevelSecurity: true,
- allowFieldLevelSecurity: true,
- validator: new RoleValidator(),
- builtinESPrivileges: {
- cluster: ['all', 'manage', 'monitor'],
- index: ['all', 'read', 'write', 'index'],
- },
- };
- const wrapper = shallowWithIntl();
- expect(wrapper).toMatchSnapshot();
-});
-
-test('it renders ClusterPrivileges', () => {
- const props = {
- role: {
- name: '',
- elasticsearch: {
- cluster: [],
- indices: [],
- run_as: [],
- },
- kibana: [],
- },
- editable: true,
- httpClient: jest.fn(),
- onChange: jest.fn(),
- runAsUsers: [],
- indexPatterns: [],
- allowDocumentLevelSecurity: true,
- allowFieldLevelSecurity: true,
- validator: new RoleValidator(),
- builtinESPrivileges: {
- cluster: ['all', 'manage', 'monitor'],
- index: ['all', 'read', 'write', 'index'],
- },
- };
- const wrapper = mountWithIntl();
- expect(wrapper.find(ClusterPrivileges)).toHaveLength(1);
-});
-
-test('it renders IndexPrivileges', () => {
- const props = {
- role: {
- name: '',
- elasticsearch: {
- cluster: [],
- indices: [],
- run_as: [],
- },
- kibana: [],
- },
- editable: true,
- httpClient: jest.fn(),
- onChange: jest.fn(),
- runAsUsers: [],
- indexPatterns: [],
- allowDocumentLevelSecurity: true,
- allowFieldLevelSecurity: true,
- validator: new RoleValidator(),
- builtinESPrivileges: {
- cluster: ['all', 'manage', 'monitor'],
- index: ['all', 'read', 'write', 'index'],
- },
- };
- const wrapper = mountWithIntl();
- expect(wrapper.find(IndexPrivileges)).toHaveLength(1);
-});
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/edit_role.html b/x-pack/legacy/plugins/security/public/views/management/edit_role/edit_role.html
deleted file mode 100644
index ca4073dcad6f5..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/edit_role.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/index.js b/x-pack/legacy/plugins/security/public/views/management/edit_role/index.js
deleted file mode 100644
index 27c9beb4ba828..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/index.js
+++ /dev/null
@@ -1,176 +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 { capabilities } from 'ui/capabilities';
-import { kfetch } from 'ui/kfetch';
-import { fatalError, toastNotifications } from 'ui/notify';
-import { npStart } from 'ui/new_platform';
-import template from 'plugins/security/views/management/edit_role/edit_role.html';
-import 'plugins/security/services/shield_role';
-import 'plugins/security/services/shield_indices';
-import { xpackInfo } from 'plugins/xpack_main/services/xpack_info';
-import { UserAPIClient } from '../../../lib/api';
-import { ROLES_PATH, CLONE_ROLES_PATH, EDIT_ROLES_PATH } from '../management_urls';
-import { getEditRoleBreadcrumbs, getCreateRoleBreadcrumbs } from '../breadcrumbs';
-
-import { EditRolePage } from './components';
-
-import React from 'react';
-import { render, unmountComponentAtNode } from 'react-dom';
-import { I18nContext } from 'ui/i18n';
-import { i18n } from '@kbn/i18n';
-
-const routeDefinition = action => ({
- template,
- k7Breadcrumbs: ($injector, $route) =>
- $injector.invoke(
- action === 'edit' && $route.current.params.name
- ? getEditRoleBreadcrumbs
- : getCreateRoleBreadcrumbs
- ),
- resolve: {
- role($route, ShieldRole, Promise, kbnUrl) {
- const name = $route.current.params.name;
-
- let role;
-
- if (name != null) {
- role = ShieldRole.get({ name }).$promise.catch(response => {
- if (response.status === 404) {
- toastNotifications.addDanger({
- title: i18n.translate('xpack.security.management.roles.roleNotFound', {
- defaultMessage: 'No "{roleName}" role found.',
- values: { roleName: name },
- }),
- });
- kbnUrl.redirect(ROLES_PATH);
- } else {
- return fatalError(response);
- }
- });
- } else {
- role = Promise.resolve(
- new ShieldRole({
- elasticsearch: {
- cluster: [],
- indices: [],
- run_as: [],
- },
- kibana: [],
- _unrecognized_applications: [],
- })
- );
- }
-
- return role.then(res => res.toJSON());
- },
- users() {
- return new UserAPIClient().getUsers().then(users => _.map(users, 'username'));
- },
- indexPatterns() {
- return npStart.plugins.data.indexPatterns.getTitles();
- },
- spaces(spacesEnabled) {
- if (spacesEnabled) {
- return kfetch({ method: 'get', pathname: '/api/spaces/space' });
- }
- return [];
- },
- kibanaPrivileges() {
- return kfetch({
- method: 'get',
- pathname: '/api/security/privileges',
- query: { includeActions: true },
- });
- },
- builtinESPrivileges() {
- return kfetch({ method: 'get', pathname: '/internal/security/esPrivileges/builtin' });
- },
- features() {
- return kfetch({ method: 'get', pathname: '/api/features' }).catch(e => {
- // TODO: This check can be removed once all of these `resolve` entries are moved out of Angular and into the React app.
- const unauthorizedForFeatures = _.get(e, 'body.statusCode') === 404;
- if (unauthorizedForFeatures) {
- return [];
- }
- throw e;
- });
- },
- },
- controllerAs: 'editRole',
- controller($injector, $scope, $http, enableSpaceAwarePrivileges) {
- const $route = $injector.get('$route');
- const role = $route.current.locals.role;
-
- const allowDocumentLevelSecurity = xpackInfo.get(
- 'features.security.allowRoleDocumentLevelSecurity'
- );
- const allowFieldLevelSecurity = xpackInfo.get('features.security.allowRoleFieldLevelSecurity');
- if (role.elasticsearch.indices.length === 0) {
- const emptyOption = {
- names: [],
- privileges: [],
- };
-
- if (allowFieldLevelSecurity) {
- emptyOption.field_security = {
- grant: ['*'],
- except: [],
- };
- }
-
- if (allowDocumentLevelSecurity) {
- emptyOption.query = '';
- }
-
- role.elasticsearch.indices.push(emptyOption);
- }
-
- const {
- users,
- indexPatterns,
- spaces,
- kibanaPrivileges,
- builtinESPrivileges,
- features,
- } = $route.current.locals;
-
- $scope.$$postDigest(async () => {
- const domNode = document.getElementById('editRoleReactRoot');
-
- render(
-
-
- ,
- domNode
- );
-
- // unmount react on controller destroy
- $scope.$on('$destroy', () => {
- unmountComponentAtNode(domNode);
- });
- });
- },
-});
-
-routes.when(`${CLONE_ROLES_PATH}/:name`, routeDefinition('clone'));
-routes.when(`${EDIT_ROLES_PATH}/:name?`, routeDefinition('edit'));
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_user/_index.scss b/x-pack/legacy/plugins/security/public/views/management/edit_user/_index.scss
deleted file mode 100644
index c5da74aa3f785..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/edit_user/_index.scss
+++ /dev/null
@@ -1 +0,0 @@
-@import './users';
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_user/edit_user.html b/x-pack/legacy/plugins/security/public/views/management/edit_user/edit_user.html
deleted file mode 100644
index 4fa2768480874..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/edit_user/edit_user.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_user/edit_user.js b/x-pack/legacy/plugins/security/public/views/management/edit_user/edit_user.js
deleted file mode 100644
index ab218022c6ee6..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/edit_user/edit_user.js
+++ /dev/null
@@ -1,58 +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 routes from 'ui/routes';
-import template from 'plugins/security/views/management/edit_user/edit_user.html';
-import 'angular-resource';
-import 'ui/angular_ui_select';
-import 'plugins/security/services/shield_role';
-import { EDIT_USERS_PATH } from '../management_urls';
-import { EditUserPage } from './components';
-import { UserAPIClient } from '../../../lib/api';
-import React from 'react';
-import { render, unmountComponentAtNode } from 'react-dom';
-import { I18nContext } from 'ui/i18n';
-import { npSetup } from 'ui/new_platform';
-import { getEditUserBreadcrumbs, getCreateUserBreadcrumbs } from '../breadcrumbs';
-
-const renderReact = (elem, changeUrl, username) => {
- render(
-
-
- ,
- elem
- );
-};
-
-routes.when(`${EDIT_USERS_PATH}/:username?`, {
- template,
- k7Breadcrumbs: ($injector, $route) =>
- $injector.invoke(
- $route.current.params.username ? getEditUserBreadcrumbs : getCreateUserBreadcrumbs
- ),
- controllerAs: 'editUser',
- controller($scope, $route, kbnUrl) {
- $scope.$on('$destroy', () => {
- const elem = document.getElementById('editUserReactRoot');
- if (elem) {
- unmountComponentAtNode(elem);
- }
- });
- $scope.$$postDigest(() => {
- const elem = document.getElementById('editUserReactRoot');
- const username = $route.current.params.username;
- const changeUrl = url => {
- kbnUrl.change(url);
- $scope.$apply();
- };
- renderReact(elem, changeUrl, username);
- });
- },
-});
diff --git a/x-pack/legacy/plugins/security/public/views/management/management.js b/x-pack/legacy/plugins/security/public/views/management/management.js
deleted file mode 100644
index f0369f232aeba..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/management.js
+++ /dev/null
@@ -1,134 +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 'plugins/security/views/management/change_password_form/change_password_form';
-import 'plugins/security/views/management/password_form/password_form';
-import 'plugins/security/views/management/users_grid/users';
-import 'plugins/security/views/management/roles_grid/roles';
-import 'plugins/security/views/management/api_keys_grid/api_keys';
-import 'plugins/security/views/management/edit_user/edit_user';
-import 'plugins/security/views/management/edit_role/index';
-import 'plugins/security/views/management/role_mappings/role_mappings_grid';
-import 'plugins/security/views/management/role_mappings/edit_role_mapping';
-import routes from 'ui/routes';
-import { xpackInfo } from 'plugins/xpack_main/services/xpack_info';
-import { ROLES_PATH, USERS_PATH, API_KEYS_PATH, ROLE_MAPPINGS_PATH } from './management_urls';
-
-import { management } from 'ui/management';
-import { npSetup } from 'ui/new_platform';
-import { i18n } from '@kbn/i18n';
-import { toastNotifications } from 'ui/notify';
-
-routes
- .defaults(/^\/management\/security(\/|$)/, {
- resolve: {
- showLinks(kbnUrl, Promise) {
- if (!xpackInfo.get('features.security.showLinks')) {
- toastNotifications.addDanger({
- title: xpackInfo.get('features.security.linksMessage'),
- });
- kbnUrl.redirect('/management');
- return Promise.halt();
- }
- },
- },
- })
- .defaults(/\/management/, {
- resolve: {
- securityManagementSection: function() {
- const showSecurityLinks = xpackInfo.get('features.security.showLinks');
- const showRoleMappingsManagementLink = xpackInfo.get(
- 'features.security.showRoleMappingsManagement'
- );
-
- function deregisterSecurity() {
- management.deregister('security');
- }
-
- function deregisterRoleMappingsManagement() {
- if (management.hasItem('security')) {
- const security = management.getSection('security');
- if (security.hasItem('roleMappings')) {
- security.deregister('roleMappings');
- }
- }
- }
-
- function ensureSecurityRegistered() {
- const registerSecurity = () =>
- management.register('security', {
- display: i18n.translate('xpack.security.management.securityTitle', {
- defaultMessage: 'Security',
- }),
- order: 100,
- icon: 'securityApp',
- });
- const getSecurity = () => management.getSection('security');
-
- const security = management.hasItem('security') ? getSecurity() : registerSecurity();
-
- if (!security.hasItem('users')) {
- security.register('users', {
- name: 'securityUsersLink',
- order: 10,
- display: i18n.translate('xpack.security.management.usersTitle', {
- defaultMessage: 'Users',
- }),
- url: `#${USERS_PATH}`,
- });
- }
-
- if (!security.hasItem('roles')) {
- security.register('roles', {
- name: 'securityRolesLink',
- order: 20,
- display: i18n.translate('xpack.security.management.rolesTitle', {
- defaultMessage: 'Roles',
- }),
- url: `#${ROLES_PATH}`,
- });
- }
-
- if (!security.hasItem('apiKeys')) {
- security.register('apiKeys', {
- name: 'securityApiKeysLink',
- order: 30,
- display: i18n.translate('xpack.security.management.apiKeysTitle', {
- defaultMessage: 'API Keys',
- }),
- url: `#${API_KEYS_PATH}`,
- });
- }
-
- if (showRoleMappingsManagementLink && !security.hasItem('roleMappings')) {
- security.register('roleMappings', {
- name: 'securityRoleMappingLink',
- order: 30,
- display: i18n.translate('xpack.security.management.roleMappingsTitle', {
- defaultMessage: 'Role Mappings',
- }),
- url: `#${ROLE_MAPPINGS_PATH}`,
- });
- }
- }
-
- if (!showSecurityLinks) {
- deregisterSecurity();
- } else {
- if (!showRoleMappingsManagementLink) {
- deregisterRoleMappingsManagement();
- }
-
- // getCurrentUser will reject if there is no authenticated user, so we prevent them from
- // seeing the security management screens.
- return npSetup.plugins.security.authc
- .getCurrentUser()
- .then(ensureSecurityRegistered)
- .catch(deregisterSecurity);
- }
- },
- },
- });
diff --git a/x-pack/legacy/plugins/security/public/views/management/password_form/password_form.html b/x-pack/legacy/plugins/security/public/views/management/password_form/password_form.html
deleted file mode 100644
index 72956992100f5..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/password_form/password_form.html
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-
-
-
-
diff --git a/x-pack/legacy/plugins/security/public/views/management/password_form/password_form.js b/x-pack/legacy/plugins/security/public/views/management/password_form/password_form.js
deleted file mode 100644
index edcccdb5e6e69..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/password_form/password_form.js
+++ /dev/null
@@ -1,24 +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 { uiModules } from 'ui/modules';
-import template from './password_form.html';
-
-const module = uiModules.get('security', ['kibana']);
-module.directive('kbnPasswordForm', function() {
- return {
- template,
- scope: {
- password: '=',
- },
- restrict: 'E',
- replace: true,
- controllerAs: 'passwordController',
- controller: function() {
- this.confirmation = null;
- },
- };
-});
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/_index.scss b/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/_index.scss
deleted file mode 100644
index 80e08ebcf1226..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/_index.scss
+++ /dev/null
@@ -1 +0,0 @@
-@import './components/rule_editor_panel/index';
\ No newline at end of file
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/edit_role_mapping_page.test.tsx b/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/edit_role_mapping_page.test.tsx
deleted file mode 100644
index 375a8d9f374a8..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/edit_role_mapping_page.test.tsx
+++ /dev/null
@@ -1,341 +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 React from 'react';
-import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers';
-import { findTestSubject } from 'test_utils/find_test_subject';
-
-// brace/ace uses the Worker class, which is not currently provided by JSDOM.
-// This is not required for the tests to pass, but it rather suppresses lengthy
-// warnings in the console which adds unnecessary noise to the test output.
-import 'test_utils/stub_web_worker';
-
-import { RoleMappingsAPI } from '../../../../../lib/role_mappings_api';
-import { EditRoleMappingPage } from '.';
-import { NoCompatibleRealms, SectionLoading, PermissionDenied } from '../../components';
-import { VisualRuleEditor } from './rule_editor_panel/visual_rule_editor';
-import { JSONRuleEditor } from './rule_editor_panel/json_rule_editor';
-import { EuiComboBox } from '@elastic/eui';
-
-jest.mock('../../../../../lib/roles_api', () => {
- return {
- RolesApi: {
- getRoles: () => Promise.resolve([{ name: 'foo_role' }, { name: 'bar role' }]),
- },
- };
-});
-
-describe('EditRoleMappingPage', () => {
- it('allows a role mapping to be created', async () => {
- const roleMappingsAPI = ({
- saveRoleMapping: jest.fn().mockResolvedValue(null),
- checkRoleMappingFeatures: jest.fn().mockResolvedValue({
- canManageRoleMappings: true,
- hasCompatibleRealms: true,
- canUseInlineScripts: true,
- canUseStoredScripts: true,
- }),
- } as unknown) as RoleMappingsAPI;
-
- const wrapper = mountWithIntl();
-
- await nextTick();
- wrapper.update();
-
- findTestSubject(wrapper, 'roleMappingFormNameInput').simulate('change', {
- target: { value: 'my-role-mapping' },
- });
-
- (wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="roleMappingFormRoleComboBox"]')
- .props() as any).onChange([{ label: 'foo_role' }]);
-
- findTestSubject(wrapper, 'roleMappingsAddRuleButton').simulate('click');
-
- findTestSubject(wrapper, 'saveRoleMappingButton').simulate('click');
-
- expect(roleMappingsAPI.saveRoleMapping).toHaveBeenCalledWith({
- name: 'my-role-mapping',
- enabled: true,
- roles: ['foo_role'],
- role_templates: [],
- rules: {
- all: [{ field: { username: '*' } }],
- },
- metadata: {},
- });
- });
-
- it('allows a role mapping to be updated', async () => {
- const roleMappingsAPI = ({
- saveRoleMapping: jest.fn().mockResolvedValue(null),
- getRoleMapping: jest.fn().mockResolvedValue({
- name: 'foo',
- role_templates: [
- {
- template: { id: 'foo' },
- },
- ],
- enabled: true,
- rules: {
- any: [{ field: { 'metadata.someCustomOption': [false, true, 'asdf'] } }],
- },
- metadata: {
- foo: 'bar',
- bar: 'baz',
- },
- }),
- checkRoleMappingFeatures: jest.fn().mockResolvedValue({
- canManageRoleMappings: true,
- hasCompatibleRealms: true,
- canUseInlineScripts: true,
- canUseStoredScripts: true,
- }),
- } as unknown) as RoleMappingsAPI;
-
- const wrapper = mountWithIntl(
-
- );
-
- await nextTick();
- wrapper.update();
-
- findTestSubject(wrapper, 'switchToRolesButton').simulate('click');
-
- (wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="roleMappingFormRoleComboBox"]')
- .props() as any).onChange([{ label: 'foo_role' }]);
-
- findTestSubject(wrapper, 'roleMappingsAddRuleButton').simulate('click');
- wrapper.find('button[id="addRuleOption"]').simulate('click');
-
- findTestSubject(wrapper, 'saveRoleMappingButton').simulate('click');
-
- expect(roleMappingsAPI.saveRoleMapping).toHaveBeenCalledWith({
- name: 'foo',
- enabled: true,
- roles: ['foo_role'],
- role_templates: [],
- rules: {
- any: [
- { field: { 'metadata.someCustomOption': [false, true, 'asdf'] } },
- { field: { username: '*' } },
- ],
- },
- metadata: {
- foo: 'bar',
- bar: 'baz',
- },
- });
- });
-
- it('renders a permission denied message when unauthorized to manage role mappings', async () => {
- const roleMappingsAPI = ({
- checkRoleMappingFeatures: jest.fn().mockResolvedValue({
- canManageRoleMappings: false,
- hasCompatibleRealms: true,
- }),
- } as unknown) as RoleMappingsAPI;
-
- const wrapper = mountWithIntl();
- expect(wrapper.find(SectionLoading)).toHaveLength(1);
- expect(wrapper.find(PermissionDenied)).toHaveLength(0);
-
- await nextTick();
- wrapper.update();
-
- expect(wrapper.find(SectionLoading)).toHaveLength(0);
- expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0);
- expect(wrapper.find(PermissionDenied)).toHaveLength(1);
- });
-
- it('renders a warning when there are no compatible realms enabled', async () => {
- const roleMappingsAPI = ({
- checkRoleMappingFeatures: jest.fn().mockResolvedValue({
- canManageRoleMappings: true,
- hasCompatibleRealms: false,
- }),
- } as unknown) as RoleMappingsAPI;
-
- const wrapper = mountWithIntl();
- expect(wrapper.find(SectionLoading)).toHaveLength(1);
- expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0);
-
- await nextTick();
- wrapper.update();
-
- expect(wrapper.find(SectionLoading)).toHaveLength(0);
- expect(wrapper.find(NoCompatibleRealms)).toHaveLength(1);
- });
-
- it('renders a warning when editing a mapping with a stored role template, when stored scripts are disabled', async () => {
- const roleMappingsAPI = ({
- getRoleMapping: jest.fn().mockResolvedValue({
- name: 'foo',
- role_templates: [
- {
- template: { id: 'foo' },
- },
- ],
- enabled: true,
- rules: {
- field: { username: '*' },
- },
- }),
- checkRoleMappingFeatures: jest.fn().mockResolvedValue({
- canManageRoleMappings: true,
- hasCompatibleRealms: true,
- canUseInlineScripts: true,
- canUseStoredScripts: false,
- }),
- } as unknown) as RoleMappingsAPI;
-
- const wrapper = mountWithIntl(
-
- );
-
- expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(0);
- expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(0);
-
- await nextTick();
- wrapper.update();
-
- expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(0);
- expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(1);
- });
-
- it('renders a warning when editing a mapping with an inline role template, when inline scripts are disabled', async () => {
- const roleMappingsAPI = ({
- getRoleMapping: jest.fn().mockResolvedValue({
- name: 'foo',
- role_templates: [
- {
- template: { source: 'foo' },
- },
- ],
- enabled: true,
- rules: {
- field: { username: '*' },
- },
- }),
- checkRoleMappingFeatures: jest.fn().mockResolvedValue({
- canManageRoleMappings: true,
- hasCompatibleRealms: true,
- canUseInlineScripts: false,
- canUseStoredScripts: true,
- }),
- } as unknown) as RoleMappingsAPI;
-
- const wrapper = mountWithIntl(
-
- );
-
- expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(0);
- expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(0);
-
- await nextTick();
- wrapper.update();
-
- expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(1);
- expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(0);
- });
-
- it('renders the visual editor by default for simple rule sets', async () => {
- const roleMappingsAPI = ({
- getRoleMapping: jest.fn().mockResolvedValue({
- name: 'foo',
- roles: ['superuser'],
- enabled: true,
- rules: {
- all: [
- {
- field: {
- username: '*',
- },
- },
- {
- field: {
- dn: null,
- },
- },
- {
- field: {
- realm: ['ldap', 'pki', null, 12],
- },
- },
- ],
- },
- }),
- checkRoleMappingFeatures: jest.fn().mockResolvedValue({
- canManageRoleMappings: true,
- hasCompatibleRealms: true,
- canUseInlineScripts: true,
- canUseStoredScripts: true,
- }),
- } as unknown) as RoleMappingsAPI;
-
- const wrapper = mountWithIntl(
-
- );
-
- await nextTick();
- wrapper.update();
-
- expect(wrapper.find(VisualRuleEditor)).toHaveLength(1);
- expect(wrapper.find(JSONRuleEditor)).toHaveLength(0);
- });
-
- it('renders the JSON editor by default for complex rule sets', async () => {
- const createRule = (depth: number): Record => {
- if (depth > 0) {
- const rule = {
- all: [
- {
- field: {
- username: '*',
- },
- },
- ],
- } as Record;
-
- const subRule = createRule(depth - 1);
- if (subRule) {
- rule.all.push(subRule);
- }
-
- return rule;
- }
- return null as any;
- };
-
- const roleMappingsAPI = ({
- getRoleMapping: jest.fn().mockResolvedValue({
- name: 'foo',
- roles: ['superuser'],
- enabled: true,
- rules: createRule(10),
- }),
- checkRoleMappingFeatures: jest.fn().mockResolvedValue({
- canManageRoleMappings: true,
- hasCompatibleRealms: true,
- canUseInlineScripts: true,
- canUseStoredScripts: true,
- }),
- } as unknown) as RoleMappingsAPI;
-
- const wrapper = mountWithIntl(
-
- );
-
- await nextTick();
- wrapper.update();
-
- expect(wrapper.find(VisualRuleEditor)).toHaveLength(0);
- expect(wrapper.find(JSONRuleEditor)).toHaveLength(1);
- });
-});
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/edit_role_mapping.html b/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/edit_role_mapping.html
deleted file mode 100644
index ca8ab9c35c49b..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/edit_role_mapping.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/index.tsx b/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/index.tsx
deleted file mode 100644
index b064a4dc50a22..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/index.tsx
+++ /dev/null
@@ -1,45 +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 React from 'react';
-import { render, unmountComponentAtNode } from 'react-dom';
-import routes from 'ui/routes';
-import { I18nContext } from 'ui/i18n';
-import { npSetup } from 'ui/new_platform';
-import { RoleMappingsAPI } from '../../../../lib/role_mappings_api';
-// @ts-ignore
-import template from './edit_role_mapping.html';
-import { CREATE_ROLE_MAPPING_PATH } from '../../management_urls';
-import { getEditRoleMappingBreadcrumbs } from '../../breadcrumbs';
-import { EditRoleMappingPage } from './components';
-
-routes.when(`${CREATE_ROLE_MAPPING_PATH}/:name?`, {
- template,
- k7Breadcrumbs: getEditRoleMappingBreadcrumbs,
- controller($scope, $route) {
- $scope.$$postDigest(() => {
- const domNode = document.getElementById('editRoleMappingReactRoot');
-
- const { name } = $route.current.params;
-
- render(
-
-
- ,
- domNode
- );
-
- // unmount react on controller destroy
- $scope.$on('$destroy', () => {
- if (domNode) {
- unmountComponentAtNode(domNode);
- }
- });
- });
- },
-});
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/role_mappings_grid_page.test.tsx b/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/role_mappings_grid_page.test.tsx
deleted file mode 100644
index 259cdc71e25a2..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/role_mappings_grid_page.test.tsx
+++ /dev/null
@@ -1,182 +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 React from 'react';
-import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers';
-import { RoleMappingsGridPage } from '.';
-import { SectionLoading, PermissionDenied, NoCompatibleRealms } from '../../components';
-import { EmptyPrompt } from './empty_prompt';
-import { findTestSubject } from 'test_utils/find_test_subject';
-import { EuiLink } from '@elastic/eui';
-import { RoleMappingsAPI } from '../../../../../lib/role_mappings_api';
-import { act } from '@testing-library/react';
-
-describe('RoleMappingsGridPage', () => {
- it('renders an empty prompt when no role mappings exist', async () => {
- const roleMappingsAPI = ({
- getRoleMappings: jest.fn().mockResolvedValue([]),
- checkRoleMappingFeatures: jest.fn().mockResolvedValue({
- canManageRoleMappings: true,
- hasCompatibleRealms: true,
- }),
- } as unknown) as RoleMappingsAPI;
-
- const wrapper = mountWithIntl();
- expect(wrapper.find(SectionLoading)).toHaveLength(1);
- expect(wrapper.find(EmptyPrompt)).toHaveLength(0);
-
- await nextTick();
- wrapper.update();
-
- expect(wrapper.find(SectionLoading)).toHaveLength(0);
- expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0);
- expect(wrapper.find(EmptyPrompt)).toHaveLength(1);
- });
-
- it('renders a permission denied message when unauthorized to manage role mappings', async () => {
- const roleMappingsAPI = ({
- checkRoleMappingFeatures: jest.fn().mockResolvedValue({
- canManageRoleMappings: false,
- hasCompatibleRealms: true,
- }),
- } as unknown) as RoleMappingsAPI;
-
- const wrapper = mountWithIntl();
- expect(wrapper.find(SectionLoading)).toHaveLength(1);
- expect(wrapper.find(PermissionDenied)).toHaveLength(0);
-
- await nextTick();
- wrapper.update();
-
- expect(wrapper.find(SectionLoading)).toHaveLength(0);
- expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0);
- expect(wrapper.find(PermissionDenied)).toHaveLength(1);
- });
-
- it('renders a warning when there are no compatible realms enabled', async () => {
- const roleMappingsAPI = ({
- getRoleMappings: jest.fn().mockResolvedValue([
- {
- name: 'some realm',
- enabled: true,
- roles: [],
- rules: { field: { username: '*' } },
- },
- ]),
- checkRoleMappingFeatures: jest.fn().mockResolvedValue({
- canManageRoleMappings: true,
- hasCompatibleRealms: false,
- }),
- } as unknown) as RoleMappingsAPI;
-
- const wrapper = mountWithIntl();
- expect(wrapper.find(SectionLoading)).toHaveLength(1);
- expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0);
-
- await nextTick();
- wrapper.update();
-
- expect(wrapper.find(SectionLoading)).toHaveLength(0);
- expect(wrapper.find(NoCompatibleRealms)).toHaveLength(1);
- });
-
- it('renders links to mapped roles', async () => {
- const roleMappingsAPI = ({
- getRoleMappings: jest.fn().mockResolvedValue([
- {
- name: 'some realm',
- enabled: true,
- roles: ['superuser'],
- rules: { field: { username: '*' } },
- },
- ]),
- checkRoleMappingFeatures: jest.fn().mockResolvedValue({
- canManageRoleMappings: true,
- hasCompatibleRealms: true,
- }),
- } as unknown) as RoleMappingsAPI;
-
- const wrapper = mountWithIntl();
- await nextTick();
- wrapper.update();
-
- const links = findTestSubject(wrapper, 'roleMappingRoles').find(EuiLink);
- expect(links).toHaveLength(1);
- expect(links.at(0).props()).toMatchObject({
- href: '#/management/security/roles/edit/superuser',
- });
- });
-
- it('describes the number of mapped role templates', async () => {
- const roleMappingsAPI = ({
- getRoleMappings: jest.fn().mockResolvedValue([
- {
- name: 'some realm',
- enabled: true,
- role_templates: [{}, {}],
- rules: { field: { username: '*' } },
- },
- ]),
- checkRoleMappingFeatures: jest.fn().mockResolvedValue({
- canManageRoleMappings: true,
- hasCompatibleRealms: true,
- }),
- } as unknown) as RoleMappingsAPI;
-
- const wrapper = mountWithIntl();
- await nextTick();
- wrapper.update();
-
- const templates = findTestSubject(wrapper, 'roleMappingRoles');
- expect(templates).toHaveLength(1);
- expect(templates.text()).toEqual(`2 role templates defined`);
- });
-
- it('allows role mappings to be deleted, refreshing the grid after', async () => {
- const roleMappingsAPI = ({
- getRoleMappings: jest.fn().mockResolvedValue([
- {
- name: 'some-realm',
- enabled: true,
- roles: ['superuser'],
- rules: { field: { username: '*' } },
- },
- ]),
- checkRoleMappingFeatures: jest.fn().mockResolvedValue({
- canManageRoleMappings: true,
- hasCompatibleRealms: true,
- }),
- deleteRoleMappings: jest.fn().mockReturnValue(
- Promise.resolve([
- {
- name: 'some-realm',
- success: true,
- },
- ])
- ),
- } as unknown) as RoleMappingsAPI;
-
- const wrapper = mountWithIntl();
- await nextTick();
- wrapper.update();
-
- expect(roleMappingsAPI.getRoleMappings).toHaveBeenCalledTimes(1);
- expect(roleMappingsAPI.deleteRoleMappings).not.toHaveBeenCalled();
-
- findTestSubject(wrapper, `deleteRoleMappingButton-some-realm`).simulate('click');
- expect(findTestSubject(wrapper, 'deleteRoleMappingConfirmationModal')).toHaveLength(1);
-
- await act(async () => {
- findTestSubject(wrapper, 'confirmModalConfirmButton').simulate('click');
- await nextTick();
- wrapper.update();
- });
-
- expect(roleMappingsAPI.deleteRoleMappings).toHaveBeenCalledWith(['some-realm']);
- // Expect an additional API call to refresh the grid
- expect(roleMappingsAPI.getRoleMappings).toHaveBeenCalledTimes(2);
- });
-});
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/index.tsx b/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/index.tsx
deleted file mode 100644
index 9e925d0fa6dc0..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/index.tsx
+++ /dev/null
@@ -1,40 +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 React from 'react';
-import { render, unmountComponentAtNode } from 'react-dom';
-import routes from 'ui/routes';
-import { I18nContext } from 'ui/i18n';
-import { npSetup } from 'ui/new_platform';
-import { RoleMappingsAPI } from '../../../../lib/role_mappings_api';
-// @ts-ignore
-import template from './role_mappings.html';
-import { ROLE_MAPPINGS_PATH } from '../../management_urls';
-import { getRoleMappingBreadcrumbs } from '../../breadcrumbs';
-import { RoleMappingsGridPage } from './components';
-
-routes.when(ROLE_MAPPINGS_PATH, {
- template,
- k7Breadcrumbs: getRoleMappingBreadcrumbs,
- controller($scope) {
- $scope.$$postDigest(() => {
- const domNode = document.getElementById('roleMappingsGridReactRoot');
-
- render(
-
-
- ,
- domNode
- );
-
- // unmount react on controller destroy
- $scope.$on('$destroy', () => {
- if (domNode) {
- unmountComponentAtNode(domNode);
- }
- });
- });
- },
-});
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/role_mappings.html b/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/role_mappings.html
deleted file mode 100644
index cff3b821d132c..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/role_mappings.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/roles.html b/x-pack/legacy/plugins/security/public/views/management/roles_grid/roles.html
deleted file mode 100644
index 0552b655afafd..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/roles_grid/roles.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/roles.js b/x-pack/legacy/plugins/security/public/views/management/roles_grid/roles.js
deleted file mode 100644
index e9c42824711b3..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/roles_grid/roles.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 React from 'react';
-import { render, unmountComponentAtNode } from 'react-dom';
-import routes from 'ui/routes';
-import template from 'plugins/security/views/management/roles_grid/roles.html';
-import { ROLES_PATH } from '../management_urls';
-import { getRolesBreadcrumbs } from '../breadcrumbs';
-import { I18nContext } from 'ui/i18n';
-import { RolesGridPage } from './components';
-
-routes.when(ROLES_PATH, {
- template,
- k7Breadcrumbs: getRolesBreadcrumbs,
- controller($scope) {
- $scope.$$postDigest(() => {
- const domNode = document.getElementById('rolesGridReactRoot');
-
- render(
-
-
- ,
- domNode
- );
-
- // unmount react on controller destroy
- $scope.$on('$destroy', () => {
- unmountComponentAtNode(domNode);
- });
- });
- },
-});
diff --git a/x-pack/legacy/plugins/security/public/views/management/users_grid/users.html b/x-pack/legacy/plugins/security/public/views/management/users_grid/users.html
deleted file mode 100644
index 3dce7326d001a..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/users_grid/users.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/x-pack/legacy/plugins/security/public/views/management/users_grid/users.js b/x-pack/legacy/plugins/security/public/views/management/users_grid/users.js
deleted file mode 100644
index 8d4e0526251d7..0000000000000
--- a/x-pack/legacy/plugins/security/public/views/management/users_grid/users.js
+++ /dev/null
@@ -1,47 +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 React from 'react';
-import { render, unmountComponentAtNode } from 'react-dom';
-import routes from 'ui/routes';
-import template from 'plugins/security/views/management/users_grid/users.html';
-import { SECURITY_PATH, USERS_PATH } from '../management_urls';
-import { UsersListPage } from './components';
-import { UserAPIClient } from '../../../lib/api';
-import { I18nContext } from 'ui/i18n';
-import { getUsersBreadcrumbs } from '../breadcrumbs';
-
-routes.when(SECURITY_PATH, {
- redirectTo: USERS_PATH,
-});
-
-const renderReact = (elem, changeUrl) => {
- render(
-
-
- ,
- elem
- );
-};
-
-routes.when(USERS_PATH, {
- template,
- k7Breadcrumbs: getUsersBreadcrumbs,
- controller($scope, $http, kbnUrl) {
- $scope.$on('$destroy', () => {
- const elem = document.getElementById('usersReactRoot');
- if (elem) unmountComponentAtNode(elem);
- });
- $scope.$$postDigest(() => {
- const elem = document.getElementById('usersReactRoot');
- const changeUrl = url => {
- kbnUrl.change(url);
- $scope.$apply();
- };
- renderReact(elem, $http, changeUrl);
- });
- },
-});
diff --git a/x-pack/legacy/plugins/security/public/views/overwritten_session/overwritten_session.tsx b/x-pack/legacy/plugins/security/public/views/overwritten_session/overwritten_session.tsx
index fb39c517e1c2c..4c79c499cc0e6 100644
--- a/x-pack/legacy/plugins/security/public/views/overwritten_session/overwritten_session.tsx
+++ b/x-pack/legacy/plugins/security/public/views/overwritten_session/overwritten_session.tsx
@@ -11,8 +11,7 @@ import { render } from 'react-dom';
import chrome from 'ui/chrome';
import { I18nContext } from 'ui/i18n';
import { npSetup } from 'ui/new_platform';
-import { SecurityPluginSetup } from '../../../../../../plugins/security/public';
-import { AuthenticatedUser } from '../../../common/model';
+import { AuthenticatedUser, SecurityPluginSetup } from '../../../../../../plugins/security/public';
import { AuthenticationStatePage } from '../../components/authentication_state_page';
chrome
diff --git a/x-pack/plugins/security/common/model/index.ts b/x-pack/plugins/security/common/model/index.ts
index f3c65ed7e3cf1..121791d113bd5 100644
--- a/x-pack/plugins/security/common/model/index.ts
+++ b/x-pack/plugins/security/common/model/index.ts
@@ -10,7 +10,16 @@ export { AuthenticatedUser, canUserChangePassword } from './authenticated_user';
export { BuiltinESPrivileges } from './builtin_es_privileges';
export { FeaturesPrivileges } from './features_privileges';
export { RawKibanaPrivileges, RawKibanaFeaturePrivileges } from './raw_kibana_privileges';
-export { Role, RoleIndexPrivilege, RoleKibanaPrivilege } from './role';
+export {
+ Role,
+ RoleIndexPrivilege,
+ RoleKibanaPrivilege,
+ copyRole,
+ isReadOnlyRole,
+ isReservedRole,
+ isRoleEnabled,
+ prepareRoleClone,
+} from './role';
export { KibanaPrivileges } from './kibana_privileges';
export {
InlineRoleTemplate,
diff --git a/x-pack/legacy/plugins/security/public/lib/role_utils.test.ts b/x-pack/plugins/security/common/model/role.test.ts
similarity index 96%
rename from x-pack/legacy/plugins/security/public/lib/role_utils.test.ts
rename to x-pack/plugins/security/common/model/role.test.ts
index 9d94017c3f0fe..d4a910a1785eb 100644
--- a/x-pack/legacy/plugins/security/public/lib/role_utils.test.ts
+++ b/x-pack/plugins/security/common/model/role.test.ts
@@ -4,14 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Role } from '../../common/model';
-import {
- copyRole,
- isReadOnlyRole,
- isReservedRole,
- isRoleEnabled,
- prepareRoleClone,
-} from './role_utils';
+import { Role, isReadOnlyRole, isReservedRole, isRoleEnabled, copyRole, prepareRoleClone } from '.';
describe('role', () => {
describe('isRoleEnabled', () => {
diff --git a/x-pack/plugins/security/common/model/role.ts b/x-pack/plugins/security/common/model/role.ts
index 89f68aaa55b5c..1edcf147262ed 100644
--- a/x-pack/plugins/security/common/model/role.ts
+++ b/x-pack/plugins/security/common/model/role.ts
@@ -4,6 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import { cloneDeep } from 'lodash';
import { FeaturesPrivileges } from './features_privileges';
export interface RoleIndexPrivilege {
@@ -40,3 +41,53 @@ export interface Role {
_transform_error?: string[];
_unrecognized_applications?: string[];
}
+
+/**
+ * Returns whether given role is enabled or not
+ *
+ * @param role Object Role JSON, as returned by roles API
+ * @return Boolean true if role is enabled; false otherwise
+ */
+export function isRoleEnabled(role: Partial) {
+ return role.transient_metadata?.enabled ?? true;
+}
+
+/**
+ * Returns whether given role is reserved or not.
+ *
+ * @param role Role as returned by roles API
+ */
+export function isReservedRole(role: Partial) {
+ return (role.metadata?._reserved as boolean) ?? false;
+}
+
+/**
+ * Returns whether given role is editable through the UI or not.
+ *
+ * @param role the Role as returned by roles API
+ */
+export function isReadOnlyRole(role: Partial): boolean {
+ return isReservedRole(role) || (role._transform_error?.length ?? 0) > 0;
+}
+
+/**
+ * Returns a deep copy of the role.
+ *
+ * @param role the Role to copy.
+ */
+export function copyRole(role: Role) {
+ return cloneDeep(role);
+}
+
+/**
+ * Creates a deep copy of the role suitable for cloning.
+ *
+ * @param role the Role to clone.
+ */
+export function prepareRoleClone(role: Role): Role {
+ const clone = copyRole(role);
+
+ clone.name = '';
+
+ return clone;
+}
diff --git a/x-pack/plugins/security/kibana.json b/x-pack/plugins/security/kibana.json
index 32f860b1423d3..7d1940e393bec 100644
--- a/x-pack/plugins/security/kibana.json
+++ b/x-pack/plugins/security/kibana.json
@@ -3,7 +3,8 @@
"version": "8.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack", "security"],
- "requiredPlugins": ["features", "licensing"],
+ "requiredPlugins": ["data", "features", "licensing"],
+ "optionalPlugins": ["home", "management"],
"server": true,
"ui": true
}
diff --git a/x-pack/plugins/security/public/_index.scss b/x-pack/plugins/security/public/_index.scss
new file mode 100644
index 0000000000000..9fa81bad7c3f4
--- /dev/null
+++ b/x-pack/plugins/security/public/_index.scss
@@ -0,0 +1,2 @@
+// Management styles
+@import './management/index';
diff --git a/x-pack/legacy/plugins/security/public/views/account/components/account_management_page.test.tsx b/x-pack/plugins/security/public/account_management/account_management_page.test.tsx
similarity index 72%
rename from x-pack/legacy/plugins/security/public/views/account/components/account_management_page.test.tsx
rename to x-pack/plugins/security/public/account_management/account_management_page.test.tsx
index 366842e58e9e4..b7cf8e6dd1418 100644
--- a/x-pack/legacy/plugins/security/public/views/account/components/account_management_page.test.tsx
+++ b/x-pack/plugins/security/public/account_management/account_management_page.test.tsx
@@ -6,11 +6,12 @@
import React from 'react';
import { act } from '@testing-library/react';
import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers';
-import { securityMock } from '../../../../../../../plugins/security/public/mocks';
+import { AuthenticatedUser } from '../../common/model';
import { AccountManagementPage } from './account_management_page';
-import { AuthenticatedUser } from '../../../../common/model';
-jest.mock('ui/kfetch');
+import { coreMock } from 'src/core/public/mocks';
+import { securityMock } from '../mocks';
+import { userAPIClientMock } from '../management/users/index.mock';
interface Options {
withFullName?: boolean;
@@ -45,7 +46,11 @@ describe('', () => {
it(`displays users full name, username, and email address`, async () => {
const user = createUser();
const wrapper = mountWithIntl(
-
+
);
await act(async () => {
@@ -63,7 +68,11 @@ describe('', () => {
it(`displays username when full_name is not provided`, async () => {
const user = createUser({ withFullName: false });
const wrapper = mountWithIntl(
-
+
);
await act(async () => {
@@ -77,7 +86,11 @@ describe('', () => {
it(`displays a placeholder when no email address is provided`, async () => {
const user = createUser({ withEmail: false });
const wrapper = mountWithIntl(
-
+
);
await act(async () => {
@@ -91,7 +104,11 @@ describe('', () => {
it(`displays change password form for users in the native realm`, async () => {
const user = createUser();
const wrapper = mountWithIntl(
-
+
);
await act(async () => {
@@ -106,7 +123,11 @@ describe('', () => {
it(`does not display change password form for users in the saml realm`, async () => {
const user = createUser({ realm: 'saml' });
const wrapper = mountWithIntl(
-
+
);
await act(async () => {
diff --git a/x-pack/legacy/plugins/security/public/views/account/components/account_management_page.tsx b/x-pack/plugins/security/public/account_management/account_management_page.tsx
similarity index 62%
rename from x-pack/legacy/plugins/security/public/views/account/components/account_management_page.tsx
rename to x-pack/plugins/security/public/account_management/account_management_page.tsx
index 6abee73e0b353..3f764adc7949f 100644
--- a/x-pack/legacy/plugins/security/public/views/account/components/account_management_page.tsx
+++ b/x-pack/plugins/security/public/account_management/account_management_page.tsx
@@ -5,20 +5,24 @@
*/
import { EuiPage, EuiPageBody, EuiPanel, EuiSpacer, EuiText } from '@elastic/eui';
import React, { useEffect, useState } from 'react';
-import { SecurityPluginSetup } from '../../../../../../../plugins/security/public';
-import { getUserDisplayName, AuthenticatedUser } from '../../../../common/model';
+import { NotificationsStart } from 'src/core/public';
+import { getUserDisplayName, AuthenticatedUser } from '../../common/model';
+import { AuthenticationServiceSetup } from '../authentication';
import { ChangePassword } from './change_password';
+import { UserAPIClient } from '../management';
import { PersonalInfo } from './personal_info';
interface Props {
- securitySetup: SecurityPluginSetup;
+ authc: AuthenticationServiceSetup;
+ apiClient: PublicMethodsOf;
+ notifications: NotificationsStart;
}
-export const AccountManagementPage = (props: Props) => {
+export const AccountManagementPage = ({ apiClient, authc, notifications }: Props) => {
const [currentUser, setCurrentUser] = useState(null);
useEffect(() => {
- props.securitySetup.authc.getCurrentUser().then(setCurrentUser);
- }, [props]);
+ authc.getCurrentUser().then(setCurrentUser);
+ }, [authc]);
if (!currentUser) {
return null;
@@ -36,7 +40,7 @@ export const AccountManagementPage = (props: Props) => {
-
+
diff --git a/x-pack/legacy/plugins/security/public/views/account/components/change_password/change_password.tsx b/x-pack/plugins/security/public/account_management/change_password/change_password.tsx
similarity index 81%
rename from x-pack/legacy/plugins/security/public/views/account/components/change_password/change_password.tsx
rename to x-pack/plugins/security/public/account_management/change_password/change_password.tsx
index 63abb4539470d..f5ac5f3b21d2e 100644
--- a/x-pack/legacy/plugins/security/public/views/account/components/change_password/change_password.tsx
+++ b/x-pack/plugins/security/public/account_management/change_password/change_password.tsx
@@ -3,18 +3,18 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import {
- // @ts-ignore
- EuiDescribedFormGroup,
-} from '@elastic/eui';
-import { FormattedMessage } from '@kbn/i18n/react';
import React, { Component } from 'react';
-import { UserAPIClient } from '../../../../lib/api';
-import { AuthenticatedUser, canUserChangePassword } from '../../../../../common/model';
-import { ChangePasswordForm } from '../../../../components/management/change_password_form';
+import { EuiDescribedFormGroup } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { NotificationsSetup } from 'src/core/public';
+import { AuthenticatedUser, canUserChangePassword } from '../../../common/model';
+import { UserAPIClient } from '../../management/users';
+import { ChangePasswordForm } from '../../management/users/components/change_password_form';
interface Props {
user: AuthenticatedUser;
+ apiClient: PublicMethodsOf;
+ notifications: NotificationsSetup;
}
export class ChangePassword extends Component {
@@ -48,7 +48,8 @@ export class ChangePassword extends Component {
);
diff --git a/x-pack/legacy/plugins/security/public/views/account/components/change_password/index.ts b/x-pack/plugins/security/public/account_management/change_password/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/account/components/change_password/index.ts
rename to x-pack/plugins/security/public/account_management/change_password/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/account/components/index.ts b/x-pack/plugins/security/public/account_management/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/account/components/index.ts
rename to x-pack/plugins/security/public/account_management/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/account/components/personal_info/index.ts b/x-pack/plugins/security/public/account_management/personal_info/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/account/components/personal_info/index.ts
rename to x-pack/plugins/security/public/account_management/personal_info/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/account/components/personal_info/personal_info.tsx b/x-pack/plugins/security/public/account_management/personal_info/personal_info.tsx
similarity index 89%
rename from x-pack/legacy/plugins/security/public/views/account/components/personal_info/personal_info.tsx
rename to x-pack/plugins/security/public/account_management/personal_info/personal_info.tsx
index 7121bf7ab28ee..9cbbc242e8400 100644
--- a/x-pack/legacy/plugins/security/public/views/account/components/personal_info/personal_info.tsx
+++ b/x-pack/plugins/security/public/account_management/personal_info/personal_info.tsx
@@ -3,15 +3,10 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import {
- // @ts-ignore
- EuiDescribedFormGroup,
- EuiFormRow,
- EuiText,
-} from '@elastic/eui';
-import { FormattedMessage } from '@kbn/i18n/react';
import React from 'react';
-import { AuthenticatedUser } from '../../../../../common/model';
+import { EuiDescribedFormGroup, EuiFormRow, EuiText } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { AuthenticatedUser } from '../../../common/model';
interface Props {
user: AuthenticatedUser;
diff --git a/x-pack/plugins/security/public/management/_index.scss b/x-pack/plugins/security/public/management/_index.scss
new file mode 100644
index 0000000000000..5d419b5323079
--- /dev/null
+++ b/x-pack/plugins/security/public/management/_index.scss
@@ -0,0 +1,3 @@
+@import './roles/index';
+@import './users/index';
+@import './role_mappings/index';
diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.mock.ts b/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.mock.ts
new file mode 100644
index 0000000000000..2a45d497029f4
--- /dev/null
+++ b/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.mock.ts
@@ -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 const apiKeysAPIClientMock = {
+ create: () => ({
+ checkPrivileges: jest.fn(),
+ getApiKeys: jest.fn(),
+ invalidateApiKeys: jest.fn(),
+ }),
+};
diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.test.ts b/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.test.ts
new file mode 100644
index 0000000000000..7d51a80459a6e
--- /dev/null
+++ b/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.test.ts
@@ -0,0 +1,86 @@
+/*
+ * 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 { APIKeysAPIClient } from './api_keys_api_client';
+
+import { httpServiceMock } from '../../../../../../src/core/public/mocks';
+
+describe('APIKeysAPIClient', () => {
+ it('checkPrivileges() queries correct endpoint', async () => {
+ const httpMock = httpServiceMock.createStartContract();
+
+ const mockResponse = Symbol('mockResponse');
+ httpMock.get.mockResolvedValue(mockResponse);
+
+ const apiClient = new APIKeysAPIClient(httpMock);
+
+ await expect(apiClient.checkPrivileges()).resolves.toBe(mockResponse);
+ expect(httpMock.get).toHaveBeenCalledTimes(1);
+ expect(httpMock.get).toHaveBeenCalledWith('/internal/security/api_key/privileges');
+ });
+
+ it('getApiKeys() queries correct endpoint', async () => {
+ const httpMock = httpServiceMock.createStartContract();
+
+ const mockResponse = Symbol('mockResponse');
+ httpMock.get.mockResolvedValue(mockResponse);
+
+ const apiClient = new APIKeysAPIClient(httpMock);
+
+ await expect(apiClient.getApiKeys()).resolves.toBe(mockResponse);
+ expect(httpMock.get).toHaveBeenCalledTimes(1);
+ expect(httpMock.get).toHaveBeenCalledWith('/internal/security/api_key', {
+ query: { isAdmin: false },
+ });
+ httpMock.get.mockClear();
+
+ await expect(apiClient.getApiKeys(false)).resolves.toBe(mockResponse);
+ expect(httpMock.get).toHaveBeenCalledTimes(1);
+ expect(httpMock.get).toHaveBeenCalledWith('/internal/security/api_key', {
+ query: { isAdmin: false },
+ });
+ httpMock.get.mockClear();
+
+ await expect(apiClient.getApiKeys(true)).resolves.toBe(mockResponse);
+ expect(httpMock.get).toHaveBeenCalledTimes(1);
+ expect(httpMock.get).toHaveBeenCalledWith('/internal/security/api_key', {
+ query: { isAdmin: true },
+ });
+ });
+
+ it('invalidateApiKeys() queries correct endpoint', async () => {
+ const httpMock = httpServiceMock.createStartContract();
+
+ const mockResponse = Symbol('mockResponse');
+ httpMock.post.mockResolvedValue(mockResponse);
+
+ const apiClient = new APIKeysAPIClient(httpMock);
+ const mockAPIKeys = [
+ { id: 'one', name: 'name-one' },
+ { id: 'two', name: 'name-two' },
+ ];
+
+ await expect(apiClient.invalidateApiKeys(mockAPIKeys)).resolves.toBe(mockResponse);
+ expect(httpMock.post).toHaveBeenCalledTimes(1);
+ expect(httpMock.post).toHaveBeenCalledWith('/internal/security/api_key/invalidate', {
+ body: JSON.stringify({ apiKeys: mockAPIKeys, isAdmin: false }),
+ });
+ httpMock.post.mockClear();
+
+ await expect(apiClient.invalidateApiKeys(mockAPIKeys, false)).resolves.toBe(mockResponse);
+ expect(httpMock.post).toHaveBeenCalledTimes(1);
+ expect(httpMock.post).toHaveBeenCalledWith('/internal/security/api_key/invalidate', {
+ body: JSON.stringify({ apiKeys: mockAPIKeys, isAdmin: false }),
+ });
+ httpMock.post.mockClear();
+
+ await expect(apiClient.invalidateApiKeys(mockAPIKeys, true)).resolves.toBe(mockResponse);
+ expect(httpMock.post).toHaveBeenCalledTimes(1);
+ expect(httpMock.post).toHaveBeenCalledWith('/internal/security/api_key/invalidate', {
+ body: JSON.stringify({ apiKeys: mockAPIKeys, isAdmin: true }),
+ });
+ });
+});
diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.ts b/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.ts
new file mode 100644
index 0000000000000..372b1e56a73c4
--- /dev/null
+++ b/x-pack/plugins/security/public/management/api_keys/api_keys_api_client.ts
@@ -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.
+ */
+
+import { HttpStart } from 'src/core/public';
+import { ApiKey, ApiKeyToInvalidate } from '../../../common/model';
+
+interface CheckPrivilegesResponse {
+ areApiKeysEnabled: boolean;
+ isAdmin: boolean;
+}
+
+interface InvalidateApiKeysResponse {
+ itemsInvalidated: ApiKeyToInvalidate[];
+ errors: any[];
+}
+
+interface GetApiKeysResponse {
+ apiKeys: ApiKey[];
+}
+
+const apiKeysUrl = '/internal/security/api_key';
+
+export class APIKeysAPIClient {
+ constructor(private readonly http: HttpStart) {}
+
+ public async checkPrivileges() {
+ return await this.http.get(`${apiKeysUrl}/privileges`);
+ }
+
+ public async getApiKeys(isAdmin = false) {
+ return await this.http.get(apiKeysUrl, { query: { isAdmin } });
+ }
+
+ public async invalidateApiKeys(apiKeys: ApiKeyToInvalidate[], isAdmin = false) {
+ return await this.http.post(`${apiKeysUrl}/invalidate`, {
+ body: JSON.stringify({ apiKeys, isAdmin }),
+ });
+ }
+}
diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/__snapshots__/api_keys_grid_page.test.tsx.snap b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/__snapshots__/api_keys_grid_page.test.tsx.snap
similarity index 91%
rename from x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/__snapshots__/api_keys_grid_page.test.tsx.snap
rename to x-pack/plugins/security/public/management/api_keys/api_keys_grid/__snapshots__/api_keys_grid_page.test.tsx.snap
index c2537235c99f6..42fd4417e238b 100644
--- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/__snapshots__/api_keys_grid_page.test.tsx.snap
+++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/__snapshots__/api_keys_grid_page.test.tsx.snap
@@ -1,7 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`ApiKeysGridPage renders a callout when API keys are not enabled 1`] = `
-
+exports[`APIKeysGridPage renders a callout when API keys are not enabled 1`] = `
+
Contact your system administrator and refer to the
`;
-exports[`ApiKeysGridPage renders permission denied if user does not have required permissions 1`] = `
+exports[`APIKeysGridPage renders permission denied if user does not have required permissions 1`] = `
({ body: { statusCode: 403 } });
-const mock500 = () => ({ body: { error: 'Internal Server Error', message: '', statusCode: 500 } });
-
-jest.mock('../../../../lib/api_keys_api', () => {
- return {
- ApiKeysApi: {
- async checkPrivileges() {
- if (mockSimulate403) {
- throw mock403();
- }
-
- return {
- isAdmin: mockIsAdmin,
- areApiKeysEnabled: mockAreApiKeysEnabled,
- };
- },
- async getApiKeys() {
- if (mockSimulate500) {
- throw mock500();
- }
-
- return {
- apiKeys: [
- {
- creation: 1571322182082,
- expiration: 1571408582082,
- id: '0QQZ2m0BO2XZwgJFuWTT',
- invalidated: false,
- name: 'my-api-key',
- realm: 'reserved',
- username: 'elastic',
- },
- ],
- };
- },
- },
- };
-});
-
import { mountWithIntl } from 'test_utils/enzyme_helpers';
-import { ApiKeysGridPage } from './api_keys_grid_page';
import React from 'react';
import { ReactWrapper } from 'enzyme';
import { EuiCallOut } from '@elastic/eui';
import { NotEnabled } from './not_enabled';
import { PermissionDenied } from './permission_denied';
+import { APIKeysAPIClient } from '../api_keys_api_client';
+import { DocumentationLinksService } from '../documentation_links';
+import { APIKeysGridPage } from './api_keys_grid_page';
+
+import { coreMock } from '../../../../../../../src/core/public/mocks';
+import { apiKeysAPIClientMock } from '../index.mock';
+
+const mock403 = () => ({ body: { statusCode: 403 } });
+const mock500 = () => ({ body: { error: 'Internal Server Error', message: '', statusCode: 500 } });
const waitForRender = async (
wrapper: ReactWrapper,
@@ -77,23 +41,51 @@ const waitForRender = async (
});
};
-describe('ApiKeysGridPage', () => {
+describe('APIKeysGridPage', () => {
+ let apiClientMock: jest.Mocked>;
beforeEach(() => {
- mockSimulate403 = false;
- mockSimulate500 = false;
- mockAreApiKeysEnabled = true;
- mockIsAdmin = true;
+ apiClientMock = apiKeysAPIClientMock.create();
+ apiClientMock.checkPrivileges.mockResolvedValue({
+ isAdmin: true,
+ areApiKeysEnabled: true,
+ });
+ apiClientMock.getApiKeys.mockResolvedValue({
+ apiKeys: [
+ {
+ creation: 1571322182082,
+ expiration: 1571408582082,
+ id: '0QQZ2m0BO2XZwgJFuWTT',
+ invalidated: false,
+ name: 'my-api-key',
+ realm: 'reserved',
+ username: 'elastic',
+ },
+ ],
+ });
});
+ const getViewProperties = () => {
+ const { docLinks, notifications } = coreMock.createStart();
+ return {
+ docLinks: new DocumentationLinksService(docLinks),
+ notifications,
+ apiKeysAPIClient: apiClientMock,
+ };
+ };
+
it('renders a loading state when fetching API keys', async () => {
- const wrapper = mountWithIntl();
+ const wrapper = mountWithIntl();
expect(wrapper.find('[data-test-subj="apiKeysSectionLoading"]')).toHaveLength(1);
});
it('renders a callout when API keys are not enabled', async () => {
- mockAreApiKeysEnabled = false;
- const wrapper = mountWithIntl();
+ apiClientMock.checkPrivileges.mockResolvedValue({
+ isAdmin: true,
+ areApiKeysEnabled: false,
+ });
+
+ const wrapper = mountWithIntl();
await waitForRender(wrapper, updatedWrapper => {
return updatedWrapper.find(NotEnabled).length > 0;
@@ -103,8 +95,9 @@ describe('ApiKeysGridPage', () => {
});
it('renders permission denied if user does not have required permissions', async () => {
- mockSimulate403 = true;
- const wrapper = mountWithIntl();
+ apiClientMock.checkPrivileges.mockRejectedValue(mock403());
+
+ const wrapper = mountWithIntl();
await waitForRender(wrapper, updatedWrapper => {
return updatedWrapper.find(PermissionDenied).length > 0;
@@ -114,8 +107,9 @@ describe('ApiKeysGridPage', () => {
});
it('renders error callout if error fetching API keys', async () => {
- mockSimulate500 = true;
- const wrapper = mountWithIntl();
+ apiClientMock.getApiKeys.mockRejectedValue(mock500());
+
+ const wrapper = mountWithIntl();
await waitForRender(wrapper, updatedWrapper => {
return updatedWrapper.find(EuiCallOut).length > 0;
@@ -125,7 +119,10 @@ describe('ApiKeysGridPage', () => {
});
describe('Admin view', () => {
- const wrapper = mountWithIntl();
+ let wrapper: ReactWrapper;
+ beforeEach(() => {
+ wrapper = mountWithIntl();
+ });
it('renders a callout indicating the user is an administrator', async () => {
const calloutEl = 'EuiCallOut[data-test-subj="apiKeyAdminDescriptionCallOut"]';
@@ -151,8 +148,15 @@ describe('ApiKeysGridPage', () => {
});
describe('Non-admin view', () => {
- mockIsAdmin = false;
- const wrapper = mountWithIntl();
+ let wrapper: ReactWrapper;
+ beforeEach(() => {
+ apiClientMock.checkPrivileges.mockResolvedValue({
+ isAdmin: false,
+ areApiKeysEnabled: true,
+ });
+
+ wrapper = mountWithIntl();
+ });
it('does NOT render a callout indicating the user is an administrator', async () => {
const descriptionEl = 'EuiText[data-test-subj="apiKeysDescriptionText"]';
diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx
similarity index 90%
rename from x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.tsx
rename to x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx
index 92633a4b0ef57..779a2302cfadf 100644
--- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/api_keys_grid_page.tsx
+++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx
@@ -27,16 +27,23 @@ import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import moment from 'moment-timezone';
import _ from 'lodash';
-import { toastNotifications } from 'ui/notify';
+import { NotificationsStart } from 'src/core/public';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import { SectionLoading } from '../../../../../../../../../src/plugins/es_ui_shared/public/components/section_loading';
-import { ApiKey, ApiKeyToInvalidate } from '../../../../../common/model';
-import { ApiKeysApi } from '../../../../lib/api_keys_api';
+import { SectionLoading } from '../../../../../../../src/plugins/es_ui_shared/public/components/section_loading';
+import { ApiKey, ApiKeyToInvalidate } from '../../../../common/model';
+import { APIKeysAPIClient } from '../api_keys_api_client';
+import { DocumentationLinksService } from '../documentation_links';
import { PermissionDenied } from './permission_denied';
import { EmptyPrompt } from './empty_prompt';
import { NotEnabled } from './not_enabled';
import { InvalidateProvider } from './invalidate_provider';
+interface Props {
+ notifications: NotificationsStart;
+ docLinks: DocumentationLinksService;
+ apiKeysAPIClient: PublicMethodsOf;
+}
+
interface State {
isLoadingApp: boolean;
isLoadingTable: boolean;
@@ -50,7 +57,7 @@ interface State {
const DATE_FORMAT = 'MMMM Do YYYY HH:mm:ss';
-export class ApiKeysGridPage extends Component {
+export class APIKeysGridPage extends Component {
constructor(props: any) {
super(props);
this.state = {
@@ -124,7 +131,7 @@ export class ApiKeysGridPage extends Component {
if (!areApiKeysEnabled) {
return (
-
+
);
}
@@ -132,7 +139,7 @@ export class ApiKeysGridPage extends Component {
if (!isLoadingTable && apiKeys && apiKeys.length === 0) {
return (
-
+
);
}
@@ -210,7 +217,11 @@ export class ApiKeysGridPage extends Component {
const search: EuiInMemoryTableProps['search'] = {
toolsLeft: selectedItems.length ? (
-
+
{invalidateApiKeyPrompt => {
return (
{
return (
-
+
{invalidateApiKeyPrompt => {
return (
{
private async checkPrivileges() {
try {
- const { isAdmin, areApiKeysEnabled } = await ApiKeysApi.checkPrivileges();
+ const { isAdmin, areApiKeysEnabled } = await this.props.apiKeysAPIClient.checkPrivileges();
this.setState({ isAdmin, areApiKeysEnabled });
if (areApiKeysEnabled) {
@@ -494,14 +509,11 @@ export class ApiKeysGridPage extends Component {
if (_.get(e, 'body.statusCode') === 403) {
this.setState({ permissionDenied: true, isLoadingApp: false });
} else {
- toastNotifications.addDanger(
- this.props.i18n.translate(
- 'xpack.security.management.apiKeys.table.fetchingApiKeysErrorMessage',
- {
- defaultMessage: 'Error checking privileges: {message}',
- values: { message: _.get(e, 'body.message', '') },
- }
- )
+ this.props.notifications.toasts.addDanger(
+ i18n.translate('xpack.security.management.apiKeys.table.fetchingApiKeysErrorMessage', {
+ defaultMessage: 'Error checking privileges: {message}',
+ values: { message: _.get(e, 'body.message', '') },
+ })
);
}
}
@@ -520,7 +532,7 @@ export class ApiKeysGridPage extends Component {
private loadApiKeys = async () => {
try {
const { isAdmin } = this.state;
- const { apiKeys } = await ApiKeysApi.getApiKeys(isAdmin);
+ const { apiKeys } = await this.props.apiKeysAPIClient.getApiKeys(isAdmin);
this.setState({ apiKeys });
} catch (e) {
this.setState({ error: e });
diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/empty_prompt/empty_prompt.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/empty_prompt.tsx
similarity index 89%
rename from x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/empty_prompt/empty_prompt.tsx
rename to x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/empty_prompt.tsx
index 957ca7010a1a0..7d762a1ceb04e 100644
--- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/empty_prompt/empty_prompt.tsx
+++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/empty_prompt/empty_prompt.tsx
@@ -7,13 +7,14 @@
import React, { Fragment } from 'react';
import { EuiEmptyPrompt, EuiButton, EuiLink } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
-import { documentationLinks } from '../../services/documentation_links';
+import { DocumentationLinksService } from '../../documentation_links';
interface Props {
isAdmin: boolean;
+ docLinks: DocumentationLinksService;
}
-export const EmptyPrompt: React.FunctionComponent = ({ isAdmin }) => (
+export const EmptyPrompt: React.FunctionComponent = ({ isAdmin, docLinks }) => (
= ({ isAdmin }) => (
defaultMessage="You can create an {link} from Console."
values={{
link: (
-
+
React.ReactElement;
+ notifications: NotificationsStart;
+ apiKeysAPIClient: PublicMethodsOf;
}
export type InvalidateApiKeys = (
@@ -23,7 +25,12 @@ export type InvalidateApiKeys = (
type OnSuccessCallback = (apiKeysInvalidated: ApiKeyToInvalidate[]) => void;
-export const InvalidateProvider: React.FunctionComponent = ({ isAdmin, children }) => {
+export const InvalidateProvider: React.FunctionComponent = ({
+ isAdmin,
+ children,
+ notifications,
+ apiKeysAPIClient,
+}) => {
const [apiKeys, setApiKeys] = useState([]);
const [isModalOpen, setIsModalOpen] = useState(false);
const onSuccessCallback = useRef(null);
@@ -48,7 +55,7 @@ export const InvalidateProvider: React.FunctionComponent = ({ isAdmin, ch
let errors;
try {
- result = await ApiKeysApi.invalidateApiKeys(apiKeys, isAdmin);
+ result = await apiKeysAPIClient.invalidateApiKeys(apiKeys, isAdmin);
} catch (e) {
error = e;
}
@@ -77,7 +84,7 @@ export const InvalidateProvider: React.FunctionComponent = ({ isAdmin, ch
values: { name: itemsInvalidated[0].name },
}
);
- toastNotifications.addSuccess(successMessage);
+ notifications.toasts.addSuccess(successMessage);
if (onSuccessCallback.current) {
onSuccessCallback.current([...itemsInvalidated]);
}
@@ -106,7 +113,7 @@ export const InvalidateProvider: React.FunctionComponent = ({ isAdmin, ch
values: { name: (errors && errors[0].name) || apiKeys[0].name },
}
);
- toastNotifications.addDanger(errorMessage);
+ notifications.toasts.addDanger(errorMessage);
}
};
diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/not_enabled/index.ts b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/not_enabled/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/not_enabled/index.ts
rename to x-pack/plugins/security/public/management/api_keys/api_keys_grid/not_enabled/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/not_enabled/not_enabled.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/not_enabled/not_enabled.tsx
similarity index 78%
rename from x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/not_enabled/not_enabled.tsx
rename to x-pack/plugins/security/public/management/api_keys/api_keys_grid/not_enabled/not_enabled.tsx
index c419e15450c1e..08fe542557757 100644
--- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/components/not_enabled/not_enabled.tsx
+++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/not_enabled/not_enabled.tsx
@@ -7,9 +7,13 @@
import React from 'react';
import { EuiCallOut, EuiLink } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
-import { documentationLinks } from '../../services/documentation_links';
+import { DocumentationLinksService } from '../../documentation_links';
-export const NotEnabled: React.FunctionComponent = () => (
+interface Props {
+ docLinks: DocumentationLinksService;
+}
+
+export const NotEnabled: React.FunctionComponent = ({ docLinks }) => (
(
defaultMessage="Contact your system administrator and refer to the {link} to enable API keys."
values={{
link: (
-
+
({
+ APIKeysGridPage: (props: any) => `Page: ${JSON.stringify(props)}`,
+}));
+
+import { apiKeysManagementApp } from './api_keys_management_app';
+import { coreMock } from '../../../../../../src/core/public/mocks';
+
+describe('apiKeysManagementApp', () => {
+ it('create() returns proper management app descriptor', () => {
+ const { getStartServices } = coreMock.createSetup();
+
+ expect(apiKeysManagementApp.create({ getStartServices: getStartServices as any }))
+ .toMatchInlineSnapshot(`
+ Object {
+ "id": "api_keys",
+ "mount": [Function],
+ "order": 30,
+ "title": "API Keys",
+ }
+ `);
+ });
+
+ it('mount() works for the `grid` page', async () => {
+ const { getStartServices } = coreMock.createSetup();
+ const container = document.createElement('div');
+
+ const setBreadcrumbs = jest.fn();
+ const unmount = await apiKeysManagementApp
+ .create({ getStartServices: getStartServices as any })
+ .mount({
+ basePath: '/some-base-path',
+ element: container,
+ setBreadcrumbs,
+ });
+
+ expect(setBreadcrumbs).toHaveBeenCalledTimes(1);
+ expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: '#/some-base-path', text: 'API Keys' }]);
+ expect(container).toMatchInlineSnapshot(`
+
+ Page: {"notifications":{"toasts":{}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"apiKeysAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}}}
+
+ `);
+
+ unmount();
+
+ expect(container).toMatchInlineSnapshot(``);
+ });
+});
diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx
new file mode 100644
index 0000000000000..35de732b84ce9
--- /dev/null
+++ b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx
@@ -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 from 'react';
+import { render, unmountComponentAtNode } from 'react-dom';
+import { i18n } from '@kbn/i18n';
+import { CoreSetup } from 'src/core/public';
+import { RegisterManagementAppArgs } from '../../../../../../src/plugins/management/public';
+import { PluginStartDependencies } from '../../plugin';
+import { APIKeysGridPage } from './api_keys_grid';
+import { APIKeysAPIClient } from './api_keys_api_client';
+import { DocumentationLinksService } from './documentation_links';
+
+interface CreateParams {
+ getStartServices: CoreSetup['getStartServices'];
+}
+
+export const apiKeysManagementApp = Object.freeze({
+ id: 'api_keys',
+ create({ getStartServices }: CreateParams) {
+ return {
+ id: this.id,
+ order: 30,
+ title: i18n.translate('xpack.security.management.apiKeysTitle', {
+ defaultMessage: 'API Keys',
+ }),
+ async mount({ basePath, element, setBreadcrumbs }) {
+ const [{ docLinks, http, notifications, i18n: i18nStart }] = await getStartServices();
+ setBreadcrumbs([
+ {
+ text: i18n.translate('xpack.security.apiKeys.breadcrumb', {
+ defaultMessage: 'API Keys',
+ }),
+ href: `#${basePath}`,
+ },
+ ]);
+
+ render(
+
+
+ ,
+ element
+ );
+
+ return () => {
+ unmountComponentAtNode(element);
+ };
+ },
+ } as RegisterManagementAppArgs;
+ },
+});
diff --git a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/services/documentation_links.ts b/x-pack/plugins/security/public/management/api_keys/documentation_links.ts
similarity index 51%
rename from x-pack/legacy/plugins/security/public/views/management/api_keys_grid/services/documentation_links.ts
rename to x-pack/plugins/security/public/management/api_keys/documentation_links.ts
index 1f03763eb542a..4165c2a2372c9 100644
--- a/x-pack/legacy/plugins/security/public/views/management/api_keys_grid/services/documentation_links.ts
+++ b/x-pack/plugins/security/public/management/api_keys/documentation_links.ts
@@ -4,18 +4,20 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links';
+import { DocLinksStart } from 'src/core/public';
-class DocumentationLinksService {
- private esDocBasePath = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`;
+export class DocumentationLinksService {
+ private readonly esDocBasePath: string;
- public getApiKeyServiceSettingsDocUrl(): string {
+ constructor(docLinks: DocLinksStart) {
+ this.esDocBasePath = `${docLinks.ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${docLinks.DOC_LINK_VERSION}/`;
+ }
+
+ public getApiKeyServiceSettingsDocUrl() {
return `${this.esDocBasePath}security-settings.html#api-key-service-settings`;
}
- public getCreateApiKeyDocUrl(): string {
+ public getCreateApiKeyDocUrl() {
return `${this.esDocBasePath}security-api-create-api-key.html`;
}
}
-
-export const documentationLinks = new DocumentationLinksService();
diff --git a/x-pack/plugins/security/public/management/api_keys/index.mock.ts b/x-pack/plugins/security/public/management/api_keys/index.mock.ts
new file mode 100644
index 0000000000000..3c11cd6bb9c65
--- /dev/null
+++ b/x-pack/plugins/security/public/management/api_keys/index.mock.ts
@@ -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 { apiKeysAPIClientMock } from './api_keys_api_client.mock';
diff --git a/x-pack/plugins/security/public/management/api_keys/index.ts b/x-pack/plugins/security/public/management/api_keys/index.ts
new file mode 100644
index 0000000000000..e15da7d5eb409
--- /dev/null
+++ b/x-pack/plugins/security/public/management/api_keys/index.ts
@@ -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 { apiKeysManagementApp } from './api_keys_management_app';
diff --git a/x-pack/plugins/security/public/management/index.ts b/x-pack/plugins/security/public/management/index.ts
new file mode 100644
index 0000000000000..e1a13d66e6883
--- /dev/null
+++ b/x-pack/plugins/security/public/management/index.ts
@@ -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 { ManagementService } from './management_service';
+export { UserAPIClient } from './users/user_api_client';
diff --git a/x-pack/plugins/security/public/management/management_service.test.ts b/x-pack/plugins/security/public/management/management_service.test.ts
new file mode 100644
index 0000000000000..53c12ad7ab12c
--- /dev/null
+++ b/x-pack/plugins/security/public/management/management_service.test.ts
@@ -0,0 +1,226 @@
+/*
+ * 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 { BehaviorSubject } from 'rxjs';
+import { ManagementApp } from '../../../../../src/plugins/management/public';
+import { SecurityLicenseFeatures } from '../../common/licensing/license_features';
+import { ManagementService } from './management_service';
+import { usersManagementApp } from './users';
+
+import { coreMock } from '../../../../../src/core/public/mocks';
+import { licenseMock } from '../../common/licensing/index.mock';
+import { securityMock } from '../mocks';
+import { rolesManagementApp } from './roles';
+import { apiKeysManagementApp } from './api_keys';
+import { roleMappingsManagementApp } from './role_mappings';
+
+describe('ManagementService', () => {
+ describe('setup()', () => {
+ it('properly registers security section and its applications', () => {
+ const { fatalErrors, getStartServices } = coreMock.createSetup();
+ const { authc } = securityMock.createSetup();
+ const license = licenseMock.create();
+
+ const mockSection = { registerApp: jest.fn() };
+ const managementSetup = {
+ sections: {
+ getSection: jest.fn(),
+ getAllSections: jest.fn(),
+ register: jest.fn().mockReturnValue(mockSection),
+ },
+ };
+
+ const service = new ManagementService();
+ service.setup({
+ getStartServices: getStartServices as any,
+ license,
+ fatalErrors,
+ authc,
+ management: managementSetup,
+ });
+
+ expect(managementSetup.sections.register).toHaveBeenCalledTimes(1);
+ expect(managementSetup.sections.register).toHaveBeenCalledWith({
+ id: 'security',
+ title: 'Security',
+ order: 100,
+ euiIconType: 'securityApp',
+ });
+
+ expect(mockSection.registerApp).toHaveBeenCalledTimes(4);
+ expect(mockSection.registerApp).toHaveBeenCalledWith({
+ id: 'users',
+ mount: expect.any(Function),
+ order: 10,
+ title: 'Users',
+ });
+ expect(mockSection.registerApp).toHaveBeenCalledWith({
+ id: 'roles',
+ mount: expect.any(Function),
+ order: 20,
+ title: 'Roles',
+ });
+ expect(mockSection.registerApp).toHaveBeenCalledWith({
+ id: 'api_keys',
+ mount: expect.any(Function),
+ order: 30,
+ title: 'API Keys',
+ });
+ expect(mockSection.registerApp).toHaveBeenCalledWith({
+ id: 'role_mappings',
+ mount: expect.any(Function),
+ order: 40,
+ title: 'Role Mappings',
+ });
+ });
+ });
+
+ describe('start()', () => {
+ function startService(initialFeatures: Partial) {
+ const { fatalErrors, getStartServices } = coreMock.createSetup();
+
+ const licenseSubject = new BehaviorSubject(
+ (initialFeatures as unknown) as SecurityLicenseFeatures
+ );
+ const license = licenseMock.create();
+ license.features$ = licenseSubject;
+
+ const service = new ManagementService();
+ service.setup({
+ getStartServices: getStartServices as any,
+ license,
+ fatalErrors,
+ authc: securityMock.createSetup().authc,
+ management: {
+ sections: {
+ getSection: jest.fn(),
+ getAllSections: jest.fn(),
+ register: jest.fn().mockReturnValue({ registerApp: jest.fn() }),
+ },
+ },
+ });
+
+ const getMockedApp = () => {
+ // All apps are enabled by default.
+ let enabled = true;
+ return ({
+ get enabled() {
+ return enabled;
+ },
+ enable: jest.fn().mockImplementation(() => {
+ enabled = true;
+ }),
+ disable: jest.fn().mockImplementation(() => {
+ enabled = false;
+ }),
+ } as unknown) as jest.Mocked;
+ };
+ const mockApps = new Map>([
+ [usersManagementApp.id, getMockedApp()],
+ [rolesManagementApp.id, getMockedApp()],
+ [apiKeysManagementApp.id, getMockedApp()],
+ [roleMappingsManagementApp.id, getMockedApp()],
+ ] as Array<[string, jest.Mocked]>);
+
+ service.start({
+ management: {
+ sections: {
+ getSection: jest
+ .fn()
+ .mockReturnValue({ getApp: jest.fn().mockImplementation(id => mockApps.get(id)) }),
+ getAllSections: jest.fn(),
+ navigateToApp: jest.fn(),
+ },
+ legacy: undefined,
+ },
+ });
+
+ return {
+ mockApps,
+ updateFeatures(features: Partial) {
+ licenseSubject.next((features as unknown) as SecurityLicenseFeatures);
+ },
+ };
+ }
+
+ it('does not do anything if `showLinks` is `true` at `start`', () => {
+ const { mockApps } = startService({ showLinks: true, showRoleMappingsManagement: true });
+ for (const [, mockApp] of mockApps) {
+ expect(mockApp.enable).not.toHaveBeenCalled();
+ expect(mockApp.disable).not.toHaveBeenCalled();
+ expect(mockApp.enabled).toBe(true);
+ }
+ });
+
+ it('disables all apps if `showLinks` is `false` at `start`', () => {
+ const { mockApps } = startService({ showLinks: false, showRoleMappingsManagement: true });
+ for (const [, mockApp] of mockApps) {
+ expect(mockApp.enabled).toBe(false);
+ }
+ });
+
+ it('disables only Role Mappings app if `showLinks` is `true`, but `showRoleMappingsManagement` is `false` at `start`', () => {
+ const { mockApps } = startService({ showLinks: true, showRoleMappingsManagement: false });
+ for (const [appId, mockApp] of mockApps) {
+ expect(mockApp.enabled).toBe(appId !== roleMappingsManagementApp.id);
+ }
+ });
+
+ it('apps are disabled if `showLinks` changes after `start`', () => {
+ const { mockApps, updateFeatures } = startService({
+ showLinks: true,
+ showRoleMappingsManagement: true,
+ });
+ for (const [, mockApp] of mockApps) {
+ expect(mockApp.enabled).toBe(true);
+ }
+
+ updateFeatures({ showLinks: false, showRoleMappingsManagement: false });
+
+ for (const [, mockApp] of mockApps) {
+ expect(mockApp.enabled).toBe(false);
+ }
+ });
+
+ it('role mappings app is disabled if `showRoleMappingsManagement` changes after `start`', () => {
+ const { mockApps, updateFeatures } = startService({
+ showLinks: true,
+ showRoleMappingsManagement: true,
+ });
+ for (const [, mockApp] of mockApps) {
+ expect(mockApp.enabled).toBe(true);
+ }
+
+ updateFeatures({ showLinks: true, showRoleMappingsManagement: false });
+
+ for (const [appId, mockApp] of mockApps) {
+ expect(mockApp.enabled).toBe(appId !== roleMappingsManagementApp.id);
+ }
+ });
+
+ it('apps are re-enabled if `showLinks` eventually transitions to `true` after `start`', () => {
+ const { mockApps, updateFeatures } = startService({
+ showLinks: true,
+ showRoleMappingsManagement: true,
+ });
+ for (const [, mockApp] of mockApps) {
+ expect(mockApp.enabled).toBe(true);
+ }
+
+ updateFeatures({ showLinks: false, showRoleMappingsManagement: false });
+
+ for (const [, mockApp] of mockApps) {
+ expect(mockApp.enabled).toBe(false);
+ }
+
+ updateFeatures({ showLinks: true, showRoleMappingsManagement: true });
+
+ for (const [, mockApp] of mockApps) {
+ expect(mockApp.enabled).toBe(true);
+ }
+ });
+ });
+});
diff --git a/x-pack/plugins/security/public/management/management_service.ts b/x-pack/plugins/security/public/management/management_service.ts
new file mode 100644
index 0000000000000..5ad3681590fbf
--- /dev/null
+++ b/x-pack/plugins/security/public/management/management_service.ts
@@ -0,0 +1,95 @@
+/*
+ * 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 { Subscription } from 'rxjs';
+import { i18n } from '@kbn/i18n';
+import { CoreSetup, FatalErrorsSetup } from 'src/core/public';
+import {
+ ManagementApp,
+ ManagementSetup,
+ ManagementStart,
+} from '../../../../../src/plugins/management/public';
+import { SecurityLicense } from '../../common/licensing';
+import { AuthenticationServiceSetup } from '../authentication';
+import { PluginStartDependencies } from '../plugin';
+import { apiKeysManagementApp } from './api_keys';
+import { roleMappingsManagementApp } from './role_mappings';
+import { rolesManagementApp } from './roles';
+import { usersManagementApp } from './users';
+
+interface SetupParams {
+ management: ManagementSetup;
+ license: SecurityLicense;
+ authc: AuthenticationServiceSetup;
+ fatalErrors: FatalErrorsSetup;
+ getStartServices: CoreSetup['getStartServices'];
+}
+
+interface StartParams {
+ management: ManagementStart;
+}
+
+export class ManagementService {
+ private license!: SecurityLicense;
+ private licenseFeaturesSubscription?: Subscription;
+
+ setup({ getStartServices, management, authc, license, fatalErrors }: SetupParams) {
+ this.license = license;
+
+ const securitySection = management.sections.register({
+ id: 'security',
+ title: i18n.translate('xpack.security.management.securityTitle', {
+ defaultMessage: 'Security',
+ }),
+ order: 100,
+ euiIconType: 'securityApp',
+ });
+
+ securitySection.registerApp(usersManagementApp.create({ authc, getStartServices }));
+ securitySection.registerApp(
+ rolesManagementApp.create({ fatalErrors, license, getStartServices })
+ );
+ securitySection.registerApp(apiKeysManagementApp.create({ getStartServices }));
+ securitySection.registerApp(roleMappingsManagementApp.create({ getStartServices }));
+ }
+
+ start({ management }: StartParams) {
+ this.licenseFeaturesSubscription = this.license.features$.subscribe(async features => {
+ const securitySection = management.sections.getSection('security')!;
+
+ const securityManagementAppsStatuses: Array<[ManagementApp, boolean]> = [
+ [securitySection.getApp(usersManagementApp.id)!, features.showLinks],
+ [securitySection.getApp(rolesManagementApp.id)!, features.showLinks],
+ [securitySection.getApp(apiKeysManagementApp.id)!, features.showLinks],
+ [
+ securitySection.getApp(roleMappingsManagementApp.id)!,
+ features.showLinks && features.showRoleMappingsManagement,
+ ],
+ ];
+
+ // Iterate over all registered apps and update their enable status depending on the available
+ // license features.
+ for (const [app, enableStatus] of securityManagementAppsStatuses) {
+ if (app.enabled === enableStatus) {
+ continue;
+ }
+
+ if (enableStatus) {
+ app.enable();
+ } else {
+ app.disable();
+ }
+ }
+ });
+ }
+
+ stop() {
+ if (this.licenseFeaturesSubscription) {
+ this.licenseFeaturesSubscription.unsubscribe();
+ this.licenseFeaturesSubscription = undefined;
+ }
+ }
+}
diff --git a/x-pack/legacy/plugins/security/public/views/management/management_urls.ts b/x-pack/plugins/security/public/management/management_urls.ts
similarity index 74%
rename from x-pack/legacy/plugins/security/public/views/management/management_urls.ts
rename to x-pack/plugins/security/public/management/management_urls.ts
index 881740c0b2895..0d4e3fc920bdb 100644
--- a/x-pack/legacy/plugins/security/public/views/management/management_urls.ts
+++ b/x-pack/plugins/security/public/management/management_urls.ts
@@ -4,19 +4,18 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export const MANAGEMENT_PATH = '/management';
-export const SECURITY_PATH = `${MANAGEMENT_PATH}/security`;
+const MANAGEMENT_PATH = '/management';
+const SECURITY_PATH = `${MANAGEMENT_PATH}/security`;
export const ROLES_PATH = `${SECURITY_PATH}/roles`;
export const EDIT_ROLES_PATH = `${ROLES_PATH}/edit`;
export const CLONE_ROLES_PATH = `${ROLES_PATH}/clone`;
export const USERS_PATH = `${SECURITY_PATH}/users`;
export const EDIT_USERS_PATH = `${USERS_PATH}/edit`;
-export const API_KEYS_PATH = `${SECURITY_PATH}/api_keys`;
export const ROLE_MAPPINGS_PATH = `${SECURITY_PATH}/role_mappings`;
-export const CREATE_ROLE_MAPPING_PATH = `${ROLE_MAPPINGS_PATH}/edit`;
+const CREATE_ROLE_MAPPING_PATH = `${ROLE_MAPPINGS_PATH}/edit`;
export const getEditRoleHref = (roleName: string) =>
- `#${EDIT_ROLES_PATH}/${encodeURIComponent(roleName)}`;
+ `#${ROLES_PATH}/edit/${encodeURIComponent(roleName)}`;
export const getCreateRoleMappingHref = () => `#${CREATE_ROLE_MAPPING_PATH}`;
diff --git a/x-pack/plugins/security/public/management/role_mappings/_index.scss b/x-pack/plugins/security/public/management/role_mappings/_index.scss
new file mode 100644
index 0000000000000..bae6effcd2ec5
--- /dev/null
+++ b/x-pack/plugins/security/public/management/role_mappings/_index.scss
@@ -0,0 +1 @@
+@import './edit_role_mapping/index';
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/delete_provider.test.tsx b/x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.test.tsx
similarity index 64%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/delete_provider.test.tsx
rename to x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.test.tsx
index b826d68053e27..69142b1ad610e 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/delete_provider.test.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.test.tsx
@@ -5,24 +5,15 @@
*/
import React from 'react';
-import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers';
-import { DeleteProvider } from '.';
-import { RoleMappingsAPI } from '../../../../../lib/role_mappings_api';
-import { RoleMapping } from '../../../../../../common/model';
import { EuiConfirmModal } from '@elastic/eui';
-import { findTestSubject } from 'test_utils/find_test_subject';
import { act } from '@testing-library/react';
-import { toastNotifications } from 'ui/notify';
-
-jest.mock('ui/notify', () => {
- return {
- toastNotifications: {
- addError: jest.fn(),
- addSuccess: jest.fn(),
- addDanger: jest.fn(),
- },
- };
-});
+import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers';
+import { findTestSubject } from 'test_utils/find_test_subject';
+import { RoleMapping } from '../../../../../common/model';
+import { DeleteProvider } from '.';
+
+import { roleMappingsAPIClientMock } from '../../index.mock';
+import { coreMock } from '../../../../../../../../src/core/public/mocks';
describe('DeleteProvider', () => {
beforeEach(() => {
@@ -30,17 +21,14 @@ describe('DeleteProvider', () => {
});
it('allows a single role mapping to be deleted', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.deleteRoleMappings.mockResolvedValue([{ name: 'delete-me', success: true }]);
+
+ const notifications = coreMock.createStart().notifications;
+
const props = {
- roleMappingsAPI: ({
- deleteRoleMappings: jest.fn().mockReturnValue(
- Promise.resolve([
- {
- name: 'delete-me',
- success: true,
- },
- ])
- ),
- } as unknown) as RoleMappingsAPI,
+ roleMappingsAPI,
+ notifications,
};
const roleMappingsToDelete = [
@@ -79,11 +67,10 @@ describe('DeleteProvider', () => {
expect(props.roleMappingsAPI.deleteRoleMappings).toHaveBeenCalledWith(['delete-me']);
- const notifications = toastNotifications as jest.Mocked;
- expect(notifications.addError).toHaveBeenCalledTimes(0);
- expect(notifications.addDanger).toHaveBeenCalledTimes(0);
- expect(notifications.addSuccess).toHaveBeenCalledTimes(1);
- expect(notifications.addSuccess.mock.calls[0]).toMatchInlineSnapshot(`
+ expect(notifications.toasts.addError).toHaveBeenCalledTimes(0);
+ expect(notifications.toasts.addDanger).toHaveBeenCalledTimes(0);
+ expect(notifications.toasts.addSuccess).toHaveBeenCalledTimes(1);
+ expect(notifications.toasts.addSuccess.mock.calls[0]).toMatchInlineSnapshot(`
Array [
Object {
"data-test-subj": "deletedRoleMappingSuccessToast",
@@ -94,21 +81,23 @@ describe('DeleteProvider', () => {
});
it('allows multiple role mappings to be deleted', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.deleteRoleMappings.mockResolvedValue([
+ {
+ name: 'delete-me',
+ success: true,
+ },
+ {
+ name: 'delete-me-too',
+ success: true,
+ },
+ ]);
+
+ const notifications = coreMock.createStart().notifications;
+
const props = {
- roleMappingsAPI: ({
- deleteRoleMappings: jest.fn().mockReturnValue(
- Promise.resolve([
- {
- name: 'delete-me',
- success: true,
- },
- {
- name: 'delete-me-too',
- success: true,
- },
- ])
- ),
- } as unknown) as RoleMappingsAPI,
+ roleMappingsAPI,
+ notifications,
};
const roleMappingsToDelete = [
@@ -152,11 +141,11 @@ describe('DeleteProvider', () => {
'delete-me',
'delete-me-too',
]);
- const notifications = toastNotifications as jest.Mocked;
- expect(notifications.addError).toHaveBeenCalledTimes(0);
- expect(notifications.addDanger).toHaveBeenCalledTimes(0);
- expect(notifications.addSuccess).toHaveBeenCalledTimes(1);
- expect(notifications.addSuccess.mock.calls[0]).toMatchInlineSnapshot(`
+
+ expect(notifications.toasts.addError).toHaveBeenCalledTimes(0);
+ expect(notifications.toasts.addDanger).toHaveBeenCalledTimes(0);
+ expect(notifications.toasts.addSuccess).toHaveBeenCalledTimes(1);
+ expect(notifications.toasts.addSuccess.mock.calls[0]).toMatchInlineSnapshot(`
Array [
Object {
"data-test-subj": "deletedRoleMappingSuccessToast",
@@ -167,22 +156,24 @@ describe('DeleteProvider', () => {
});
it('handles mixed success/failure conditions', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.deleteRoleMappings.mockResolvedValue([
+ {
+ name: 'delete-me',
+ success: true,
+ },
+ {
+ name: 'i-wont-work',
+ success: false,
+ error: new Error('something went wrong. sad.'),
+ },
+ ]);
+
+ const notifications = coreMock.createStart().notifications;
+
const props = {
- roleMappingsAPI: ({
- deleteRoleMappings: jest.fn().mockReturnValue(
- Promise.resolve([
- {
- name: 'delete-me',
- success: true,
- },
- {
- name: 'i-wont-work',
- success: false,
- error: new Error('something went wrong. sad.'),
- },
- ])
- ),
- } as unknown) as RoleMappingsAPI,
+ roleMappingsAPI,
+ notifications,
};
const roleMappingsToDelete = [
@@ -223,10 +214,9 @@ describe('DeleteProvider', () => {
'i-wont-work',
]);
- const notifications = toastNotifications as jest.Mocked;
- expect(notifications.addError).toHaveBeenCalledTimes(0);
- expect(notifications.addSuccess).toHaveBeenCalledTimes(1);
- expect(notifications.addSuccess.mock.calls[0]).toMatchInlineSnapshot(`
+ expect(notifications.toasts.addError).toHaveBeenCalledTimes(0);
+ expect(notifications.toasts.addSuccess).toHaveBeenCalledTimes(1);
+ expect(notifications.toasts.addSuccess.mock.calls[0]).toMatchInlineSnapshot(`
Array [
Object {
"data-test-subj": "deletedRoleMappingSuccessToast",
@@ -235,8 +225,8 @@ describe('DeleteProvider', () => {
]
`);
- expect(notifications.addDanger).toHaveBeenCalledTimes(1);
- expect(notifications.addDanger.mock.calls[0]).toMatchInlineSnapshot(`
+ expect(notifications.toasts.addDanger).toHaveBeenCalledTimes(1);
+ expect(notifications.toasts.addDanger.mock.calls[0]).toMatchInlineSnapshot(`
Array [
"Error deleting role mapping 'i-wont-work'",
]
@@ -244,12 +234,13 @@ describe('DeleteProvider', () => {
});
it('handles errors calling the API', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.deleteRoleMappings.mockRejectedValue(new Error('AHHHHH'));
+
+ const notifications = coreMock.createStart().notifications;
const props = {
- roleMappingsAPI: ({
- deleteRoleMappings: jest.fn().mockImplementation(() => {
- throw new Error('AHHHHH');
- }),
- } as unknown) as RoleMappingsAPI,
+ roleMappingsAPI,
+ notifications,
};
const roleMappingsToDelete = [
@@ -284,12 +275,11 @@ describe('DeleteProvider', () => {
expect(props.roleMappingsAPI.deleteRoleMappings).toHaveBeenCalledWith(['delete-me']);
- const notifications = toastNotifications as jest.Mocked;
- expect(notifications.addDanger).toHaveBeenCalledTimes(0);
- expect(notifications.addSuccess).toHaveBeenCalledTimes(0);
+ expect(notifications.toasts.addDanger).toHaveBeenCalledTimes(0);
+ expect(notifications.toasts.addSuccess).toHaveBeenCalledTimes(0);
- expect(notifications.addError).toHaveBeenCalledTimes(1);
- expect(notifications.addError.mock.calls[0]).toMatchInlineSnapshot(`
+ expect(notifications.toasts.addError).toHaveBeenCalledTimes(1);
+ expect(notifications.toasts.addError.mock.calls[0]).toMatchInlineSnapshot(`
Array [
[Error: AHHHHH],
Object {
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/delete_provider.tsx b/x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.tsx
similarity index 93%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/delete_provider.tsx
rename to x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.tsx
index 2072cedeab462..860fe22cb8032 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/delete_provider.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.tsx
@@ -6,13 +6,14 @@
import React, { Fragment, useRef, useState, ReactElement } from 'react';
import { EuiConfirmModal, EuiOverlayMask } from '@elastic/eui';
-import { toastNotifications } from 'ui/notify';
import { i18n } from '@kbn/i18n';
-import { RoleMapping } from '../../../../../../common/model';
-import { RoleMappingsAPI } from '../../../../../lib/role_mappings_api';
+import { NotificationsStart } from 'src/core/public';
+import { RoleMapping } from '../../../../../common/model';
+import { RoleMappingsAPIClient } from '../../role_mappings_api_client';
interface Props {
- roleMappingsAPI: RoleMappingsAPI;
+ roleMappingsAPI: PublicMethodsOf;
+ notifications: NotificationsStart;
children: (deleteMappings: DeleteRoleMappings) => ReactElement;
}
@@ -23,7 +24,11 @@ export type DeleteRoleMappings = (
type OnSuccessCallback = (deletedRoleMappings: string[]) => void;
-export const DeleteProvider: React.FunctionComponent = ({ roleMappingsAPI, children }) => {
+export const DeleteProvider: React.FunctionComponent = ({
+ roleMappingsAPI,
+ children,
+ notifications,
+}) => {
const [roleMappings, setRoleMappings] = useState([]);
const [isModalOpen, setIsModalOpen] = useState(false);
const [isDeleteInProgress, setIsDeleteInProgress] = useState(false);
@@ -55,7 +60,7 @@ export const DeleteProvider: React.FunctionComponent = ({ roleMappingsAPI
try {
result = await roleMappingsAPI.deleteRoleMappings(roleMappings.map(rm => rm.name));
} catch (e) {
- toastNotifications.addError(e, {
+ notifications.toasts.addError(e, {
title: i18n.translate(
'xpack.security.management.roleMappings.deleteRoleMapping.unknownError',
{
@@ -92,7 +97,7 @@ export const DeleteProvider: React.FunctionComponent = ({ roleMappingsAPI
values: { name: successfulDeletes[0].name },
}
);
- toastNotifications.addSuccess({
+ notifications.toasts.addSuccess({
title: successMessage,
'data-test-subj': 'deletedRoleMappingSuccessToast',
});
@@ -121,7 +126,7 @@ export const DeleteProvider: React.FunctionComponent = ({ roleMappingsAPI
values: { name: erroredDeletes[0].name },
}
);
- toastNotifications.addDanger(errorMessage);
+ notifications.toasts.addDanger(errorMessage);
}
};
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/index.ts b/x-pack/plugins/security/public/management/role_mappings/components/delete_provider/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/components/delete_provider/index.ts
rename to x-pack/plugins/security/public/management/role_mappings/components/delete_provider/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/index.ts b/x-pack/plugins/security/public/management/role_mappings/components/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/components/index.ts
rename to x-pack/plugins/security/public/management/role_mappings/components/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/no_compatible_realms/index.ts b/x-pack/plugins/security/public/management/role_mappings/components/no_compatible_realms/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/components/no_compatible_realms/index.ts
rename to x-pack/plugins/security/public/management/role_mappings/components/no_compatible_realms/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/no_compatible_realms/no_compatible_realms.tsx b/x-pack/plugins/security/public/management/role_mappings/components/no_compatible_realms/no_compatible_realms.tsx
similarity index 78%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/components/no_compatible_realms/no_compatible_realms.tsx
rename to x-pack/plugins/security/public/management/role_mappings/components/no_compatible_realms/no_compatible_realms.tsx
index 969832b3ecbae..5e14b0c179bfd 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/components/no_compatible_realms/no_compatible_realms.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/components/no_compatible_realms/no_compatible_realms.tsx
@@ -7,9 +7,13 @@
import React from 'react';
import { EuiCallOut, EuiLink } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
-import { documentationLinks } from '../../services/documentation_links';
+import { DocumentationLinksService } from '../../documentation_links';
-export const NoCompatibleRealms: React.FunctionComponent = () => (
+interface Props {
+ docLinks: DocumentationLinksService;
+}
+
+export const NoCompatibleRealms: React.FunctionComponent = ({ docLinks }: Props) => (
(
defaultMessage="Role mappings will not be applied to any users. Contact your system administrator and refer to the {link} for more information."
values={{
link: (
-
+
{
+ let rolesAPI: PublicMethodsOf;
+ beforeEach(() => {
+ rolesAPI = rolesAPIClientMock.create();
+ (rolesAPI as jest.Mocked).getRoles.mockResolvedValue([
+ { name: 'foo_role' },
+ { name: 'bar role' },
+ ] as Role[]);
+ });
+
+ it('allows a role mapping to be created', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.saveRoleMapping.mockResolvedValue(null);
+ roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({
+ canManageRoleMappings: true,
+ hasCompatibleRealms: true,
+ canUseInlineScripts: true,
+ canUseStoredScripts: true,
+ });
+
+ const { docLinks, notifications } = coreMock.createStart();
+ const wrapper = mountWithIntl(
+
+ );
+
+ await nextTick();
+ wrapper.update();
+
+ findTestSubject(wrapper, 'roleMappingFormNameInput').simulate('change', {
+ target: { value: 'my-role-mapping' },
+ });
+
+ (wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="roleMappingFormRoleComboBox"]')
+ .props() as any).onChange([{ label: 'foo_role' }]);
+
+ findTestSubject(wrapper, 'roleMappingsAddRuleButton').simulate('click');
+
+ findTestSubject(wrapper, 'saveRoleMappingButton').simulate('click');
+
+ expect(roleMappingsAPI.saveRoleMapping).toHaveBeenCalledWith({
+ name: 'my-role-mapping',
+ enabled: true,
+ roles: ['foo_role'],
+ role_templates: [],
+ rules: {
+ all: [{ field: { username: '*' } }],
+ },
+ metadata: {},
+ });
+ });
+
+ it('allows a role mapping to be updated', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.saveRoleMapping.mockResolvedValue(null);
+ roleMappingsAPI.getRoleMapping.mockResolvedValue({
+ name: 'foo',
+ role_templates: [
+ {
+ template: { id: 'foo' },
+ },
+ ],
+ enabled: true,
+ rules: {
+ any: [{ field: { 'metadata.someCustomOption': [false, true, 'asdf'] } }],
+ },
+ metadata: {
+ foo: 'bar',
+ bar: 'baz',
+ },
+ });
+ roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({
+ canManageRoleMappings: true,
+ hasCompatibleRealms: true,
+ canUseInlineScripts: true,
+ canUseStoredScripts: true,
+ });
+
+ const { docLinks, notifications } = coreMock.createStart();
+ const wrapper = mountWithIntl(
+
+ );
+
+ await nextTick();
+ wrapper.update();
+
+ findTestSubject(wrapper, 'switchToRolesButton').simulate('click');
+
+ (wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="roleMappingFormRoleComboBox"]')
+ .props() as any).onChange([{ label: 'foo_role' }]);
+
+ findTestSubject(wrapper, 'roleMappingsAddRuleButton').simulate('click');
+ wrapper.find('button[id="addRuleOption"]').simulate('click');
+
+ findTestSubject(wrapper, 'saveRoleMappingButton').simulate('click');
+
+ expect(roleMappingsAPI.saveRoleMapping).toHaveBeenCalledWith({
+ name: 'foo',
+ enabled: true,
+ roles: ['foo_role'],
+ role_templates: [],
+ rules: {
+ any: [
+ { field: { 'metadata.someCustomOption': [false, true, 'asdf'] } },
+ { field: { username: '*' } },
+ ],
+ },
+ metadata: {
+ foo: 'bar',
+ bar: 'baz',
+ },
+ });
+ });
+
+ it('renders a permission denied message when unauthorized to manage role mappings', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({
+ canManageRoleMappings: false,
+ hasCompatibleRealms: true,
+ });
+
+ const { docLinks, notifications } = coreMock.createStart();
+ const wrapper = mountWithIntl(
+
+ );
+ expect(wrapper.find(SectionLoading)).toHaveLength(1);
+ expect(wrapper.find(PermissionDenied)).toHaveLength(0);
+
+ await nextTick();
+ wrapper.update();
+
+ expect(wrapper.find(SectionLoading)).toHaveLength(0);
+ expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0);
+ expect(wrapper.find(PermissionDenied)).toHaveLength(1);
+ });
+
+ it('renders a warning when there are no compatible realms enabled', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({
+ canManageRoleMappings: true,
+ hasCompatibleRealms: false,
+ });
+
+ const { docLinks, notifications } = coreMock.createStart();
+ const wrapper = mountWithIntl(
+
+ );
+ expect(wrapper.find(SectionLoading)).toHaveLength(1);
+ expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0);
+
+ await nextTick();
+ wrapper.update();
+
+ expect(wrapper.find(SectionLoading)).toHaveLength(0);
+ expect(wrapper.find(NoCompatibleRealms)).toHaveLength(1);
+ });
+
+ it('renders a warning when editing a mapping with a stored role template, when stored scripts are disabled', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.getRoleMapping.mockResolvedValue({
+ name: 'foo',
+ role_templates: [
+ {
+ template: { id: 'foo' },
+ },
+ ],
+ enabled: true,
+ rules: {
+ field: { username: '*' },
+ },
+ });
+ roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({
+ canManageRoleMappings: true,
+ hasCompatibleRealms: true,
+ canUseInlineScripts: true,
+ canUseStoredScripts: false,
+ });
+
+ const { docLinks, notifications } = coreMock.createStart();
+ const wrapper = mountWithIntl(
+
+ );
+
+ expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(0);
+ expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(0);
+
+ await nextTick();
+ wrapper.update();
+
+ expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(0);
+ expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(1);
+ });
+
+ it('renders a warning when editing a mapping with an inline role template, when inline scripts are disabled', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.getRoleMapping.mockResolvedValue({
+ name: 'foo',
+ role_templates: [
+ {
+ template: { source: 'foo' },
+ },
+ ],
+ enabled: true,
+ rules: {
+ field: { username: '*' },
+ },
+ });
+ roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({
+ canManageRoleMappings: true,
+ hasCompatibleRealms: true,
+ canUseInlineScripts: false,
+ canUseStoredScripts: true,
+ });
+
+ const { docLinks, notifications } = coreMock.createStart();
+ const wrapper = mountWithIntl(
+
+ );
+
+ expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(0);
+ expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(0);
+
+ await nextTick();
+ wrapper.update();
+
+ expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(1);
+ expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(0);
+ });
+
+ it('renders the visual editor by default for simple rule sets', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.getRoleMapping.mockResolvedValue({
+ name: 'foo',
+ roles: ['superuser'],
+ enabled: true,
+ rules: {
+ all: [
+ {
+ field: {
+ username: '*',
+ },
+ },
+ {
+ field: {
+ dn: null,
+ },
+ },
+ {
+ field: {
+ realm: ['ldap', 'pki', null, 12],
+ },
+ },
+ ],
+ },
+ });
+ roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({
+ canManageRoleMappings: true,
+ hasCompatibleRealms: true,
+ canUseInlineScripts: true,
+ canUseStoredScripts: true,
+ });
+
+ const { docLinks, notifications } = coreMock.createStart();
+ const wrapper = mountWithIntl(
+
+ );
+
+ await nextTick();
+ wrapper.update();
+
+ expect(wrapper.find(VisualRuleEditor)).toHaveLength(1);
+ expect(wrapper.find(JSONRuleEditor)).toHaveLength(0);
+ });
+
+ it('renders the JSON editor by default for complex rule sets', async () => {
+ const createRule = (depth: number): Record => {
+ if (depth > 0) {
+ const rule = {
+ all: [
+ {
+ field: {
+ username: '*',
+ },
+ },
+ ],
+ } as Record;
+
+ const subRule = createRule(depth - 1);
+ if (subRule) {
+ rule.all.push(subRule);
+ }
+
+ return rule;
+ }
+ return null as any;
+ };
+
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.getRoleMapping.mockResolvedValue({
+ name: 'foo',
+ roles: ['superuser'],
+ enabled: true,
+ rules: createRule(10),
+ });
+ roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({
+ canManageRoleMappings: true,
+ hasCompatibleRealms: true,
+ canUseInlineScripts: true,
+ canUseStoredScripts: true,
+ });
+
+ const { docLinks, notifications } = coreMock.createStart();
+ const wrapper = mountWithIntl(
+
+ );
+
+ await nextTick();
+ wrapper.update();
+
+ expect(wrapper.find(VisualRuleEditor)).toHaveLength(0);
+ expect(wrapper.find(JSONRuleEditor)).toHaveLength(1);
+ });
+});
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/edit_role_mapping_page.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx
similarity index 87%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/edit_role_mapping_page.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx
index b8a75a4ad9fdf..142b53cbb50f2 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/edit_role_mapping_page.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx
@@ -19,20 +19,21 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { toastNotifications } from 'ui/notify';
-import { RoleMapping } from '../../../../../../common/model';
-import { RoleMappingsAPI } from '../../../../../lib/role_mappings_api';
+import { NotificationsStart } from 'src/core/public';
+import { RoleMapping } from '../../../../common/model';
import { RuleEditorPanel } from './rule_editor_panel';
import {
NoCompatibleRealms,
PermissionDenied,
DeleteProvider,
SectionLoading,
-} from '../../components';
-import { ROLE_MAPPINGS_PATH } from '../../../management_urls';
-import { validateRoleMappingForSave } from '../services/role_mapping_validation';
+} from '../components';
+import { RolesAPIClient } from '../../roles';
+import { ROLE_MAPPINGS_PATH } from '../../management_urls';
+import { validateRoleMappingForSave } from './services/role_mapping_validation';
import { MappingInfoPanel } from './mapping_info_panel';
-import { documentationLinks } from '../../services/documentation_links';
+import { DocumentationLinksService } from '../documentation_links';
+import { RoleMappingsAPIClient } from '../role_mappings_api_client';
interface State {
loadState: 'loading' | 'permissionDenied' | 'ready' | 'saveInProgress';
@@ -50,7 +51,10 @@ interface State {
interface Props {
name?: string;
- roleMappingsAPI: RoleMappingsAPI;
+ roleMappingsAPI: PublicMethodsOf;
+ rolesAPIClient: PublicMethodsOf;
+ notifications: NotificationsStart;
+ docLinks: DocumentationLinksService;
}
export class EditRoleMappingPage extends Component {
@@ -74,6 +78,12 @@ export class EditRoleMappingPage extends Component {
this.loadAppData();
}
+ public async componentDidUpdate(prevProps: Props) {
+ if (prevProps.name !== this.props.name) {
+ await this.loadAppData();
+ }
+ }
+
public render() {
const { loadState } = this.state;
@@ -101,6 +111,8 @@ export class EditRoleMappingPage extends Component {
validateForm={this.state.validateForm}
canUseInlineScripts={this.state.canUseInlineScripts}
canUseStoredScripts={this.state.canUseStoredScripts}
+ rolesAPIClient={this.props.rolesAPIClient}
+ docLinks={this.props.docLinks}
/>
{
},
})
}
+ docLinks={this.props.docLinks}
/>
{this.getFormButtons()}
@@ -149,7 +162,7 @@ export class EditRoleMappingPage extends Component {
values={{
learnMoreLink: (
@@ -166,7 +179,7 @@ export class EditRoleMappingPage extends Component {
{!this.state.hasCompatibleRealms && (
<>
-
+
>
)}
@@ -201,7 +214,10 @@ export class EditRoleMappingPage extends Component {
{this.editingExistingRoleMapping() && (
-
+
{deleteRoleMappingsPrompt => {
return (
{
this.props.roleMappingsAPI
.saveRoleMapping(this.state.roleMapping)
.then(() => {
- toastNotifications.addSuccess({
+ this.props.notifications.toasts.addSuccess({
title: i18n.translate('xpack.security.management.editRoleMapping.saveSuccess', {
defaultMessage: `Saved role mapping '{roleMappingName}'`,
values: {
@@ -264,7 +280,7 @@ export class EditRoleMappingPage extends Component {
this.backToRoleMappingsList();
})
.catch(e => {
- toastNotifications.addError(e, {
+ this.props.notifications.toasts.addError(e, {
title: i18n.translate('xpack.security.management.editRoleMapping.saveError', {
defaultMessage: `Error saving role mapping`,
}),
@@ -312,7 +328,7 @@ export class EditRoleMappingPage extends Component {
roleMapping,
});
} catch (e) {
- toastNotifications.addDanger({
+ this.props.notifications.toasts.addDanger({
title: i18n.translate(
'xpack.security.management.editRoleMapping.table.fetchingRoleMappingsErrorMessage',
{
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/index.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/index.ts
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/index.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/index.ts
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/mapping_info_panel.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.test.tsx
similarity index 82%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/mapping_info_panel.test.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.test.tsx
index d821b33ace6a7..9b62ca27ca569 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/mapping_info_panel.test.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.test.tsx
@@ -6,21 +6,27 @@
import React from 'react';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
-import { MappingInfoPanel } from '.';
-import { RoleMapping } from '../../../../../../../common/model';
import { findTestSubject } from 'test_utils/find_test_subject';
+import { Role, RoleMapping } from '../../../../../common/model';
+import { RolesAPIClient } from '../../../roles';
+import { DocumentationLinksService } from '../../documentation_links';
import { RoleSelector } from '../role_selector';
import { RoleTemplateEditor } from '../role_selector/role_template_editor';
+import { MappingInfoPanel } from '.';
-jest.mock('../../../../../../lib/roles_api', () => {
- return {
- RolesApi: {
- getRoles: () => Promise.resolve([{ name: 'foo_role' }, { name: 'bar role' }]),
- },
- };
-});
+import { rolesAPIClientMock } from '../../../roles/roles_api_client.mock';
+import { coreMock } from '../../../../../../../../src/core/public/mocks';
describe('MappingInfoPanel', () => {
+ let rolesAPI: PublicMethodsOf;
+ beforeEach(() => {
+ rolesAPI = rolesAPIClientMock.create();
+ (rolesAPI as jest.Mocked).getRoles.mockResolvedValue([
+ { name: 'foo_role' },
+ { name: 'bar role' },
+ ] as Role[]);
+ });
+
it('renders when creating a role mapping, default to the "roles" view', () => {
const props = {
roleMapping: {
@@ -32,6 +38,8 @@ describe('MappingInfoPanel', () => {
metadata: {},
} as RoleMapping,
mode: 'create',
+ docLinks: new DocumentationLinksService(coreMock.createStart().docLinks),
+ rolesAPIClient: rolesAPI,
} as MappingInfoPanel['props'];
const wrapper = mountWithIntl();
@@ -77,6 +85,8 @@ describe('MappingInfoPanel', () => {
metadata: {},
} as RoleMapping,
mode: 'edit',
+ docLinks: new DocumentationLinksService(coreMock.createStart().docLinks),
+ rolesAPIClient: rolesAPI,
} as MappingInfoPanel['props'];
const wrapper = mountWithIntl();
@@ -101,6 +111,8 @@ describe('MappingInfoPanel', () => {
canUseInlineScripts: true,
canUseStoredScripts: false,
validateForm: false,
+ docLinks: new DocumentationLinksService(coreMock.createStart().docLinks),
+ rolesAPIClient: rolesAPI,
};
const wrapper = mountWithIntl();
@@ -140,6 +152,8 @@ describe('MappingInfoPanel', () => {
canUseInlineScripts: false,
canUseStoredScripts: true,
validateForm: false,
+ docLinks: new DocumentationLinksService(coreMock.createStart().docLinks),
+ rolesAPIClient: rolesAPI,
};
const wrapper = mountWithIntl();
@@ -179,6 +193,8 @@ describe('MappingInfoPanel', () => {
canUseInlineScripts: false,
canUseStoredScripts: false,
validateForm: false,
+ docLinks: new DocumentationLinksService(coreMock.createStart().docLinks),
+ rolesAPIClient: rolesAPI,
};
const wrapper = mountWithIntl();
@@ -202,6 +218,8 @@ describe('MappingInfoPanel', () => {
metadata: {},
} as RoleMapping,
mode: 'edit',
+ docLinks: new DocumentationLinksService(coreMock.createStart().docLinks),
+ rolesAPIClient: rolesAPI,
} as MappingInfoPanel['props'];
const wrapper = mountWithIntl();
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/mapping_info_panel.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.tsx
similarity index 95%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/mapping_info_panel.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.tsx
index a02b4fc1709f0..02af6bfbafa7e 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/mapping_info_panel/mapping_info_panel.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.tsx
@@ -18,14 +18,15 @@ import {
EuiSwitch,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
-import { RoleMapping } from '../../../../../../../common/model';
+import { RoleMapping } from '../../../../../common/model';
+import { RolesAPIClient } from '../../../roles';
import {
validateRoleMappingName,
validateRoleMappingRoles,
validateRoleMappingRoleTemplates,
-} from '../../services/role_mapping_validation';
+} from '../services/role_mapping_validation';
import { RoleSelector } from '../role_selector';
-import { documentationLinks } from '../../../services/documentation_links';
+import { DocumentationLinksService } from '../../documentation_links';
interface Props {
roleMapping: RoleMapping;
@@ -34,6 +35,8 @@ interface Props {
validateForm: boolean;
canUseInlineScripts: boolean;
canUseStoredScripts: boolean;
+ rolesAPIClient: PublicMethodsOf;
+ docLinks: DocumentationLinksService;
}
interface State {
@@ -163,6 +166,7 @@ export class MappingInfoPanel extends Component {
>
{
defaultMessage="Create templates that describe the roles to assign to your users."
/>{' '}
@@ -230,6 +234,7 @@ export class MappingInfoPanel extends Component {
>
{
- return {
- RolesApi: {
- getRoles: () => Promise.resolve([{ name: 'foo_role' }, { name: 'bar role' }]),
- },
- };
-});
+import { RolesAPIClient } from '../../../roles';
+import { rolesAPIClientMock } from '../../../roles/roles_api_client.mock';
describe('RoleSelector', () => {
+ let rolesAPI: PublicMethodsOf;
+ beforeEach(() => {
+ rolesAPI = rolesAPIClientMock.create();
+ (rolesAPI as jest.Mocked).getRoles.mockResolvedValue([
+ { name: 'foo_role' },
+ { name: 'bar role' },
+ ] as Role[]);
+ });
+
it('allows roles to be selected, removing any previously selected role templates', () => {
const props = {
roleMapping: {
@@ -36,6 +39,7 @@ describe('RoleSelector', () => {
canUseInlineScripts: true,
onChange: jest.fn(),
mode: 'roles',
+ rolesAPIClient: rolesAPI,
} as RoleSelector['props'];
const wrapper = mountWithIntl();
@@ -57,6 +61,7 @@ describe('RoleSelector', () => {
canUseInlineScripts: true,
onChange: jest.fn(),
mode: 'templates',
+ rolesAPIClient: rolesAPI,
} as RoleSelector['props'];
const wrapper = mountWithIntl();
@@ -87,6 +92,7 @@ describe('RoleSelector', () => {
canUseInlineScripts: true,
onChange: jest.fn(),
mode: 'templates',
+ rolesAPIClient: rolesAPI,
} as RoleSelector['props'];
const wrapper = mountWithIntl();
@@ -122,6 +128,7 @@ describe('RoleSelector', () => {
canUseInlineScripts: true,
onChange: jest.fn(),
mode: 'templates',
+ rolesAPIClient: rolesAPI,
} as RoleSelector['props'];
const wrapper = mountWithIntl();
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_selector.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_selector.tsx
similarity index 94%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_selector.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_selector.tsx
index 6b92d6b4907f1..992c2741ae93e 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_selector.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_selector.tsx
@@ -7,12 +7,13 @@
import React, { Fragment } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiComboBox, EuiFormRow, EuiHorizontalRule } from '@elastic/eui';
-import { RoleMapping, Role } from '../../../../../../../common/model';
-import { RolesApi } from '../../../../../../lib/roles_api';
+import { RoleMapping, Role } from '../../../../../common/model';
+import { RolesAPIClient } from '../../../roles';
import { AddRoleTemplateButton } from './add_role_template_button';
import { RoleTemplateEditor } from './role_template_editor';
interface Props {
+ rolesAPIClient: PublicMethodsOf;
roleMapping: RoleMapping;
canUseInlineScripts: boolean;
canUseStoredScripts: boolean;
@@ -32,7 +33,7 @@ export class RoleSelector extends React.Component {
}
public async componentDidMount() {
- const roles = await RolesApi.getRoles();
+ const roles = await this.props.rolesAPIClient.getRoles();
this.setState({ roles });
}
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_editor.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_editor.test.tsx
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_editor.test.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_editor.test.tsx
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_editor.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_editor.tsx
similarity index 98%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_editor.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_editor.tsx
index 4b8d34d271996..d79651d7b9cd6 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_editor.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_editor.tsx
@@ -18,12 +18,12 @@ import {
EuiSpacer,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { RoleTemplate } from '../../../../../../../common/model';
+import { RoleTemplate } from '../../../../../common/model';
import {
isInlineRoleTemplate,
isStoredRoleTemplate,
isInvalidRoleTemplate,
-} from '../../services/role_template_type';
+} from '../services/role_template_type';
import { RoleTemplateTypeSelect } from './role_template_type_select';
interface Props {
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_type_select.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_type_select.tsx
similarity index 92%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_type_select.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_type_select.tsx
index 4a06af0fb436b..aa65c5c9bcae7 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/role_selector/role_template_type_select.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_template_type_select.tsx
@@ -7,8 +7,8 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import { EuiComboBox } from '@elastic/eui';
-import { RoleTemplate } from '../../../../../../../common/model';
-import { isInlineRoleTemplate, isStoredRoleTemplate } from '../../services/role_template_type';
+import { RoleTemplate } from '../../../../../common/model';
+import { isInlineRoleTemplate, isStoredRoleTemplate } from '../services/role_template_type';
const templateTypeOptions = [
{
diff --git a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/_index.scss b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/_index.scss
new file mode 100644
index 0000000000000..c3b2764e64713
--- /dev/null
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/_index.scss
@@ -0,0 +1 @@
+@import './rule_editor_group';
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/_index.scss b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/_rule_editor_group.scss
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/_index.scss
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/_rule_editor_group.scss
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/add_rule_button.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/add_rule_button.test.tsx
similarity index 97%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/add_rule_button.test.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/add_rule_button.test.tsx
index 917b822acef3f..d1411bd9bf2b9 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/add_rule_button.test.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/add_rule_button.test.tsx
@@ -8,7 +8,7 @@ import React from 'react';
import { AddRuleButton } from './add_rule_button';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
import { findTestSubject } from 'test_utils/find_test_subject';
-import { FieldRule, AllRule } from '../../../model';
+import { FieldRule, AllRule } from '../../model';
describe('AddRuleButton', () => {
it('allows a field rule to be created', () => {
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/add_rule_button.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/add_rule_button.tsx
similarity index 97%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/add_rule_button.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/add_rule_button.tsx
index 100c0dd3eeaee..9696fa337a74f 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/add_rule_button.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/add_rule_button.tsx
@@ -7,7 +7,7 @@
import React, { useState } from 'react';
import { EuiButtonEmpty, EuiPopover, EuiContextMenuPanel, EuiContextMenuItem } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
-import { Rule, FieldRule, AllRule } from '../../../model';
+import { Rule, FieldRule, AllRule } from '../../model';
interface Props {
onClick: (newRule: Rule) => void;
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/field_rule_editor.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/field_rule_editor.test.tsx
similarity index 99%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/field_rule_editor.test.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/field_rule_editor.test.tsx
index 8d5d5c99ee99d..5374f4625336d 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/field_rule_editor.test.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/field_rule_editor.test.tsx
@@ -7,7 +7,7 @@
import React from 'react';
import { FieldRuleEditor } from './field_rule_editor';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
-import { FieldRule } from '../../../model';
+import { FieldRule } from '../../model';
import { findTestSubject } from 'test_utils/find_test_subject';
import { ReactWrapper } from 'enzyme';
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/field_rule_editor.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/field_rule_editor.tsx
similarity index 99%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/field_rule_editor.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/field_rule_editor.tsx
index 52cf70dbd12bd..2506c18dcaf3a 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/field_rule_editor.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/field_rule_editor.tsx
@@ -18,7 +18,7 @@ import {
EuiIcon,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { FieldRule, FieldRuleValue } from '../../../model';
+import { FieldRule, FieldRuleValue } from '../../model';
interface Props {
rule: FieldRule;
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/index.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/index.tsx
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/index.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/index.tsx
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/json_rule_editor.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.test.tsx
similarity index 89%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/json_rule_editor.test.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.test.tsx
index 8a9b37ab0f406..263c456e901cd 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/json_rule_editor.test.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.test.tsx
@@ -17,7 +17,10 @@ import { act } from 'react-dom/test-utils';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
import { JSONRuleEditor } from './json_rule_editor';
import { EuiCodeEditor } from '@elastic/eui';
-import { AllRule, AnyRule, FieldRule, ExceptAnyRule, ExceptAllRule } from '../../../model';
+import { AllRule, AnyRule, FieldRule, ExceptAnyRule, ExceptAllRule } from '../../model';
+import { DocumentationLinksService } from '../../documentation_links';
+
+import { coreMock } from '../../../../../../../../src/core/public/mocks';
describe('JSONRuleEditor', () => {
it('renders an empty rule set', () => {
@@ -25,6 +28,7 @@ describe('JSONRuleEditor', () => {
rules: null,
onChange: jest.fn(),
onValidityChange: jest.fn(),
+ docLinks: new DocumentationLinksService(coreMock.createStart().docLinks),
};
const wrapper = mountWithIntl();
@@ -46,6 +50,7 @@ describe('JSONRuleEditor', () => {
]),
onChange: jest.fn(),
onValidityChange: jest.fn(),
+ docLinks: new DocumentationLinksService(coreMock.createStart().docLinks),
};
const wrapper = mountWithIntl();
@@ -79,6 +84,7 @@ describe('JSONRuleEditor', () => {
rules: null,
onChange: jest.fn(),
onValidityChange: jest.fn(),
+ docLinks: new DocumentationLinksService(coreMock.createStart().docLinks),
};
const wrapper = mountWithIntl();
@@ -100,6 +106,7 @@ describe('JSONRuleEditor', () => {
rules: null,
onChange: jest.fn(),
onValidityChange: jest.fn(),
+ docLinks: new DocumentationLinksService(coreMock.createStart().docLinks),
};
const wrapper = mountWithIntl();
@@ -130,6 +137,7 @@ describe('JSONRuleEditor', () => {
rules: null,
onChange: jest.fn(),
onValidityChange: jest.fn(),
+ docLinks: new DocumentationLinksService(coreMock.createStart().docLinks),
};
const wrapper = mountWithIntl();
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/json_rule_editor.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.tsx
similarity index 95%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/json_rule_editor.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.tsx
index 371fb59f7a5d1..e7a9149513d20 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/json_rule_editor.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.tsx
@@ -11,13 +11,14 @@ import 'brace/theme/github';
import { EuiCodeEditor, EuiFormRow, EuiButton, EuiSpacer, EuiLink, EuiText } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
-import { Rule, RuleBuilderError, generateRulesFromRaw } from '../../../model';
-import { documentationLinks } from '../../../services/documentation_links';
+import { DocumentationLinksService } from '../../documentation_links';
+import { Rule, RuleBuilderError, generateRulesFromRaw } from '../../model';
interface Props {
rules: Rule | null;
onChange: (updatedRules: Rule | null) => void;
onValidityChange: (isValid: boolean) => void;
+ docLinks: DocumentationLinksService;
}
export const JSONRuleEditor = (props: Props) => {
@@ -107,7 +108,7 @@ export const JSONRuleEditor = (props: Props) => {
values={{
roleMappingAPI: (
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_editor_panel.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_editor_panel.test.tsx
similarity index 88%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_editor_panel.test.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_editor_panel.test.tsx
index 809264183d30c..b9c650cc1f77a 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_editor_panel.test.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_editor_panel.test.tsx
@@ -15,8 +15,11 @@ import { findTestSubject } from 'test_utils/find_test_subject';
// This is not required for the tests to pass, but it rather suppresses lengthy
// warnings in the console which adds unnecessary noise to the test output.
import 'test_utils/stub_web_worker';
-import { AllRule, FieldRule } from '../../../model';
+import { AllRule, FieldRule } from '../../model';
import { EuiErrorBoundary } from '@elastic/eui';
+import { DocumentationLinksService } from '../../documentation_links';
+
+import { coreMock } from '../../../../../../../../src/core/public/mocks';
describe('RuleEditorPanel', () => {
it('renders the visual editor when no rules are defined', () => {
@@ -25,6 +28,7 @@ describe('RuleEditorPanel', () => {
onChange: jest.fn(),
onValidityChange: jest.fn(),
validateForm: false,
+ docLinks: new DocumentationLinksService(coreMock.createStart().docLinks),
};
const wrapper = mountWithIntl();
expect(wrapper.find(VisualRuleEditor)).toHaveLength(1);
@@ -45,6 +49,7 @@ describe('RuleEditorPanel', () => {
onChange: jest.fn(),
onValidityChange: jest.fn(),
validateForm: false,
+ docLinks: new DocumentationLinksService(coreMock.createStart().docLinks),
};
const wrapper = mountWithIntl();
expect(wrapper.find(VisualRuleEditor)).toHaveLength(1);
@@ -68,6 +73,7 @@ describe('RuleEditorPanel', () => {
onChange: jest.fn(),
onValidityChange: jest.fn(),
validateForm: false,
+ docLinks: new DocumentationLinksService(coreMock.createStart().docLinks),
};
const wrapper = mountWithIntl();
@@ -103,6 +109,7 @@ describe('RuleEditorPanel', () => {
onChange: jest.fn(),
onValidityChange: jest.fn(),
validateForm: false,
+ docLinks: new DocumentationLinksService(coreMock.createStart().docLinks),
};
const wrapper = mountWithIntl();
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_editor_panel.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_editor_panel.tsx
similarity index 94%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_editor_panel.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_editor_panel.tsx
index 4aab49b2b2efc..6e6641caa1f39 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_editor_panel.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_editor_panel.tsx
@@ -22,19 +22,20 @@ import {
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
-import { RoleMapping } from '../../../../../../../common/model';
+import { RoleMapping } from '../../../../../common/model';
import { VisualRuleEditor } from './visual_rule_editor';
import { JSONRuleEditor } from './json_rule_editor';
-import { VISUAL_MAX_RULE_DEPTH } from '../../services/role_mapping_constants';
-import { Rule, generateRulesFromRaw } from '../../../model';
-import { validateRoleMappingRules } from '../../services/role_mapping_validation';
-import { documentationLinks } from '../../../services/documentation_links';
+import { VISUAL_MAX_RULE_DEPTH } from '../services/role_mapping_constants';
+import { Rule, generateRulesFromRaw } from '../../model';
+import { DocumentationLinksService } from '../../documentation_links';
+import { validateRoleMappingRules } from '../services/role_mapping_validation';
interface Props {
rawRules: RoleMapping['rules'];
onChange: (rawRules: RoleMapping['rules']) => void;
onValidityChange: (isValid: boolean) => void;
validateForm: boolean;
+ docLinks: DocumentationLinksService;
}
interface State {
@@ -91,7 +92,7 @@ export class RuleEditorPanel extends Component {
values={{
learnMoreLink: (
@@ -214,6 +215,7 @@ export class RuleEditorPanel extends Component {
rules={this.state.rules}
onChange={this.onRuleChange}
onValidityChange={this.onValidityChange}
+ docLinks={this.props.docLinks}
/>
);
default:
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_editor.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_editor.test.tsx
similarity index 99%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_editor.test.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_editor.test.tsx
index 3e0e0e386e98c..5946aac4306b1 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_editor.test.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_editor.test.tsx
@@ -7,7 +7,7 @@
import React from 'react';
import { RuleGroupEditor } from './rule_group_editor';
import { shallowWithIntl, mountWithIntl, nextTick } from 'test_utils/enzyme_helpers';
-import { AllRule, FieldRule, AnyRule, ExceptAnyRule } from '../../../model';
+import { AllRule, FieldRule, AnyRule, ExceptAnyRule } from '../../model';
import { FieldRuleEditor } from './field_rule_editor';
import { AddRuleButton } from './add_rule_button';
import { EuiContextMenuItem } from '@elastic/eui';
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_editor.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_editor.tsx
similarity index 97%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_editor.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_editor.tsx
index 6fb33db179e8a..c17a853a65467 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_editor.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_editor.tsx
@@ -16,8 +16,8 @@ import { FormattedMessage } from '@kbn/i18n/react';
import { AddRuleButton } from './add_rule_button';
import { RuleGroupTitle } from './rule_group_title';
import { FieldRuleEditor } from './field_rule_editor';
-import { RuleGroup, Rule, FieldRule } from '../../../model';
-import { isRuleGroup } from '../../services/is_rule_group';
+import { RuleGroup, Rule, FieldRule } from '../../model';
+import { isRuleGroup } from '../services/is_rule_group';
interface Props {
rule: RuleGroup;
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_title.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_title.tsx
similarity index 97%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_title.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_title.tsx
index e46893afd4d86..6bef9c09eeef3 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/rule_group_title.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/rule_group_title.tsx
@@ -15,14 +15,7 @@ import {
EuiConfirmModal,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
-import {
- RuleGroup,
- AllRule,
- AnyRule,
- ExceptAllRule,
- ExceptAnyRule,
- FieldRule,
-} from '../../../model';
+import { RuleGroup, AllRule, AnyRule, ExceptAllRule, ExceptAnyRule, FieldRule } from '../../model';
interface Props {
rule: RuleGroup;
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/visual_rule_editor.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/visual_rule_editor.test.tsx
similarity index 99%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/visual_rule_editor.test.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/visual_rule_editor.test.tsx
index 7c63613ee1cc9..b40f0063acb08 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/visual_rule_editor.test.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/visual_rule_editor.test.tsx
@@ -8,7 +8,7 @@ import React from 'react';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
import { VisualRuleEditor } from './visual_rule_editor';
import { findTestSubject } from 'test_utils/find_test_subject';
-import { AnyRule, AllRule, FieldRule, ExceptAnyRule, ExceptAllRule } from '../../../model';
+import { AnyRule, AllRule, FieldRule, ExceptAnyRule, ExceptAllRule } from '../../model';
import { RuleGroupEditor } from './rule_group_editor';
import { FieldRuleEditor } from './field_rule_editor';
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/visual_rule_editor.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/visual_rule_editor.tsx
similarity index 95%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/visual_rule_editor.tsx
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/visual_rule_editor.tsx
index 214c583189fb8..2e3db275788ee 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/components/rule_editor_panel/visual_rule_editor.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/visual_rule_editor.tsx
@@ -9,9 +9,9 @@ import { EuiEmptyPrompt, EuiCallOut, EuiSpacer, EuiButton } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { FieldRuleEditor } from './field_rule_editor';
import { RuleGroupEditor } from './rule_group_editor';
-import { VISUAL_MAX_RULE_DEPTH } from '../../services/role_mapping_constants';
-import { Rule, FieldRule, RuleGroup, AllRule } from '../../../model';
-import { isRuleGroup } from '../../services/is_rule_group';
+import { VISUAL_MAX_RULE_DEPTH } from '../services/role_mapping_constants';
+import { Rule, FieldRule, RuleGroup, AllRule } from '../../model';
+import { isRuleGroup } from '../services/is_rule_group';
interface Props {
rules: Rule | null;
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/is_rule_group.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/is_rule_group.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/is_rule_group.ts
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/is_rule_group.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_constants.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_constants.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_constants.ts
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_constants.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_validation.test.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_validation.test.ts
similarity index 98%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_validation.test.ts
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_validation.test.ts
index 9614c4338b631..0c3f988ae6b10 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_validation.test.ts
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_validation.test.ts
@@ -10,7 +10,7 @@ import {
validateRoleMappingRules,
validateRoleMappingForSave,
} from './role_mapping_validation';
-import { RoleMapping } from '../../../../../../common/model';
+import { RoleMapping } from '../../../../../common/model';
describe('validateRoleMappingName', () => {
it('requires a value', () => {
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_validation.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_validation.ts
similarity index 97%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_validation.ts
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_validation.ts
index 5916d6fd9e189..7695f1da14881 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_mapping_validation.ts
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_mapping_validation.ts
@@ -5,7 +5,7 @@
*/
import { i18n } from '@kbn/i18n';
-import { RoleMapping } from '../../../../../../common/model';
+import { RoleMapping } from '../../../../../common/model';
import { generateRulesFromRaw } from '../../model';
interface ValidationResult {
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_template_type.test.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_template_type.test.ts
similarity index 96%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_template_type.test.ts
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_template_type.test.ts
index 8e1f47a4157ae..c093bb1b3fbbc 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_template_type.test.ts
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_template_type.test.ts
@@ -9,7 +9,7 @@ import {
isInlineRoleTemplate,
isInvalidRoleTemplate,
} from './role_template_type';
-import { RoleTemplate } from '../../../../../../common/model';
+import { RoleTemplate } from '../../../../../common/model';
describe('#isStoredRoleTemplate', () => {
it('returns true for stored templates, false otherwise', () => {
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_template_type.ts b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_template_type.ts
similarity index 96%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_template_type.ts
rename to x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_template_type.ts
index 90d8d1a09e587..5e646535a6c4d 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/edit_role_mapping/services/role_template_type.ts
+++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/services/role_template_type.ts
@@ -9,7 +9,7 @@ import {
StoredRoleTemplate,
InlineRoleTemplate,
InvalidRoleTemplate,
-} from '../../../../../../common/model';
+} from '../../../../../common/model';
export function isStoredRoleTemplate(
roleMappingTemplate: RoleTemplate
diff --git a/x-pack/plugins/security/public/management/role_mappings/index.mock.ts b/x-pack/plugins/security/public/management/role_mappings/index.mock.ts
new file mode 100644
index 0000000000000..826477a1a5b15
--- /dev/null
+++ b/x-pack/plugins/security/public/management/role_mappings/index.mock.ts
@@ -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 { roleMappingsAPIClientMock } from './role_mappings_api_client.mock';
diff --git a/x-pack/plugins/security/public/management/role_mappings/index.ts b/x-pack/plugins/security/public/management/role_mappings/index.ts
new file mode 100644
index 0000000000000..f670ea6181038
--- /dev/null
+++ b/x-pack/plugins/security/public/management/role_mappings/index.ts
@@ -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 { roleMappingsManagementApp } from './role_mappings_management_app';
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/__snapshots__/rule_builder.test.ts.snap b/x-pack/plugins/security/public/management/role_mappings/model/__snapshots__/rule_builder.test.ts.snap
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/__snapshots__/rule_builder.test.ts.snap
rename to x-pack/plugins/security/public/management/role_mappings/model/__snapshots__/rule_builder.test.ts.snap
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/all_rule.test.ts b/x-pack/plugins/security/public/management/role_mappings/model/all_rule.test.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/all_rule.test.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/all_rule.test.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/all_rule.ts b/x-pack/plugins/security/public/management/role_mappings/model/all_rule.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/all_rule.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/all_rule.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/any_rule.test.ts b/x-pack/plugins/security/public/management/role_mappings/model/any_rule.test.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/any_rule.test.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/any_rule.test.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/any_rule.ts b/x-pack/plugins/security/public/management/role_mappings/model/any_rule.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/any_rule.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/any_rule.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_all_rule.test.ts b/x-pack/plugins/security/public/management/role_mappings/model/except_all_rule.test.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_all_rule.test.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/except_all_rule.test.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_all_rule.ts b/x-pack/plugins/security/public/management/role_mappings/model/except_all_rule.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_all_rule.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/except_all_rule.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_any_rule.test.ts b/x-pack/plugins/security/public/management/role_mappings/model/except_any_rule.test.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_any_rule.test.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/except_any_rule.test.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_any_rule.ts b/x-pack/plugins/security/public/management/role_mappings/model/except_any_rule.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/except_any_rule.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/except_any_rule.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/field_rule.test.ts b/x-pack/plugins/security/public/management/role_mappings/model/field_rule.test.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/field_rule.test.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/field_rule.test.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/field_rule.ts b/x-pack/plugins/security/public/management/role_mappings/model/field_rule.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/field_rule.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/field_rule.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/index.ts b/x-pack/plugins/security/public/management/role_mappings/model/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/index.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule.ts b/x-pack/plugins/security/public/management/role_mappings/model/rule.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/rule.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder.test.ts b/x-pack/plugins/security/public/management/role_mappings/model/rule_builder.test.ts
similarity index 99%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder.test.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/rule_builder.test.ts
index ebd48f6d15d99..ad486a8b314c4 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder.test.ts
+++ b/x-pack/plugins/security/public/management/role_mappings/model/rule_builder.test.ts
@@ -5,7 +5,7 @@
*/
import { generateRulesFromRaw, FieldRule } from '.';
-import { RoleMapping } from '../../../../../common/model';
+import { RoleMapping } from '../../../../common/model';
import { RuleBuilderError } from './rule_builder_error';
describe('generateRulesFromRaw', () => {
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder.ts b/x-pack/plugins/security/public/management/role_mappings/model/rule_builder.ts
similarity index 99%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/rule_builder.ts
index fe344b2ae38dd..a384e61e521ab 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder.ts
+++ b/x-pack/plugins/security/public/management/role_mappings/model/rule_builder.ts
@@ -5,7 +5,7 @@
*/
import { i18n } from '@kbn/i18n';
-import { RoleMapping } from '../../../../../common/model';
+import { RoleMapping } from '../../../../common/model';
import { FieldRule, FieldRuleValue } from './field_rule';
import { AllRule } from './all_rule';
import { AnyRule } from './any_rule';
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder_error.ts b/x-pack/plugins/security/public/management/role_mappings/model/rule_builder_error.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_builder_error.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/rule_builder_error.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_group.ts b/x-pack/plugins/security/public/management/role_mappings/model/rule_group.ts
similarity index 94%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_group.ts
rename to x-pack/plugins/security/public/management/role_mappings/model/rule_group.ts
index 3e1e7fad9b36f..5077c79a543c4 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/model/rule_group.ts
+++ b/x-pack/plugins/security/public/management/role_mappings/model/rule_group.ts
@@ -7,7 +7,7 @@
import { Rule } from './rule';
/**
- * Represents a catagory of Role Mapping rules which are capable of containing other rules.
+ * Represents a category of Role Mapping rules which are capable of containing other rules.
*/
export abstract class RuleGroup extends Rule {
/**
diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.mock.ts b/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.mock.ts
new file mode 100644
index 0000000000000..07d583d1e983f
--- /dev/null
+++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.mock.ts
@@ -0,0 +1,15 @@
+/*
+ * 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 roleMappingsAPIClientMock = {
+ create: () => ({
+ checkRoleMappingFeatures: jest.fn(),
+ getRoleMappings: jest.fn(),
+ getRoleMapping: jest.fn(),
+ saveRoleMapping: jest.fn(),
+ deleteRoleMappings: jest.fn(),
+ }),
+};
diff --git a/x-pack/legacy/plugins/security/public/lib/role_mappings_api.ts b/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.ts
similarity index 89%
rename from x-pack/legacy/plugins/security/public/lib/role_mappings_api.ts
rename to x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.ts
index b8bcba91388b5..0a88ed1da9ac3 100644
--- a/x-pack/legacy/plugins/security/public/lib/role_mappings_api.ts
+++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.ts
@@ -4,8 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { CoreSetup } from 'src/core/public';
-import { RoleMapping } from '../../common/model';
+import { HttpStart } from 'src/core/public';
+import { RoleMapping } from '../../../common/model';
interface CheckRoleMappingFeaturesResponse {
canManageRoleMappings: boolean;
@@ -20,8 +20,8 @@ type DeleteRoleMappingsResponse = Array<{
error?: Error;
}>;
-export class RoleMappingsAPI {
- constructor(private readonly http: CoreSetup['http']) {}
+export class RoleMappingsAPIClient {
+ constructor(private readonly http: HttpStart) {}
public async checkRoleMappingFeatures(): Promise {
return this.http.get(`/internal/security/_check_role_mapping_features`);
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/create_role_mapping_button/create_role_mapping_button.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx
similarity index 90%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/create_role_mapping_button/create_role_mapping_button.tsx
rename to x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx
index 2342eeb97d03e..6fe4bcc7a0bbb 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/create_role_mapping_button/create_role_mapping_button.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/create_role_mapping_button.tsx
@@ -7,7 +7,7 @@
import React from 'react';
import { EuiButton } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
-import { getCreateRoleMappingHref } from '../../../../management_urls';
+import { getCreateRoleMappingHref } from '../../../management_urls';
export const CreateRoleMappingButton = () => {
return (
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/create_role_mapping_button/index.ts b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/create_role_mapping_button/index.ts
rename to x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/create_role_mapping_button/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/empty_prompt/empty_prompt.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/empty_prompt/empty_prompt.tsx
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/empty_prompt/empty_prompt.tsx
rename to x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/empty_prompt/empty_prompt.tsx
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/empty_prompt/index.ts b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/empty_prompt/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/empty_prompt/index.ts
rename to x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/empty_prompt/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/index.ts b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/index.ts
rename to x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/index.ts
diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx
new file mode 100644
index 0000000000000..de0722b4cd85e
--- /dev/null
+++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx
@@ -0,0 +1,219 @@
+/*
+ * 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 { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers';
+import { RoleMappingsGridPage } from '.';
+import { SectionLoading, PermissionDenied, NoCompatibleRealms } from '../components';
+import { EmptyPrompt } from './empty_prompt';
+import { findTestSubject } from 'test_utils/find_test_subject';
+import { EuiLink } from '@elastic/eui';
+import { act } from '@testing-library/react';
+import { DocumentationLinksService } from '../documentation_links';
+
+import { coreMock } from '../../../../../../../src/core/public/mocks';
+import { roleMappingsAPIClientMock } from '../role_mappings_api_client.mock';
+
+describe('RoleMappingsGridPage', () => {
+ it('renders an empty prompt when no role mappings exist', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.getRoleMappings.mockResolvedValue([]);
+ roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({
+ canManageRoleMappings: true,
+ hasCompatibleRealms: true,
+ });
+
+ const { docLinks, notifications } = coreMock.createStart();
+ const wrapper = mountWithIntl(
+
+ );
+ expect(wrapper.find(SectionLoading)).toHaveLength(1);
+ expect(wrapper.find(EmptyPrompt)).toHaveLength(0);
+
+ await nextTick();
+ wrapper.update();
+
+ expect(wrapper.find(SectionLoading)).toHaveLength(0);
+ expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0);
+ expect(wrapper.find(EmptyPrompt)).toHaveLength(1);
+ });
+
+ it('renders a permission denied message when unauthorized to manage role mappings', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({
+ canManageRoleMappings: false,
+ hasCompatibleRealms: true,
+ });
+
+ const { docLinks, notifications } = coreMock.createStart();
+ const wrapper = mountWithIntl(
+
+ );
+ expect(wrapper.find(SectionLoading)).toHaveLength(1);
+ expect(wrapper.find(PermissionDenied)).toHaveLength(0);
+
+ await nextTick();
+ wrapper.update();
+
+ expect(wrapper.find(SectionLoading)).toHaveLength(0);
+ expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0);
+ expect(wrapper.find(PermissionDenied)).toHaveLength(1);
+ });
+
+ it('renders a warning when there are no compatible realms enabled', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.getRoleMappings.mockResolvedValue([
+ {
+ name: 'some realm',
+ enabled: true,
+ roles: [],
+ rules: { field: { username: '*' } },
+ },
+ ]);
+ roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({
+ canManageRoleMappings: true,
+ hasCompatibleRealms: false,
+ });
+
+ const { docLinks, notifications } = coreMock.createStart();
+ const wrapper = mountWithIntl(
+
+ );
+ expect(wrapper.find(SectionLoading)).toHaveLength(1);
+ expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0);
+
+ await nextTick();
+ wrapper.update();
+
+ expect(wrapper.find(SectionLoading)).toHaveLength(0);
+ expect(wrapper.find(NoCompatibleRealms)).toHaveLength(1);
+ });
+
+ it('renders links to mapped roles', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.getRoleMappings.mockResolvedValue([
+ {
+ name: 'some realm',
+ enabled: true,
+ roles: ['superuser'],
+ rules: { field: { username: '*' } },
+ },
+ ]);
+ roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({
+ canManageRoleMappings: true,
+ hasCompatibleRealms: true,
+ });
+
+ const { docLinks, notifications } = coreMock.createStart();
+ const wrapper = mountWithIntl(
+
+ );
+ await nextTick();
+ wrapper.update();
+
+ const links = findTestSubject(wrapper, 'roleMappingRoles').find(EuiLink);
+ expect(links).toHaveLength(1);
+ expect(links.at(0).props()).toMatchObject({
+ href: '#/management/security/roles/edit/superuser',
+ });
+ });
+
+ it('describes the number of mapped role templates', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.getRoleMappings.mockResolvedValue([
+ {
+ name: 'some realm',
+ enabled: true,
+ role_templates: [{}, {}],
+ rules: { field: { username: '*' } },
+ },
+ ]);
+ roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({
+ canManageRoleMappings: true,
+ hasCompatibleRealms: true,
+ });
+
+ const { docLinks, notifications } = coreMock.createStart();
+ const wrapper = mountWithIntl(
+
+ );
+ await nextTick();
+ wrapper.update();
+
+ const templates = findTestSubject(wrapper, 'roleMappingRoles');
+ expect(templates).toHaveLength(1);
+ expect(templates.text()).toEqual(`2 role templates defined`);
+ });
+
+ it('allows role mappings to be deleted, refreshing the grid after', async () => {
+ const roleMappingsAPI = roleMappingsAPIClientMock.create();
+ roleMappingsAPI.getRoleMappings.mockResolvedValue([
+ {
+ name: 'some-realm',
+ enabled: true,
+ roles: ['superuser'],
+ rules: { field: { username: '*' } },
+ },
+ ]);
+ roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({
+ canManageRoleMappings: true,
+ hasCompatibleRealms: true,
+ });
+ roleMappingsAPI.deleteRoleMappings.mockResolvedValue([
+ {
+ name: 'some-realm',
+ success: true,
+ },
+ ]);
+
+ const { docLinks, notifications } = coreMock.createStart();
+ const wrapper = mountWithIntl(
+
+ );
+ await nextTick();
+ wrapper.update();
+
+ expect(roleMappingsAPI.getRoleMappings).toHaveBeenCalledTimes(1);
+ expect(roleMappingsAPI.deleteRoleMappings).not.toHaveBeenCalled();
+
+ findTestSubject(wrapper, `deleteRoleMappingButton-some-realm`).simulate('click');
+ expect(findTestSubject(wrapper, 'deleteRoleMappingConfirmationModal')).toHaveLength(1);
+
+ await act(async () => {
+ findTestSubject(wrapper, 'confirmModalConfirmButton').simulate('click');
+ await nextTick();
+ wrapper.update();
+ });
+
+ expect(roleMappingsAPI.deleteRoleMappings).toHaveBeenCalledWith(['some-realm']);
+ // Expect an additional API call to refresh the grid
+ expect(roleMappingsAPI.getRoleMappings).toHaveBeenCalledTimes(2);
+ });
+});
diff --git a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/role_mappings_grid_page.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx
similarity index 93%
rename from x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/role_mappings_grid_page.tsx
rename to x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx
index 7b23f2288d1ba..feb918cb6b301 100644
--- a/x-pack/legacy/plugins/security/public/views/management/role_mappings/role_mappings_grid/components/role_mappings_grid_page.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx
@@ -25,24 +25,27 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { RoleMapping } from '../../../../../../common/model';
-import { RoleMappingsAPI } from '../../../../../lib/role_mappings_api';
+import { NotificationsStart } from 'src/core/public';
+import { RoleMapping } from '../../../../common/model';
import { EmptyPrompt } from './empty_prompt';
import {
NoCompatibleRealms,
DeleteProvider,
PermissionDenied,
SectionLoading,
-} from '../../components';
-import { documentationLinks } from '../../services/documentation_links';
+} from '../components';
import {
getCreateRoleMappingHref,
getEditRoleMappingHref,
getEditRoleHref,
-} from '../../../management_urls';
+} from '../../management_urls';
+import { DocumentationLinksService } from '../documentation_links';
+import { RoleMappingsAPIClient } from '../role_mappings_api_client';
interface Props {
- roleMappingsAPI: RoleMappingsAPI;
+ roleMappingsAPI: PublicMethodsOf;
+ notifications: NotificationsStart;
+ docLinks: DocumentationLinksService;
}
interface State {
@@ -140,7 +143,7 @@ export class RoleMappingsGridPage extends Component {
values={{
learnMoreLink: (
@@ -168,7 +171,7 @@ export class RoleMappingsGridPage extends Component {
{!this.state.hasCompatibleRealms && (
<>
-
+
>
)}
@@ -214,7 +217,10 @@ export class RoleMappingsGridPage extends Component {
const search = {
toolsLeft: selectedItems.length ? (
-
+
{deleteRoleMappingsPrompt => {
return (
{
return (
-
+
{deleteRoleMappingPrompt => {
return (
({
+ RoleMappingsGridPage: (props: any) => `Role Mappings Page: ${JSON.stringify(props)}`,
+}));
+
+jest.mock('./edit_role_mapping', () => ({
+ EditRoleMappingPage: (props: any) => `Role Mapping Edit Page: ${JSON.stringify(props)}`,
+}));
+
+import { roleMappingsManagementApp } from './role_mappings_management_app';
+
+import { coreMock } from '../../../../../../src/core/public/mocks';
+
+async function mountApp(basePath: string) {
+ const container = document.createElement('div');
+ const setBreadcrumbs = jest.fn();
+
+ const unmount = await roleMappingsManagementApp
+ .create({ getStartServices: coreMock.createSetup().getStartServices as any })
+ .mount({ basePath, element: container, setBreadcrumbs });
+
+ return { unmount, container, setBreadcrumbs };
+}
+
+describe('roleMappingsManagementApp', () => {
+ it('create() returns proper management app descriptor', () => {
+ expect(
+ roleMappingsManagementApp.create({
+ getStartServices: coreMock.createSetup().getStartServices as any,
+ })
+ ).toMatchInlineSnapshot(`
+ Object {
+ "id": "role_mappings",
+ "mount": [Function],
+ "order": 40,
+ "title": "Role Mappings",
+ }
+ `);
+ });
+
+ it('mount() works for the `grid` page', async () => {
+ const basePath = '/some-base-path/role_mappings';
+ window.location.hash = basePath;
+
+ const { setBreadcrumbs, container, unmount } = await mountApp(basePath);
+
+ expect(setBreadcrumbs).toHaveBeenCalledTimes(1);
+ expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `#${basePath}`, text: 'Role Mappings' }]);
+ expect(container).toMatchInlineSnapshot(`
+
+ Role Mappings Page: {"notifications":{"toasts":{}},"roleMappingsAPI":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"}}
+
+ `);
+
+ unmount();
+
+ expect(container).toMatchInlineSnapshot(``);
+ });
+
+ it('mount() works for the `create role mapping` page', async () => {
+ const basePath = '/some-base-path/role_mappings';
+ window.location.hash = `${basePath}/edit`;
+
+ const { setBreadcrumbs, container, unmount } = await mountApp(basePath);
+
+ expect(setBreadcrumbs).toHaveBeenCalledTimes(1);
+ expect(setBreadcrumbs).toHaveBeenCalledWith([
+ { href: `#${basePath}`, text: 'Role Mappings' },
+ { text: 'Create' },
+ ]);
+ expect(container).toMatchInlineSnapshot(`
+
+ Role Mapping Edit Page: {"roleMappingsAPI":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"}}
+
+ `);
+
+ unmount();
+
+ expect(container).toMatchInlineSnapshot(``);
+ });
+
+ it('mount() works for the `edit role mapping` page', async () => {
+ const basePath = '/some-base-path/role_mappings';
+ const roleMappingName = 'someRoleMappingName';
+ window.location.hash = `${basePath}/edit/${roleMappingName}`;
+
+ const { setBreadcrumbs, container, unmount } = await mountApp(basePath);
+
+ expect(setBreadcrumbs).toHaveBeenCalledTimes(1);
+ expect(setBreadcrumbs).toHaveBeenCalledWith([
+ { href: `#${basePath}`, text: 'Role Mappings' },
+ { href: `#/some-base-path/role_mappings/edit/${roleMappingName}`, text: roleMappingName },
+ ]);
+ expect(container).toMatchInlineSnapshot(`
+
+ Role Mapping Edit Page: {"name":"someRoleMappingName","roleMappingsAPI":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"}}
+
+ `);
+
+ unmount();
+
+ expect(container).toMatchInlineSnapshot(``);
+ });
+
+ it('mount() properly encodes role mapping name in `edit role mapping` page link in breadcrumbs', async () => {
+ const basePath = '/some-base-path/role_mappings';
+ const roleMappingName = 'some 安全性 role mapping';
+ window.location.hash = `${basePath}/edit/${roleMappingName}`;
+
+ const { setBreadcrumbs } = await mountApp(basePath);
+
+ expect(setBreadcrumbs).toHaveBeenCalledTimes(1);
+ expect(setBreadcrumbs).toHaveBeenCalledWith([
+ { href: `#${basePath}`, text: 'Role Mappings' },
+ {
+ href:
+ '#/some-base-path/role_mappings/edit/some%20%E5%AE%89%E5%85%A8%E6%80%A7%20role%20mapping',
+ text: roleMappingName,
+ },
+ ]);
+ });
+});
diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx
new file mode 100644
index 0000000000000..af1572cedbade
--- /dev/null
+++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx
@@ -0,0 +1,104 @@
+/*
+ * 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 { render, unmountComponentAtNode } from 'react-dom';
+import { HashRouter as Router, Route, Switch, useParams } from 'react-router-dom';
+import { i18n } from '@kbn/i18n';
+import { CoreSetup } from 'src/core/public';
+import { RegisterManagementAppArgs } from '../../../../../../src/plugins/management/public';
+import { PluginStartDependencies } from '../../plugin';
+import { RolesAPIClient } from '../roles';
+import { RoleMappingsAPIClient } from './role_mappings_api_client';
+import { DocumentationLinksService } from './documentation_links';
+import { RoleMappingsGridPage } from './role_mappings_grid';
+import { EditRoleMappingPage } from './edit_role_mapping';
+
+interface CreateParams {
+ getStartServices: CoreSetup['getStartServices'];
+}
+
+export const roleMappingsManagementApp = Object.freeze({
+ id: 'role_mappings',
+ create({ getStartServices }: CreateParams) {
+ return {
+ id: this.id,
+ order: 40,
+ title: i18n.translate('xpack.security.management.roleMappingsTitle', {
+ defaultMessage: 'Role Mappings',
+ }),
+ async mount({ basePath, element, setBreadcrumbs }) {
+ const [{ docLinks, http, notifications, i18n: i18nStart }] = await getStartServices();
+ const roleMappingsBreadcrumbs = [
+ {
+ text: i18n.translate('xpack.security.roleMapping.breadcrumb', {
+ defaultMessage: 'Role Mappings',
+ }),
+ href: `#${basePath}`,
+ },
+ ];
+
+ const roleMappingsAPIClient = new RoleMappingsAPIClient(http);
+ const dockLinksService = new DocumentationLinksService(docLinks);
+ const RoleMappingsGridPageWithBreadcrumbs = () => {
+ setBreadcrumbs(roleMappingsBreadcrumbs);
+ return (
+
+ );
+ };
+
+ const EditRoleMappingsPageWithBreadcrumbs = () => {
+ const { name } = useParams<{ name?: string }>();
+
+ setBreadcrumbs([
+ ...roleMappingsBreadcrumbs,
+ name
+ ? { text: name, href: `#${basePath}/edit/${encodeURIComponent(name)}` }
+ : {
+ text: i18n.translate('xpack.security.roleMappings.createBreadcrumb', {
+ defaultMessage: 'Create',
+ }),
+ },
+ ]);
+
+ return (
+
+ );
+ };
+
+ render(
+
+
+
+
+
+
+
+
+
+
+
+ ,
+ element
+ );
+
+ return () => {
+ unmountComponentAtNode(element);
+ };
+ },
+ } as RegisterManagementAppArgs;
+ },
+});
diff --git a/x-pack/plugins/security/public/management/roles/_index.scss b/x-pack/plugins/security/public/management/roles/_index.scss
new file mode 100644
index 0000000000000..5256c79f01f10
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/_index.scss
@@ -0,0 +1 @@
+@import './edit_role/index';
diff --git a/x-pack/plugins/security/public/management/roles/documentation_links.ts b/x-pack/plugins/security/public/management/roles/documentation_links.ts
new file mode 100644
index 0000000000000..cf46973d3541c
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/documentation_links.ts
@@ -0,0 +1,27 @@
+/*
+ * 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 { DocLinksStart } from 'src/core/public';
+
+export class DocumentationLinksService {
+ private readonly esDocBasePath: string;
+
+ constructor(docLinks: DocLinksStart) {
+ this.esDocBasePath = `${docLinks.ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${docLinks.DOC_LINK_VERSION}/`;
+ }
+
+ public getESClusterPrivilegesDocUrl() {
+ return `${this.esDocBasePath}security-privileges.html#privileges-list-cluster`;
+ }
+
+ public getESRunAsPrivilegesDocUrl() {
+ return `${this.esDocBasePath}security-privileges.html#_run_as_privilege`;
+ }
+
+ public getESIndicesPrivilegesDocUrl() {
+ return `${this.esDocBasePath}security-privileges.html#privileges-list-indices`;
+ }
+}
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/lib/__snapshots__/validate_role.test.ts.snap b/x-pack/plugins/security/public/management/roles/edit_role/__snapshots__/validate_role.test.ts.snap
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/lib/__snapshots__/validate_role.test.ts.snap
rename to x-pack/plugins/security/public/management/roles/edit_role/__snapshots__/validate_role.test.ts.snap
diff --git a/x-pack/plugins/security/public/management/roles/edit_role/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/_index.scss
new file mode 100644
index 0000000000000..0153b1734ceba
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/edit_role/_index.scss
@@ -0,0 +1,3 @@
+@import './collapsible_panel/index';
+@import './spaces_popover_list/index';
+@import './privileges/index';
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/__snapshots__/collapsible_panel.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/__snapshots__/collapsible_panel.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/__snapshots__/collapsible_panel.test.tsx.snap
rename to x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/__snapshots__/collapsible_panel.test.tsx.snap
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/_collapsible_panel.scss b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/_collapsible_panel.scss
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/_collapsible_panel.scss
rename to x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/_collapsible_panel.scss
diff --git a/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/_index.scss
new file mode 100644
index 0000000000000..c0f4f8ab9a870
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/_index.scss
@@ -0,0 +1 @@
+@import './collapsible_panel';
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/collapsible_panel.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/collapsible_panel.test.tsx
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/collapsible_panel.test.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/collapsible_panel.test.tsx
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/collapsible_panel.tsx b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/collapsible_panel.tsx
similarity index 99%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/collapsible_panel.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/collapsible_panel.tsx
index 416dd7f6c4e5c..01af7cb4509f6 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/collapsible_panel.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/collapsible_panel.tsx
@@ -50,7 +50,6 @@ export class CollapsiblePanel extends Component {
public getTitle = () => {
return (
- // @ts-ignore
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/collapsible_panel/index.ts
rename to x-pack/plugins/security/public/management/roles/edit_role/collapsible_panel/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/delete_role_button.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/delete_role_button.test.tsx
similarity index 94%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/delete_role_button.test.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/delete_role_button.test.tsx
index cc16866c88355..f4af935be6648 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/delete_role_button.test.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/delete_role_button.test.tsx
@@ -4,11 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import {
- EuiButtonEmpty,
- // @ts-ignore
- EuiConfirmModal,
-} from '@elastic/eui';
+import { EuiButtonEmpty, EuiConfirmModal } from '@elastic/eui';
import React from 'react';
import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
import { DeleteRoleButton } from './delete_role_button';
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/delete_role_button.tsx b/x-pack/plugins/security/public/management/roles/edit_role/delete_role_button.tsx
similarity index 95%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/delete_role_button.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/delete_role_button.tsx
index 1ae84d3fb7224..c6a10396f235c 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/delete_role_button.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/delete_role_button.tsx
@@ -4,13 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import {
- EuiButtonEmpty,
- // @ts-ignore
- EuiConfirmModal,
- // @ts-ignore
- EuiOverlayMask,
-} from '@elastic/eui';
+import { EuiButtonEmpty, EuiConfirmModal, EuiOverlayMask } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import React, { Component, Fragment } from 'react';
diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx
new file mode 100644
index 0000000000000..2b3d7c811f6de
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx
@@ -0,0 +1,552 @@
+/*
+ * 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 { ReactWrapper } from 'enzyme';
+import React from 'react';
+import { act } from '@testing-library/react';
+import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers';
+import { Capabilities } from 'src/core/public';
+import { Space } from '../../../../../spaces/common/model/space';
+import { Feature } from '../../../../../features/public';
+// These modules should be moved into a common directory
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { Actions } from '../../../../server/authorization/actions';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { privilegesFactory } from '../../../../server/authorization/privileges';
+import { Role } from '../../../../common/model';
+import { DocumentationLinksService } from '../documentation_links';
+import { EditRolePage } from './edit_role_page';
+import { SimplePrivilegeSection } from './privileges/kibana/simple_privilege_section';
+import { SpaceAwarePrivilegeSection } from './privileges/kibana/space_aware_privilege_section';
+
+import { TransformErrorSection } from './privileges/kibana/transform_error_section';
+import { coreMock } from '../../../../../../../src/core/public/mocks';
+import { dataPluginMock } from '../../../../../../../src/plugins/data/public/mocks';
+import { licenseMock } from '../../../../common/licensing/index.mock';
+import { userAPIClientMock } from '../../users/index.mock';
+import { rolesAPIClientMock, indicesAPIClientMock, privilegesAPIClientMock } from '../index.mock';
+
+const buildFeatures = () => {
+ return [
+ {
+ id: 'feature1',
+ name: 'Feature 1',
+ icon: 'addDataApp',
+ app: ['feature1App'],
+ privileges: {
+ all: {
+ app: ['feature1App'],
+ ui: ['feature1-ui'],
+ savedObject: {
+ all: [],
+ read: [],
+ },
+ },
+ },
+ },
+ {
+ id: 'feature2',
+ name: 'Feature 2',
+ icon: 'addDataApp',
+ app: ['feature2App'],
+ privileges: {
+ all: {
+ app: ['feature2App'],
+ ui: ['feature2-ui'],
+ savedObject: {
+ all: ['feature2'],
+ read: ['config'],
+ },
+ },
+ },
+ },
+ ] as Feature[];
+};
+
+const buildRawKibanaPrivileges = () => {
+ return privilegesFactory(new Actions('unit_test_version'), {
+ getFeatures: () => buildFeatures(),
+ }).get();
+};
+
+const buildBuiltinESPrivileges = () => {
+ return {
+ cluster: ['all', 'manage', 'monitor'],
+ index: ['all', 'read', 'write', 'index'],
+ };
+};
+
+const buildUICapabilities = (canManageSpaces = true) => {
+ return {
+ catalogue: {},
+ management: {},
+ navLinks: {},
+ spaces: {
+ manage: canManageSpaces,
+ },
+ } as Capabilities;
+};
+
+const buildSpaces = () => {
+ return [
+ {
+ id: 'default',
+ name: 'Default',
+ disabledFeatures: [],
+ _reserved: true,
+ },
+ {
+ id: 'space_1',
+ name: 'Space 1',
+ disabledFeatures: [],
+ },
+ {
+ id: 'space_2',
+ name: 'Space 2',
+ disabledFeatures: ['feature2'],
+ },
+ ] as Space[];
+};
+
+const expectReadOnlyFormButtons = (wrapper: ReactWrapper) => {
+ expect(wrapper.find('button[data-test-subj="roleFormReturnButton"]')).toHaveLength(1);
+ expect(wrapper.find('button[data-test-subj="roleFormSaveButton"]')).toHaveLength(0);
+};
+
+const expectSaveFormButtons = (wrapper: ReactWrapper) => {
+ expect(wrapper.find('button[data-test-subj="roleFormReturnButton"]')).toHaveLength(0);
+ expect(wrapper.find('button[data-test-subj="roleFormSaveButton"]')).toHaveLength(1);
+};
+
+function getProps({
+ action,
+ role,
+ canManageSpaces = true,
+ spacesEnabled = true,
+}: {
+ action: 'edit' | 'clone';
+ role?: Role;
+ canManageSpaces?: boolean;
+ spacesEnabled?: boolean;
+}) {
+ const rolesAPIClient = rolesAPIClientMock.create();
+ rolesAPIClient.getRole.mockResolvedValue(role);
+
+ const indexPatterns = dataPluginMock.createStartContract().indexPatterns;
+ indexPatterns.getTitles = jest.fn().mockResolvedValue(['foo*', 'bar*']);
+
+ const indicesAPIClient = indicesAPIClientMock.create();
+
+ const userAPIClient = userAPIClientMock.create();
+ userAPIClient.getUsers.mockResolvedValue([]);
+
+ const privilegesAPIClient = privilegesAPIClientMock.create();
+ privilegesAPIClient.getAll.mockResolvedValue(buildRawKibanaPrivileges());
+ privilegesAPIClient.getBuiltIn.mockResolvedValue(buildBuiltinESPrivileges());
+
+ const license = licenseMock.create();
+ license.getFeatures.mockReturnValue({
+ allowRoleDocumentLevelSecurity: true,
+ allowRoleFieldLevelSecurity: true,
+ } as any);
+
+ const { fatalErrors } = coreMock.createSetup();
+ const { http, docLinks, notifications } = coreMock.createStart();
+ http.get.mockImplementation(async path => {
+ if (path === '/api/features') {
+ return buildFeatures();
+ }
+
+ if (path === '/api/spaces/space') {
+ return buildSpaces();
+ }
+ });
+
+ return {
+ action,
+ roleName: role?.name,
+ license,
+ http,
+ indexPatterns,
+ indicesAPIClient,
+ privilegesAPIClient,
+ rolesAPIClient,
+ userAPIClient,
+ notifications,
+ docLinks: new DocumentationLinksService(docLinks),
+ fatalErrors,
+ spacesEnabled,
+ uiCapabilities: buildUICapabilities(canManageSpaces),
+ };
+}
+
+describe('', () => {
+ describe('with spaces enabled', () => {
+ it('can render a reserved role', async () => {
+ const wrapper = mountWithIntl(
+
+ );
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ });
+
+ expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(1);
+ expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1);
+ expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
+ expectReadOnlyFormButtons(wrapper);
+ });
+
+ it('can render a user defined role', async () => {
+ const wrapper = mountWithIntl(
+
+ );
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ });
+
+ expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0);
+ expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1);
+ expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
+ expectSaveFormButtons(wrapper);
+ });
+
+ it('can render when creating a new role', async () => {
+ const wrapper = mountWithIntl();
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ });
+
+ expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1);
+ expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
+ expectSaveFormButtons(wrapper);
+ });
+
+ it('can render when cloning an existing role', async () => {
+ const wrapper = mountWithIntl(
+
+ );
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ });
+
+ expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1);
+ expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
+ expectSaveFormButtons(wrapper);
+ });
+
+ it('renders an auth error when not authorized to manage spaces', async () => {
+ const wrapper = mountWithIntl(
+
+ );
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ });
+
+ expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0);
+
+ expect(
+ wrapper.find('EuiCallOut[data-test-subj="userCannotManageSpacesCallout"]')
+ ).toHaveLength(1);
+
+ expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1);
+ expectSaveFormButtons(wrapper);
+ });
+
+ it('renders a partial read-only view when there is a transform error', async () => {
+ const wrapper = mountWithIntl(
+
+ );
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ });
+
+ expect(wrapper.find(TransformErrorSection)).toHaveLength(1);
+ expectReadOnlyFormButtons(wrapper);
+ });
+ });
+
+ describe('with spaces disabled', () => {
+ it('can render a reserved role', async () => {
+ const wrapper = mountWithIntl(
+
+ );
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ });
+
+ expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(1);
+ expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1);
+ expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
+ expectReadOnlyFormButtons(wrapper);
+ });
+
+ it('can render a user defined role', async () => {
+ const wrapper = mountWithIntl(
+
+ );
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ });
+
+ expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0);
+ expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1);
+ expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
+ expectSaveFormButtons(wrapper);
+ });
+
+ it('can render when creating a new role', async () => {
+ const wrapper = mountWithIntl(
+
+ );
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ });
+
+ expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1);
+ expectSaveFormButtons(wrapper);
+ });
+
+ it('can render when cloning an existing role', async () => {
+ const wrapper = mountWithIntl(
+
+ );
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ });
+
+ expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1);
+ expectSaveFormButtons(wrapper);
+ });
+
+ it('does not care if user cannot manage spaces', async () => {
+ const wrapper = mountWithIntl(
+
+ );
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ });
+
+ expect(wrapper.find('[data-test-subj="reservedRoleBadgeTooltip"]')).toHaveLength(0);
+
+ expect(
+ wrapper.find('EuiCallOut[data-test-subj="userCannotManageSpacesCallout"]')
+ ).toHaveLength(0);
+
+ expect(wrapper.find(SimplePrivilegeSection)).toHaveLength(1);
+ expectSaveFormButtons(wrapper);
+ });
+
+ it('renders a partial read-only view when there is a transform error', async () => {
+ const wrapper = mountWithIntl(
+
+ );
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ });
+
+ expect(wrapper.find(TransformErrorSection)).toHaveLength(1);
+ expectReadOnlyFormButtons(wrapper);
+ });
+ });
+
+ it('can render if features are not available', async () => {
+ const { http } = coreMock.createStart();
+ http.get.mockImplementation(async path => {
+ if (path === '/api/features') {
+ const error = { response: { status: 404 } };
+ throw error;
+ }
+
+ if (path === '/api/spaces/space') {
+ return buildSpaces();
+ }
+ });
+
+ const wrapper = mountWithIntl();
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ });
+
+ expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1);
+ expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
+ expectSaveFormButtons(wrapper);
+ });
+
+ it('can render if index patterns are not available', async () => {
+ const indexPatterns = dataPluginMock.createStartContract().indexPatterns;
+ indexPatterns.getTitles = jest.fn().mockRejectedValue({ response: { status: 403 } });
+
+ const wrapper = mountWithIntl(
+
+ );
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ });
+
+ expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1);
+ expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
+ expectSaveFormButtons(wrapper);
+ });
+});
diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx
new file mode 100644
index 0000000000000..33e69a68ca896
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx
@@ -0,0 +1,594 @@
+/*
+ * 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 _, { get } from 'lodash';
+import {
+ EuiButton,
+ EuiButtonEmpty,
+ EuiFieldText,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiForm,
+ EuiFormRow,
+ EuiPanel,
+ EuiSpacer,
+ EuiText,
+ EuiTitle,
+} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import React, {
+ ChangeEvent,
+ Fragment,
+ FunctionComponent,
+ HTMLProps,
+ useEffect,
+ useRef,
+ useState,
+} from 'react';
+import {
+ Capabilities,
+ FatalErrorsSetup,
+ HttpStart,
+ IHttpFetchError,
+ NotificationsStart,
+} from 'src/core/public';
+import { IndexPatternsContract } from '../../../../../../../src/plugins/data/public';
+import { Space } from '../../../../../spaces/common/model/space';
+import { Feature } from '../../../../../features/public';
+import {
+ KibanaPrivileges,
+ RawKibanaPrivileges,
+ Role,
+ BuiltinESPrivileges,
+ isReadOnlyRole as checkIfRoleReadOnly,
+ isReservedRole as checkIfRoleReserved,
+ copyRole,
+ prepareRoleClone,
+ RoleIndexPrivilege,
+} from '../../../../common/model';
+import { ROLES_PATH } from '../../management_urls';
+import { RoleValidationResult, RoleValidator } from './validate_role';
+import { DeleteRoleButton } from './delete_role_button';
+import { ElasticsearchPrivileges, KibanaPrivilegesRegion } from './privileges';
+import { ReservedRoleBadge } from './reserved_role_badge';
+import { SecurityLicense } from '../../../../common/licensing';
+import { UserAPIClient } from '../../users';
+import { DocumentationLinksService } from '../documentation_links';
+import { IndicesAPIClient } from '../indices_api_client';
+import { RolesAPIClient } from '../roles_api_client';
+import { PrivilegesAPIClient } from '../privileges_api_client';
+
+interface Props {
+ action: 'edit' | 'clone';
+ roleName?: string;
+ indexPatterns: IndexPatternsContract;
+ userAPIClient: PublicMethodsOf;
+ indicesAPIClient: PublicMethodsOf;
+ rolesAPIClient: PublicMethodsOf;
+ privilegesAPIClient: PublicMethodsOf;
+ docLinks: DocumentationLinksService;
+ http: HttpStart;
+ license: SecurityLicense;
+ spacesEnabled: boolean;
+ uiCapabilities: Capabilities;
+ notifications: NotificationsStart;
+ fatalErrors: FatalErrorsSetup;
+}
+
+function useRunAsUsers(
+ userAPIClient: PublicMethodsOf,
+ fatalErrors: FatalErrorsSetup
+) {
+ const [userNames, setUserNames] = useState(null);
+ useEffect(() => {
+ userAPIClient.getUsers().then(
+ users => setUserNames(users.map(user => user.username)),
+ err => fatalErrors.add(err)
+ );
+ }, [fatalErrors, userAPIClient]);
+
+ return userNames;
+}
+
+function useIndexPatternsTitles(
+ indexPatterns: IndexPatternsContract,
+ fatalErrors: FatalErrorsSetup,
+ notifications: NotificationsStart
+) {
+ const [indexPatternsTitles, setIndexPatternsTitles] = useState(null);
+ useEffect(() => {
+ indexPatterns
+ .getTitles()
+ .catch((err: IHttpFetchError) => {
+ // If user doesn't have access to the index patterns they still should be able to create new
+ // or edit existing role.
+ if (err.response?.status === 403) {
+ notifications.toasts.addDanger({
+ title: i18n.translate('xpack.security.management.roles.noIndexPatternsPermission', {
+ defaultMessage: 'You need permission to access the list of available index patterns.',
+ }),
+ });
+ return [];
+ }
+
+ fatalErrors.add(err);
+ throw err;
+ })
+ .then(setIndexPatternsTitles);
+ }, [fatalErrors, indexPatterns, notifications]);
+
+ return indexPatternsTitles;
+}
+
+function usePrivileges(
+ privilegesAPIClient: PublicMethodsOf,
+ fatalErrors: FatalErrorsSetup
+) {
+ const [privileges, setPrivileges] = useState<[RawKibanaPrivileges, BuiltinESPrivileges] | null>(
+ null
+ );
+ useEffect(() => {
+ Promise.all([
+ privilegesAPIClient.getAll({ includeActions: true }),
+ privilegesAPIClient.getBuiltIn(),
+ ]).then(
+ ([kibanaPrivileges, builtInESPrivileges]) =>
+ setPrivileges([kibanaPrivileges, builtInESPrivileges]),
+ err => fatalErrors.add(err)
+ );
+ }, [privilegesAPIClient, fatalErrors]);
+
+ return privileges;
+}
+
+function useRole(
+ rolesAPIClient: PublicMethodsOf,
+ fatalErrors: FatalErrorsSetup,
+ notifications: NotificationsStart,
+ license: SecurityLicense,
+ action: string,
+ roleName?: string
+) {
+ const [role, setRole] = useState(null);
+ useEffect(() => {
+ const rolePromise = roleName
+ ? rolesAPIClient.getRole(roleName)
+ : Promise.resolve({
+ name: '',
+ elasticsearch: { cluster: [], indices: [], run_as: [] },
+ kibana: [],
+ _unrecognized_applications: [],
+ } as Role);
+
+ rolePromise
+ .then(fetchedRole => {
+ if (action === 'clone' && checkIfRoleReserved(fetchedRole)) {
+ backToRoleList();
+ return;
+ }
+
+ if (fetchedRole.elasticsearch.indices.length === 0) {
+ const emptyOption: RoleIndexPrivilege = {
+ names: [],
+ privileges: [],
+ };
+
+ const {
+ allowRoleDocumentLevelSecurity,
+ allowRoleFieldLevelSecurity,
+ } = license.getFeatures();
+
+ if (allowRoleFieldLevelSecurity) {
+ emptyOption.field_security = {
+ grant: ['*'],
+ except: [],
+ };
+ }
+
+ if (allowRoleDocumentLevelSecurity) {
+ emptyOption.query = '';
+ }
+
+ fetchedRole.elasticsearch.indices.push(emptyOption);
+ }
+
+ setRole(action === 'clone' ? prepareRoleClone(fetchedRole) : copyRole(fetchedRole));
+ })
+ .catch((err: IHttpFetchError) => {
+ if (err.response?.status === 404) {
+ notifications.toasts.addDanger({
+ title: i18n.translate('xpack.security.management.roles.roleNotFound', {
+ defaultMessage: 'No "{roleName}" role found.',
+ values: { roleName },
+ }),
+ });
+ backToRoleList();
+ } else {
+ fatalErrors.add(err);
+ }
+ });
+ }, [roleName, action, fatalErrors, rolesAPIClient, notifications, license]);
+
+ return [role, setRole] as [Role | null, typeof setRole];
+}
+
+function useSpaces(http: HttpStart, fatalErrors: FatalErrorsSetup, spacesEnabled: boolean) {
+ const [spaces, setSpaces] = useState(null);
+ useEffect(() => {
+ (spacesEnabled ? http.get('/api/spaces/space') : Promise.resolve([])).then(
+ fetchedSpaces => setSpaces(fetchedSpaces),
+ err => fatalErrors.add(err)
+ );
+ }, [http, fatalErrors, spacesEnabled]);
+
+ return spaces;
+}
+
+function useFeatures(http: HttpStart, fatalErrors: FatalErrorsSetup) {
+ const [features, setFeatures] = useState(null);
+ useEffect(() => {
+ http
+ .get('/api/features')
+ .catch((err: IHttpFetchError) => {
+ // Currently, the `/api/features` endpoint effectively requires the "Global All" kibana privilege (e.g., what
+ // the `kibana_user` grants), because it returns information about all registered features (#35841). It's
+ // possible that a user with `manage_security` will attempt to visit the role management page without the
+ // correct Kibana privileges. If that's the case, then they receive a partial view of the role, and the UI does
+ // not allow them to make changes to that role's kibana privileges. When this user visits the edit role page,
+ // this API endpoint will throw a 404, which causes view to fail completely. So we instead attempt to detect the
+ // 404 here, and respond in a way that still allows the UI to render itself.
+ const unauthorizedForFeatures = err.response?.status === 404;
+ if (unauthorizedForFeatures) {
+ return [];
+ }
+
+ fatalErrors.add(err);
+ throw err;
+ })
+ .then(setFeatures);
+ }, [http, fatalErrors]);
+
+ return features;
+}
+
+function backToRoleList() {
+ window.location.hash = ROLES_PATH;
+}
+
+export const EditRolePage: FunctionComponent = ({
+ userAPIClient,
+ indexPatterns,
+ rolesAPIClient,
+ indicesAPIClient,
+ privilegesAPIClient,
+ http,
+ roleName,
+ action,
+ fatalErrors,
+ spacesEnabled,
+ license,
+ docLinks,
+ uiCapabilities,
+ notifications,
+}) => {
+ // We should keep the same mutable instance of Validator for every re-render since we'll
+ // eventually enable validation after the first time user tries to save a role.
+ const { current: validator } = useRef(new RoleValidator({ shouldValidate: false }));
+
+ const [formError, setFormError] = useState(null);
+ const runAsUsers = useRunAsUsers(userAPIClient, fatalErrors);
+ const indexPatternsTitles = useIndexPatternsTitles(indexPatterns, fatalErrors, notifications);
+ const privileges = usePrivileges(privilegesAPIClient, fatalErrors);
+ const spaces = useSpaces(http, fatalErrors, spacesEnabled);
+ const features = useFeatures(http, fatalErrors);
+ const [role, setRole] = useRole(
+ rolesAPIClient,
+ fatalErrors,
+ notifications,
+ license,
+ action,
+ roleName
+ );
+
+ if (!role || !runAsUsers || !indexPatternsTitles || !privileges || !spaces || !features) {
+ return null;
+ }
+
+ const isEditingExistingRole = !!roleName && action === 'edit';
+ const isReadOnlyRole = checkIfRoleReadOnly(role);
+ const isReservedRole = checkIfRoleReserved(role);
+
+ const [kibanaPrivileges, builtInESPrivileges] = privileges;
+
+ const getFormTitle = () => {
+ let titleText;
+ const props: HTMLProps = {
+ tabIndex: 0,
+ };
+ if (isReservedRole) {
+ titleText = (
+
+ );
+ props['aria-describedby'] = 'reservedRoleDescription';
+ } else if (isEditingExistingRole) {
+ titleText = (
+
+ );
+ } else {
+ titleText = (
+
+ );
+ }
+
+ return (
+
+
+ {titleText}
+
+
+ );
+ };
+
+ const getActionButton = () => {
+ if (isEditingExistingRole && !isReadOnlyRole) {
+ return (
+
+
+
+ );
+ }
+
+ return null;
+ };
+
+ const getRoleName = () => {
+ return (
+
+
+ }
+ helpText={
+ !isReservedRole && isEditingExistingRole ? (
+
+ ) : (
+ undefined
+ )
+ }
+ {...validator.validateRoleName(role)}
+ >
+
+
+
+ );
+ };
+
+ const onNameChange = (e: ChangeEvent) =>
+ setRole({
+ ...role,
+ name: e.target.value.replace(/\s/g, '_'),
+ });
+
+ const getElasticsearchPrivileges = () => {
+ return (
+
+
+
+
+ );
+ };
+
+ const onRoleChange = (newRole: Role) => setRole(newRole);
+
+ const getKibanaPrivileges = () => {
+ return (
+
+
+
+
+ );
+ };
+
+ const getFormButtons = () => {
+ if (isReadOnlyRole) {
+ return getReturnToRoleListButton();
+ }
+
+ return (
+
+ {getSaveButton()}
+ {getCancelButton()}
+
+ {getActionButton()}
+
+ );
+ };
+
+ const getReturnToRoleListButton = () => {
+ return (
+
+
+
+ );
+ };
+
+ const getSaveButton = () => {
+ const saveText = isEditingExistingRole ? (
+
+ ) : (
+
+ );
+
+ return (
+
+ {saveText}
+
+ );
+ };
+
+ const getCancelButton = () => {
+ return (
+
+
+
+ );
+ };
+
+ const saveRole = async () => {
+ validator.enableValidation();
+
+ const result = validator.validateForSave(role);
+ if (result.isInvalid) {
+ setFormError(result);
+ } else {
+ setFormError(null);
+
+ try {
+ await rolesAPIClient.saveRole({ role, spacesEnabled });
+ } catch (error) {
+ notifications.toasts.addDanger(get(error, 'data.message'));
+ return;
+ }
+
+ notifications.toasts.addSuccess(
+ i18n.translate(
+ 'xpack.security.management.editRole.roleSuccessfullySavedNotificationMessage',
+ { defaultMessage: 'Saved role' }
+ )
+ );
+
+ backToRoleList();
+ }
+ };
+
+ const handleDeleteRole = async () => {
+ try {
+ await rolesAPIClient.deleteRole(role.name);
+ } catch (error) {
+ notifications.toasts.addDanger(get(error, 'data.message'));
+ return;
+ }
+
+ notifications.toasts.addSuccess(
+ i18n.translate(
+ 'xpack.security.management.editRole.roleSuccessfullyDeletedNotificationMessage',
+ { defaultMessage: 'Deleted role' }
+ )
+ );
+
+ backToRoleList();
+ };
+
+ const description = spacesEnabled ? (
+
+ ) : (
+
+ );
+
+ return (
+
+
+ {getFormTitle()}
+
+
+
+ {description}
+
+ {isReservedRole && (
+
+
+
+
+
+
+
+
+ )}
+
+
+
+ {getRoleName()}
+
+ {getElasticsearchPrivileges()}
+
+ {getKibanaPrivileges()}
+
+
+
+ {getFormButtons()}
+
+
+ );
+};
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/index.ts
rename to x-pack/plugins/security/public/management/roles/edit_role/index.ts
diff --git a/x-pack/legacy/plugins/security/public/lib/privilege_utils.test.ts b/x-pack/plugins/security/public/management/roles/edit_role/privilege_utils.test.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/lib/privilege_utils.test.ts
rename to x-pack/plugins/security/public/management/roles/edit_role/privilege_utils.test.ts
diff --git a/x-pack/legacy/plugins/security/public/lib/privilege_utils.ts b/x-pack/plugins/security/public/management/roles/edit_role/privilege_utils.ts
similarity index 93%
rename from x-pack/legacy/plugins/security/public/lib/privilege_utils.ts
rename to x-pack/plugins/security/public/management/roles/edit_role/privilege_utils.ts
index 74bde71dc421a..3fd8536951967 100644
--- a/x-pack/legacy/plugins/security/public/lib/privilege_utils.ts
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privilege_utils.ts
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { RoleKibanaPrivilege } from '../../common/model';
+import { RoleKibanaPrivilege } from '../../../../common/model';
/**
* Determines if the passed privilege spec defines global privileges.
diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/privileges/_index.scss
new file mode 100644
index 0000000000000..a1a9d038065e6
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/_index.scss
@@ -0,0 +1,2 @@
+@import './privilege_feature_icon';
+@import './kibana/index';
diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/_privilege_feature_icon.scss b/x-pack/plugins/security/public/management/roles/edit_role/privileges/_privilege_feature_icon.scss
new file mode 100644
index 0000000000000..a7f24c96a2821
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/_privilege_feature_icon.scss
@@ -0,0 +1,4 @@
+.secPrivilegeFeatureIcon {
+ flex-shrink: 0;
+ margin-right: $euiSizeS;
+}
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/__snapshots__/cluster_privileges.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/__snapshots__/cluster_privileges.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/__snapshots__/cluster_privileges.test.tsx.snap
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/es/__snapshots__/cluster_privileges.test.tsx.snap
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap
similarity index 87%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap
index 795131337c31f..323629de7578d 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/__snapshots__/elasticsearch_privileges.test.tsx.snap
@@ -15,7 +15,7 @@ exports[`it renders without crashing 1`] = `
/>
{
+ expect(shallowWithIntl()).toMatchSnapshot();
+});
+
+test('it renders ClusterPrivileges', () => {
+ expect(
+ mountWithIntl().find(ClusterPrivileges)
+ ).toHaveLength(1);
+});
+
+test('it renders IndexPrivileges', () => {
+ expect(
+ mountWithIntl().find(IndexPrivileges)
+ ).toHaveLength(1);
+});
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/elasticsearch_privileges.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/elasticsearch_privileges.tsx
similarity index 89%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/elasticsearch_privileges.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/es/elasticsearch_privileges.tsx
index c0e6db3fef21c..96249ccf3ff87 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/elasticsearch_privileges.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/elasticsearch_privileges.tsx
@@ -7,7 +7,6 @@
import {
EuiButton,
EuiComboBox,
- // @ts-ignore
EuiDescribedFormGroup,
EuiFormRow,
EuiHorizontalRule,
@@ -19,26 +18,26 @@ import {
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import React, { Component, Fragment } from 'react';
-import { Role, BuiltinESPrivileges } from '../../../../../../../common/model';
-// @ts-ignore
-import { documentationLinks } from '../../../../../../documentation_links';
-import { RoleValidator } from '../../../lib/validate_role';
+import { Role, BuiltinESPrivileges } from '../../../../../../common/model';
+import { SecurityLicense } from '../../../../../../common/licensing';
+import { IndicesAPIClient } from '../../../indices_api_client';
+import { RoleValidator } from '../../validate_role';
import { CollapsiblePanel } from '../../collapsible_panel';
import { ClusterPrivileges } from './cluster_privileges';
-
import { IndexPrivileges } from './index_privileges';
+import { DocumentationLinksService } from '../../../documentation_links';
interface Props {
role: Role;
editable: boolean;
- httpClient: any;
+ indicesAPIClient: PublicMethodsOf;
+ docLinks: DocumentationLinksService;
+ license: SecurityLicense;
onChange: (role: Role) => void;
runAsUsers: string[];
validator: RoleValidator;
builtinESPrivileges: BuiltinESPrivileges;
indexPatterns: string[];
- allowDocumentLevelSecurity: boolean;
- allowFieldLevelSecurity: boolean;
}
export class ElasticsearchPrivileges extends Component {
@@ -53,23 +52,22 @@ export class ElasticsearchPrivileges extends Component {
public getForm = () => {
const {
role,
- httpClient,
+ indicesAPIClient,
+ docLinks,
validator,
onChange,
editable,
indexPatterns,
- allowDocumentLevelSecurity,
- allowFieldLevelSecurity,
+ license,
builtinESPrivileges,
} = this.props;
const indexProps = {
role,
- httpClient,
+ indicesAPIClient,
validator,
indexPatterns,
- allowDocumentLevelSecurity,
- allowFieldLevelSecurity,
+ license,
onChange,
availableIndexPrivileges: builtinESPrivileges.index,
};
@@ -91,7 +89,7 @@ export class ElasticsearchPrivileges extends Component {
id="xpack.security.management.editRole.elasticSearchPrivileges.manageRoleActionsDescription"
defaultMessage="Manage the actions this role can perform against your cluster. "
/>
- {this.learnMore(documentationLinks.esClusterPrivileges)}
+ {this.learnMore(docLinks.getESClusterPrivilegesDocUrl())}
}
>
@@ -121,7 +119,7 @@ export class ElasticsearchPrivileges extends Component {
id="xpack.security.management.editRole.elasticSearchPrivileges.howToBeSubmittedOnBehalfOfOtherUsersDescription"
defaultMessage="Allow requests to be submitted on the behalf of other users. "
/>
- {this.learnMore(documentationLinks.esRunAsPrivileges)}
+ {this.learnMore(docLinks.getESRunAsPrivilegesDocUrl())}
}
>
@@ -165,7 +163,7 @@ export class ElasticsearchPrivileges extends Component {
id="xpack.security.management.editRole.elasticSearchPrivileges.controlAccessToClusterDataDescription"
defaultMessage="Control access to the data in your cluster. "
/>
- {this.learnMore(documentationLinks.esIndicesPrivileges)}
+ {this.learnMore(docLinks.getESIndicesPrivilegesDocUrl())}
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privilege_form.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privilege_form.test.tsx
similarity index 99%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privilege_form.test.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privilege_form.test.tsx
index 6d386fd78a11b..5e2da51314365 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privilege_form.test.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privilege_form.test.tsx
@@ -6,7 +6,7 @@
import { EuiButtonIcon, EuiTextArea } from '@elastic/eui';
import React from 'react';
import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
-import { RoleValidator } from '../../../lib/validate_role';
+import { RoleValidator } from '../../validate_role';
import { IndexPrivilegeForm } from './index_privilege_form';
test('it renders without crashing', () => {
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privilege_form.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privilege_form.tsx
similarity index 98%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privilege_form.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privilege_form.tsx
index bafc56dc167ea..15e0367c2b6dc 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privilege_form.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privilege_form.tsx
@@ -19,8 +19,8 @@ import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import _ from 'lodash';
import React, { ChangeEvent, Component, Fragment } from 'react';
-import { RoleIndexPrivilege } from '../../../../../../../common/model';
-import { RoleValidator } from '../../../lib/validate_role';
+import { RoleIndexPrivilege } from '../../../../../../common/model';
+import { RoleValidator } from '../../validate_role';
const fromOption = (option: any) => option.label;
const toOption = (value: string) => ({ label: value });
@@ -164,7 +164,6 @@ export class IndexPrivilegeForm extends Component {
{!isReadOnlyRole && (
{
- // @ts-ignore missing "compressed" prop definition
{
}
return (
- // @ts-ignore
{!this.props.isReadOnlyRole && (
{
- // @ts-ignore missing "compressed" proptype
new Promise(setImmediate);
test('it renders without crashing', async () => {
+ const license = licenseMock.create();
+ license.getFeatures.mockReturnValue({
+ allowRoleFieldLevelSecurity: true,
+ allowRoleDocumentLevelSecurity: true,
+ } as any);
+
const props = {
role: {
name: '',
@@ -25,14 +34,13 @@ test('it renders without crashing', async () => {
run_as: [],
},
},
- httpClient: jest.fn(),
onChange: jest.fn(),
indexPatterns: [],
editable: true,
- allowDocumentLevelSecurity: true,
- allowFieldLevelSecurity: true,
validator: new RoleValidator(),
availableIndexPrivileges: ['all', 'read', 'write', 'index'],
+ indicesAPIClient: indicesAPIClientMock.create(),
+ license,
};
const wrapper = shallowWithIntl();
await flushPromises();
@@ -40,6 +48,12 @@ test('it renders without crashing', async () => {
});
test('it renders a IndexPrivilegeForm for each privilege on the role', async () => {
+ const license = licenseMock.create();
+ license.getFeatures.mockReturnValue({
+ allowRoleFieldLevelSecurity: true,
+ allowRoleDocumentLevelSecurity: true,
+ } as any);
+
const props = {
role: {
name: '',
@@ -59,14 +73,13 @@ test('it renders a IndexPrivilegeForm for each privilege on the role', async ()
run_as: [],
},
},
- httpClient: jest.fn(),
onChange: jest.fn(),
indexPatterns: [],
editable: true,
- allowDocumentLevelSecurity: true,
- allowFieldLevelSecurity: true,
validator: new RoleValidator(),
availableIndexPrivileges: ['all', 'read', 'write', 'index'],
+ indicesAPIClient: indicesAPIClientMock.create(),
+ license,
};
const wrapper = mountWithIntl();
await flushPromises();
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privileges.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privileges.tsx
similarity index 84%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privileges.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privileges.tsx
index f09084ad2bb38..2c745067fede2 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/es/index_privileges.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privileges.tsx
@@ -5,19 +5,23 @@
*/
import _ from 'lodash';
import React, { Component, Fragment } from 'react';
-import { Role, RoleIndexPrivilege } from '../../../../../../../common/model';
-import { isReadOnlyRole, isRoleEnabled } from '../../../../../../lib/role_utils';
-import { getFields } from '../../../../../../objects';
-import { RoleValidator } from '../../../lib/validate_role';
+import {
+ Role,
+ RoleIndexPrivilege,
+ isReadOnlyRole,
+ isRoleEnabled,
+} from '../../../../../../common/model';
+import { SecurityLicense } from '../../../../../../common/licensing';
+import { IndicesAPIClient } from '../../../indices_api_client';
+import { RoleValidator } from '../../validate_role';
import { IndexPrivilegeForm } from './index_privilege_form';
interface Props {
role: Role;
indexPatterns: string[];
availableIndexPrivileges: string[];
- allowDocumentLevelSecurity: boolean;
- allowFieldLevelSecurity: boolean;
- httpClient: any;
+ indicesAPIClient: PublicMethodsOf;
+ license: SecurityLicense;
onChange: (role: Role) => void;
validator: RoleValidator;
}
@@ -43,20 +47,16 @@ export class IndexPrivileges extends Component {
public render() {
const { indices = [] } = this.props.role.elasticsearch;
- const {
- indexPatterns,
- allowDocumentLevelSecurity,
- allowFieldLevelSecurity,
- availableIndexPrivileges,
- } = this.props;
+ const { indexPatterns, license, availableIndexPrivileges } = this.props;
+ const { allowRoleDocumentLevelSecurity, allowRoleFieldLevelSecurity } = license.getFeatures();
const props = {
indexPatterns,
// 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),
+ allowDocumentLevelSecurity: allowRoleDocumentLevelSecurity || !isRoleEnabled(this.props.role),
+ allowFieldLevelSecurity: allowRoleFieldLevelSecurity || !isRoleEnabled(this.props.role),
isReadOnlyRole: isReadOnlyRole(this.props.role),
};
@@ -171,7 +171,7 @@ export class IndexPrivileges extends Component {
try {
return {
- [pattern]: await getFields(this.props.httpClient, pattern),
+ [pattern]: await this.props.indicesAPIClient.getFields(pattern),
};
} catch (e) {
return {
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/index.ts
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/__snapshots__/kibana_privileges_region.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/__snapshots__/kibana_privileges_region.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/__snapshots__/kibana_privileges_region.test.tsx.snap
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/__snapshots__/kibana_privileges_region.test.tsx.snap
diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/_index.scss
new file mode 100644
index 0000000000000..19547c0e1953e
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/_index.scss
@@ -0,0 +1,2 @@
+@import './feature_table/index';
+@import './space_aware_privilege_section/index';
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/lib/constants.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/constants.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/lib/constants.ts
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/constants.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/__snapshots__/feature_table.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/__snapshots__/feature_table.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/__snapshots__/feature_table.test.tsx.snap
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/__snapshots__/feature_table.test.tsx.snap
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/_change_all_privileges.scss
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/_index.scss
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/_change_all_privileges.scss
diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/_index.scss
new file mode 100644
index 0000000000000..6a96553742819
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/_index.scss
@@ -0,0 +1 @@
+@import './change_all_privileges';
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/change_all_privileges.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/change_all_privileges.tsx
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/change_all_privileges.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/change_all_privileges.tsx
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/feature_table.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx
similarity index 94%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/feature_table.test.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx
index 9648bf1d111bf..dea42e16f99d4 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/feature_table.test.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx
@@ -3,12 +3,11 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-// @ts-ignore
import { EuiInMemoryTable } from '@elastic/eui';
import React from 'react';
import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
-import { FeaturesPrivileges, KibanaPrivileges, Role } from '../../../../../../../../common/model';
-import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator';
+import { FeaturesPrivileges, KibanaPrivileges, Role } from '../../../../../../../common/model';
+import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator';
import { FeatureTable } from './feature_table';
const defaultPrivilegeDefinition = new KibanaPrivileges({
@@ -113,7 +112,6 @@ describe('FeatureTable', () => {
onChange={jest.fn()}
onChangeAll={jest.fn()}
spacesIndex={0}
- intl={null as any}
/>
);
@@ -141,7 +139,6 @@ describe('FeatureTable', () => {
onChange={jest.fn()}
onChangeAll={jest.fn()}
spacesIndex={-1}
- intl={null as any}
/>
);
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/feature_table.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx
similarity index 91%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/feature_table.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx
index a05dc687fce4a..8283efe23260a 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/feature_table/feature_table.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx
@@ -4,28 +4,27 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import _ from 'lodash';
+import React, { Component } from 'react';
import {
- // @ts-ignore
EuiButtonGroup,
EuiIcon,
EuiIconTip,
- // @ts-ignore
EuiInMemoryTable,
EuiText,
IconType,
} from '@elastic/eui';
-import { FormattedMessage, InjectedIntl } from '@kbn/i18n/react';
-import _ from 'lodash';
-import React, { Component } from 'react';
-import { Feature } from '../../../../../../../../../../../plugins/features/public';
-import { FeaturesPrivileges, KibanaPrivileges, Role } from '../../../../../../../../common/model';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { Feature } from '../../../../../../../../features/public';
+import { FeaturesPrivileges, KibanaPrivileges, Role } from '../../../../../../../common/model';
import {
AllowedPrivilege,
CalculatedPrivilege,
PrivilegeExplanation,
-} from '../../../../../../../lib/kibana_privilege_calculator';
-import { isGlobalPrivilegeDefinition } from '../../../../../../../lib/privilege_utils';
-import { NO_PRIVILEGE_VALUE } from '../../../../lib/constants';
+} from '../kibana_privilege_calculator';
+import { isGlobalPrivilegeDefinition } from '../../../privilege_utils';
+import { NO_PRIVILEGE_VALUE } from '../constants';
import { PrivilegeDisplay } from '../space_aware_privilege_section/privilege_display';
import { ChangeAllPrivilegesControl } from './change_all_privileges';
@@ -36,7 +35,6 @@ interface Props {
allowedPrivileges: AllowedPrivilege;
rankedFeaturePrivileges: FeaturesPrivileges;
kibanaPrivileges: KibanaPrivileges;
- intl: InjectedIntl;
spacesIndex: number;
onChange: (featureId: string, privileges: string[]) => void;
onChangeAll: (privileges: string[]) => void;
@@ -100,9 +98,7 @@ export class FeatureTable extends Component {
const availablePrivileges = Object.values(rankedFeaturePrivileges)[0];
return (
- // @ts-ignore missing responsive from typedef
{
private getColumns = (availablePrivileges: string[]) => [
{
field: 'feature',
- name: this.props.intl.formatMessage({
- id: 'xpack.security.management.editRole.featureTable.enabledRoleFeaturesFeatureColumnTitle',
- defaultMessage: 'Feature',
- }),
+ name: i18n.translate(
+ 'xpack.security.management.editRole.featureTable.enabledRoleFeaturesFeatureColumnTitle',
+ { defaultMessage: 'Feature' }
+ ),
render: (feature: TableFeature) => {
let tooltipElement = null;
if (feature.privilegesTooltip) {
@@ -239,9 +235,7 @@ export class FeatureTable extends Component {
});
return (
- // @ts-ignore missing name from typedef
void;
validator: RoleValidator;
- intl: InjectedIntl;
}
export class KibanaPrivilegesRegion extends Component {
@@ -81,7 +79,6 @@ export class KibanaPrivilegesRegion extends Component {
privilegeCalculatorFactory={privilegeCalculatorFactory}
onChange={onChange}
editable={editable}
- intl={this.props.intl}
/>
);
}
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/__snapshots__/simple_privilege_section.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/__snapshots__/simple_privilege_section.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/__snapshots__/simple_privilege_section.test.tsx.snap
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/__snapshots__/simple_privilege_section.test.tsx.snap
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/index.ts
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/privilege_selector.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/privilege_selector.tsx
similarity index 95%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/privilege_selector.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/privilege_selector.tsx
index 135419cc9a10d..bda0227372c09 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/privilege_selector.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/privilege_selector.tsx
@@ -6,7 +6,7 @@
import { EuiSelect } from '@elastic/eui';
import React, { ChangeEvent, Component } from 'react';
-import { NO_PRIVILEGE_VALUE } from '../../../../lib/constants';
+import { NO_PRIVILEGE_VALUE } from '../constants';
interface Props {
['data-test-subj']: string;
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/simple_privilege_section.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.test.tsx
similarity index 95%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/simple_privilege_section.test.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.test.tsx
index f97fa93294ff5..db1e3cfd61621 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/simple_privilege_section.test.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.test.tsx
@@ -3,13 +3,13 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-// @ts-ignore
+
import { EuiButtonGroup, EuiButtonGroupProps, EuiComboBox, EuiSuperSelect } from '@elastic/eui';
import React from 'react';
import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
-import { Feature } from '../../../../../../../../../../../plugins/features/public';
-import { KibanaPrivileges, Role } from '../../../../../../../../common/model';
-import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator';
+import { Feature } from '../../../../../../../../features/public';
+import { KibanaPrivileges, Role } from '../../../../../../../common/model';
+import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator';
import { SimplePrivilegeSection } from './simple_privilege_section';
import { UnsupportedSpacePrivilegesWarning } from './unsupported_space_privileges_warning';
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx
similarity index 94%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx
index 7768dc769a32f..2221fc6bab279 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx
@@ -6,21 +6,24 @@
import {
EuiComboBox,
- // @ts-ignore
EuiDescribedFormGroup,
EuiFormRow,
EuiSuperSelect,
EuiText,
} from '@elastic/eui';
-import { FormattedMessage, InjectedIntl } from '@kbn/i18n/react';
+import { FormattedMessage } from '@kbn/i18n/react';
import React, { Component, Fragment } from 'react';
-import { Feature } from '../../../../../../../../../../../plugins/features/public';
-import { KibanaPrivileges, Role, RoleKibanaPrivilege } from '../../../../../../../../common/model';
-import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator';
-import { isGlobalPrivilegeDefinition } from '../../../../../../../lib/privilege_utils';
-import { copyRole } from '../../../../../../../lib/role_utils';
-import { CUSTOM_PRIVILEGE_VALUE, NO_PRIVILEGE_VALUE } from '../../../../lib/constants';
+import { Feature } from '../../../../../../../../features/public';
+import {
+ KibanaPrivileges,
+ Role,
+ RoleKibanaPrivilege,
+ copyRole,
+} from '../../../../../../../common/model';
+import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator';
+import { isGlobalPrivilegeDefinition } from '../../../privilege_utils';
+import { CUSTOM_PRIVILEGE_VALUE, NO_PRIVILEGE_VALUE } from '../constants';
import { FeatureTable } from '../feature_table';
import { UnsupportedSpacePrivilegesWarning } from './unsupported_space_privileges_warning';
@@ -31,7 +34,6 @@ interface Props {
features: Feature[];
onChange: (role: Role) => void;
editable: boolean;
- intl: InjectedIntl;
}
interface State {
@@ -230,7 +232,6 @@ export class SimplePrivilegeSection extends Component {
allowedPrivileges={allowedPrivileges}
rankedFeaturePrivileges={privilegeCalculator.rankedFeaturePrivileges}
features={this.props.features}
- intl={this.props.intl}
onChange={this.onFeaturePrivilegeChange}
onChangeAll={this.onChangeAllFeaturePrivileges}
spacesIndex={this.props.role.kibana.findIndex(k => isGlobalPrivilegeDefinition(k))}
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/unsupported_space_privileges_warning.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/unsupported_space_privileges_warning.tsx
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/simple_privilege_section/unsupported_space_privileges_warning.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/unsupported_space_privileges_warning.tsx
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__fixtures__/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__fixtures__/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__fixtures__/index.ts
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__fixtures__/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__fixtures__/raw_kibana_privileges.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__fixtures__/raw_kibana_privileges.ts
similarity index 94%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__fixtures__/raw_kibana_privileges.ts
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__fixtures__/raw_kibana_privileges.ts
index d412ba63403e1..428836c9f181b 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__fixtures__/raw_kibana_privileges.ts
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__fixtures__/raw_kibana_privileges.ts
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { RawKibanaPrivileges } from '../../../../../../../../../common/model';
+import { RawKibanaPrivileges } from '../../../../../../../../common/model';
export const rawKibanaPrivileges: RawKibanaPrivileges = {
global: {
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_display.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_display.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_display.test.tsx.snap
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_display.test.tsx.snap
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_space_form.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_space_form.test.tsx.snap
similarity index 82%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_space_form.test.tsx.snap
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_space_form.test.tsx.snap
index c20a391cdb20c..e9f2f946e9885 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_space_form.test.tsx.snap
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__snapshots__/privilege_space_form.test.tsx.snap
@@ -351,108 +351,6 @@ exports[` renders without crashing 1`] = `
}
disabled={true}
features={Array []}
- intl={
- Object {
- "defaultFormats": Object {},
- "defaultLocale": "en",
- "formatDate": [Function],
- "formatHTMLMessage": [Function],
- "formatMessage": [Function],
- "formatNumber": [Function],
- "formatPlural": [Function],
- "formatRelative": [Function],
- "formatTime": [Function],
- "formats": Object {
- "date": Object {
- "full": Object {
- "day": "numeric",
- "month": "long",
- "weekday": "long",
- "year": "numeric",
- },
- "long": Object {
- "day": "numeric",
- "month": "long",
- "year": "numeric",
- },
- "medium": Object {
- "day": "numeric",
- "month": "short",
- "year": "numeric",
- },
- "short": Object {
- "day": "numeric",
- "month": "numeric",
- "year": "2-digit",
- },
- },
- "number": Object {
- "currency": Object {
- "style": "currency",
- },
- "percent": Object {
- "style": "percent",
- },
- },
- "relative": Object {
- "days": Object {
- "units": "day",
- },
- "hours": Object {
- "units": "hour",
- },
- "minutes": Object {
- "units": "minute",
- },
- "months": Object {
- "units": "month",
- },
- "seconds": Object {
- "units": "second",
- },
- "years": Object {
- "units": "year",
- },
- },
- "time": Object {
- "full": Object {
- "hour": "numeric",
- "minute": "numeric",
- "second": "numeric",
- "timeZoneName": "short",
- },
- "long": Object {
- "hour": "numeric",
- "minute": "numeric",
- "second": "numeric",
- "timeZoneName": "short",
- },
- "medium": Object {
- "hour": "numeric",
- "minute": "numeric",
- "second": "numeric",
- },
- "short": Object {
- "hour": "numeric",
- "minute": "numeric",
- },
- },
- },
- "formatters": Object {
- "getDateTimeFormat": [Function],
- "getMessageFormat": [Function],
- "getNumberFormat": [Function],
- "getPluralFormat": [Function],
- "getRelativeFormat": [Function],
- },
- "locale": "en",
- "messages": Object {},
- "now": [Function],
- "onError": [Function],
- "textComponent": Symbol(react.fragment),
- "timeZone": null,
- }
- }
kibanaPrivileges={
KibanaPrivileges {
"rawKibanaPrivileges": Object {
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__snapshots__/space_aware_privilege_section.test.tsx.snap b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__snapshots__/space_aware_privilege_section.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/__snapshots__/space_aware_privilege_section.test.tsx.snap
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/__snapshots__/space_aware_privilege_section.test.tsx.snap
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/_index.scss
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/_index.scss
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/_index.scss
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/_privilege_matrix.scss b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/_privilege_matrix.scss
similarity index 87%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/_privilege_matrix.scss
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/_privilege_matrix.scss
index 5f9fbced5ee6a..8f47727fdf8d6 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/_privilege_matrix.scss
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/_privilege_matrix.scss
@@ -9,6 +9,6 @@
.secPrivilegeMatrix__row--isBasePrivilege,
.secPrivilegeMatrix__cell--isGlobalPrivilege,
-.secPrivilegeTable__row--isGlobalSpace, {
+.secPrivilegeTable__row--isGlobalSpace {
background-color: $euiColorLightestShade;
}
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/index.ts
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_display.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.test.tsx
similarity index 96%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_display.test.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.test.tsx
index 62e22050132fd..c6268e19abfd1 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_display.test.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.test.tsx
@@ -7,7 +7,7 @@
import { EuiIconTip, EuiText, EuiToolTip } from '@elastic/eui';
import React from 'react';
import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
-import { PRIVILEGE_SOURCE } from '../../../../../../../lib/kibana_privilege_calculator';
+import { PRIVILEGE_SOURCE } from '../kibana_privilege_calculator';
import { PrivilegeDisplay } from './privilege_display';
describe('PrivilegeDisplay', () => {
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_display.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.tsx
similarity index 96%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_display.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.tsx
index 6af7672f6fef8..55ac99da4c8c1 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_display.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.tsx
@@ -7,11 +7,8 @@ import { EuiIcon, EuiIconTip, EuiText, IconType, PropsOf, EuiToolTip } from '@el
import { FormattedMessage } from '@kbn/i18n/react';
import _ from 'lodash';
import React, { ReactNode, FC } from 'react';
-import {
- PRIVILEGE_SOURCE,
- PrivilegeExplanation,
-} from '../../../../../../../lib/kibana_privilege_calculator';
-import { NO_PRIVILEGE_VALUE } from '../../../../lib/constants';
+import { PRIVILEGE_SOURCE, PrivilegeExplanation } from '../kibana_privilege_calculator';
+import { NO_PRIVILEGE_VALUE } from '../constants';
interface Props extends PropsOf {
privilege: string | string[] | undefined;
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_matrix.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_matrix.test.tsx
similarity index 89%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_matrix.test.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_matrix.test.tsx
index ee121caa13a2a..16aad4826ae44 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_matrix.test.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_matrix.test.tsx
@@ -3,14 +3,14 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-// @ts-ignore
+
import { EuiButtonEmpty, EuiInMemoryTable } from '@elastic/eui';
import React from 'react';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
-import { Space } from '../../../../../../../../../spaces/common/model/space';
-import { Feature } from '../../../../../../../../../../../plugins/features/public';
-import { KibanaPrivileges, Role } from '../../../../../../../../common/model';
-import { KibanaPrivilegeCalculatorFactory } from '../../../../../../..//lib/kibana_privilege_calculator';
+import { Space } from '../../../../../../../../spaces/common/model/space';
+import { Feature } from '../../../../../../../../features/public';
+import { KibanaPrivileges, Role } from '../../../../../../../common/model';
+import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator';
import { PrivilegeMatrix } from './privilege_matrix';
describe('PrivilegeMatrix', () => {
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_matrix.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_matrix.tsx
similarity index 93%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_matrix.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_matrix.tsx
index 962487312c83d..b3449e32c6c91 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_matrix.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_matrix.tsx
@@ -8,7 +8,6 @@ import {
EuiButtonEmpty,
EuiIcon,
EuiIconTip,
- // @ts-ignore
EuiInMemoryTable,
EuiModal,
EuiModalBody,
@@ -16,18 +15,16 @@ import {
EuiModalHeader,
EuiModalHeaderTitle,
EuiOverlayMask,
- // @ts-ignore
- EuiToolTip,
IconType,
} from '@elastic/eui';
import { FormattedMessage, InjectedIntl } from '@kbn/i18n/react';
import React, { Component, Fragment } from 'react';
-import { Space } from '../../../../../../../../../spaces/common/model/space';
-import { SpaceAvatar } from '../../../../../../../../../spaces/public/space_avatar';
-import { Feature } from '../../../../../../../../../../../plugins/features/public';
-import { FeaturesPrivileges, Role } from '../../../../../../../../common/model';
-import { CalculatedPrivilege } from '../../../../../../../lib/kibana_privilege_calculator';
-import { isGlobalPrivilegeDefinition } from '../../../../../../../lib/privilege_utils';
+import { SpaceAvatar } from '../../../../../../../../../legacy/plugins/spaces/public/space_avatar';
+import { Space } from '../../../../../../../../spaces/common/model/space';
+import { Feature } from '../../../../../../../../features/public';
+import { FeaturesPrivileges, Role } from '../../../../../../../common/model';
+import { CalculatedPrivilege } from '../kibana_privilege_calculator';
+import { isGlobalPrivilegeDefinition } from '../../../privilege_utils';
import { SpacesPopoverList } from '../../../spaces_popover_list';
import { PrivilegeDisplay } from './privilege_display';
@@ -258,11 +255,9 @@ export class PrivilegeMatrix extends Component {
];
return (
- // @ts-ignore missing rowProps from typedef
{
return {
className: item.feature.isBase ? 'secPrivilegeMatrix__row--isBasePrivilege' : '',
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx
similarity index 95%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx
index 2b7d87f663d72..675f02a81f9e1 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx
@@ -9,8 +9,8 @@ import { merge } from 'lodash';
// @ts-ignore
import { findTestSubject } from '@elastic/eui/lib/test';
import { shallowWithIntl, mountWithIntl } from 'test_utils/enzyme_helpers';
-import { KibanaPrivileges } from '../../../../../../../../common/model';
-import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator';
+import { KibanaPrivileges } from '../../../../../../../common/model';
+import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator';
import { PrivilegeSpaceForm } from './privilege_space_form';
import { rawKibanaPrivileges } from './__fixtures__';
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx
similarity index 96%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx
index 5abb87d23bb6e..6d1f5117c52e9 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx
@@ -24,17 +24,16 @@ import {
} from '@elastic/eui';
import { FormattedMessage, InjectedIntl } from '@kbn/i18n/react';
import React, { Component, Fragment } from 'react';
-import { Space } from '../../../../../../../../../spaces/common/model/space';
-import { Feature } from '../../../../../../../../../../../plugins/features/public';
-import { KibanaPrivileges, Role } from '../../../../../../../../common/model';
+import { Space } from '../../../../../../../../spaces/common/model/space';
+import { Feature } from '../../../../../../../../features/public';
+import { KibanaPrivileges, Role, copyRole } from '../../../../../../../common/model';
import {
AllowedPrivilege,
KibanaPrivilegeCalculatorFactory,
PrivilegeExplanation,
-} from '../../../../../../../lib/kibana_privilege_calculator';
-import { hasAssignedFeaturePrivileges } from '../../../../../../../lib/privilege_utils';
-import { copyRole } from '../../../../../../../lib/role_utils';
-import { CUSTOM_PRIVILEGE_VALUE } from '../../../../lib/constants';
+} from '../kibana_privilege_calculator';
+import { hasAssignedFeaturePrivileges } from '../../../privilege_utils';
+import { CUSTOM_PRIVILEGE_VALUE } from '../constants';
import { FeatureTable } from '../feature_table';
import { SpaceSelector } from './space_selector';
@@ -285,7 +284,6 @@ export class PrivilegeSpaceForm extends Component {
calculatedPrivileges={calculatedPrivileges}
allowedPrivileges={allowedPrivileges}
rankedFeaturePrivileges={privilegeCalculator.rankedFeaturePrivileges}
- intl={this.props.intl}
onChange={this.onFeaturePrivilegesChange}
onChangeAll={this.onChangeAllFeaturePrivileges}
kibanaPrivileges={this.props.kibanaPrivileges}
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx
similarity index 99%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx
index 37ee43c5473b0..f0a391c98c910 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx
@@ -10,8 +10,8 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers';
import { ReactWrapper } from 'enzyme';
import { PrivilegeSpaceTable } from './privilege_space_table';
import { PrivilegeDisplay } from './privilege_display';
-import { KibanaPrivileges, Role, RoleKibanaPrivilege } from '../../../../../../../../common/model';
-import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator';
+import { KibanaPrivileges, Role, RoleKibanaPrivilege } from '../../../../../../../common/model';
+import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator';
import { rawKibanaPrivileges } from './__fixtures__';
interface TableRow {
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx
similarity index 94%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx
index 65a3df9fb47a1..1c27ec84f50dc 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx
@@ -12,22 +12,21 @@ import {
EuiBasicTableColumn,
} from '@elastic/eui';
import { FormattedMessage, InjectedIntl } from '@kbn/i18n/react';
-import _ from 'lodash';
import React, { Component } from 'react';
-import { getSpaceColor } from '../../../../../../../../../spaces/public/space_avatar';
-import { Space } from '../../../../../../../../../spaces/common/model/space';
+import { getSpaceColor } from '../../../../../../../../../legacy/plugins/spaces/public/space_avatar';
+import { Space } from '../../../../../../../../spaces/common/model/space';
import {
FeaturesPrivileges,
Role,
RoleKibanaPrivilege,
-} from '../../../../../../../../common/model';
-import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator';
+ copyRole,
+} from '../../../../../../../common/model';
+import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator';
import {
isGlobalPrivilegeDefinition,
hasAssignedFeaturePrivileges,
-} from '../../../../../../../lib/privilege_utils';
-import { copyRole } from '../../../../../../../lib/role_utils';
-import { CUSTOM_PRIVILEGE_VALUE, NO_PRIVILEGE_VALUE } from '../../../../lib/constants';
+} from '../../../privilege_utils';
+import { CUSTOM_PRIVILEGE_VALUE, NO_PRIVILEGE_VALUE } from '../constants';
import { SpacesPopoverList } from '../../../spaces_popover_list';
import { PrivilegeDisplay } from './privilege_display';
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.test.tsx
similarity index 95%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.test.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.test.tsx
index 2756b1c447274..e06d2a4f7dc33 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.test.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.test.tsx
@@ -6,9 +6,9 @@
import React from 'react';
import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
-import { KibanaPrivileges } from '../../../../../../../../common/model';
-import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator';
-import { RoleValidator } from '../../../../lib/validate_role';
+import { KibanaPrivileges } from '../../../../../../../common/model';
+import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator';
+import { RoleValidator } from '../../../validate_role';
import { PrivilegeMatrix } from './privilege_matrix';
import { PrivilegeSpaceForm } from './privilege_space_form';
import { PrivilegeSpaceTable } from './privilege_space_table';
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx
similarity index 93%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx
index d324cf99c8418..21cadfafe1790 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx
@@ -14,13 +14,12 @@ import {
import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react';
import _ from 'lodash';
import React, { Component, Fragment } from 'react';
-import { UICapabilities } from 'ui/capabilities';
-import { Space } from '../../../../../../../../../spaces/common/model/space';
-import { Feature } from '../../../../../../../../../../../plugins/features/public';
-import { KibanaPrivileges, Role } from '../../../../../../../../common/model';
-import { KibanaPrivilegeCalculatorFactory } from '../../../../../../../lib/kibana_privilege_calculator';
-import { isReservedRole } from '../../../../../../../lib/role_utils';
-import { RoleValidator } from '../../../../lib/validate_role';
+import { Capabilities } from 'src/core/public';
+import { Space } from '../../../../../../../../spaces/common/model/space';
+import { Feature } from '../../../../../../../../features/public';
+import { KibanaPrivileges, Role, isReservedRole } from '../../../../../../../common/model';
+import { KibanaPrivilegeCalculatorFactory } from '../kibana_privilege_calculator';
+import { RoleValidator } from '../../../validate_role';
import { PrivilegeMatrix } from './privilege_matrix';
import { PrivilegeSpaceForm } from './privilege_space_form';
import { PrivilegeSpaceTable } from './privilege_space_table';
@@ -34,7 +33,7 @@ interface Props {
editable: boolean;
validator: RoleValidator;
intl: InjectedIntl;
- uiCapabilities: UICapabilities;
+ uiCapabilities: Capabilities;
features: Feature[];
}
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_selector.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_selector.tsx
similarity index 93%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_selector.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_selector.tsx
index 0eb9cf0b0ee9d..cfeb5b9f37d8c 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/space_aware_privilege_section/space_selector.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_selector.tsx
@@ -7,8 +7,8 @@
import { EuiComboBox, EuiComboBoxOptionProps, EuiHealth, EuiHighlight } from '@elastic/eui';
import { InjectedIntl } from '@kbn/i18n/react';
import React, { Component } from 'react';
-import { Space } from '../../../../../../../../../spaces/common/model/space';
-import { getSpaceColor } from '../../../../../../../../../spaces/public/space_avatar';
+import { getSpaceColor } from '../../../../../../../../../legacy/plugins/spaces/public/space_avatar';
+import { Space } from '../../../../../../../../spaces/common/model/space';
const spaceToOption = (space?: Space, currentSelection?: 'global' | 'spaces') => {
if (!space) {
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/transform_error_section/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/transform_error_section/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/transform_error_section/index.ts
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/transform_error_section/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/transform_error_section/transform_error_section.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/transform_error_section/transform_error_section.tsx
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/privileges/kibana/transform_error_section/transform_error_section.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/transform_error_section/transform_error_section.tsx
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/reserved_role_badge.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/reserved_role_badge.test.tsx
similarity index 96%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/reserved_role_badge.test.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/reserved_role_badge.test.tsx
index 9b483d92cde41..d29b442420a90 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/reserved_role_badge.test.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/reserved_role_badge.test.tsx
@@ -7,7 +7,7 @@
import { EuiIcon } from '@elastic/eui';
import { shallow } from 'enzyme';
import React from 'react';
-import { Role } from '../../../../../common/model';
+import { Role } from '../../../../common/model';
import { ReservedRoleBadge } from './reserved_role_badge';
const reservedRole: Role = {
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/reserved_role_badge.tsx b/x-pack/plugins/security/public/management/roles/edit_role/reserved_role_badge.tsx
similarity index 89%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/reserved_role_badge.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/reserved_role_badge.tsx
index 3d817d1e07d21..501ca7589dafd 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/reserved_role_badge.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/reserved_role_badge.tsx
@@ -8,8 +8,7 @@ import React from 'react';
import { EuiIcon, EuiToolTip } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
-import { Role } from '../../../../../common/model';
-import { isReservedRole } from '../../../../lib/role_utils';
+import { Role, isReservedRole } from '../../../../common/model';
interface Props {
role: Role;
diff --git a/x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/_index.scss b/x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/_index.scss
new file mode 100644
index 0000000000000..b40a32cb8df96
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/_index.scss
@@ -0,0 +1 @@
+@import './spaces_popover_list';
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/spaces_popover_list/_spaces_popover_list.scss b/x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/_spaces_popover_list.scss
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/spaces_popover_list/_spaces_popover_list.scss
rename to x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/_spaces_popover_list.scss
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/spaces_popover_list/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/spaces_popover_list/index.ts
rename to x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/spaces_popover_list/spaces_popover_list.tsx b/x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/spaces_popover_list.tsx
similarity index 95%
rename from x-pack/legacy/plugins/security/public/views/management/edit_role/components/spaces_popover_list/spaces_popover_list.tsx
rename to x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/spaces_popover_list.tsx
index a99e389044eaa..bb7a6db97f7c8 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_role/components/spaces_popover_list/spaces_popover_list.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/spaces_popover_list/spaces_popover_list.tsx
@@ -14,9 +14,9 @@ import {
} from '@elastic/eui';
import { FormattedMessage, InjectedIntl } from '@kbn/i18n/react';
import React, { Component } from 'react';
-import { SpaceAvatar } from '../../../../../../../spaces/public/space_avatar';
-import { SPACE_SEARCH_COUNT_THRESHOLD } from '../../../../../../../../../plugins/spaces/common/constants';
-import { Space } from '../../../../../../../../../plugins/spaces/common/model/space';
+import { SpaceAvatar } from '../../../../../../../legacy/plugins/spaces/public/space_avatar';
+import { SPACE_SEARCH_COUNT_THRESHOLD } from '../../../../../../spaces/common';
+import { Space } from '../../../../../../spaces/common/model/space';
interface Props {
spaces: Space[];
@@ -146,7 +146,6 @@ export class SpacesPopoverList extends Component {
return (
{
- // @ts-ignore onSearch isn't defined on the type
({
+ getFields: jest.fn(),
+ }),
+};
diff --git a/x-pack/plugins/security/public/management/roles/indices_api_client.ts b/x-pack/plugins/security/public/management/roles/indices_api_client.ts
new file mode 100644
index 0000000000000..65d9a40a776eb
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/indices_api_client.ts
@@ -0,0 +1,18 @@
+/*
+ * 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 { HttpStart } from 'src/core/public';
+
+export class IndicesAPIClient {
+ constructor(private readonly http: HttpStart) {}
+
+ async getFields(query: string) {
+ return (
+ (await this.http.get(`/internal/security/fields/${encodeURIComponent(query)}`)) ||
+ []
+ );
+ }
+}
diff --git a/x-pack/plugins/security/public/management/roles/privileges_api_client.mock.ts b/x-pack/plugins/security/public/management/roles/privileges_api_client.mock.ts
new file mode 100644
index 0000000000000..2564914a1d3d8
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/privileges_api_client.mock.ts
@@ -0,0 +1,12 @@
+/*
+ * 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 privilegesAPIClientMock = {
+ create: () => ({
+ getAll: jest.fn(),
+ getBuiltIn: jest.fn(),
+ }),
+};
diff --git a/x-pack/plugins/security/public/management/roles/privileges_api_client.ts b/x-pack/plugins/security/public/management/roles/privileges_api_client.ts
new file mode 100644
index 0000000000000..45bd2fd8fb3a6
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/privileges_api_client.ts
@@ -0,0 +1,22 @@
+/*
+ * 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 { HttpStart } from 'src/core/public';
+import { BuiltinESPrivileges, RawKibanaPrivileges } from '../../../common/model';
+
+export class PrivilegesAPIClient {
+ constructor(private readonly http: HttpStart) {}
+
+ async getAll({ includeActions }: { includeActions: boolean }) {
+ return await this.http.get('/api/security/privileges', {
+ query: { includeActions },
+ });
+ }
+
+ async getBuiltIn() {
+ return await this.http.get('/internal/security/esPrivileges/builtin');
+ }
+}
diff --git a/x-pack/plugins/security/public/management/roles/roles_api_client.mock.ts b/x-pack/plugins/security/public/management/roles/roles_api_client.mock.ts
new file mode 100644
index 0000000000000..c4d3724c0ecb5
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/roles_api_client.mock.ts
@@ -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.
+ */
+
+export const rolesAPIClientMock = {
+ create: () => ({
+ getRoles: jest.fn(),
+ getRole: jest.fn(),
+ deleteRole: jest.fn(),
+ saveRole: jest.fn(),
+ }),
+};
diff --git a/x-pack/legacy/plugins/security/public/lib/transform_role_for_save.test.ts b/x-pack/plugins/security/public/management/roles/roles_api_client.test.ts
similarity index 82%
rename from x-pack/legacy/plugins/security/public/lib/transform_role_for_save.test.ts
rename to x-pack/plugins/security/public/management/roles/roles_api_client.test.ts
index 1ea19f2637305..7561161368405 100644
--- a/x-pack/legacy/plugins/security/public/lib/transform_role_for_save.test.ts
+++ b/x-pack/plugins/security/public/management/roles/roles_api_client.test.ts
@@ -4,12 +4,23 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Role } from '../../common/model';
-import { transformRoleForSave } from './transform_role_for_save';
+import { Role } from '../../../common/model';
+import { RolesAPIClient } from './roles_api_client';
+import { httpServiceMock } from '../../../../../../src/core/public/mocks';
+
+describe('RolesAPIClient', () => {
+ async function saveRole(role: Role, spacesEnabled: boolean) {
+ const httpMock = httpServiceMock.createStartContract();
+ const rolesAPIClient = new RolesAPIClient(httpMock);
+
+ await rolesAPIClient.saveRole({ role, spacesEnabled });
+ expect(httpMock.put).toHaveBeenCalledTimes(1);
+
+ return JSON.parse(httpMock.put.mock.calls[0][1]?.body as any);
+ }
-describe('transformRoleForSave', () => {
describe('spaces disabled', () => {
- it('removes placeholder index privileges', () => {
+ it('removes placeholder index privileges', async () => {
const role: Role = {
name: 'my role',
elasticsearch: {
@@ -20,7 +31,7 @@ describe('transformRoleForSave', () => {
kibana: [],
};
- const result = transformRoleForSave(role, false);
+ const result = await saveRole(role, false);
expect(result).toEqual({
elasticsearch: {
@@ -32,7 +43,7 @@ describe('transformRoleForSave', () => {
});
});
- it('removes placeholder query entries', () => {
+ it('removes placeholder query entries', async () => {
const role: Role = {
name: 'my role',
elasticsearch: {
@@ -43,7 +54,7 @@ describe('transformRoleForSave', () => {
kibana: [],
};
- const result = transformRoleForSave(role, false);
+ const result = await saveRole(role, false);
expect(result).toEqual({
elasticsearch: {
@@ -55,7 +66,7 @@ describe('transformRoleForSave', () => {
});
});
- it('removes transient fields not required for save', () => {
+ it('removes transient fields not required for save', async () => {
const role: Role = {
name: 'my role',
transient_metadata: {
@@ -74,7 +85,7 @@ describe('transformRoleForSave', () => {
kibana: [],
};
- const result = transformRoleForSave(role, false);
+ const result = await saveRole(role, false);
expect(result).toEqual({
metadata: {
@@ -89,7 +100,7 @@ describe('transformRoleForSave', () => {
});
});
- it('does not remove actual query entries', () => {
+ it('does not remove actual query entries', async () => {
const role: Role = {
name: 'my role',
elasticsearch: {
@@ -100,7 +111,7 @@ describe('transformRoleForSave', () => {
kibana: [],
};
- const result = transformRoleForSave(role, false);
+ const result = await saveRole(role, false);
expect(result).toEqual({
elasticsearch: {
@@ -112,7 +123,7 @@ describe('transformRoleForSave', () => {
});
});
- it('should remove feature privileges if a corresponding base privilege is defined', () => {
+ it('should remove feature privileges if a corresponding base privilege is defined', async () => {
const role: Role = {
name: 'my role',
elasticsearch: {
@@ -132,7 +143,7 @@ describe('transformRoleForSave', () => {
],
};
- const result = transformRoleForSave(role, false);
+ const result = await saveRole(role, false);
expect(result).toEqual({
elasticsearch: {
@@ -150,7 +161,7 @@ describe('transformRoleForSave', () => {
});
});
- it('should not remove feature privileges if a corresponding base privilege is not defined', () => {
+ it('should not remove feature privileges if a corresponding base privilege is not defined', async () => {
const role: Role = {
name: 'my role',
elasticsearch: {
@@ -170,7 +181,7 @@ describe('transformRoleForSave', () => {
],
};
- const result = transformRoleForSave(role, false);
+ const result = await saveRole(role, false);
expect(result).toEqual({
elasticsearch: {
@@ -191,7 +202,7 @@ describe('transformRoleForSave', () => {
});
});
- it('should remove space privileges', () => {
+ it('should remove space privileges', async () => {
const role: Role = {
name: 'my role',
elasticsearch: {
@@ -219,7 +230,7 @@ describe('transformRoleForSave', () => {
],
};
- const result = transformRoleForSave(role, false);
+ const result = await saveRole(role, false);
expect(result).toEqual({
elasticsearch: {
@@ -242,7 +253,7 @@ describe('transformRoleForSave', () => {
});
describe('spaces enabled', () => {
- it('removes placeholder index privileges', () => {
+ it('removes placeholder index privileges', async () => {
const role: Role = {
name: 'my role',
elasticsearch: {
@@ -253,7 +264,7 @@ describe('transformRoleForSave', () => {
kibana: [],
};
- const result = transformRoleForSave(role, true);
+ const result = await saveRole(role, true);
expect(result).toEqual({
elasticsearch: {
@@ -265,7 +276,7 @@ describe('transformRoleForSave', () => {
});
});
- it('removes placeholder query entries', () => {
+ it('removes placeholder query entries', async () => {
const role: Role = {
name: 'my role',
elasticsearch: {
@@ -276,7 +287,7 @@ describe('transformRoleForSave', () => {
kibana: [],
};
- const result = transformRoleForSave(role, true);
+ const result = await saveRole(role, true);
expect(result).toEqual({
elasticsearch: {
@@ -288,7 +299,7 @@ describe('transformRoleForSave', () => {
});
});
- it('removes transient fields not required for save', () => {
+ it('removes transient fields not required for save', async () => {
const role: Role = {
name: 'my role',
transient_metadata: {
@@ -307,7 +318,7 @@ describe('transformRoleForSave', () => {
kibana: [],
};
- const result = transformRoleForSave(role, true);
+ const result = await saveRole(role, true);
expect(result).toEqual({
metadata: {
@@ -322,7 +333,7 @@ describe('transformRoleForSave', () => {
});
});
- it('does not remove actual query entries', () => {
+ it('does not remove actual query entries', async () => {
const role: Role = {
name: 'my role',
elasticsearch: {
@@ -333,7 +344,7 @@ describe('transformRoleForSave', () => {
kibana: [],
};
- const result = transformRoleForSave(role, true);
+ const result = await saveRole(role, true);
expect(result).toEqual({
elasticsearch: {
@@ -345,7 +356,7 @@ describe('transformRoleForSave', () => {
});
});
- it('should remove feature privileges if a corresponding base privilege is defined', () => {
+ it('should remove feature privileges if a corresponding base privilege is defined', async () => {
const role: Role = {
name: 'my role',
elasticsearch: {
@@ -365,7 +376,7 @@ describe('transformRoleForSave', () => {
],
};
- const result = transformRoleForSave(role, true);
+ const result = await saveRole(role, true);
expect(result).toEqual({
elasticsearch: {
@@ -383,7 +394,7 @@ describe('transformRoleForSave', () => {
});
});
- it('should not remove feature privileges if a corresponding base privilege is not defined', () => {
+ it('should not remove feature privileges if a corresponding base privilege is not defined', async () => {
const role: Role = {
name: 'my role',
elasticsearch: {
@@ -403,7 +414,7 @@ describe('transformRoleForSave', () => {
],
};
- const result = transformRoleForSave(role, true);
+ const result = await saveRole(role, true);
expect(result).toEqual({
elasticsearch: {
@@ -424,7 +435,7 @@ describe('transformRoleForSave', () => {
});
});
- it('should not remove space privileges', () => {
+ it('should not remove space privileges', async () => {
const role: Role = {
name: 'my role',
elasticsearch: {
@@ -452,7 +463,7 @@ describe('transformRoleForSave', () => {
],
};
- const result = transformRoleForSave(role, true);
+ const result = await saveRole(role, true);
expect(result).toEqual({
elasticsearch: {
diff --git a/x-pack/plugins/security/public/management/roles/roles_api_client.ts b/x-pack/plugins/security/public/management/roles/roles_api_client.ts
new file mode 100644
index 0000000000000..d7e98e03a965b
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/roles_api_client.ts
@@ -0,0 +1,62 @@
+/*
+ * 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 { HttpStart } from 'src/core/public';
+import { Role, RoleIndexPrivilege, copyRole } from '../../../common/model';
+import { isGlobalPrivilegeDefinition } from './edit_role/privilege_utils';
+
+export class RolesAPIClient {
+ constructor(private readonly http: HttpStart) {}
+
+ public async getRoles() {
+ return await this.http.get('/api/security/role');
+ }
+
+ public async getRole(roleName: string) {
+ return await this.http.get(`/api/security/role/${encodeURIComponent(roleName)}`);
+ }
+
+ public async deleteRole(roleName: string) {
+ await this.http.delete(`/api/security/role/${encodeURIComponent(roleName)}`);
+ }
+
+ public async saveRole({ role, spacesEnabled }: { role: Role; spacesEnabled: boolean }) {
+ await this.http.put(`/api/security/role/${encodeURIComponent(role.name)}`, {
+ body: JSON.stringify(this.transformRoleForSave(copyRole(role), spacesEnabled)),
+ });
+ }
+
+ private transformRoleForSave(role: Role, spacesEnabled: boolean) {
+ // Remove any placeholder index privileges
+ const isPlaceholderPrivilege = (indexPrivilege: RoleIndexPrivilege) =>
+ indexPrivilege.names.length === 0;
+ role.elasticsearch.indices = role.elasticsearch.indices.filter(
+ indexPrivilege => !isPlaceholderPrivilege(indexPrivilege)
+ );
+
+ // Remove any placeholder query entries
+ role.elasticsearch.indices.forEach(index => index.query || delete index.query);
+
+ // If spaces are disabled, then do not persist any space privileges
+ if (!spacesEnabled) {
+ role.kibana = role.kibana.filter(isGlobalPrivilegeDefinition);
+ }
+
+ role.kibana.forEach(kibanaPrivilege => {
+ // If a base privilege is defined, then do not persist feature privileges
+ if (kibanaPrivilege.base.length > 0) {
+ kibanaPrivilege.feature = {};
+ }
+ });
+
+ delete role.name;
+ delete role.transient_metadata;
+ delete role._unrecognized_applications;
+ delete role._transform_error;
+
+ return role;
+ }
+}
diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/__snapshots__/roles_grid_page.test.tsx.snap b/x-pack/plugins/security/public/management/roles/roles_grid/__snapshots__/roles_grid_page.test.tsx.snap
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/roles_grid/components/__snapshots__/roles_grid_page.test.tsx.snap
rename to x-pack/plugins/security/public/management/roles/roles_grid/__snapshots__/roles_grid_page.test.tsx.snap
diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/confirm_delete/confirm_delete.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/confirm_delete.tsx
similarity index 72%
rename from x-pack/legacy/plugins/security/public/views/management/roles_grid/components/confirm_delete/confirm_delete.tsx
rename to x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/confirm_delete.tsx
index 34784b4b2accb..37eed3357241d 100644
--- a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/confirm_delete/confirm_delete.tsx
+++ b/x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/confirm_delete.tsx
@@ -4,6 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import React, { Component, Fragment } from 'react';
import {
EuiButton,
EuiButtonEmpty,
@@ -15,23 +16,24 @@ import {
EuiOverlayMask,
EuiText,
} from '@elastic/eui';
-import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react';
-import React, { Component, Fragment } from 'react';
-import { toastNotifications } from 'ui/notify';
-import { RolesApi } from '../../../../../lib/roles_api';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { NotificationsStart } from 'src/core/public';
+import { RolesAPIClient } from '../../roles_api_client';
interface Props {
rolesToDelete: string[];
- intl: InjectedIntl;
callback: (rolesToDelete: string[], errors: string[]) => void;
onCancel: () => void;
+ notifications: NotificationsStart;
+ rolesAPIClient: PublicMethodsOf;
}
interface State {
deleteInProgress: boolean;
}
-class ConfirmDeleteUI extends Component {
+export class ConfirmDelete extends Component {
constructor(props: Props) {
super(props);
this.state = {
@@ -40,15 +42,12 @@ class ConfirmDeleteUI extends Component {
}
public render() {
- const { rolesToDelete, intl } = this.props;
+ const { rolesToDelete } = this.props;
const moreThanOne = rolesToDelete.length > 1;
- const title = intl.formatMessage(
- {
- id: 'xpack.security.management.roles.deleteRoleTitle',
- defaultMessage: 'Delete role{value, plural, one {{roleName}} other {s}}',
- },
- { value: rolesToDelete.length, roleName: ` ${rolesToDelete[0]}` }
- );
+ const title = i18n.translate('xpack.security.management.roles.deleteRoleTitle', {
+ defaultMessage: 'Delete role{value, plural, one {{roleName}} other {s}}',
+ values: { value: rolesToDelete.length, roleName: ` ${rolesToDelete[0]}` },
+ });
// This is largely the same as the built-in EuiConfirmModal component, but we needed the ability
// to disable the buttons since this could be a long-running operation
@@ -128,32 +127,24 @@ class ConfirmDeleteUI extends Component {
};
private deleteRoles = async () => {
- const { rolesToDelete, callback } = this.props;
+ const { rolesToDelete, callback, rolesAPIClient, notifications } = this.props;
const errors: string[] = [];
const deleteOperations = rolesToDelete.map(roleName => {
const deleteRoleTask = async () => {
try {
- await RolesApi.deleteRole(roleName);
- toastNotifications.addSuccess(
- this.props.intl.formatMessage(
- {
- id:
- 'xpack.security.management.roles.confirmDelete.roleSuccessfullyDeletedNotificationMessage',
- defaultMessage: 'Deleted role {roleName}',
- },
- { roleName }
+ await rolesAPIClient.deleteRole(roleName);
+ notifications.toasts.addSuccess(
+ i18n.translate(
+ 'xpack.security.management.roles.confirmDelete.roleSuccessfullyDeletedNotificationMessage',
+ { defaultMessage: 'Deleted role {roleName}', values: { roleName } }
)
);
} catch (e) {
errors.push(roleName);
- toastNotifications.addDanger(
- this.props.intl.formatMessage(
- {
- id:
- 'xpack.security.management.roles.confirmDelete.roleDeletingErrorNotificationMessage',
- defaultMessage: 'Error deleting role {roleName}',
- },
- { roleName }
+ notifications.toasts.addDanger(
+ i18n.translate(
+ 'xpack.security.management.roles.confirmDelete.roleDeletingErrorNotificationMessage',
+ { defaultMessage: 'Error deleting role {roleName}', values: { roleName } }
)
);
}
@@ -167,5 +158,3 @@ class ConfirmDeleteUI extends Component {
callback(rolesToDelete, errors);
};
}
-
-export const ConfirmDelete = injectI18n(ConfirmDeleteUI);
diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/confirm_delete/index.ts b/x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/roles_grid/components/confirm_delete/index.ts
rename to x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/index.ts b/x-pack/plugins/security/public/management/roles/roles_grid/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/roles_grid/components/index.ts
rename to x-pack/plugins/security/public/management/roles/roles_grid/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/permission_denied/index.ts b/x-pack/plugins/security/public/management/roles/roles_grid/permission_denied/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/roles_grid/components/permission_denied/index.ts
rename to x-pack/plugins/security/public/management/roles/roles_grid/permission_denied/index.ts
diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/permission_denied/permission_denied.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/permission_denied/permission_denied.tsx
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/roles_grid/components/permission_denied/permission_denied.tsx
rename to x-pack/plugins/security/public/management/roles/roles_grid/permission_denied/permission_denied.tsx
diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/roles_grid_page.test.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx
similarity index 63%
rename from x-pack/legacy/plugins/security/public/views/management/roles_grid/components/roles_grid_page.test.tsx
rename to x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx
index 6da2f2442d488..63ace53420612 100644
--- a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/roles_grid_page.test.tsx
+++ b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx
@@ -4,50 +4,19 @@
* you may not use this file except in compliance with the Elastic License.
*/
-let mockSimulate403 = false;
-const mock403 = () => ({ body: { statusCode: 403 } });
-jest.mock('../../../../lib/roles_api', () => {
- return {
- RolesApi: {
- async getRoles() {
- if (mockSimulate403) {
- throw mock403();
- }
- return [
- {
- name: 'test-role-1',
- elasticsearch: { cluster: [], indices: [], run_as: [] },
- kibana: { global: [], space: {} },
- },
- {
- name: 'reserved-role',
- elasticsearch: { cluster: [], indices: [], run_as: [] },
- kibana: { global: [], space: {} },
- metadata: {
- _reserved: true,
- },
- },
- {
- name: 'disabled-role',
- elasticsearch: { cluster: [], indices: [], run_as: [] },
- kibana: { global: [], space: {} },
- transient_metadata: {
- enabled: false,
- },
- },
- ];
- },
- },
- };
-});
-
import { EuiIcon } from '@elastic/eui';
import { ReactWrapper } from 'enzyme';
import React from 'react';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
+import { RolesAPIClient } from '../roles_api_client';
import { PermissionDenied } from './permission_denied';
import { RolesGridPage } from './roles_grid_page';
+import { coreMock } from '../../../../../../../src/core/public/mocks';
+import { rolesAPIClientMock } from '../index.mock';
+
+const mock403 = () => ({ body: { statusCode: 403 } });
+
const waitForRender = async (
wrapper: ReactWrapper,
condition: (wrapper: ReactWrapper) => boolean
@@ -69,12 +38,37 @@ const waitForRender = async (
};
describe('', () => {
+ let apiClientMock: jest.Mocked>;
beforeEach(() => {
- mockSimulate403 = false;
+ apiClientMock = rolesAPIClientMock.create();
+ apiClientMock.getRoles.mockResolvedValue([
+ {
+ name: 'test-role-1',
+ elasticsearch: { cluster: [], indices: [], run_as: [] },
+ kibana: [{ base: [], spaces: [], feature: {} }],
+ },
+ {
+ name: 'reserved-role',
+ elasticsearch: { cluster: [], indices: [], run_as: [] },
+ kibana: [{ base: [], spaces: [], feature: {} }],
+ metadata: { _reserved: true },
+ },
+ {
+ name: 'disabled-role',
+ elasticsearch: { cluster: [], indices: [], run_as: [] },
+ kibana: [{ base: [], spaces: [], feature: {} }],
+ transient_metadata: { enabled: false },
+ },
+ ]);
});
it(`renders reserved roles as such`, async () => {
- const wrapper = mountWithIntl();
+ const wrapper = mountWithIntl(
+
+ );
const initialIconCount = wrapper.find(EuiIcon).length;
await waitForRender(wrapper, updatedWrapper => {
@@ -87,8 +81,14 @@ describe('', () => {
});
it('renders permission denied if required', async () => {
- mockSimulate403 = true;
- const wrapper = mountWithIntl();
+ apiClientMock.getRoles.mockRejectedValue(mock403());
+
+ const wrapper = mountWithIntl(
+
+ );
await waitForRender(wrapper, updatedWrapper => {
return updatedWrapper.find(PermissionDenied).length > 0;
});
@@ -96,7 +96,12 @@ describe('', () => {
});
it('renders role actions as appropriate', async () => {
- const wrapper = mountWithIntl();
+ const wrapper = mountWithIntl(
+
+ );
const initialIconCount = wrapper.find(EuiIcon).length;
await waitForRender(wrapper, updatedWrapper => {
diff --git a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/roles_grid_page.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx
similarity index 78%
rename from x-pack/legacy/plugins/security/public/views/management/roles_grid/components/roles_grid_page.tsx
rename to x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx
index 2083a93f4b33c..7c686bef391a7 100644
--- a/x-pack/legacy/plugins/security/public/views/management/roles_grid/components/roles_grid_page.tsx
+++ b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx
@@ -4,6 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import _ from 'lodash';
+import React, { Component } from 'react';
import {
EuiButton,
EuiIcon,
@@ -18,18 +20,17 @@ import {
EuiButtonIcon,
EuiBasicTableColumn,
} from '@elastic/eui';
-import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react';
-import _ from 'lodash';
-import React, { Component } from 'react';
-import { toastNotifications } from 'ui/notify';
-import { Role } from '../../../../../common/model';
-import { isRoleEnabled, isReadOnlyRole, isReservedRole } from '../../../../lib/role_utils';
-import { RolesApi } from '../../../../lib/roles_api';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { NotificationsStart } from 'src/core/public';
+import { Role, isRoleEnabled, isReadOnlyRole, isReservedRole } from '../../../../common/model';
+import { RolesAPIClient } from '../roles_api_client';
import { ConfirmDelete } from './confirm_delete';
import { PermissionDenied } from './permission_denied';
interface Props {
- intl: InjectedIntl;
+ notifications: NotificationsStart;
+ rolesAPIClient: PublicMethodsOf;
}
interface State {
@@ -44,7 +45,7 @@ const getRoleManagementHref = (action: 'edit' | 'clone', roleName?: string) => {
return `#/management/security/roles/${action}${roleName ? `/${roleName}` : ''}`;
};
-class RolesGridPageUI extends Component {
+export class RolesGridPage extends Component {
constructor(props: Props) {
super(props);
this.state = {
@@ -68,7 +69,6 @@ class RolesGridPageUI extends Component {
private getPageContent = () => {
const { roles } = this.state;
- const { intl } = this.props;
return (
@@ -105,6 +105,8 @@ class RolesGridPageUI extends Component {
onCancel={this.onCancelDelete}
rolesToDelete={this.state.selection.map(role => role.name)}
callback={this.handleDelete}
+ notifications={this.props.notifications}
+ rolesAPIClient={this.props.rolesAPIClient}
/>
) : null}
@@ -112,7 +114,7 @@ class RolesGridPageUI extends Component {
!role.metadata || !role.metadata._reserved,
@@ -155,17 +157,16 @@ class RolesGridPageUI extends Component {
);
};
- private getColumnConfig = (intl: InjectedIntl) => {
- const reservedRoleDesc = intl.formatMessage({
- id: 'xpack.security.management.roles.reservedColumnDescription',
- defaultMessage: 'Reserved roles are built-in and cannot be edited or removed.',
- });
+ private getColumnConfig = () => {
+ const reservedRoleDesc = i18n.translate(
+ 'xpack.security.management.roles.reservedColumnDescription',
+ { defaultMessage: 'Reserved roles are built-in and cannot be edited or removed.' }
+ );
return [
{
field: 'name',
- name: intl.formatMessage({
- id: 'xpack.security.management.roles.nameColumnName',
+ name: i18n.translate('xpack.security.management.roles.nameColumnName', {
defaultMessage: 'Role',
}),
sortable: true,
@@ -188,8 +189,7 @@ class RolesGridPageUI extends Component {
},
{
field: 'metadata',
- name: intl.formatMessage({
- id: 'xpack.security.management.roles.reservedColumnName',
+ name: i18n.translate('xpack.security.management.roles.reservedColumnName', {
defaultMessage: 'Reserved',
}),
sortable: ({ metadata }: Role) => Boolean(metadata && metadata._reserved),
@@ -197,8 +197,7 @@ class RolesGridPageUI extends Component {
align: 'right',
description: reservedRoleDesc,
render: (metadata: Role['metadata']) => {
- const label = intl.formatMessage({
- id: 'xpack.security.management.roles.reservedRoleIconLabel',
+ const label = i18n.translate('xpack.security.management.roles.reservedRoleIconLabel', {
defaultMessage: 'Reserved role',
});
@@ -210,8 +209,7 @@ class RolesGridPageUI extends Component {
},
},
{
- name: intl.formatMessage({
- id: 'xpack.security.management.roles.actionsColumnName',
+ name: i18n.translate('xpack.security.management.roles.actionsColumnName', {
defaultMessage: 'Actions',
}),
width: '150px',
@@ -219,15 +217,10 @@ class RolesGridPageUI extends Component {
{
available: (role: Role) => !isReadOnlyRole(role),
render: (role: Role) => {
- const title = intl.formatMessage(
- {
- id: 'xpack.security.management.roles.editRoleActionName',
- defaultMessage: `Edit {roleName}`,
- },
- {
- roleName: role.name,
- }
- );
+ const title = i18n.translate('xpack.security.management.roles.editRoleActionName', {
+ defaultMessage: `Edit {roleName}`,
+ values: { roleName: role.name },
+ });
return (
{
{
available: (role: Role) => !isReservedRole(role),
render: (role: Role) => {
- const title = intl.formatMessage(
- {
- id: 'xpack.security.management.roles.cloneRoleActionName',
- defaultMessage: `Clone {roleName}`,
- },
- {
- roleName: role.name,
- }
- );
+ const title = i18n.translate('xpack.security.management.roles.cloneRoleActionName', {
+ defaultMessage: `Clone {roleName}`,
+ values: { roleName: role.name },
+ });
return (
{
private async loadRoles() {
try {
- const roles = await RolesApi.getRoles();
+ const roles = await this.props.rolesAPIClient.getRoles();
this.setState({ roles });
} catch (e) {
if (_.get(e, 'body.statusCode') === 403) {
this.setState({ permissionDenied: true });
} else {
- toastNotifications.addDanger(
- this.props.intl.formatMessage(
- {
- id: 'xpack.security.management.roles.fetchingRolesErrorMessage',
- defaultMessage: 'Error fetching roles: {message}',
- },
- { message: _.get(e, 'body.message', '') }
- )
+ this.props.notifications.toasts.addDanger(
+ i18n.translate('xpack.security.management.roles.fetchingRolesErrorMessage', {
+ defaultMessage: 'Error fetching roles: {message}',
+ values: { message: _.get(e, 'body.message', '') },
+ })
);
}
}
@@ -339,5 +324,3 @@ class RolesGridPageUI extends Component {
this.setState({ showDeleteConfirmation: false });
};
}
-
-export const RolesGridPage = injectI18n(RolesGridPageUI);
diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx
new file mode 100644
index 0000000000000..48bc1a6580a93
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx
@@ -0,0 +1,160 @@
+/*
+ * 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 { licenseMock } from '../../../common/licensing/index.mock';
+
+jest.mock('./roles_grid', () => ({
+ RolesGridPage: (props: any) => `Roles Page: ${JSON.stringify(props)}`,
+}));
+
+jest.mock('./edit_role', () => ({
+ EditRolePage: (props: any) => `Role Edit Page: ${JSON.stringify(props)}`,
+}));
+
+import { rolesManagementApp } from './roles_management_app';
+
+import { coreMock } from '../../../../../../src/core/public/mocks';
+
+async function mountApp(basePath: string) {
+ const { fatalErrors } = coreMock.createSetup();
+ const container = document.createElement('div');
+ const setBreadcrumbs = jest.fn();
+
+ const unmount = await rolesManagementApp
+ .create({
+ license: licenseMock.create(),
+ fatalErrors,
+ getStartServices: jest.fn().mockResolvedValue([coreMock.createStart(), { data: {} }]),
+ })
+ .mount({ basePath, element: container, setBreadcrumbs });
+
+ return { unmount, container, setBreadcrumbs };
+}
+
+describe('rolesManagementApp', () => {
+ it('create() returns proper management app descriptor', () => {
+ const { fatalErrors, getStartServices } = coreMock.createSetup();
+
+ expect(
+ rolesManagementApp.create({
+ license: licenseMock.create(),
+ fatalErrors,
+ getStartServices: getStartServices as any,
+ })
+ ).toMatchInlineSnapshot(`
+ Object {
+ "id": "roles",
+ "mount": [Function],
+ "order": 20,
+ "title": "Roles",
+ }
+ `);
+ });
+
+ it('mount() works for the `grid` page', async () => {
+ const basePath = '/some-base-path/roles';
+ window.location.hash = basePath;
+
+ const { setBreadcrumbs, container, unmount } = await mountApp(basePath);
+
+ expect(setBreadcrumbs).toHaveBeenCalledTimes(1);
+ expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `#${basePath}`, text: 'Roles' }]);
+ expect(container).toMatchInlineSnapshot(`
+
+ Roles Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}}}
+
+ `);
+
+ unmount();
+
+ expect(container).toMatchInlineSnapshot(``);
+ });
+
+ it('mount() works for the `create role` page', async () => {
+ const basePath = '/some-base-path/roles';
+ window.location.hash = `${basePath}/edit`;
+
+ const { setBreadcrumbs, container, unmount } = await mountApp(basePath);
+
+ expect(setBreadcrumbs).toHaveBeenCalledTimes(1);
+ expect(setBreadcrumbs).toHaveBeenCalledWith([
+ { href: `#${basePath}`, text: 'Roles' },
+ { text: 'Create' },
+ ]);
+ expect(container).toMatchInlineSnapshot(`
+
+ Role Edit Page: {"action":"edit","rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"userAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"indicesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"http":{"basePath":{"basePath":""},"anonymousPaths":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}}}
+
+ `);
+
+ unmount();
+
+ expect(container).toMatchInlineSnapshot(``);
+ });
+
+ it('mount() works for the `edit role` page', async () => {
+ const basePath = '/some-base-path/roles';
+ const roleName = 'someRoleName';
+ window.location.hash = `${basePath}/edit/${roleName}`;
+
+ const { setBreadcrumbs, container, unmount } = await mountApp(basePath);
+
+ expect(setBreadcrumbs).toHaveBeenCalledTimes(1);
+ expect(setBreadcrumbs).toHaveBeenCalledWith([
+ { href: `#${basePath}`, text: 'Roles' },
+ { href: `#/some-base-path/roles/edit/${roleName}`, text: roleName },
+ ]);
+ expect(container).toMatchInlineSnapshot(`
+
+ Role Edit Page: {"action":"edit","roleName":"someRoleName","rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"userAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"indicesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"http":{"basePath":{"basePath":""},"anonymousPaths":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}}}
+
+ `);
+
+ unmount();
+
+ expect(container).toMatchInlineSnapshot(``);
+ });
+
+ it('mount() works for the `clone role` page', async () => {
+ const basePath = '/some-base-path/roles';
+ const roleName = 'someRoleName';
+ window.location.hash = `${basePath}/clone/${roleName}`;
+
+ const { setBreadcrumbs, container, unmount } = await mountApp(basePath);
+
+ expect(setBreadcrumbs).toHaveBeenCalledTimes(1);
+ expect(setBreadcrumbs).toHaveBeenCalledWith([
+ { href: `#${basePath}`, text: 'Roles' },
+ { text: 'Create' },
+ ]);
+ expect(container).toMatchInlineSnapshot(`
+
+ Role Edit Page: {"action":"clone","roleName":"someRoleName","rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"userAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"indicesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"http":{"basePath":{"basePath":""},"anonymousPaths":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{"_isScalar":false}},"docLinks":{"esDocBasePath":"https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/"},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{}}}
+
+ `);
+
+ unmount();
+
+ expect(container).toMatchInlineSnapshot(``);
+ });
+
+ it('mount() properly encodes role name in `edit role` page link in breadcrumbs', async () => {
+ const basePath = '/some-base-path/roles';
+ const roleName = 'some 安全性 role';
+ window.location.hash = `${basePath}/edit/${roleName}`;
+
+ const { setBreadcrumbs } = await mountApp(basePath);
+
+ expect(setBreadcrumbs).toHaveBeenCalledTimes(1);
+ expect(setBreadcrumbs).toHaveBeenCalledWith([
+ { href: `#${basePath}`, text: 'Roles' },
+ {
+ href: '#/some-base-path/roles/edit/some%20%E5%AE%89%E5%85%A8%E6%80%A7%20role',
+ text: roleName,
+ },
+ ]);
+ });
+});
diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.tsx
new file mode 100644
index 0000000000000..4e8c95b61c2f1
--- /dev/null
+++ b/x-pack/plugins/security/public/management/roles/roles_management_app.tsx
@@ -0,0 +1,116 @@
+/*
+ * 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 { render, unmountComponentAtNode } from 'react-dom';
+import { HashRouter as Router, Route, Switch, useParams } from 'react-router-dom';
+import { i18n } from '@kbn/i18n';
+import { CoreSetup, FatalErrorsSetup } from 'src/core/public';
+import { RegisterManagementAppArgs } from '../../../../../../src/plugins/management/public';
+import { SecurityLicense } from '../../../common/licensing';
+import { PluginStartDependencies } from '../../plugin';
+import { UserAPIClient } from '../users';
+import { RolesAPIClient } from './roles_api_client';
+import { RolesGridPage } from './roles_grid';
+import { EditRolePage } from './edit_role';
+import { DocumentationLinksService } from './documentation_links';
+import { IndicesAPIClient } from './indices_api_client';
+import { PrivilegesAPIClient } from './privileges_api_client';
+
+interface CreateParams {
+ fatalErrors: FatalErrorsSetup;
+ license: SecurityLicense;
+ getStartServices: CoreSetup['getStartServices'];
+}
+
+export const rolesManagementApp = Object.freeze({
+ id: 'roles',
+ create({ license, fatalErrors, getStartServices }: CreateParams) {
+ return {
+ id: this.id,
+ order: 20,
+ title: i18n.translate('xpack.security.management.rolesTitle', { defaultMessage: 'Roles' }),
+ async mount({ basePath, element, setBreadcrumbs }) {
+ const [
+ { application, docLinks, http, i18n: i18nStart, injectedMetadata, notifications },
+ { data },
+ ] = await getStartServices();
+
+ const rolesBreadcrumbs = [
+ {
+ text: i18n.translate('xpack.security.roles.breadcrumb', { defaultMessage: 'Roles' }),
+ href: `#${basePath}`,
+ },
+ ];
+
+ const rolesAPIClient = new RolesAPIClient(http);
+ const RolesGridPageWithBreadcrumbs = () => {
+ setBreadcrumbs(rolesBreadcrumbs);
+ return ;
+ };
+
+ const EditRolePageWithBreadcrumbs = ({ action }: { action: 'edit' | 'clone' }) => {
+ const { roleName } = useParams<{ roleName?: string }>();
+
+ setBreadcrumbs([
+ ...rolesBreadcrumbs,
+ action === 'edit' && roleName
+ ? { text: roleName, href: `#${basePath}/edit/${encodeURIComponent(roleName)}` }
+ : {
+ text: i18n.translate('xpack.security.roles.createBreadcrumb', {
+ defaultMessage: 'Create',
+ }),
+ },
+ ]);
+
+ return (
+
+ );
+ };
+
+ render(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ,
+ element
+ );
+
+ return () => {
+ unmountComponentAtNode(element);
+ };
+ },
+ } as RegisterManagementAppArgs;
+ },
+});
diff --git a/x-pack/plugins/security/public/management/users/_index.scss b/x-pack/plugins/security/public/management/users/_index.scss
new file mode 100644
index 0000000000000..35df0c1b96583
--- /dev/null
+++ b/x-pack/plugins/security/public/management/users/_index.scss
@@ -0,0 +1 @@
+@import './edit_user/index';
diff --git a/x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.test.tsx b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.test.tsx
similarity index 82%
rename from x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.test.tsx
rename to x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.test.tsx
index 221120532318c..be46612767a59 100644
--- a/x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.test.tsx
+++ b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.test.tsx
@@ -7,10 +7,12 @@ import { EuiFieldText } from '@elastic/eui';
import { ReactWrapper } from 'enzyme';
import React from 'react';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
-import { User } from '../../../../common/model';
-import { UserAPIClient } from '../../../lib/api';
+import { User } from '../../../../../common/model';
import { ChangePasswordForm } from './change_password_form';
+import { coreMock } from '../../../../../../../../src/core/public/mocks';
+import { userAPIClientMock } from '../../index.mock';
+
function getCurrentPasswordField(wrapper: ReactWrapper) {
return wrapper.find(EuiFieldText).filter('[data-test-subj="currentPassword"]');
}
@@ -23,8 +25,6 @@ function getConfirmPasswordField(wrapper: ReactWrapper) {
return wrapper.find(EuiFieldText).filter('[data-test-subj="confirmNewPassword"]');
}
-jest.mock('ui/kfetch');
-
describe('', () => {
describe('for the current user', () => {
it('shows fields for current and new passwords', () => {
@@ -40,7 +40,8 @@ describe('', () => {
);
@@ -60,15 +61,15 @@ describe('', () => {
const callback = jest.fn();
- const apiClient = new UserAPIClient();
- apiClient.changePassword = jest.fn();
+ const apiClientMock = userAPIClientMock.create();
const wrapper = mountWithIntl(
);
@@ -83,8 +84,8 @@ describe('', () => {
wrapper.find('button[data-test-subj="changePasswordButton"]').simulate('click');
- expect(apiClient.changePassword).toHaveBeenCalledTimes(1);
- expect(apiClient.changePassword).toHaveBeenCalledWith(
+ expect(apiClientMock.changePassword).toHaveBeenCalledTimes(1);
+ expect(apiClientMock.changePassword).toHaveBeenCalledWith(
'user',
'myNewPassword',
'myCurrentPassword'
@@ -106,7 +107,8 @@ describe('', () => {
);
diff --git a/x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.tsx b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx
similarity index 96%
rename from x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.tsx
rename to x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx
index 61c0b77decd56..6dcf330ec6f9e 100644
--- a/x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.tsx
+++ b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx
@@ -5,10 +5,7 @@
*/
import {
EuiButton,
- // @ts-ignore
EuiButtonEmpty,
- // @ts-ignore
- EuiDescribedFormGroup,
EuiFieldText,
EuiFlexGroup,
EuiFlexItem,
@@ -18,15 +15,16 @@ import {
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import React, { ChangeEvent, Component } from 'react';
-import { toastNotifications } from 'ui/notify';
-import { User } from '../../../../common/model';
-import { UserAPIClient } from '../../../lib/api';
+import { NotificationsStart } from 'src/core/public';
+import { User } from '../../../../../common/model';
+import { UserAPIClient } from '../..';
interface Props {
user: User;
isUserChangingOwnPassword: boolean;
onChangePassword?: () => void;
- apiClient: UserAPIClient;
+ apiClient: PublicMethodsOf;
+ notifications: NotificationsStart;
}
interface State {
@@ -294,7 +292,7 @@ export class ChangePasswordForm extends Component {
};
private handleChangePasswordSuccess = () => {
- toastNotifications.addSuccess({
+ this.props.notifications.toasts.addSuccess({
title: i18n.translate('xpack.security.account.changePasswordSuccess', {
defaultMessage: 'Your password has been changed.',
}),
@@ -317,7 +315,7 @@ export class ChangePasswordForm extends Component {
if (error.body && error.body.statusCode === 403) {
this.setState({ currentPasswordError: true });
} else {
- toastNotifications.addDanger(
+ this.props.notifications.toasts.addDanger(
i18n.translate('xpack.security.management.users.editUser.settingPasswordErrorMessage', {
defaultMessage: 'Error setting password: {message}',
values: { message: _.get(error, 'body.message') },
diff --git a/x-pack/legacy/plugins/security/public/components/management/change_password_form/index.ts b/x-pack/plugins/security/public/management/users/components/change_password_form/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/components/management/change_password_form/index.ts
rename to x-pack/plugins/security/public/management/users/components/change_password_form/index.ts
diff --git a/x-pack/legacy/plugins/security/public/components/management/users/confirm_delete.test.tsx b/x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.test.tsx
similarity index 58%
rename from x-pack/legacy/plugins/security/public/components/management/users/confirm_delete.test.tsx
rename to x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.test.tsx
index 9f69fc7a7551f..bcec707b03f93 100644
--- a/x-pack/legacy/plugins/security/public/components/management/users/confirm_delete.test.tsx
+++ b/x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.test.tsx
@@ -5,16 +5,21 @@
*/
import { mountWithIntl } from 'test_utils/enzyme_helpers';
-import { ConfirmDeleteUsers } from './confirm_delete';
+import { ConfirmDeleteUsers } from './confirm_delete_users';
import React from 'react';
-import { UserAPIClient } from '../../../lib/api';
-jest.mock('ui/kfetch');
+import { coreMock } from '../../../../../../../../src/core/public/mocks';
+import { userAPIClientMock } from '../../index.mock';
describe('ConfirmDeleteUsers', () => {
it('renders a warning for a single user', () => {
const wrapper = mountWithIntl(
-
+
);
expect(wrapper.find('EuiModalHeaderTitle').text()).toMatchInlineSnapshot(`"Delete user foo"`);
@@ -23,7 +28,8 @@ describe('ConfirmDeleteUsers', () => {
it('renders a warning for a multiple users', () => {
const wrapper = mountWithIntl(
@@ -35,7 +41,12 @@ describe('ConfirmDeleteUsers', () => {
it('fires onCancel when the operation is cancelled', () => {
const onCancel = jest.fn();
const wrapper = mountWithIntl(
-
+
);
expect(onCancel).toBeCalledTimes(0);
@@ -47,50 +58,48 @@ describe('ConfirmDeleteUsers', () => {
it('deletes the requested users when confirmed', () => {
const onCancel = jest.fn();
- const deleteUser = jest.fn();
-
- const apiClient = new UserAPIClient();
- apiClient.deleteUser = deleteUser;
+ const apiClientMock = userAPIClientMock.create();
const wrapper = mountWithIntl(
);
wrapper.find('EuiButton[data-test-subj="confirmModalConfirmButton"]').simulate('click');
- expect(deleteUser).toBeCalledTimes(2);
- expect(deleteUser).toBeCalledWith('foo');
- expect(deleteUser).toBeCalledWith('bar');
+ expect(apiClientMock.deleteUser).toBeCalledTimes(2);
+ expect(apiClientMock.deleteUser).toBeCalledWith('foo');
+ expect(apiClientMock.deleteUser).toBeCalledWith('bar');
});
it('attempts to delete all users even if some fail', () => {
const onCancel = jest.fn();
- const deleteUser = jest.fn().mockImplementation(user => {
+
+ const apiClientMock = userAPIClientMock.create();
+ apiClientMock.deleteUser.mockImplementation(user => {
if (user === 'foo') {
return Promise.reject('something terrible happened');
}
return Promise.resolve();
});
- const apiClient = new UserAPIClient();
- apiClient.deleteUser = deleteUser;
-
const wrapper = mountWithIntl(
);
wrapper.find('EuiButton[data-test-subj="confirmModalConfirmButton"]').simulate('click');
- expect(deleteUser).toBeCalledTimes(2);
- expect(deleteUser).toBeCalledWith('foo');
- expect(deleteUser).toBeCalledWith('bar');
+ expect(apiClientMock.deleteUser).toBeCalledTimes(2);
+ expect(apiClientMock.deleteUser).toBeCalledWith('foo');
+ expect(apiClientMock.deleteUser).toBeCalledWith('bar');
});
});
diff --git a/x-pack/legacy/plugins/security/public/components/management/users/confirm_delete.tsx b/x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.tsx
similarity index 50%
rename from x-pack/legacy/plugins/security/public/components/management/users/confirm_delete.tsx
rename to x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.tsx
index 53bb022afb513..b7269e0168d7d 100644
--- a/x-pack/legacy/plugins/security/public/components/management/users/confirm_delete.tsx
+++ b/x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.tsx
@@ -6,51 +6,46 @@
import React, { Component, Fragment } from 'react';
import { EuiOverlayMask, EuiConfirmModal } from '@elastic/eui';
-import { toastNotifications } from 'ui/notify';
-import { FormattedMessage, injectI18n, InjectedIntl } from '@kbn/i18n/react';
-import { UserAPIClient } from '../../../lib/api';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { NotificationsStart } from 'src/core/public';
+import { UserAPIClient } from '../..';
interface Props {
- intl: InjectedIntl;
usersToDelete: string[];
- apiClient: UserAPIClient;
+ apiClient: PublicMethodsOf;
+ notifications: NotificationsStart;
onCancel: () => void;
callback?: (usersToDelete: string[], errors: string[]) => void;
}
-class ConfirmDeleteUI extends Component {
+export class ConfirmDeleteUsers extends Component {
public render() {
- const { usersToDelete, onCancel, intl } = this.props;
+ const { usersToDelete, onCancel } = this.props;
const moreThanOne = usersToDelete.length > 1;
const title = moreThanOne
- ? intl.formatMessage(
- {
- id: 'xpack.security.management.users.confirmDelete.deleteMultipleUsersTitle',
- defaultMessage: 'Delete {userLength} users',
- },
- { userLength: usersToDelete.length }
- )
- : intl.formatMessage(
- {
- id: 'xpack.security.management.users.confirmDelete.deleteOneUserTitle',
- defaultMessage: 'Delete user {userLength}',
- },
- { userLength: usersToDelete[0] }
- );
+ ? i18n.translate('xpack.security.management.users.confirmDelete.deleteMultipleUsersTitle', {
+ defaultMessage: 'Delete {userLength} users',
+ values: { userLength: usersToDelete.length },
+ })
+ : i18n.translate('xpack.security.management.users.confirmDelete.deleteOneUserTitle', {
+ defaultMessage: 'Delete user {userLength}',
+ values: { userLength: usersToDelete[0] },
+ });
return (
@@ -82,31 +77,23 @@ class ConfirmDeleteUI extends Component
{
}
private deleteUsers = () => {
- const { usersToDelete, callback, apiClient } = this.props;
+ const { usersToDelete, callback, apiClient, notifications } = this.props;
const errors: string[] = [];
usersToDelete.forEach(async username => {
try {
await apiClient.deleteUser(username);
- toastNotifications.addSuccess(
- this.props.intl.formatMessage(
- {
- id:
- 'xpack.security.management.users.confirmDelete.userSuccessfullyDeletedNotificationMessage',
- defaultMessage: 'Deleted user {username}',
- },
- { username }
+ notifications.toasts.addSuccess(
+ i18n.translate(
+ 'xpack.security.management.users.confirmDelete.userSuccessfullyDeletedNotificationMessage',
+ { defaultMessage: 'Deleted user {username}', values: { username } }
)
);
} catch (e) {
errors.push(username);
- toastNotifications.addDanger(
- this.props.intl.formatMessage(
- {
- id:
- 'xpack.security.management.users.confirmDelete.userDeletingErrorNotificationMessage',
- defaultMessage: 'Error deleting user {username}',
- },
- { username }
+ notifications.toasts.addDanger(
+ i18n.translate(
+ 'xpack.security.management.users.confirmDelete.userDeletingErrorNotificationMessage',
+ { defaultMessage: 'Error deleting user {username}', values: { username } }
)
);
}
@@ -116,5 +103,3 @@ class ConfirmDeleteUI extends Component {
});
};
}
-
-export const ConfirmDeleteUsers = injectI18n(ConfirmDeleteUI);
diff --git a/x-pack/legacy/plugins/security/public/components/management/users/index.ts b/x-pack/plugins/security/public/management/users/components/confirm_delete_users/index.ts
similarity index 79%
rename from x-pack/legacy/plugins/security/public/components/management/users/index.ts
rename to x-pack/plugins/security/public/management/users/components/confirm_delete_users/index.ts
index 813e671c05ccf..fde35ab0f0d02 100644
--- a/x-pack/legacy/plugins/security/public/components/management/users/index.ts
+++ b/x-pack/plugins/security/public/management/users/components/confirm_delete_users/index.ts
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { ConfirmDeleteUsers } from './confirm_delete';
+export { ConfirmDeleteUsers } from './confirm_delete_users';
diff --git a/x-pack/plugins/security/public/management/users/components/index.ts b/x-pack/plugins/security/public/management/users/components/index.ts
new file mode 100644
index 0000000000000..54011a6a24cbd
--- /dev/null
+++ b/x-pack/plugins/security/public/management/users/components/index.ts
@@ -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 { ChangePasswordForm } from './change_password_form';
+export { ConfirmDeleteUsers } from './confirm_delete_users';
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_user/_users.scss b/x-pack/plugins/security/public/management/users/edit_user/_edit_user_page.scss
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_user/_users.scss
rename to x-pack/plugins/security/public/management/users/edit_user/_edit_user_page.scss
diff --git a/x-pack/plugins/security/public/management/users/edit_user/_index.scss b/x-pack/plugins/security/public/management/users/edit_user/_index.scss
new file mode 100644
index 0000000000000..734ba7882ba72
--- /dev/null
+++ b/x-pack/plugins/security/public/management/users/edit_user/_index.scss
@@ -0,0 +1 @@
+@import './edit_user_page';
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_user/components/edit_user_page.test.tsx b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx
similarity index 70%
rename from x-pack/legacy/plugins/security/public/views/management/edit_user/components/edit_user_page.test.tsx
rename to x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx
index 639646ce48e22..543d20bb92afe 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_user/components/edit_user_page.test.tsx
+++ b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx
@@ -8,13 +8,14 @@ import { act } from '@testing-library/react';
import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers';
import { EditUserPage } from './edit_user_page';
import React from 'react';
-import { securityMock } from '../../../../../../../../plugins/security/public/mocks';
-import { UserAPIClient } from '../../../../lib/api';
-import { User, Role } from '../../../../../common/model';
+import { User, Role } from '../../../../common/model';
import { ReactWrapper } from 'enzyme';
-import { mockAuthenticatedUser } from '../../../../../../../../plugins/security/common/model/authenticated_user.mock';
-jest.mock('ui/kfetch');
+import { coreMock } from '../../../../../../../src/core/public/mocks';
+import { mockAuthenticatedUser } from '../../../../common/model/authenticated_user.mock';
+import { securityMock } from '../../../mocks';
+import { rolesAPIClientMock } from '../../roles/index.mock';
+import { userAPIClientMock } from '../index.mock';
const createUser = (username: string) => {
const user: User = {
@@ -34,14 +35,12 @@ const createUser = (username: string) => {
return user;
};
-const buildClient = () => {
- const apiClient = new UserAPIClient();
+const buildClients = () => {
+ const apiClient = userAPIClientMock.create();
+ apiClient.getUser.mockImplementation(async (username: string) => createUser(username));
- apiClient.getUser = jest
- .fn()
- .mockImplementation(async (username: string) => createUser(username));
-
- apiClient.getRoles = jest.fn().mockImplementation(() => {
+ const rolesAPIClient = rolesAPIClientMock.create();
+ rolesAPIClient.getRoles.mockImplementation(() => {
return Promise.resolve([
{
name: 'role 1',
@@ -64,7 +63,7 @@ const buildClient = () => {
] as Role[]);
});
- return apiClient;
+ return { apiClient, rolesAPIClient };
};
function buildSecuritySetup() {
@@ -85,15 +84,15 @@ function expectMissingSaveButton(wrapper: ReactWrapper) {
describe('EditUserPage', () => {
it('allows reserved users to be viewed', async () => {
- const apiClient = buildClient();
+ const { apiClient, rolesAPIClient } = buildClients();
const securitySetup = buildSecuritySetup();
const wrapper = mountWithIntl(
- path}
- intl={null as any}
+ rolesAPIClient={rolesAPIClient}
+ authc={securitySetup.authc}
+ notifications={coreMock.createStart().notifications}
/>
);
@@ -106,15 +105,15 @@ describe('EditUserPage', () => {
});
it('allows new users to be created', async () => {
- const apiClient = buildClient();
+ const { apiClient, rolesAPIClient } = buildClients();
const securitySetup = buildSecuritySetup();
const wrapper = mountWithIntl(
- path}
- intl={null as any}
+ rolesAPIClient={rolesAPIClient}
+ authc={securitySetup.authc}
+ notifications={coreMock.createStart().notifications}
/>
);
@@ -127,15 +126,15 @@ describe('EditUserPage', () => {
});
it('allows existing users to be edited', async () => {
- const apiClient = buildClient();
+ const { apiClient, rolesAPIClient } = buildClients();
const securitySetup = buildSecuritySetup();
const wrapper = mountWithIntl(
- path}
- intl={null as any}
+ rolesAPIClient={rolesAPIClient}
+ authc={securitySetup.authc}
+ notifications={coreMock.createStart().notifications}
/>
);
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_user/components/edit_user_page.tsx b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx
similarity index 77%
rename from x-pack/legacy/plugins/security/public/views/management/edit_user/components/edit_user_page.tsx
rename to x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx
index bbffe07485f8d..576f3ff9e6008 100644
--- a/x-pack/legacy/plugins/security/public/views/management/edit_user/components/edit_user_page.tsx
+++ b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx
@@ -26,22 +26,23 @@ import {
EuiHorizontalRule,
EuiSpacer,
} from '@elastic/eui';
-import { toastNotifications } from 'ui/notify';
-import { FormattedMessage, injectI18n, InjectedIntl } from '@kbn/i18n/react';
-import { SecurityPluginSetup } from '../../../../../../../../plugins/security/public';
-import { UserValidator, UserValidationResult } from '../../../../lib/validate_user';
-import { User, EditUser, Role } from '../../../../../common/model';
-import { USERS_PATH } from '../../../../views/management/management_urls';
-import { ConfirmDeleteUsers } from '../../../../components/management/users';
-import { UserAPIClient } from '../../../../lib/api';
-import { ChangePasswordForm } from '../../../../components/management/change_password_form';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { NotificationsStart } from 'src/core/public';
+import { User, EditUser, Role } from '../../../../common/model';
+import { AuthenticationServiceSetup } from '../../../authentication';
+import { USERS_PATH } from '../../management_urls';
+import { RolesAPIClient } from '../../roles';
+import { ConfirmDeleteUsers, ChangePasswordForm } from '../components';
+import { UserValidator, UserValidationResult } from './validate_user';
+import { UserAPIClient } from '..';
interface Props {
- username: string;
- intl: InjectedIntl;
- changeUrl: (path: string) => void;
- apiClient: UserAPIClient;
- securitySetup: SecurityPluginSetup;
+ username?: string;
+ apiClient: PublicMethodsOf;
+ rolesAPIClient: PublicMethodsOf;
+ authc: AuthenticationServiceSetup;
+ notifications: NotificationsStart;
}
interface State {
@@ -56,7 +57,11 @@ interface State {
formError: UserValidationResult | null;
}
-class EditUserPageUI extends Component {
+function backToUserList() {
+ window.location.hash = USERS_PATH;
+}
+
+export class EditUserPage extends Component {
private validator: UserValidator;
constructor(props: Props) {
@@ -84,7 +89,17 @@ class EditUserPageUI extends Component {
}
public async componentDidMount() {
- const { username, apiClient, securitySetup } = this.props;
+ await this.setCurrentUser();
+ }
+
+ public async componentDidUpdate(prevProps: Props) {
+ if (prevProps.username !== this.props.username) {
+ await this.setCurrentUser();
+ }
+ }
+
+ private async setCurrentUser() {
+ const { username, apiClient, rolesAPIClient, notifications, authc } = this.props;
let { user, currentUser } = this.state;
if (username) {
try {
@@ -93,26 +108,24 @@ class EditUserPageUI extends Component {
password: '',
confirmPassword: '',
};
- currentUser = await securitySetup.authc.getCurrentUser();
+ currentUser = await authc.getCurrentUser();
} catch (err) {
- toastNotifications.addDanger({
- title: this.props.intl.formatMessage({
- id: 'xpack.security.management.users.editUser.errorLoadingUserTitle',
+ notifications.toasts.addDanger({
+ title: i18n.translate('xpack.security.management.users.editUser.errorLoadingUserTitle', {
defaultMessage: 'Error loading user',
}),
text: get(err, 'body.message') || err.message,
});
- return;
+ return backToUserList();
}
}
let roles: Role[] = [];
try {
- roles = await apiClient.getRoles();
+ roles = await rolesAPIClient.getRoles();
} catch (err) {
- toastNotifications.addDanger({
- title: this.props.intl.formatMessage({
- id: 'xpack.security.management.users.editUser.errorLoadingRolesTitle',
+ notifications.toasts.addDanger({
+ title: i18n.translate('xpack.security.management.users.editUser.errorLoadingRolesTitle', {
defaultMessage: 'Error loading roles',
}),
text: get(err, 'body.message') || err.message,
@@ -131,8 +144,7 @@ class EditUserPageUI extends Component {
private handleDelete = (usernames: string[], errors: string[]) => {
if (errors.length === 0) {
- const { changeUrl } = this.props;
- changeUrl(USERS_PATH);
+ backToUserList();
}
};
@@ -148,7 +160,7 @@ class EditUserPageUI extends Component {
this.setState({
formError: null,
});
- const { changeUrl, apiClient } = this.props;
+ const { apiClient } = this.props;
const { user, isNewUser, selectedRoles } = this.state;
const userToSave: EditUser = { ...user };
if (!isNewUser) {
@@ -160,26 +172,23 @@ class EditUserPageUI extends Component {
});
try {
await apiClient.saveUser(userToSave);
- toastNotifications.addSuccess(
- this.props.intl.formatMessage(
+ this.props.notifications.toasts.addSuccess(
+ i18n.translate(
+ 'xpack.security.management.users.editUser.userSuccessfullySavedNotificationMessage',
{
- id:
- 'xpack.security.management.users.editUser.userSuccessfullySavedNotificationMessage',
defaultMessage: 'Saved user {message}',
- },
- { message: user.username }
+ values: { message: user.username },
+ }
)
);
- changeUrl(USERS_PATH);
+
+ backToUserList();
} catch (e) {
- toastNotifications.addDanger(
- this.props.intl.formatMessage(
- {
- id: 'xpack.security.management.users.editUser.savingUserErrorMessage',
- defaultMessage: 'Error saving user: {message}',
- },
- { message: get(e, 'body.message', 'Unknown error') }
- )
+ this.props.notifications.toasts.addDanger(
+ i18n.translate('xpack.security.management.users.editUser.savingUserErrorMessage', {
+ defaultMessage: 'Error saving user: {message}',
+ values: { message: get(e, 'body.message', 'Unknown error') },
+ })
);
}
}
@@ -189,8 +198,7 @@ class EditUserPageUI extends Component {
return (
{
/>
{
{user.username === 'kibana' ? (
@@ -260,6 +268,7 @@ class EditUserPageUI extends Component {
isUserChangingOwnPassword={userIsLoggedInUser}
onChangePassword={this.toggleChangePasswordForm}
apiClient={this.props.apiClient}
+ notifications={this.props.notifications}
/>
);
@@ -352,7 +361,6 @@ class EditUserPageUI extends Component {
};
public render() {
- const { changeUrl, intl } = this.props;
const {
user,
roles,
@@ -417,6 +425,7 @@ class EditUserPageUI extends Component {
usersToDelete={[user.username]}
callback={this.handleDelete}
apiClient={this.props.apiClient}
+ notifications={this.props.notifications}
/>
) : null}
@@ -425,17 +434,16 @@ class EditUserPageUI extends Component {
{...this.validator.validateUsername(this.state.user)}
helpText={
!isNewUser && !reserved
- ? intl.formatMessage({
- id:
- 'xpack.security.management.users.editUser.changingUserNameAfterCreationDescription',
- defaultMessage: `Usernames can't be changed after creation.`,
- })
+ ? i18n.translate(
+ 'xpack.security.management.users.editUser.changingUserNameAfterCreationDescription',
+ { defaultMessage: `Usernames can't be changed after creation.` }
+ )
: null
}
- label={intl.formatMessage({
- id: 'xpack.security.management.users.editUser.usernameFormRowLabel',
- defaultMessage: 'Username',
- })}
+ label={i18n.translate(
+ 'xpack.security.management.users.editUser.usernameFormRowLabel',
+ { defaultMessage: 'Username' }
+ )}
>
{
{reserved ? null : (
{
{
)}
{
@@ -513,7 +521,7 @@ class EditUserPageUI extends Component {
{reserved && (
- changeUrl(USERS_PATH)}>
+
{
- changeUrl(USERS_PATH)}
- >
+
{
);
}
}
-
-export const EditUserPage = injectI18n(EditUserPageUI);
diff --git a/x-pack/legacy/plugins/security/public/views/management/edit_user/components/index.ts b/x-pack/plugins/security/public/management/users/edit_user/index.ts
similarity index 100%
rename from x-pack/legacy/plugins/security/public/views/management/edit_user/components/index.ts
rename to x-pack/plugins/security/public/management/users/edit_user/index.ts
diff --git a/x-pack/legacy/plugins/security/public/lib/validate_user.test.ts b/x-pack/plugins/security/public/management/users/edit_user/validate_user.test.ts
similarity index 98%
rename from x-pack/legacy/plugins/security/public/lib/validate_user.test.ts
rename to x-pack/plugins/security/public/management/users/edit_user/validate_user.test.ts
index 0535248fede88..6050e1868a759 100644
--- a/x-pack/legacy/plugins/security/public/lib/validate_user.test.ts
+++ b/x-pack/plugins/security/public/management/users/edit_user/validate_user.test.ts
@@ -5,7 +5,7 @@
*/
import { UserValidator, UserValidationResult } from './validate_user';
-import { User, EditUser } from '../../common/model';
+import { User, EditUser } from '../../../../common/model';
function expectValid(result: UserValidationResult) {
expect(result.isInvalid).toBe(false);
diff --git a/x-pack/legacy/plugins/security/public/lib/validate_user.ts b/x-pack/plugins/security/public/management/users/edit_user/validate_user.ts
similarity index 98%
rename from x-pack/legacy/plugins/security/public/lib/validate_user.ts
rename to x-pack/plugins/security/public/management/users/edit_user/validate_user.ts
index 113aaacdcbf96..5edd96c68bf0d 100644
--- a/x-pack/legacy/plugins/security/public/lib/validate_user.ts
+++ b/x-pack/plugins/security/public/management/users/edit_user/validate_user.ts
@@ -5,7 +5,7 @@
*/
import { i18n } from '@kbn/i18n';
-import { User, EditUser } from '../../common/model';
+import { User, EditUser } from '../../../../common/model';
interface UserValidatorOptions {
shouldValidate?: boolean;
diff --git a/x-pack/legacy/plugins/security/public/views/management/index.js b/x-pack/plugins/security/public/management/users/index.mock.ts
similarity index 80%
rename from x-pack/legacy/plugins/security/public/views/management/index.js
rename to x-pack/plugins/security/public/management/users/index.mock.ts
index 0ed6fe09ef80a..f090f88da500d 100644
--- a/x-pack/legacy/plugins/security/public/views/management/index.js
+++ b/x-pack/plugins/security/public/management/users/index.mock.ts
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import './management';
+export { userAPIClientMock } from './user_api_client.mock';
diff --git a/x-pack/legacy/plugins/security/public/objects/index.ts b/x-pack/plugins/security/public/management/users/index.ts
similarity index 68%
rename from x-pack/legacy/plugins/security/public/objects/index.ts
rename to x-pack/plugins/security/public/management/users/index.ts
index a6238ca879901..c8b4d41973da6 100644
--- a/x-pack/legacy/plugins/security/public/objects/index.ts
+++ b/x-pack/plugins/security/public/management/users/index.ts
@@ -4,6 +4,5 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { saveRole, deleteRole } from './lib/roles';
-
-export { getFields } from './lib/get_fields';
+export { UserAPIClient } from './user_api_client';
+export { usersManagementApp } from './users_management_app';
diff --git a/x-pack/plugins/security/public/management/users/user_api_client.mock.ts b/x-pack/plugins/security/public/management/users/user_api_client.mock.ts
new file mode 100644
index 0000000000000..7223f78d57fdc
--- /dev/null
+++ b/x-pack/plugins/security/public/management/users/user_api_client.mock.ts
@@ -0,0 +1,15 @@
+/*
+ * 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 userAPIClientMock = {
+ create: () => ({
+ getUsers: jest.fn(),
+ getUser: jest.fn(),
+ deleteUser: jest.fn(),
+ saveUser: jest.fn(),
+ changePassword: jest.fn(),
+ }),
+};
diff --git a/x-pack/plugins/security/public/management/users/user_api_client.ts b/x-pack/plugins/security/public/management/users/user_api_client.ts
new file mode 100644
index 0000000000000..61dd09d2c5e3d
--- /dev/null
+++ b/x-pack/plugins/security/public/management/users/user_api_client.ts
@@ -0,0 +1,45 @@
+/*
+ * 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 { HttpStart } from 'src/core/public';
+import { User, EditUser } from '../../../common/model';
+
+const usersUrl = '/internal/security/users';
+
+export class UserAPIClient {
+ constructor(private readonly http: HttpStart) {}
+
+ public async getUsers() {
+ return await this.http.get(usersUrl);
+ }
+
+ public async getUser(username: string) {
+ return await this.http.get(`${usersUrl}/${encodeURIComponent(username)}`);
+ }
+
+ public async deleteUser(username: string) {
+ await this.http.delete(`${usersUrl}/${encodeURIComponent(username)}`);
+ }
+
+ public async saveUser(user: EditUser) {
+ await this.http.post(`${usersUrl}/${encodeURIComponent(user.username)}`, {
+ body: JSON.stringify(user),
+ });
+ }
+
+ public async changePassword(username: string, password: string, currentPassword: string) {
+ const data: Record = {
+ newPassword: password,
+ };
+ if (currentPassword) {
+ data.password = currentPassword;
+ }
+
+ await this.http.post(`${usersUrl}/${encodeURIComponent(username)}/password`, {
+ body: JSON.stringify(data),
+ });
+ }
+}
diff --git a/x-pack/legacy/plugins/security/public/views/management/users_grid/components/index.ts b/x-pack/plugins/security/public/management/users/users_grid/index.ts
similarity index 82%
rename from x-pack/legacy/plugins/security/public/views/management/users_grid/components/index.ts
rename to x-pack/plugins/security/public/management/users/users_grid/index.ts
index 03721f5ce93b1..90e16248e19c3 100644
--- a/x-pack/legacy/plugins/security/public/views/management/users_grid/components/index.ts
+++ b/x-pack/plugins/security/public/management/users/users_grid/index.ts
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { UsersListPage } from './users_list_page';
+export { UsersGridPage } from './users_grid_page';
diff --git a/x-pack/legacy/plugins/security/public/views/management/users_grid/components/users_list_page.test.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx
similarity index 63%
rename from x-pack/legacy/plugins/security/public/views/management/users_grid/components/users_list_page.test.tsx
rename to x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx
index bdc0df9bae67c..def0649953437 100644
--- a/x-pack/legacy/plugins/security/public/views/management/users_grid/components/users_list_page.test.tsx
+++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx
@@ -4,19 +4,18 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { UserAPIClient } from '../../../../lib/api';
-import { User } from '../../../../../common/model';
+import { User } from '../../../../common/model';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
-import { UsersListPage } from './users_list_page';
+import { UsersGridPage } from './users_grid_page';
import React from 'react';
import { ReactWrapper } from 'enzyme';
+import { userAPIClientMock } from '../index.mock';
+import { coreMock } from '../../../../../../../src/core/public/mocks';
-jest.mock('ui/kfetch');
-
-describe('UsersListPage', () => {
+describe('UsersGridPage', () => {
it('renders the list of users', async () => {
- const apiClient = new UserAPIClient();
- apiClient.getUsers = jest.fn().mockImplementation(() => {
+ const apiClientMock = userAPIClientMock.create();
+ apiClientMock.getUsers.mockImplementation(() => {
return Promise.resolve([
{
username: 'foo',
@@ -38,22 +37,27 @@ describe('UsersListPage', () => {
]);
});
- const wrapper = mountWithIntl();
+ const wrapper = mountWithIntl(
+
+ );
await waitForRender(wrapper);
- expect(apiClient.getUsers).toBeCalledTimes(1);
+ expect(apiClientMock.getUsers).toBeCalledTimes(1);
expect(wrapper.find('EuiInMemoryTable')).toHaveLength(1);
expect(wrapper.find('EuiTableRow')).toHaveLength(2);
});
it('renders a forbidden message if user is not authorized', async () => {
- const apiClient = new UserAPIClient();
- apiClient.getUsers = jest.fn().mockImplementation(() => {
- return Promise.reject({ body: { statusCode: 403 } });
- });
+ const apiClient = userAPIClientMock.create();
+ apiClient.getUsers.mockRejectedValue({ body: { statusCode: 403 } });
- const wrapper = mountWithIntl();
+ const wrapper = mountWithIntl(
+
+ );
await waitForRender(wrapper);
diff --git a/x-pack/legacy/plugins/security/public/views/management/users_grid/components/users_list_page.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx
similarity index 85%
rename from x-pack/legacy/plugins/security/public/views/management/users_grid/components/users_list_page.tsx
rename to x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx
index df8522e5f32f9..fa15c3388fcc9 100644
--- a/x-pack/legacy/plugins/security/public/views/management/users_grid/components/users_list_page.tsx
+++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx
@@ -19,15 +19,16 @@ import {
EuiEmptyPrompt,
EuiBasicTableColumn,
} from '@elastic/eui';
-import { toastNotifications } from 'ui/notify';
-import { injectI18n, FormattedMessage, InjectedIntl } from '@kbn/i18n/react';
-import { ConfirmDeleteUsers } from '../../../../components/management/users';
-import { User } from '../../../../../common/model';
-import { UserAPIClient } from '../../../../lib/api';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { NotificationsStart } from 'src/core/public';
+import { User } from '../../../../common/model';
+import { ConfirmDeleteUsers } from '../components';
+import { UserAPIClient } from '..';
interface Props {
- intl: InjectedIntl;
- apiClient: UserAPIClient;
+ apiClient: PublicMethodsOf;
+ notifications: NotificationsStart;
}
interface State {
@@ -38,7 +39,7 @@ interface State {
filter: string;
}
-class UsersListPageUI extends Component {
+export class UsersGridPage extends Component {
constructor(props: Props) {
super(props);
this.state = {
@@ -56,7 +57,6 @@ class UsersListPageUI extends Component {
public render() {
const { users, filter, permissionDenied, showDeleteConfirmation, selection } = this.state;
- const { intl } = this.props;
if (permissionDenied) {
return (
@@ -88,8 +88,7 @@ class UsersListPageUI extends Component {
const columns: Array> = [
{
field: 'full_name',
- name: intl.formatMessage({
- id: 'xpack.security.management.users.fullNameColumnName',
+ name: i18n.translate('xpack.security.management.users.fullNameColumnName', {
defaultMessage: 'Full Name',
}),
sortable: true,
@@ -100,8 +99,7 @@ class UsersListPageUI extends Component {
},
{
field: 'username',
- name: intl.formatMessage({
- id: 'xpack.security.management.users.userNameColumnName',
+ name: i18n.translate('xpack.security.management.users.userNameColumnName', {
defaultMessage: 'User Name',
}),
sortable: true,
@@ -114,8 +112,7 @@ class UsersListPageUI extends Component {
},
{
field: 'email',
- name: intl.formatMessage({
- id: 'xpack.security.management.users.emailAddressColumnName',
+ name: i18n.translate('xpack.security.management.users.emailAddressColumnName', {
defaultMessage: 'Email Address',
}),
sortable: true,
@@ -126,8 +123,7 @@ class UsersListPageUI extends Component {
},
{
field: 'roles',
- name: intl.formatMessage({
- id: 'xpack.security.management.users.rolesColumnName',
+ name: i18n.translate('xpack.security.management.users.rolesColumnName', {
defaultMessage: 'Roles',
}),
render: (rolenames: string[]) => {
@@ -144,15 +140,13 @@ class UsersListPageUI extends Component {
},
{
field: 'metadata',
- name: intl.formatMessage({
- id: 'xpack.security.management.users.reservedColumnName',
+ name: i18n.translate('xpack.security.management.users.reservedColumnName', {
defaultMessage: 'Reserved',
}),
sortable: ({ metadata }: User) => Boolean(metadata && metadata._reserved),
width: '100px',
align: 'right',
- description: intl.formatMessage({
- id: 'xpack.security.management.users.reservedColumnDescription',
+ description: i18n.translate('xpack.security.management.users.reservedColumnDescription', {
defaultMessage:
'Reserved users are built-in and cannot be removed. Only the password can be changed.',
}),
@@ -233,6 +227,7 @@ class UsersListPageUI extends Component {
usersToDelete={selection.map(user => user.username)}
callback={this.handleDelete}
apiClient={this.props.apiClient}
+ notifications={this.props.notifications}
/>
) : null}
@@ -275,14 +270,11 @@ class UsersListPageUI extends Component {
if (e.body.statusCode === 403) {
this.setState({ permissionDenied: true });
} else {
- toastNotifications.addDanger(
- this.props.intl.formatMessage(
- {
- id: 'xpack.security.management.users.fetchingUsersErrorMessage',
- defaultMessage: 'Error fetching users: {message}',
- },
- { message: e.body.message }
- )
+ this.props.notifications.toasts.addDanger(
+ i18n.translate('xpack.security.management.users.fetchingUsersErrorMessage', {
+ defaultMessage: 'Error fetching users: {message}',
+ values: { message: e.body.message },
+ })
);
}
}
@@ -315,5 +307,3 @@ class UsersListPageUI extends Component {
this.setState({ showDeleteConfirmation: false });
};
}
-
-export const UsersListPage = injectI18n(UsersListPageUI);
diff --git a/x-pack/plugins/security/public/management/users/users_management_app.test.tsx b/x-pack/plugins/security/public/management/users/users_management_app.test.tsx
new file mode 100644
index 0000000000000..48ffcfc550a84
--- /dev/null
+++ b/x-pack/plugins/security/public/management/users/users_management_app.test.tsx
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+jest.mock('./users_grid', () => ({
+ UsersGridPage: (props: any) => `Users Page: ${JSON.stringify(props)}`,
+}));
+
+jest.mock('./edit_user', () => ({
+ EditUserPage: (props: any) => `User Edit Page: ${JSON.stringify(props)}`,
+}));
+
+import { usersManagementApp } from './users_management_app';
+
+import { coreMock } from '../../../../../../src/core/public/mocks';
+import { securityMock } from '../../mocks';
+
+async function mountApp(basePath: string) {
+ const container = document.createElement('div');
+ const setBreadcrumbs = jest.fn();
+
+ const unmount = await usersManagementApp
+ .create({
+ authc: securityMock.createSetup().authc,
+ getStartServices: coreMock.createSetup().getStartServices as any,
+ })
+ .mount({ basePath, element: container, setBreadcrumbs });
+
+ return { unmount, container, setBreadcrumbs };
+}
+
+describe('usersManagementApp', () => {
+ it('create() returns proper management app descriptor', () => {
+ expect(
+ usersManagementApp.create({
+ authc: securityMock.createSetup().authc,
+ getStartServices: coreMock.createSetup().getStartServices as any,
+ })
+ ).toMatchInlineSnapshot(`
+ Object {
+ "id": "users",
+ "mount": [Function],
+ "order": 10,
+ "title": "Users",
+ }
+ `);
+ });
+
+ it('mount() works for the `grid` page', async () => {
+ const basePath = '/some-base-path/users';
+ window.location.hash = basePath;
+
+ const { setBreadcrumbs, container, unmount } = await mountApp(basePath);
+
+ expect(setBreadcrumbs).toHaveBeenCalledTimes(1);
+ expect(setBreadcrumbs).toHaveBeenCalledWith([{ href: `#${basePath}`, text: 'Users' }]);
+ expect(container).toMatchInlineSnapshot(`
+
+ Users Page: {"notifications":{"toasts":{}},"apiClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}}}
+
+ `);
+
+ unmount();
+
+ expect(container).toMatchInlineSnapshot(``);
+ });
+
+ it('mount() works for the `create user` page', async () => {
+ const basePath = '/some-base-path/users';
+ window.location.hash = `${basePath}/edit`;
+
+ const { setBreadcrumbs, container, unmount } = await mountApp(basePath);
+
+ expect(setBreadcrumbs).toHaveBeenCalledTimes(1);
+ expect(setBreadcrumbs).toHaveBeenCalledWith([
+ { href: `#${basePath}`, text: 'Users' },
+ { text: 'Create' },
+ ]);
+ expect(container).toMatchInlineSnapshot(`
+
+ User Edit Page: {"authc":{},"apiClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}}}
+
+ `);
+
+ unmount();
+
+ expect(container).toMatchInlineSnapshot(``);
+ });
+
+ it('mount() works for the `edit user` page', async () => {
+ const basePath = '/some-base-path/users';
+ const userName = 'someUserName';
+ window.location.hash = `${basePath}/edit/${userName}`;
+
+ const { setBreadcrumbs, container, unmount } = await mountApp(basePath);
+
+ expect(setBreadcrumbs).toHaveBeenCalledTimes(1);
+ expect(setBreadcrumbs).toHaveBeenCalledWith([
+ { href: `#${basePath}`, text: 'Users' },
+ { href: `#/some-base-path/users/edit/${userName}`, text: userName },
+ ]);
+ expect(container).toMatchInlineSnapshot(`
+
+ User Edit Page: {"authc":{},"apiClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":""},"anonymousPaths":{}}},"notifications":{"toasts":{}},"username":"someUserName"}
+
+ `);
+
+ unmount();
+
+ expect(container).toMatchInlineSnapshot(``);
+ });
+
+ it('mount() properly encodes user name in `edit user` page link in breadcrumbs', async () => {
+ const basePath = '/some-base-path/users';
+ const username = 'some 安全性 user';
+ window.location.hash = `${basePath}/edit/${username}`;
+
+ const { setBreadcrumbs } = await mountApp(basePath);
+
+ expect(setBreadcrumbs).toHaveBeenCalledTimes(1);
+ expect(setBreadcrumbs).toHaveBeenCalledWith([
+ { href: `#${basePath}`, text: 'Users' },
+ {
+ href: '#/some-base-path/users/edit/some%20%E5%AE%89%E5%85%A8%E6%80%A7%20user',
+ text: username,
+ },
+ ]);
+ });
+});
diff --git a/x-pack/plugins/security/public/management/users/users_management_app.tsx b/x-pack/plugins/security/public/management/users/users_management_app.tsx
new file mode 100644
index 0000000000000..9aebb396ce9a9
--- /dev/null
+++ b/x-pack/plugins/security/public/management/users/users_management_app.tsx
@@ -0,0 +1,94 @@
+/*
+ * 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 { render, unmountComponentAtNode } from 'react-dom';
+import { HashRouter as Router, Route, Switch, useParams } from 'react-router-dom';
+import { i18n } from '@kbn/i18n';
+import { CoreSetup } from 'src/core/public';
+import { RegisterManagementAppArgs } from '../../../../../../src/plugins/management/public';
+import { AuthenticationServiceSetup } from '../../authentication';
+import { PluginStartDependencies } from '../../plugin';
+import { RolesAPIClient } from '../roles';
+import { UserAPIClient } from './user_api_client';
+import { UsersGridPage } from './users_grid';
+import { EditUserPage } from './edit_user';
+
+interface CreateParams {
+ authc: AuthenticationServiceSetup;
+ getStartServices: CoreSetup['getStartServices'];
+}
+
+export const usersManagementApp = Object.freeze({
+ id: 'users',
+ create({ authc, getStartServices }: CreateParams) {
+ return {
+ id: this.id,
+ order: 10,
+ title: i18n.translate('xpack.security.management.usersTitle', { defaultMessage: 'Users' }),
+ async mount({ basePath, element, setBreadcrumbs }) {
+ const [{ http, notifications, i18n: i18nStart }] = await getStartServices();
+ const usersBreadcrumbs = [
+ {
+ text: i18n.translate('xpack.security.users.breadcrumb', { defaultMessage: 'Users' }),
+ href: `#${basePath}`,
+ },
+ ];
+
+ const userAPIClient = new UserAPIClient(http);
+ const UsersGridPageWithBreadcrumbs = () => {
+ setBreadcrumbs(usersBreadcrumbs);
+ return ;
+ };
+
+ const EditUserPageWithBreadcrumbs = () => {
+ const { username } = useParams<{ username?: string }>();
+
+ setBreadcrumbs([
+ ...usersBreadcrumbs,
+ username
+ ? { text: username, href: `#${basePath}/edit/${encodeURIComponent(username)}` }
+ : {
+ text: i18n.translate('xpack.security.users.createBreadcrumb', {
+ defaultMessage: 'Create',
+ }),
+ },
+ ]);
+
+ return (
+
+ );
+ };
+
+ render(
+
+
+
+
+
+
+
+
+
+
+
+ ,
+ element
+ );
+
+ return () => {
+ unmountComponentAtNode(element);
+ };
+ },
+ } as RegisterManagementAppArgs;
+ },
+});
diff --git a/x-pack/plugins/security/public/plugin.ts b/x-pack/plugins/security/public/plugin.ts
deleted file mode 100644
index 50e0b838c750f..0000000000000
--- a/x-pack/plugins/security/public/plugin.ts
+++ /dev/null
@@ -1,74 +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 { Plugin, CoreSetup, CoreStart } from 'src/core/public';
-import { LicensingPluginSetup } from '../../licensing/public';
-import {
- SessionExpired,
- SessionTimeout,
- ISessionTimeout,
- SessionTimeoutHttpInterceptor,
- UnauthorizedResponseHttpInterceptor,
-} from './session';
-import { SecurityLicenseService } from '../common/licensing';
-import { SecurityNavControlService } from './nav_control';
-import { AuthenticationService } from './authentication';
-
-export interface PluginSetupDependencies {
- licensing: LicensingPluginSetup;
-}
-
-export class SecurityPlugin implements Plugin {
- private sessionTimeout!: ISessionTimeout;
-
- private navControlService!: SecurityNavControlService;
-
- private securityLicenseService!: SecurityLicenseService;
-
- public setup(core: CoreSetup, { licensing }: PluginSetupDependencies) {
- const { http, notifications, injectedMetadata } = core;
- const { basePath, anonymousPaths } = http;
- anonymousPaths.register('/login');
- anonymousPaths.register('/logout');
- anonymousPaths.register('/logged_out');
-
- const tenant = `${injectedMetadata.getInjectedVar('session.tenant', '')}`;
- const sessionExpired = new SessionExpired(basePath, tenant);
- http.intercept(new UnauthorizedResponseHttpInterceptor(sessionExpired, anonymousPaths));
- this.sessionTimeout = new SessionTimeout(notifications, sessionExpired, http, tenant);
- http.intercept(new SessionTimeoutHttpInterceptor(this.sessionTimeout, anonymousPaths));
-
- this.navControlService = new SecurityNavControlService();
- this.securityLicenseService = new SecurityLicenseService();
- const { license } = this.securityLicenseService.setup({ license$: licensing.license$ });
-
- const authc = new AuthenticationService().setup({ http: core.http });
-
- this.navControlService.setup({
- securityLicense: license,
- authc,
- });
-
- return {
- authc,
- sessionTimeout: this.sessionTimeout,
- };
- }
-
- public start(core: CoreStart) {
- this.sessionTimeout.start();
- this.navControlService.start({ core });
- }
-
- public stop() {
- this.sessionTimeout.stop();
- this.navControlService.stop();
- this.securityLicenseService.stop();
- }
-}
-
-export type SecurityPluginSetup = ReturnType;
-export type SecurityPluginStart = ReturnType;
diff --git a/x-pack/plugins/security/public/plugin.tsx b/x-pack/plugins/security/public/plugin.tsx
new file mode 100644
index 0000000000000..394e23cbbf646
--- /dev/null
+++ b/x-pack/plugins/security/public/plugin.tsx
@@ -0,0 +1,147 @@
+/*
+ * 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 { Plugin, CoreSetup, CoreStart } from 'src/core/public';
+import { i18n } from '@kbn/i18n';
+import React from 'react';
+import { DataPublicPluginStart } from '../../../../src/plugins/data/public';
+import {
+ FeatureCatalogueCategory,
+ HomePublicPluginSetup,
+} from '../../../../src/plugins/home/public';
+import { LicensingPluginSetup } from '../../licensing/public';
+import { ManagementSetup, ManagementStart } from '../../../../src/plugins/management/public';
+import {
+ SessionExpired,
+ SessionTimeout,
+ ISessionTimeout,
+ SessionTimeoutHttpInterceptor,
+ UnauthorizedResponseHttpInterceptor,
+} from './session';
+import { SecurityLicenseService } from '../common/licensing';
+import { SecurityNavControlService } from './nav_control';
+import { AccountManagementPage } from './account_management';
+import { AuthenticationService, AuthenticationServiceSetup } from './authentication';
+import { ManagementService, UserAPIClient } from './management';
+
+export interface PluginSetupDependencies {
+ licensing: LicensingPluginSetup;
+ home?: HomePublicPluginSetup;
+ management?: ManagementSetup;
+}
+
+export interface PluginStartDependencies {
+ data: DataPublicPluginStart;
+ management?: ManagementStart;
+}
+
+export class SecurityPlugin
+ implements
+ Plugin<
+ SecurityPluginSetup,
+ SecurityPluginStart,
+ PluginSetupDependencies,
+ PluginStartDependencies
+ > {
+ private sessionTimeout!: ISessionTimeout;
+ private readonly navControlService = new SecurityNavControlService();
+ private readonly securityLicenseService = new SecurityLicenseService();
+ private readonly managementService = new ManagementService();
+ private authc!: AuthenticationServiceSetup;
+
+ public setup(
+ core: CoreSetup,
+ { home, licensing, management }: PluginSetupDependencies
+ ) {
+ const { http, notifications, injectedMetadata } = core;
+ const { basePath, anonymousPaths } = http;
+ anonymousPaths.register('/login');
+ anonymousPaths.register('/logout');
+ anonymousPaths.register('/logged_out');
+
+ const tenant = `${injectedMetadata.getInjectedVar('session.tenant', '')}`;
+ const sessionExpired = new SessionExpired(basePath, tenant);
+ http.intercept(new UnauthorizedResponseHttpInterceptor(sessionExpired, anonymousPaths));
+ this.sessionTimeout = new SessionTimeout(notifications, sessionExpired, http, tenant);
+ http.intercept(new SessionTimeoutHttpInterceptor(this.sessionTimeout, anonymousPaths));
+
+ const { license } = this.securityLicenseService.setup({ license$: licensing.license$ });
+
+ this.authc = new AuthenticationService().setup({ http: core.http });
+
+ this.navControlService.setup({
+ securityLicense: license,
+ authc: this.authc,
+ });
+
+ if (management) {
+ this.managementService.setup({
+ license,
+ management,
+ authc: this.authc,
+ fatalErrors: core.fatalErrors,
+ getStartServices: core.getStartServices,
+ });
+ }
+
+ if (management && home) {
+ home.featureCatalogue.register({
+ id: 'security',
+ title: i18n.translate('xpack.security.registerFeature.securitySettingsTitle', {
+ defaultMessage: 'Security Settings',
+ }),
+ description: i18n.translate('xpack.security.registerFeature.securitySettingsDescription', {
+ defaultMessage:
+ 'Protect your data and easily manage who has access to what with users and roles.',
+ }),
+ icon: 'securityApp',
+ path: '/app/kibana#/management/security/users',
+ showOnHomePage: true,
+ category: FeatureCatalogueCategory.ADMIN,
+ });
+ }
+
+ return {
+ authc: this.authc,
+ sessionTimeout: this.sessionTimeout,
+ };
+ }
+
+ public start(core: CoreStart, { data, management }: PluginStartDependencies) {
+ this.sessionTimeout.start();
+ this.navControlService.start({ core });
+
+ if (management) {
+ this.managementService.start({ management });
+ }
+
+ return {
+ __legacyCompat: {
+ account_management: {
+ AccountManagementPage: () => (
+
+
+
+ ),
+ },
+ },
+ };
+ }
+
+ public stop() {
+ this.sessionTimeout.stop();
+ this.navControlService.stop();
+ this.securityLicenseService.stop();
+ this.managementService.stop();
+ }
+}
+
+export type SecurityPluginSetup = ReturnType;
+export type SecurityPluginStart = ReturnType;
diff --git a/x-pack/plugins/security/server/routes/role_mapping/get.ts b/x-pack/plugins/security/server/routes/role_mapping/get.ts
index 9cd5cf83092e1..def6fabc0e322 100644
--- a/x-pack/plugins/security/server/routes/role_mapping/get.ts
+++ b/x-pack/plugins/security/server/routes/role_mapping/get.ts
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { schema } from '@kbn/config-schema';
-import { RoleMapping } from '../../../../../legacy/plugins/security/common/model';
+import { RoleMapping } from '../../../common/model';
import { createLicensedRouteHandler } from '../licensed_route_handler';
import { wrapError } from '../../errors';
import { RouteDefinitionParams } from '..';
diff --git a/x-pack/plugins/spaces/common/index.ts b/x-pack/plugins/spaces/common/index.ts
index 65baa1bd99102..c1f0f8bd3ece4 100644
--- a/x-pack/plugins/spaces/common/index.ts
+++ b/x-pack/plugins/spaces/common/index.ts
@@ -5,5 +5,5 @@
*/
export { isReservedSpace } from './is_reserved_space';
-export { MAX_SPACE_INITIALS } from './constants';
+export { MAX_SPACE_INITIALS, SPACE_SEARCH_COUNT_THRESHOLD } from './constants';
export { addSpaceIdToPath, getSpaceIdFromPath } from './lib/spaces_url_parser';
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index ce3edbbb59828..c3e46a9c04e1c 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -10595,17 +10595,6 @@
"xpack.security.management.apiKeys.table.userFilterLabel": "ユーザー",
"xpack.security.management.apiKeys.table.userNameColumnName": "ユーザー",
"xpack.security.management.apiKeysTitle": "API キー",
- "xpack.security.management.changePasswordForm.cancelButtonLabel": "キャンセル",
- "xpack.security.management.changePasswordForm.changePasswordLinkLabel": "パスワードを変更",
- "xpack.security.management.changePasswordForm.confirmPasswordLabel": "パスワードの確認",
- "xpack.security.management.changePasswordForm.currentPasswordLabel": "現在のパスワード",
- "xpack.security.management.changePasswordForm.incorrectPasswordDescription": "入力された現在のパスワードが正しくありません。",
- "xpack.security.management.changePasswordForm.newPasswordLabel": "新しいパスワード",
- "xpack.security.management.changePasswordForm.passwordDontMatchDescription": "パスワードが一致しません",
- "xpack.security.management.changePasswordForm.passwordLabel": "パスワード",
- "xpack.security.management.changePasswordForm.passwordLengthDescription": "パスワードは最低 6 文字必要です",
- "xpack.security.management.changePasswordForm.saveChangesButtonLabel": "変更を保存",
- "xpack.security.management.changePasswordForm.updateAndRestartKibanaDescription": "Kibana ユーザーのパスワードを変更後、kibana.yml ファイルを更新し Kibana を再起動する必要があります。",
"xpack.security.management.editRole.cancelButtonLabel": "キャンセル",
"xpack.security.management.editRole.changeAllPrivilegesLink": "(すべて変更)",
"xpack.security.management.editRole.collapsiblePanel.hideLinkText": "非表示",
@@ -10730,10 +10719,6 @@
"xpack.security.management.editRolespacePrivilegeForm.createPrivilegeButton": "スペース権限を作成",
"xpack.security.management.editRolespacePrivilegeForm.updateGlobalPrivilegeButton": "グローバル特権を更新",
"xpack.security.management.editRolespacePrivilegeForm.updatePrivilegeButton": "スペース権限を更新",
- "xpack.security.management.passwordForm.confirmPasswordLabel": "パスワードの確認",
- "xpack.security.management.passwordForm.passwordDontMatchDescription": "パスワードが一致しません",
- "xpack.security.management.passwordForm.passwordLabel": "パスワード",
- "xpack.security.management.passwordForm.passwordLengthDescription": "パスワードは最低 6 文字必要です",
"xpack.security.management.roles.actionsColumnName": "アクション",
"xpack.security.management.roles.cloneRoleActionName": "{roleName} を複製",
"xpack.security.management.roles.confirmDelete.cancelButtonLabel": "キャンセル",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index dc72e83ebe3c3..c40b8c8d0393c 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -10594,17 +10594,6 @@
"xpack.security.management.apiKeys.table.userFilterLabel": "用户",
"xpack.security.management.apiKeys.table.userNameColumnName": "用户",
"xpack.security.management.apiKeysTitle": "API 密钥",
- "xpack.security.management.changePasswordForm.cancelButtonLabel": "取消",
- "xpack.security.management.changePasswordForm.changePasswordLinkLabel": "更改密码",
- "xpack.security.management.changePasswordForm.confirmPasswordLabel": "确认密码",
- "xpack.security.management.changePasswordForm.currentPasswordLabel": "当前密码",
- "xpack.security.management.changePasswordForm.incorrectPasswordDescription": "您输入的当前密码不正确。",
- "xpack.security.management.changePasswordForm.newPasswordLabel": "新密码",
- "xpack.security.management.changePasswordForm.passwordDontMatchDescription": "密码不匹配",
- "xpack.security.management.changePasswordForm.passwordLabel": "密码",
- "xpack.security.management.changePasswordForm.passwordLengthDescription": "密码长度必须至少为 6 个字符",
- "xpack.security.management.changePasswordForm.saveChangesButtonLabel": "保存更改",
- "xpack.security.management.changePasswordForm.updateAndRestartKibanaDescription": "更改 Kibana 用户的密码后,必须更新 kibana.yml 文件并重新启动 Kibana",
"xpack.security.management.editRole.cancelButtonLabel": "取消",
"xpack.security.management.editRole.changeAllPrivilegesLink": "(全部更改)",
"xpack.security.management.editRole.collapsiblePanel.hideLinkText": "隐藏",
@@ -10729,10 +10718,6 @@
"xpack.security.management.editRolespacePrivilegeForm.createPrivilegeButton": "创建工作区权限",
"xpack.security.management.editRolespacePrivilegeForm.updateGlobalPrivilegeButton": "更新全局权限",
"xpack.security.management.editRolespacePrivilegeForm.updatePrivilegeButton": "更新工作区权限",
- "xpack.security.management.passwordForm.confirmPasswordLabel": "确认密码",
- "xpack.security.management.passwordForm.passwordDontMatchDescription": "密码不匹配",
- "xpack.security.management.passwordForm.passwordLabel": "密码",
- "xpack.security.management.passwordForm.passwordLengthDescription": "密码长度必须至少为 6 个字符",
"xpack.security.management.roles.actionsColumnName": "鎿嶄綔",
"xpack.security.management.roles.cloneRoleActionName": "克隆 {roleName}",
"xpack.security.management.roles.confirmDelete.cancelButtonLabel": "取消",
diff --git a/x-pack/test/functional/apps/security/management.js b/x-pack/test/functional/apps/security/management.js
index 45a35029ffba2..8ab84126b2b30 100644
--- a/x-pack/test/functional/apps/security/management.js
+++ b/x-pack/test/functional/apps/security/management.js
@@ -11,7 +11,7 @@ import {
ROLES_PATH,
EDIT_ROLES_PATH,
CLONE_ROLES_PATH,
-} from '../../../../legacy/plugins/security/public/views/management/management_urls';
+} from '../../../../plugins/security/public/management/management_urls';
export default function({ getService, getPageObjects }) {
const kibanaServer = getService('kibanaServer');
diff --git a/x-pack/test/functional/apps/security/role_mappings.ts b/x-pack/test/functional/apps/security/role_mappings.ts
index 5fed56ee79e3d..a1517e1934a28 100644
--- a/x-pack/test/functional/apps/security/role_mappings.ts
+++ b/x-pack/test/functional/apps/security/role_mappings.ts
@@ -93,7 +93,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
const url = parse(await browser.getCurrentUrl());
- expect(url.hash).to.eql('#/management/security/role_mappings?_g=()');
+ expect(url.hash).to.eql('#/management/security/role_mappings');
});
describe('with role mappings', () => {