kibana/x-pack/test/functional/page_objects/security_page.js
Spencer 61ca36f15d
Switch to K7 design by default (#29009)
* [visualize] update breadcrumbs when updating visualization

* [ftr] auto-scroll elements passed the fixed header if necessary

* [uiSettings] enable the k7design by default

* [ftr/services/flyout] add ensureClosed() and ensureAllClosed()

* [ftr/services/globalNav] implement globalNav service

* [ftr/services/appsMenu] implement service for using app menu

* [ftr/services/userMenu] add service for using user menu

* [ftr/discover+visualize] update assertions that are based on the app width

* [ftr/monitoring] pass test subjects to new breadcrumbs

* [headerGlobalNav] don't offset the app container in embed mode

* update heights for slightly smaller header
2019-01-18 12:39:01 -08:00

379 lines
13 KiB
JavaScript

/*
* 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 { map as mapAsync } from 'bluebird';
export function SecurityPageProvider({ getService, getPageObjects }) {
const browser = getService('browser');
const config = getService('config');
const retry = getService('retry');
const find = getService('find');
const log = getService('log');
const kibanaServer = getService('kibanaServer');
const testSubjects = getService('testSubjects');
const esArchiver = getService('esArchiver');
const userMenu = getService('userMenu');
const PageObjects = getPageObjects(['common', 'header', 'settings', 'home']);
class LoginPage {
async login(username, password, options = {}) {
const [superUsername, superPassword] = config.get('servers.elasticsearch.auth').split(':');
username = username || superUsername;
password = password || superPassword;
const expectSpaceSelector = options.expectSpaceSelector || false;
const expectSuccess = options.expectSuccess;
await PageObjects.common.navigateToApp('login');
await testSubjects.setValue('loginUsername', username);
await testSubjects.setValue('loginPassword', password);
await testSubjects.click('loginSubmit');
// wait for either space selector, kibanaChrome or loginErrorMessage
if (expectSpaceSelector) {
await retry.try(() => testSubjects.find('kibanaSpaceSelector'));
log.debug(`Finished login process, landed on space selector. currentUrl = ${await browser.getCurrentUrl()}`);
} else if (expectSuccess) {
await find.byCssSelector('[data-test-subj="kibanaChrome"] nav:not(.ng-hide) ', 20000);
log.debug(`Finished login process currentUrl = ${await browser.getCurrentUrl()}`);
}
}
async getErrorMessage() {
return await retry.try(async () => {
const errorMessageContainer = await retry.try(() => testSubjects.find('loginErrorMessage'));
const errorMessageText = await errorMessageContainer.getVisibleText();
if (!errorMessageText) {
throw new Error('Login Error Message not present yet');
}
return errorMessageText;
});
}
}
class SecurityPage {
constructor() {
this.loginPage = new LoginPage();
}
async initTests() {
log.debug('SecurityPage:initTests');
await esArchiver.load('empty_kibana');
await kibanaServer.uiSettings.disableToastAutohide();
await esArchiver.loadIfNeeded('logstash_functional');
browser.setWindowSize(1600, 1000);
}
async login(username, password, options = {}) {
await this.loginPage.login(username, password, options);
if (options.expectSpaceSelector) {
return;
}
await retry.waitFor('logout button visible', async () => (
await userMenu.logoutLinkExists()
));
}
async logout() {
log.debug('SecurityPage.logout');
if (!await userMenu.logoutLinkExists()) {
log.debug('Logout not found');
return;
}
await userMenu.clickLogoutButton();
await retry.waitForWithTimeout('login form', config.get('timeouts.waitFor') * 5, async () => (
await find.existsByDisplayedByCssSelector('.login-form')
));
}
async clickRolesSection() {
await testSubjects.click('roles');
}
async clickUsersSection() {
await testSubjects.click('users');
}
async clickCreateNewUser() {
await retry.try(() => testSubjects.click('createUserButton'));
}
async clickCreateNewRole() {
await retry.try(() => testSubjects.click('createRoleButton'));
}
async getCreateIndexPatternInputFieldExists() {
return await testSubjects.exists('createIndexPatternNameInput');
}
async clickCancelEditUser() {
await testSubjects.click('userFormCancelButton');
}
async clickCancelEditRole() {
await testSubjects.click('roleFormCancelButton');
}
async clickSaveEditUser() {
await testSubjects.click('userFormSaveButton');
await PageObjects.header.waitUntilLoadingHasFinished();
}
async clickSaveEditRole() {
const saveButton = await retry.try(() => testSubjects.find('roleFormSaveButton'));
await browser.moveMouseTo(saveButton);
await saveButton.click();
await PageObjects.header.waitUntilLoadingHasFinished();
}
async addIndexToRole(index) {
log.debug(`Adding index ${index} to role`);
const indexInput = await retry.try(() => find.byCssSelector('[data-test-subj="indicesInput0"] input'));
await indexInput.type(index);
await indexInput.type('\n');
}
async addPrivilegeToRole(privilege) {
log.debug(`Adding privilege ${privilege} to role`);
const privilegeInput =
await retry.try(() => find.byCssSelector('[data-test-subj="privilegesInput0"] input'));
await privilegeInput.type(privilege);
const btn = await find.byButtonText(privilege);
await btn.click();
// const options = await find.byCssSelector(`.euiComboBoxOption`);
// Object.entries(options).forEach(([key, prop]) => {
// console.log({ key, proto: prop.__proto__ });
// });
// await options.click();
}
async assignRoleToUser(role) {
await this.selectRole(role);
}
async navigateTo() {
await PageObjects.common.navigateToApp('settings');
}
async clickElasticsearchUsers() {
await this.navigateTo();
await this.clickUsersSection();
}
async clickElasticsearchRoles() {
await this.navigateTo();
await this.clickRolesSection();
}
async getElasticsearchUsers() {
const users = await testSubjects.findAll('userRow');
return mapAsync(users, async user => {
const fullnameElement = await user.findByCssSelector('[data-test-subj="userRowFullName"]');
const usernameElement = await user.findByCssSelector('[data-test-subj="userRowUserName"]');
const emailElement = await user.findByCssSelector('[data-header="Email Address"]');
const rolesElement = await user.findByCssSelector('[data-test-subj="userRowRoles"]');
const isReservedElementVisible = await user.findByCssSelector('td:last-child');
return {
username: await usernameElement.getVisibleText(),
fullname: await fullnameElement.getVisibleText(),
email: await emailElement.getVisibleText(),
roles: (await rolesElement.getVisibleText()).split(',').map(role => role.trim()),
reserved: (await isReservedElementVisible.getProperty('innerHTML')).includes('reservedUser')
};
});
}
async getElasticsearchRoles() {
const users = await testSubjects.findAll('roleRow');
return mapAsync(users, async role => {
const rolenameElement = await role.findByCssSelector('[data-test-subj="roleRowName"]');
const isReservedElementVisible = await role.findByCssSelector('td:nth-child(3)');
return {
rolename: await rolenameElement.getVisibleText(),
reserved: (await isReservedElementVisible.getProperty('innerHTML')).includes('roleRowReserved')
};
});
}
async clickNewUser() {
return await testSubjects.click('createUserButton');
}
async clickNewRole() {
return await testSubjects.click('createRoleButton');
}
async addUser(userObj) {
const self = this;
await this.clickNewUser();
log.debug('username = ' + userObj.username);
await testSubjects.setValue('userFormUserNameInput', userObj.username);
await testSubjects.setValue('passwordInput', userObj.password);
await testSubjects.setValue('passwordConfirmationInput', userObj.confirmPassword);
if (userObj.fullname) {
await testSubjects.setValue('userFormFullNameInput', userObj.fullname);
}
if (userObj.email) {
await testSubjects.setValue('userFormEmailInput', userObj.email);
}
log.debug('Add roles: ', userObj.roles);
const rolesToAdd = userObj.roles || [];
for (let i = 0; i < rolesToAdd.length; i++) {
await self.selectRole(rolesToAdd[i]);
}
log.debug('After Add role: , userObj.roleName');
if (userObj.save === true) {
await testSubjects.click('userFormSaveButton');
} else {
await testSubjects.click('userFormCancelButton');
}
}
addRole(roleName, userObj) {
const self = this;
return this.clickNewRole()
.then(function () {
// We have to use non-test-subject selectors because this markup is generated by ui-select.
log.debug('userObj.indices[0].names = ' + userObj.elasticsearch.indices[0].names);
return testSubjects.append('roleFormNameInput', roleName);
})
.then(function () {
return find.setValue('[data-test-subj="indicesInput0"] input', userObj.elasticsearch.indices[0].names + '\n');
})
.then(function () {
return testSubjects.click('restrictDocumentsQuery0');
})
.then(function () {
if (userObj.elasticsearch.indices[0].query) {
return testSubjects.setValue('queryInput0', userObj.elasticsearch.indices[0].query);
}
})
//KibanaPriv
.then(function () {
function addKibanaPriv(priv) {
return priv.reduce(function (promise, privName) {
// We have to use non-test-subject selectors because this markup is generated by ui-select.
return promise
.then(async function () {
log.debug('priv item = ' + privName);
return find.byCssSelector(`[data-test-subj="kibanaMinimumPrivilege"] option[value="${privName}"]`);
})
.then(function (element) {
return element.click();
});
}, Promise.resolve());
}
return userObj.kibana.global ? addKibanaPriv(userObj.kibana.global) : Promise.resolve();
})
.then(function () {
function addPriv(priv) {
return priv.reduce(function (promise, privName) {
// We have to use non-test-subject selectors because this markup is generated by ui-select.
return promise.then(() => self.addPrivilegeToRole(privName)).then(() => PageObjects.common.sleep(250));
}, Promise.resolve());
}
return addPriv(userObj.elasticsearch.indices[0].privileges);
})
//clicking the Granted fields and removing the asterix
.then(function () {
function addGrantedField(field) {
return field.reduce(function (promise, fieldName) {
return promise
.then(function () {
return find.setValue('[data-test-subj="fieldInput0"] input', fieldName + '\n');
})
.then(function () {
return PageObjects.common.sleep(1000);
});
}, Promise.resolve());
}
if (userObj.elasticsearch.indices[0].field_security) {
// have to remove the '*'
return find.clickByCssSelector('div[data-test-subj="fieldInput0"] .euiBadge[title="*"]')
.then(function () {
return addGrantedField(userObj.elasticsearch.indices[0].field_security.grant);
});
}
}) //clicking save button
.then(function () {
log.debug('click save button');
testSubjects.click('roleFormSaveButton');
})
.then(function () {
return PageObjects.common.sleep(5000);
});
}
async selectRole(role) {
const dropdown = await testSubjects.find("userFormRolesDropdown");
const input = await dropdown.findByCssSelector("input");
await input.type(role);
await testSubjects.click(`roleOption-${role}`);
await testSubjects.click('comboBoxToggleListButton');
await testSubjects.find(`roleOption-${role}`);
}
deleteUser(username) {
let alertText;
log.debug('Delete user ' + username);
return find.clickByDisplayedLinkText(username)
.then(() => {
return PageObjects.header.awaitGlobalLoadingIndicatorHidden();
})
.then(() => {
log.debug('Find delete button and click');
return testSubjects.click('userFormDeleteButton');
})
.then(() => {
return PageObjects.common.sleep(2000);
})
.then(() => {
return testSubjects.getVisibleText('confirmModalBodyText');
})
.then((alert) => {
alertText = alert;
log.debug('Delete user alert text = ' + alertText);
return testSubjects.click('confirmModalConfirmButton');
})
.then(() => {
return alertText;
});
}
async getPermissionDeniedMessage() {
const el = await find.displayedByCssSelector('span.kuiInfoPanelHeader__title');
return await el.getVisibleText();
}
}
return new SecurityPage();
}