Skip to content

Commit

Permalink
Merge branch 'feature/supporting-multiple-datasources' of github.com:…
Browse files Browse the repository at this point in the history
…opensearch-project/security-dashboards-plugin into ui-fixes

Signed-off-by: Derek Ho <[email protected]>
  • Loading branch information
derek-ho committed Apr 11, 2024
2 parents 8627e9f + 1ddef9b commit 51ce31d
Show file tree
Hide file tree
Showing 45 changed files with 246 additions and 102 deletions.
4 changes: 4 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ module.exports = {
},
plugins: [
'cypress',
"unused-imports"
],
rules: {
// "@osd/eslint/require-license-header": "off"
Expand All @@ -44,6 +45,9 @@ module.exports = {
'cypress/assertion-before-screenshot': 'warn',
'cypress/no-force': 'warn',
'cypress/no-async-tests': 'error',
// Unused imports and variables rules
"no-unused-vars": "off",
"unused-imports/no-unused-imports": "error",
},
overrides: [
{
Expand Down
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @cliu123 @cwperks @DarshitChanpura @davidlago @peternied @RyanL1997 @scrawfor99
* @cliu123 @cwperks @DarshitChanpura @davidlago @derek-ho @peternied @RyanL1997 @scrawfor99
2 changes: 1 addition & 1 deletion .github/actions/run-cypress-tests/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ runs:
if: ${{ runner.os == 'Linux' }}
run: |
cd ./OpenSearch-Dashboards/plugins/security-dashboards-plugin
yarn pretest:jest_server
yarn runIdp
shell: bash

- name: Run OpenSearch Dashboards with provided configuration
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ env:
TEST_BROWSER_HEADLESS: 1
CI: 1
PLUGIN_NAME: opensearch-security
OPENSEARCH_INITIAL_ADMIN_PASSWORD: admin
OPENSEARCH_INITIAL_ADMIN_PASSWORD: myStrongPassword123!

jobs:
tests:
Expand Down Expand Up @@ -98,13 +98,15 @@ jobs:
run: |
echo "check if opensearch is ready"
curl -XGET https://localhost:9200 -u 'admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }}' -k
yarn test:jest_server --coverage
ADMIN_PASSWORD=${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} yarn test:jest_server --coverage
shell: bash
working-directory: ${{ steps.install-dashboards.outputs.plugin-directory }}

- name: Run integration tests on Windows
if: ${{ runner.os == 'Windows' }}
run: |
echo "check if opensearch is ready"
curl -XGET https://localhost:9200 -u 'admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }}' -k
node .\test\run_jest_tests.js --runInBand --detectOpenHandles --forceExit --config .\test\jest.config.server.js
export ADMIN_PASSWORD=${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} && node ./test/run_jest_tests.js --runInBand --detectOpenHandles --forceExit --config ./test/jest.config.server.js
shell: bash
working-directory: ${{ steps.install-dashboards.outputs.plugin-directory }}
4 changes: 4 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

yarn lint:es --fix
1 change: 1 addition & 0 deletions MAINTAINERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ This document contains a list of maintainers in this repo. See [opensearch-proje
| Craig Perkins | [cwperks](https://github.com/cwperks) | Amazon |
| Ryan Liang | [RyanL1997](https://github.com/RyanL1997) | Amazon |
| Stephen Crawford | [scrawfor99](https://github.com/scrawfor99) | Amazon |
| Derek Ho | [derek-ho](https://github.com/derek-ho) | Amazon |

## Emeritus

Expand Down
13 changes: 8 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@
"lint:es": "node ../../scripts/eslint",
"lint:style": "node ../../scripts/stylelint",
"lint": "yarn run lint:es && yarn run lint:style",
"pretest:jest_server": "node ./test/jest_integration/runIdpServer.js &",
"test:jest_server": "node ./test/run_jest_tests.js --config ./test/jest.config.server.js",
"test:jest_ui": "node ./test/run_jest_tests.js --config ./test/jest.config.ui.js"
"runIdp": "node ./test/jest_integration/runIdpServer.js &",
"test:jest_server": "ADMIN_PASSWORD=$ADMIN_PASSWORD node ./test/run_jest_tests.js --config ./test/jest.config.server.js",
"test:jest_ui": "node ./test/run_jest_tests.js --config ./test/jest.config.ui.js",
"prepare": "husky install"
},
"devDependencies": {
"@elastic/eslint-import-resolver-kibana": "link:../../packages/osd-eslint-import-resolver-opensearch-dashboards",
Expand All @@ -34,7 +35,9 @@
"saml-idp": "^1.2.1",
"selfsigned": "^2.0.1",
"typescript": "4.0.2",
"eslint-plugin-cypress": "^2.8.1"
"eslint-plugin-cypress": "^2.8.1",
"eslint-plugin-unused-imports": "3.1.0",
"husky": "^8.0.0"
},
"dependencies": {
"@hapi/cryptiles": "5.0.0",
Expand All @@ -46,4 +49,4 @@
"glob-parent": "^5.1.2",
"debug": "^4.3.4"
}
}
}
2 changes: 1 addition & 1 deletion public/apps/account/tenant-switch-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import {
} from '../configuration/utils/tenant-utils';
import { fetchAccountInfo } from './utils';
import { constructErrorMessageAndLog } from '../error-utils';
import { getSavedTenant, setSavedTenant } from '../../utils/storage-utils';
import { setSavedTenant } from '../../utils/storage-utils';
import { getDashboardsInfo } from '../../utils/dashboards-info-utils';

interface TenantSwitchPanelProps {
Expand Down
43 changes: 40 additions & 3 deletions public/apps/account/test/plugin.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,39 @@
* permissions and limitations under the License.
*/

import { LOGIN_PAGE_URI } from '../../../../common';
import { interceptError } from '../../../utils/logout-utils';
import { setShouldShowTenantPopup } from '../../../utils/storage-utils';
import { LOGIN_PAGE_URI } from '../../../../common';

jest.mock('../../../utils/storage-utils', () => ({
setShouldShowTenantPopup: jest.fn(),
}));

interface LooseObject {
[key: string]: any;
}

// Mock sessionStorage
const sessionStorageMock = (() => {
let store = {} as LooseObject;
return {
clear() {
store = {};
},
};
})();

Object.defineProperty(window, 'sessionStorage', { value: sessionStorageMock });

describe('Intercept error handler', () => {
beforeEach(() => {
jest.spyOn(window.sessionStorage, 'clear');
});

afterEach(() => {
jest.restoreAllMocks();
});

const fakeError401 = {
response: {
status: 401,
Expand All @@ -34,15 +58,28 @@ describe('Intercept error handler', () => {
},
};

it('Intercept error handler Should call setShouldShowTenantPopup on session timeout', () => {
it('Intercept error handler should call setShouldShowTenantPopup on session timeout', () => {
const sessionTimeoutFn = interceptError(LOGIN_PAGE_URI, window);
sessionTimeoutFn(fakeError401, null);
expect(setShouldShowTenantPopup).toBeCalledTimes(1);
expect(sessionStorage.clear).toBeCalledTimes(1);
});

it('Intercept error handler should clear the session', () => {
const sessionTimeoutFn = interceptError(LOGIN_PAGE_URI, window);
sessionTimeoutFn(fakeError401, null);
expect(sessionStorage.clear).toBeCalledTimes(1);
});

it('Intercept error handler Should not call setShouldShowTenantPopup on session timeout', () => {
it('Intercept error handler should not call setShouldShowTenantPopup on session timeout', () => {
const sessionTimeoutFn = interceptError(LOGIN_PAGE_URI, window);
sessionTimeoutFn(fakeError400, null);
expect(setShouldShowTenantPopup).toBeCalledTimes(0);
});

it('Intercept error handler should not clear the session', () => {
const sessionTimeoutFn = interceptError(LOGIN_PAGE_URI, window);
sessionTimeoutFn(fakeError400, null);
expect(sessionStorage.clear).toBeCalledTimes(0);
});
});
24 changes: 3 additions & 21 deletions public/apps/account/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,11 @@
*/

import { HttpStart } from 'opensearch-dashboards/public';
import {
API_AUTH_LOGOUT,
LOGIN_PAGE_URI,
OPENID_AUTH_LOGOUT,
SAML_AUTH_LOGOUT,
} from '../../../common';
import { API_AUTH_LOGOUT } from '../../../common';
import { setShouldShowTenantPopup } from '../../utils/storage-utils';
import { httpGet, httpGetWithIgnores, httpPost } from '../configuration/utils/request-utils';
import { API_ENDPOINT_ACCOUNT_INFO } from './constants';
import { AccountInfo } from './types';
import { httpGet, httpGetWithIgnores, httpPost } from '../configuration/utils/request-utils';
import { setShouldShowTenantPopup } from '../../utils/storage-utils';

export function fetchAccountInfo(http: HttpStart): Promise<AccountInfo> {
return httpGet({ http, url: API_ENDPOINT_ACCOUNT_INFO });
Expand All @@ -45,19 +40,6 @@ export async function logout(http: HttpStart, logoutUrl?: string): Promise<void>
logoutUrl || `${http.basePath.serverBasePath}/app/login?nextUrl=${nextUrl}`;
}

export async function samlLogout(http: HttpStart): Promise<void> {
// This will ensure tenancy is picked up from local storage in the next login.
setShouldShowTenantPopup(null);
window.location.href = `${http.basePath.serverBasePath}${SAML_AUTH_LOGOUT}`;
}

export async function openidLogout(http: HttpStart): Promise<void> {
// This will ensure tenancy is picked up from local storage in the next login.
setShouldShowTenantPopup(null);
sessionStorage.clear();
window.location.href = `${http.basePath.serverBasePath}${OPENID_AUTH_LOGOUT}`;
}

export async function externalLogout(http: HttpStart, logoutEndpoint: string): Promise<void> {
// This will ensure tenancy is picked up from local storage in the next login.
setShouldShowTenantPopup(null);
Expand Down
46 changes: 43 additions & 3 deletions public/apps/configuration/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,24 +145,64 @@ export const CLUSTER_PERMISSIONS: string[] = [
'cluster:admin/opensearch/ql/async_query/result',
'cluster:admin/opensearch/ql/async_query/delete',
'cluster:admin/opensearch/ppl',
'cluster:admin/opensearch/ml/agents/delete',
'cluster:admin/opensearch/ml/agents/get',
'cluster:admin/opensearch/ml/agents/register',
'cluster:admin/opensearch/ml/agents/search',
'cluster:admin/opensearch/ml/config/get',
'cluster:admin/opensearch/ml/create_connector',
'cluster:admin/opensearch/ml/connectors/get',
'cluster:admin/opensearch/ml/connectors/search',
'cluster:admin/opensearch/ml/connectors/update',
'cluster:admin/opensearch/ml/controllers/create',
'cluster:admin/opensearch/ml/controllers/delete',
'cluster:admin/opensearch/ml/controllers/deploy',
'cluster:admin/opensearch/ml/controllers/get',
'cluster:admin/opensearch/ml/controllers/undeploy',
'cluster:admin/opensearch/ml/controllers/update',
'cluster:admin/opensearch/ml/create_model_meta',
'cluster:admin/opensearch/ml/execute',
'cluster:admin/opensearch/ml/load_model',
'cluster:admin/opensearch/ml/load_model_on_nodes',
'cluster:admin/opensearch/ml/deploy_model',
'cluster:admin/opensearch/ml/deploy_model_on_nodes',
'cluster:admin/opensearch/ml/memory/conversation/get',
'cluster:admin/opensearch/ml/memory/conversation/interaction/search',
'cluster:admin/opensearch/ml/memory/conversation/delete',
'cluster:admin/opensearch/ml/memory/conversation/list',
'cluster:admin/opensearch/ml/memory/conversation/search',
'cluster:admin/opensearch/ml/memory/conversation/create',
'cluster:admin/opensearch/ml/memory/conversation/update',
'cluster:admin/opensearch/ml/memory/interaction/create',
'cluster:admin/opensearch/ml/memory/interaction/update',
'cluster:admin/opensearch/ml/memory/interaction/get',
'cluster:admin/opensearch/ml/memory/interaction/list',
'cluster:admin/opensearch/ml/memory/trace/get',
'cluster:admin/opensearch/ml/model_groups/delete',
'cluster:admin/opensearch/ml/model_groups/get',
'cluster:admin/opensearch/ml/model_groups/search',
'cluster:admin/opensearch/ml/register_model_group',
'cluster:admin/opensearch/ml/update_model_group',
'cluster:admin/opensearch/ml/models/delete',
'cluster:admin/opensearch/ml/models/get',
'cluster:admin/opensearch/ml/models/search',
'cluster:admin/opensearch/ml/models/update',
'cluster:admin/opensearch/ml/models/update_cache',
'cluster:admin/opensearch/ml/predict',
'cluster:admin/opensearch/ml/profile/nodes',
'cluster:admin/opensearch/ml/register_model',
'cluster:admin/opensearch/ml/register_model_meta',
'cluster:admin/opensearch/ml/stats/nodes',
'cluster:admin/opensearch/ml/tasks/delete',
'cluster:admin/opensearch/ml/tasks/get',
'cluster:admin/opensearch/ml/tasks/search',
'cluster:admin/opensearch/ml/tools/get',
'cluster:admin/opensearch/ml/tools/list',
'cluster:admin/opensearch/ml/train',
'cluster:admin/opensearch/ml/trainAndPredict',
'cluster:admin/opensearch/ml/unload_model',
'cluster:admin/opensearch/ml/undeploy_model',
'cluster:admin/opensearch/ml/undeploy_models',
'cluster:admin/opensearch/ml/upload_model',
'cluster:admin/opensearch/ml/upload_model_chunk',
'cluster:admin/opensearch/mlinternal/forward',
'cluster:admin/opensearch/observability/create',
'cluster:admin/opensearch/observability/delete',
'cluster:admin/opensearch/observability/get',
Expand Down
3 changes: 1 addition & 2 deletions public/apps/configuration/panels/get-started.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@ import {
EuiTitle,
EuiGlobalToastList,
} from '@elastic/eui';
import React, { useContext, useState } from 'react';
import React, { useContext } from 'react';
import { FormattedMessage } from '@osd/i18n/react';
import { DataSourceOption } from '../../../../../../src/plugins/data_source_management/public/components/data_source_selector/data_source_selector';
import { AppDependencies } from '../../types';
import { buildHashUrl } from '../utils/url-builder';
import { Action } from '../types';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
* permissions and limitations under the License.
*/

import { EuiFieldText, EuiFlexGroup, EuiFormRow } from '@elastic/eui';
import { mount, shallow } from 'enzyme';
import { EuiFieldText, EuiFlexGroup } from '@elastic/eui';
import { shallow } from 'enzyme';
import React from 'react';
import {
appendElementToArray,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

import { EuiButton, EuiFieldText } from '@elastic/eui';
import { EuiButton } from '@elastic/eui';
import { shallow } from 'enzyme';
import React from 'react';
import { updateRole } from '../../../utils/role-detail-utils';
Expand Down
2 changes: 1 addition & 1 deletion public/apps/configuration/panels/role-view/role-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

import React, { useState, useEffect, useContext } from 'react';
import React, { useState, useContext } from 'react';

import {
EuiButton,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

import React, { useState, useEffect } from 'react';
import React from 'react';
import {
EuiInMemoryTable,
EuiLink,
Expand Down
2 changes: 1 addition & 1 deletion public/apps/configuration/panels/service-account-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
EuiTitle,
Query,
} from '@elastic/eui';
import { Dictionary, difference, isEmpty, map } from 'lodash';
import { Dictionary, isEmpty, map } from 'lodash';
import React, { useState } from 'react';
import { getAuthInfo } from '../../../utils/auth-info-utils';
import { AppDependencies } from '../../types';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ export function ConfigureTab1(props: AppDependencies) {
<EuiPageContentHeader>
<EuiPageContentHeaderSection>
<EuiTitle size="l">
<h3>Multi-tenancy</h3>
<h3>Dashboards multi-tenancy</h3>
</EuiTitle>
<EuiHorizontalRule />

Expand Down Expand Up @@ -360,15 +360,15 @@ export function ConfigureTab1(props: AppDependencies) {
<EuiPageContentHeader>
<EuiPageContentHeaderSection>
<EuiTitle size="l">
<h3>Tenants</h3>
<h3>Dashboards tenants</h3>
</EuiTitle>
<EuiHorizontalRule />
<EuiDescribedFormGroup
title={<h4>Global Tenant</h4>}
description={
<p4>
{' '}
Global tenant is shared amaong all Dashboards users and cannot be disabled.{' '}
Global tenant is shared among all Dashboards users and cannot be disabled.{' '}
</p4>
}
className="described-form-group2"
Expand Down Expand Up @@ -407,7 +407,7 @@ export function ConfigureTab1(props: AppDependencies) {
<EuiPageContentHeader>
<EuiPageContentHeaderSection>
<EuiTitle size="l">
<h3>Default tenant</h3>
<h3>Dashboards default tenant</h3>
</EuiTitle>
<EuiHorizontalRule />
<EuiDescribedFormGroup
Expand Down
Loading

0 comments on commit 51ce31d

Please sign in to comment.