diff --git a/.eslintrc.js b/.eslintrc.js index 8762c1dc02d2d..9aca4136881b2 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -326,7 +326,7 @@ module.exports = { allowSameFolder: true, }, { - target: ['src/core/**/*'], + target: ['src/**/*'], from: ['x-pack/**/*'], errorMessage: 'OSS cannot import x-pack files.', }, diff --git a/.github/workflows/pr-project-assigner.yml b/.github/workflows/pr-project-assigner.yml new file mode 100644 index 0000000000000..aea8a9cad6b1f --- /dev/null +++ b/.github/workflows/pr-project-assigner.yml @@ -0,0 +1,15 @@ +on: + pull_request: + types: [labeled, unlabeled] + +jobs: + assign_to_project: + runs-on: ubuntu-latest + name: Assign a PR to project based on label + steps: + - name: Assign to project + uses: elastic/github-actions/project-assigner@v1.0.0 + id: project_assigner + with: + issue-mappings: '[{"label": "Team:AppAch", "projectName": "kibana-app-arch", "columnId": 6173897}]' + ghToken: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/project-assigner.yml b/.github/workflows/project-assigner.yml new file mode 100644 index 0000000000000..c7f17993249eb --- /dev/null +++ b/.github/workflows/project-assigner.yml @@ -0,0 +1,17 @@ +on: + issues: + types: [labeled, unlabeled] + +jobs: + assign_to_project: + runs-on: ubuntu-latest + name: Assign issue or PR to project based on label + steps: + - name: Assign to project + uses: elastic/github-actions/project-assigner@v1.0.0 + id: project_assigner + with: + issue-mappings: '[{"label": "Team:AppArch", "projectName": "kibana-app-arch", "columnId": 6173895}]' + ghToken: ${{ secrets.GITHUB_TOKEN }} + + diff --git a/packages/kbn-test/src/failed_tests_reporter/__fixtures__/ftr_report.xml b/packages/kbn-test/src/failed_tests_reporter/__fixtures__/ftr_report.xml index 9da63234e03d4..3bfc686f9e845 100644 --- a/packages/kbn-test/src/failed_tests_reporter/__fixtures__/ftr_report.xml +++ b/packages/kbn-test/src/failed_tests_reporter/__fixtures__/ftr_report.xml @@ -18,7 +18,7 @@ Wait timed out after 10055ms at onFailure (/var/lib/jenkins/workspace/elastic+kibana+master/JOB/x-pack-ciGroup7/node/immutable/kibana/test/common/services/retry/retry_for_success.ts:68:13)]]> - + { + at onFailure (/var/lib/jenkins/workspace/elastic+kibana+master/JOB/x-pack-ciGroup7/node/immutable/kibana/test/common/services/retry/retry_for_success.ts:68:13) ‹/failure› ‹/testcase› - ‹testcase name="maps app "after all" hook" classname="Chrome X-Pack UI Functional Tests.x-pack/test/functional/apps/maps" time="0.179"› + ‹testcase name="maps app "after all" hook" classname="Chrome X-Pack UI Functional Tests.x-pack/test/functional/apps/maps" time="0.179" metadata-json="{"messages":["foo"],"screenshots":[{"name":"failure[dashboard app using current data dashboard snapshots compare TSVB snapshot]","url":"https://storage.googleapis.com/kibana-ci-artifacts/jobs/elastic+kibana+7.x/1632/kibana-oss-tests/test/functional/screenshots/failure/dashboard%20app%20using%20current%20data%20dashboard%20snapshots%20compare%20TSVB%20snapshot.png"}]}"› ‹system-out› - ‹![CDATA[[00:00:00] │ + [00:00:00] │ diff --git a/packages/kbn-test/src/failed_tests_reporter/get_failures.test.ts b/packages/kbn-test/src/failed_tests_reporter/get_failures.test.ts index fe6e0bbc796ee..23d9805727f32 100644 --- a/packages/kbn-test/src/failed_tests_reporter/get_failures.test.ts +++ b/packages/kbn-test/src/failed_tests_reporter/get_failures.test.ts @@ -48,6 +48,7 @@ it('discovers failures in ftr report', async () => { at process._tickCallback (internal/process/next_tick.js:68:7) name: 'NoSuchSessionError', remoteStacktrace: '' } ", "likelyIrrelevant": true, + "metadata-json": "{\\"messages\\":[\\"foo\\"],\\"screenshots\\":[{\\"name\\":\\"failure[dashboard app using current data dashboard snapshots compare TSVB snapshot]\\",\\"url\\":\\"https://storage.googleapis.com/kibana-ci-artifacts/jobs/elastic+kibana+7.x/1632/kibana-oss-tests/test/functional/screenshots/failure/dashboard%20app%20using%20current%20data%20dashboard%20snapshots%20compare%20TSVB%20snapshot.png\\"}]}", "name": "maps app \\"after all\\" hook", "time": "0.179", }, diff --git a/packages/kbn-test/src/failed_tests_reporter/report_metadata.test.ts b/packages/kbn-test/src/failed_tests_reporter/report_metadata.test.ts new file mode 100644 index 0000000000000..729d80ddfcb44 --- /dev/null +++ b/packages/kbn-test/src/failed_tests_reporter/report_metadata.test.ts @@ -0,0 +1,49 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { getReportMessageIter } from './report_metadata'; +import { parseTestReport } from './test_report'; +import { FTR_REPORT, JEST_REPORT, KARMA_REPORT, MOCHA_REPORT } from './__fixtures__'; + +it('reads messages and screenshots from metadata-json properties', async () => { + const ftrReport = await parseTestReport(FTR_REPORT); + expect(Array.from(getReportMessageIter(ftrReport))).toMatchInlineSnapshot(` + Array [ + Object { + "classname": "Chrome X-Pack UI Functional Tests.x-pack/test/functional/apps/maps", + "message": "foo", + "name": "maps app \\"after all\\" hook", + }, + Object { + "classname": "Chrome X-Pack UI Functional Tests.x-pack/test/functional/apps/maps", + "message": "Screenshot: failure[dashboard app using current data dashboard snapshots compare TSVB snapshot] https://storage.googleapis.com/kibana-ci-artifacts/jobs/elastic+kibana+7.x/1632/kibana-oss-tests/test/functional/screenshots/failure/dashboard%20app%20using%20current%20data%20dashboard%20snapshots%20compare%20TSVB%20snapshot.png", + "name": "maps app \\"after all\\" hook", + }, + ] + `); + + const jestReport = await parseTestReport(JEST_REPORT); + expect(Array.from(getReportMessageIter(jestReport))).toMatchInlineSnapshot(`Array []`); + + const mochaReport = await parseTestReport(MOCHA_REPORT); + expect(Array.from(getReportMessageIter(mochaReport))).toMatchInlineSnapshot(`Array []`); + + const karmaReport = await parseTestReport(KARMA_REPORT); + expect(Array.from(getReportMessageIter(karmaReport))).toMatchInlineSnapshot(`Array []`); +}); diff --git a/packages/kbn-test/src/failed_tests_reporter/report_metadata.ts b/packages/kbn-test/src/failed_tests_reporter/report_metadata.ts index aad4c5d3c30c0..5484948e59976 100644 --- a/packages/kbn-test/src/failed_tests_reporter/report_metadata.ts +++ b/packages/kbn-test/src/failed_tests_reporter/report_metadata.ts @@ -18,36 +18,25 @@ */ import { TestReport, makeTestCaseIter } from './test_report'; -import { Message } from './add_messages_to_report'; -export function* getMetadataIter(report: TestReport) { +export function* getReportMessageIter(report: TestReport) { for (const testCase of makeTestCaseIter(report)) { - if (!testCase.$['metadata-json']) { - yield [{}, testCase]; - } else { - yield [{}, JSON.parse(testCase.$['metadata-json'])]; - } - } -} + const metadata = testCase.$['metadata-json'] ? JSON.parse(testCase.$['metadata-json']) : {}; -export function getReportMessages(report: TestReport) { - const messages: Message[] = []; - for (const [metadata, testCase] of getMetadataIter(report)) { for (const message of metadata.messages || []) { - messages.push({ + yield { classname: testCase.$.classname, name: testCase.$.name, - message, - }); + message: String(message), + }; } for (const screenshot of metadata.screenshots || []) { - messages.push({ + yield { classname: testCase.$.classname, name: testCase.$.name, message: `Screenshot: ${screenshot.name} ${screenshot.url}`, - }); + }; } } - return messages; } diff --git a/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts b/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts index fd7976d6e87e1..fc52fa6cbf9e7 100644 --- a/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts +++ b/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts @@ -26,7 +26,7 @@ import { updateFailureIssue, createFailureIssue } from './report_failure'; import { getIssueMetadata } from './issue_metadata'; import { readTestReport } from './test_report'; import { addMessagesToReport } from './add_messages_to_report'; -import { getReportMessages } from './report_metadata'; +import { getReportMessageIter } from './report_metadata'; export function runFailedTestsReporterCli() { run( @@ -75,7 +75,7 @@ export function runFailedTestsReporterCli() { for (const reportPath of reportPaths) { const report = await readTestReport(reportPath); - const messages = getReportMessages(report); + const messages = Array.from(getReportMessageIter(report)); for (const failure of await getFailures(report)) { const pushMessage = (msg: string) => { diff --git a/src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/mode/elasticsearch_sql_highlight_rules.ts b/src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/mode/elasticsearch_sql_highlight_rules.ts new file mode 100644 index 0000000000000..398cf531612ef --- /dev/null +++ b/src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/mode/elasticsearch_sql_highlight_rules.ts @@ -0,0 +1,113 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import ace from 'brace'; + +const { TextHighlightRules } = ace.acequire('ace/mode/text_highlight_rules'); +const oop = ace.acequire('ace/lib/oop'); + +export const ElasticsearchSqlHighlightRules = function(this: any) { + // See https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-commands.html + const keywords = + 'describe|between|in|like|not|and|or|desc|select|from|where|having|group|by|order' + + 'asc|desc|pivot|for|in|as|show|columns|include|frozen|tables|escape|limit|rlike|all|distinct|is'; + + const builtinConstants = 'true|false'; + + // See https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-syntax-show-functions.html + const builtinFunctions = + 'avg|count|first|first_value|last|last_value|max|min|sum|kurtosis|mad|percentile|percentile_rank|skewness' + + '|stddev_pop|sum_of_squares|var_pop|histogram|case|coalesce|greatest|ifnull|iif|isnull|least|nullif|nvl' + + '|curdate|current_date|current_time|current_timestamp|curtime|dateadd|datediff|datepart|datetrunc|date_add' + + '|date_diff|date_part|date_trunc|day|dayname|dayofmonth|dayofweek|dayofyear|day_name|day_of_month|day_of_week' + + '|day_of_year|dom|dow|doy|hour|hour_of_day|idow|isodayofweek|isodow|isoweek|isoweekofyear|iso_day_of_week|iso_week_of_year' + + '|iw|iwoy|minute|minute_of_day|minute_of_hour|month|monthname|month_name|month_of_year|now|quarter|second|second_of_minute' + + '|timestampadd|timestampdiff|timestamp_add|timestamp_diff|today|week|week_of_year|year|abs|acos|asin|atan|atan2|cbrt' + + '|ceil|ceiling|cos|cosh|cot|degrees|e|exp|expm1|floor|log|log10|mod|pi|power|radians|rand|random|round|sign|signum|sin' + + '|sinh|sqrt|tan|truncate|ascii|bit_length|char|character_length|char_length|concat|insert|lcase|left|length|locate' + + '|ltrim|octet_length|position|repeat|replace|right|rtrim|space|substring|ucase|cast|convert|database|user|st_astext|st_aswkt' + + '|st_distance|st_geometrytype|st_geomfromtext|st_wkttosql|st_x|st_y|st_z|score'; + + // See https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-data-types.html + const dataTypes = + 'null|boolean|byte|short|integer|long|double|float|half_float|scaled_float|keyword|text|binary|date|ip|object|nested|time' + + '|interval_year|interval_month|interval_day|interval_hour|interval_minute|interval_second|interval_year_to_month' + + 'inteval_day_to_hour|interval_day_to_minute|interval_day_to_second|interval_hour_to_minute|interval_hour_to_second' + + 'interval_minute_to_second|geo_point|geo_shape|shape'; + + const keywordMapper = this.createKeywordMapper( + { + keyword: [keywords, builtinFunctions, builtinConstants, dataTypes].join('|'), + }, + 'identifier', + true + ); + + this.$rules = { + start: [ + { + token: 'comment', + regex: '--.*$', + }, + { + token: 'comment', + start: '/\\*', + end: '\\*/', + }, + { + token: 'string', // " string + regex: '".*?"', + }, + { + token: 'constant', // ' string + regex: "'.*?'", + }, + { + token: 'string', // ` string (apache drill) + regex: '`.*?`', + }, + { + token: 'entity.name.function', // float + regex: '[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b', + }, + { + token: keywordMapper, + regex: '[a-zA-Z_$][a-zA-Z0-9_$]*\\b', + }, + { + token: 'keyword.operator', + regex: '⇐|<⇒|\\*|\\.|\\:\\:|\\+|\\-|\\/|\\/\\/|%|&|\\^|~|<|>|<=|=>|==|!=|<>|=', + }, + { + token: 'paren.lparen', + regex: '[\\(]', + }, + { + token: 'paren.rparen', + regex: '[\\)]', + }, + { + token: 'text', + regex: '\\s+', + }, + ], + }; + this.normalizeRules(); +}; + +oop.inherits(ElasticsearchSqlHighlightRules, TextHighlightRules); diff --git a/src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/mode/input_highlight_rules.js b/src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/mode/input_highlight_rules.js index 9ef1a8f31ac72..17c1e3876f076 100644 --- a/src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/mode/input_highlight_rules.js +++ b/src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/mode/input_highlight_rules.js @@ -20,27 +20,33 @@ const ace = require('brace'); import { addToRules } from './x_json_highlight_rules'; -const oop = ace.acequire('ace/lib/oop'); -const { TextHighlightRules } = ace.acequire('ace/mode/text_highlight_rules'); -export function InputHighlightRules() { - function mergeTokens(/* ... */) { - return [].concat.apply([], arguments); +export function addEOL(tokens, reg, nextIfEOL, normalNext) { + if (typeof reg === 'object') { + reg = reg.source; } + return [ + { token: tokens.concat(['whitespace']), regex: reg + '(\\s*)$', next: nextIfEOL }, + { token: tokens, regex: reg, next: normalNext } + ]; +} - function addEOL(tokens, reg, nextIfEOL, normalNext) { - if (typeof reg === 'object') { - reg = reg.source; - } - return [ - { token: tokens.concat(['whitespace']), regex: reg + '(\\s*)$', next: nextIfEOL }, - { token: tokens, regex: reg, next: normalNext } - ]; - } +export function mergeTokens(/* ... */) { + return [].concat.apply([], arguments); +} + +const oop = ace.acequire('ace/lib/oop'); +const { TextHighlightRules } = ace.acequire('ace/mode/text_highlight_rules'); +export function InputHighlightRules() { // regexp must not have capturing parentheses. Use (?:) instead. // regexps are ordered -> the first match is used /*jshint -W015 */ this.$rules = { + 'start-sql': [ + { token: 'whitespace', regex: '\\s+' }, + { token: 'paren.lparen', regex: '{', next: 'json-sql', push: true }, + { regex: '', next: 'start' } + ], 'start': mergeTokens([ { 'token': 'warning', 'regex': '#!.*$' }, { token: 'comment', regex: /^#.*$/ }, @@ -65,6 +71,7 @@ export function InputHighlightRules() { addEOL(['whitespace'], /(\s+)/, 'start', 'url') ), 'url': mergeTokens( + addEOL(['url.part'], /(_sql)/, 'start-sql', 'url-sql'), addEOL(['url.part'], /([^?\/,\s]+)/, 'start'), addEOL(['url.comma'], /(,)/, 'start'), addEOL(['url.slash'], /(\/)/, 'start'), @@ -74,7 +81,17 @@ export function InputHighlightRules() { addEOL(['url.param', 'url.equal', 'url.value'], /([^&=]+)(=)([^&]*)/, 'start'), addEOL(['url.param'], /([^&=]+)/, 'start'), addEOL(['url.amp'], /(&)/, 'start') - ) + ), + 'url-sql': mergeTokens( + addEOL(['url.comma'], /(,)/, 'start-sql'), + addEOL(['url.slash'], /(\/)/, 'start-sql'), + addEOL(['url.questionmark'], /(\?)/, 'start-sql', 'urlParams-sql') + ), + 'urlParams-sql': mergeTokens( + addEOL(['url.param', 'url.equal', 'url.value'], /([^&=]+)(=)([^&]*)/, 'start-sql'), + addEOL(['url.param'], /([^&=]+)/, 'start-sql'), + addEOL(['url.amp'], /(&)/, 'start-sql') + ), }; addToRules(this); diff --git a/src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/mode/x_json_highlight_rules.js b/src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/mode/x_json_highlight_rules.js index 28453a409bf22..d0d54f38b68fb 100644 --- a/src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/mode/x_json_highlight_rules.js +++ b/src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/mode/x_json_highlight_rules.js @@ -18,12 +18,14 @@ */ const _ = require('lodash'); -const ScriptHighlightRules = require('./script_highlight_rules').ScriptHighlightRules; + +import { ElasticsearchSqlHighlightRules } from './elasticsearch_sql_highlight_rules'; +const { ScriptHighlightRules } = require('./script_highlight_rules'); const jsonRules = function (root) { root = root ? root : 'json'; const rules = {}; - rules[root] = [ + const xJsonRules = [ { token: ['variable', 'whitespace', 'ace.punctuation.colon', 'whitespace', 'punctuation.start_triple_quote'], regex: '("(?:[^"]*_)?script"|"inline"|"source")(\\s*?)(:)(\\s*?)(""")', @@ -106,6 +108,16 @@ const jsonRules = function (root) { regex: '.+?' } ]; + + rules[root] = xJsonRules; + rules[root + '-sql'] = [{ + token: ['variable', 'whitespace', 'ace.punctuation.colon', 'whitespace', 'punctuation.start_triple_quote'], + regex: '("query")(\\s*?)(:)(\\s*?)(""")', + next: 'sql-start', + merge: false, + push: true + }].concat(xJsonRules); + rules.string_literal = [ { token: 'punctuation.end_triple_quote', @@ -127,4 +139,9 @@ export function addToRules(otherRules, embedUnder) { regex: '"""', next: 'pop', }]); + otherRules.embedRules(ElasticsearchSqlHighlightRules, 'sql-', [{ + token: 'punctuation.end_triple_quote', + regex: '"""', + next: 'pop', + }]); } diff --git a/src/legacy/core_plugins/console/public/np_ready/lib/autocomplete/autocomplete.ts b/src/legacy/core_plugins/console/public/np_ready/lib/autocomplete/autocomplete.ts index 8edb26f7817e4..7520807ca77f5 100644 --- a/src/legacy/core_plugins/console/public/np_ready/lib/autocomplete/autocomplete.ts +++ b/src/legacy/core_plugins/console/public/np_ready/lib/autocomplete/autocomplete.ts @@ -990,7 +990,7 @@ export default function({ coreEditor: editor, parser }: { coreEditor: CoreEditor score: 0, context, }; - // we only need out custom insertMatch behavior for the body + // we only need our custom insertMatch behavior for the body if (context.autoCompleteType === 'body') { defaults.completer = { insertMatch() { diff --git a/src/legacy/core_plugins/console/public/np_ready/lib/autocomplete/components/full_request_component.ts b/src/legacy/core_plugins/console/public/np_ready/lib/autocomplete/components/full_request_component.ts new file mode 100644 index 0000000000000..a534928c6677c --- /dev/null +++ b/src/legacy/core_plugins/console/public/np_ready/lib/autocomplete/components/full_request_component.ts @@ -0,0 +1,33 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// @ts-ignore +import { ConstantComponent } from './constant_component'; + +export class FullRequestComponent extends ConstantComponent { + private readonly name: string; + constructor(name: string, parent: any, private readonly template: string) { + super(name, parent); + this.name = name; + } + + getTerms() { + return [{ name: this.name, snippet: this.template }]; + } +} diff --git a/src/legacy/core_plugins/console/public/np_ready/lib/autocomplete/components/url_pattern_matcher.js b/src/legacy/core_plugins/console/public/np_ready/lib/autocomplete/components/url_pattern_matcher.js index dfae1382bed9b..93aac27cf94fb 100644 --- a/src/legacy/core_plugins/console/public/np_ready/lib/autocomplete/components/url_pattern_matcher.js +++ b/src/legacy/core_plugins/console/public/np_ready/lib/autocomplete/components/url_pattern_matcher.js @@ -25,6 +25,8 @@ import { SimpleParamComponent, } from './index'; +import { FullRequestComponent } from './full_request_component'; + /** * @param parametrizedComponentFactories a dict of the following structure * that will be used as a fall back for pattern parameters (i.e.: {indices}) @@ -54,6 +56,9 @@ export class UrlPatternMatcher { endpoint.methods.forEach((method) => { let c; let activeComponent = this[method].rootComponent; + if (endpoint.template) { + new FullRequestComponent(pattern + '[body]', activeComponent, endpoint.template); + } const endpointComponents = endpoint.url_components || {}; const partList = pattern.split('/'); _.each( diff --git a/src/legacy/core_plugins/console/public/np_ready/lib/row_parser.ts b/src/legacy/core_plugins/console/public/np_ready/lib/row_parser.ts index b56d15e178810..e92817f8eae7d 100644 --- a/src/legacy/core_plugins/console/public/np_ready/lib/row_parser.ts +++ b/src/legacy/core_plugins/console/public/np_ready/lib/row_parser.ts @@ -44,7 +44,10 @@ export default class RowParser { return MODE.BETWEEN_REQUESTS; } // shouldn't really happen - if (mode !== 'start') { + // If another "start" mode is added here because we want to allow for new language highlighting + // please see https://github.com/elastic/kibana/pull/51446 for a discussion on why + // should consider a different approach. + if (mode !== 'start' && mode !== 'start-sql') { return MODE.IN_REQUEST; } let line = (this.editor.getLineValue(lineNumber) || '').trim(); diff --git a/src/legacy/core_plugins/kibana/public/discover/index.ts b/src/legacy/core_plugins/kibana/public/discover/index.ts index 7f8ca4e96c5ac..35c8da9e3f265 100644 --- a/src/legacy/core_plugins/kibana/public/discover/index.ts +++ b/src/legacy/core_plugins/kibana/public/discover/index.ts @@ -23,10 +23,8 @@ import { DiscoverPlugin, DiscoverSetup, DiscoverStart } from './plugin'; import { start as navigation } from '../../../navigation/public/legacy'; // Core will be looking for this when loading our plugin in the new platform -export const plugin: PluginInitializer = ( - initializerContext: PluginInitializerContext -) => { - return new DiscoverPlugin(initializerContext); +export const plugin: PluginInitializer = () => { + return new DiscoverPlugin(); }; // Legacy compatiblity part - to be removed at cutover, replaced by a kibana.json file diff --git a/src/legacy/core_plugins/kibana/public/discover/plugin.ts b/src/legacy/core_plugins/kibana/public/discover/plugin.ts index a5a1ead93188a..cb84463c18438 100644 --- a/src/legacy/core_plugins/kibana/public/discover/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/discover/plugin.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'kibana/public'; +import { AppMountParameters, CoreSetup, CoreStart, Plugin } from 'kibana/public'; import angular from 'angular'; import { IUiActionsStart } from 'src/plugins/ui_actions/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; @@ -69,14 +69,13 @@ export class DiscoverPlugin implements Plugin { */ public initializeInnerAngular?: () => void; public initializeServices?: () => void; - constructor(initializerContext: PluginInitializerContext) {} setup(core: CoreSetup, plugins: DiscoverSetupPlugins): DiscoverSetup { plugins.kibana_legacy.registerLegacyApp({ id: 'discover', title: 'Discover', order: -1004, euiIconType: 'discoverApp', - mount: async (context, params) => { + mount: async (params: AppMountParameters) => { if (!this.initializeServices) { throw Error('Discover plugin method initializeServices is undefined'); } diff --git a/src/legacy/ui/public/new_platform/new_platform.ts b/src/legacy/ui/public/new_platform/new_platform.ts index 547d22c58cfc1..d80d11e1b1bdd 100644 --- a/src/legacy/ui/public/new_platform/new_platform.ts +++ b/src/legacy/ui/public/new_platform/new_platform.ts @@ -32,7 +32,6 @@ import { DevToolsSetup, DevToolsStart } from '../../../../plugins/dev_tools/publ import { KibanaLegacySetup, KibanaLegacyStart } from '../../../../plugins/kibana_legacy/public'; import { HomePublicPluginSetup, HomePublicPluginStart } from '../../../../plugins/home/public'; import { SharePluginSetup, SharePluginStart } from '../../../../plugins/share/public'; -import { LicensingPluginSetup } from '../../../../../x-pack/plugins/licensing/common/types'; export interface PluginsSetup { data: ReturnType; @@ -44,7 +43,6 @@ export interface PluginsSetup { dev_tools: DevToolsSetup; kibana_legacy: KibanaLegacySetup; share: SharePluginSetup; - licensing: LicensingPluginSetup; } export interface PluginsStart { diff --git a/x-pack/legacy/plugins/actions/server/plugin.ts b/x-pack/legacy/plugins/actions/server/plugin.ts index 27eead7d736c1..510e2a3b94894 100644 --- a/x-pack/legacy/plugins/actions/server/plugin.ts +++ b/x-pack/legacy/plugins/actions/server/plugin.ts @@ -69,30 +69,6 @@ export class Plugin { this.adminClient = await core.elasticsearch.adminClient$.pipe(first()).toPromise(); this.defaultKibanaIndex = (await this.kibana$.pipe(first()).toPromise()).index; - plugins.xpack_main.registerFeature({ - id: 'actions', - name: 'Actions', - app: ['actions', 'kibana'], - privileges: { - all: { - savedObject: { - all: ['action', 'action_task_params'], - read: [], - }, - ui: [], - api: ['actions-read', 'actions-all'], - }, - read: { - savedObject: { - all: ['action_task_params'], - read: ['action'], - }, - ui: [], - api: ['actions-read'], - }, - }, - }); - // Encrypted attributes // - `secrets` properties will be encrypted // - `config` will be included in AAD diff --git a/x-pack/legacy/plugins/alerting/server/plugin.ts b/x-pack/legacy/plugins/alerting/server/plugin.ts index c50bc795757f3..32e5753687367 100644 --- a/x-pack/legacy/plugins/alerting/server/plugin.ts +++ b/x-pack/legacy/plugins/alerting/server/plugin.ts @@ -60,30 +60,6 @@ export class Plugin { ): Promise { this.adminClient = await core.elasticsearch.adminClient$.pipe(first()).toPromise(); - plugins.xpack_main.registerFeature({ - id: 'alerting', - name: 'Alerting', - app: ['alerting', 'kibana'], - privileges: { - all: { - savedObject: { - all: ['alert'], - read: [], - }, - ui: [], - api: ['alerting-read', 'alerting-all'], - }, - read: { - savedObject: { - all: [], - read: ['alert'], - }, - ui: [], - api: ['alerting-read'], - }, - }, - }); - // Encrypted attributes plugins.encryptedSavedObjects.registerType({ type: 'alert', diff --git a/x-pack/legacy/plugins/console_extensions/spec/overrides/sql.query.json b/x-pack/legacy/plugins/console_extensions/spec/overrides/sql.query.json index f2fe456a0c6e2..843fba30bb489 100644 --- a/x-pack/legacy/plugins/console_extensions/spec/overrides/sql.query.json +++ b/x-pack/legacy/plugins/console_extensions/spec/overrides/sql.query.json @@ -18,6 +18,7 @@ "cbor", "smile" ] - } + }, + "template": "_sql?format=json\n{\n \"query\": \"\"\"\n SELECT * FROM \"${1:TABLE}\"\n \"\"\"\n}\n" } } diff --git a/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace.js b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace.js deleted file mode 100644 index 444e68dd03520..0000000000000 --- a/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace.js +++ /dev/null @@ -1,67 +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 { SavedObjectProvider } from 'ui/saved_objects/saved_object'; -import { i18n } from '@kbn/i18n'; -import { - extractReferences, - injectReferences, -} from './saved_workspace_references'; - -export function SavedWorkspaceProvider(Private) { - // SavedWorkspace constructor. Usually you'd interact with an instance of this. - // ID is option, without it one will be generated on save. - const SavedObject = Private(SavedObjectProvider); - class SavedWorkspace extends SavedObject { - constructor(id) { - // Gives our SavedWorkspace the properties of a SavedObject - super ({ - type: SavedWorkspace.type, - mapping: SavedWorkspace.mapping, - searchSource: SavedWorkspace.searchsource, - extractReferences: extractReferences, - injectReferences: injectReferences, - - // if this is null/undefined then the SavedObject will be assigned the defaults - id: id, - - // default values that will get assigned if the doc is new - defaults: { - title: i18n.translate('xpack.graph.savedWorkspace.workspaceNameTitle', { - defaultMessage: 'New Graph Workspace' - }), - numLinks: 0, - numVertices: 0, - wsState: '{}', - version: 1 - } - - }); - - // Overwrite the default getDisplayName function which uses type and which is not very - // user friendly for this object. - this.getDisplayName = function () { - return 'graph workspace'; - }; - } - - } //End of class - - SavedWorkspace.type = 'graph-workspace'; - - // if type:workspace has no mapping, we push this mapping into ES - SavedWorkspace.mapping = { - title: 'text', - description: 'text', - numLinks: 'integer', - numVertices: 'integer', - version: 'integer', - wsState: 'json' - }; - - SavedWorkspace.searchsource = false; - return SavedWorkspace; -} diff --git a/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace.ts b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace.ts new file mode 100644 index 0000000000000..bcde72a02f02e --- /dev/null +++ b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace.ts @@ -0,0 +1,65 @@ +/* + * 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 { SavedObject, SavedObjectKibanaServices } from 'ui/saved_objects/types'; +import { createSavedObjectClass } from 'ui/saved_objects/saved_object'; +import { i18n } from '@kbn/i18n'; +import { extractReferences, injectReferences } from './saved_workspace_references'; + +export interface SavedWorkspace extends SavedObject { + wsState?: string; +} + +export function createSavedWorkspaceClass(services: SavedObjectKibanaServices) { + // SavedWorkspace constructor. Usually you'd interact with an instance of this. + // ID is option, without it one will be generated on save. + const SavedObjectClass = createSavedObjectClass(services); + class SavedWorkspaceClass extends SavedObjectClass { + public static type: string = 'graph-workspace'; + // if type:workspace has no mapping, we push this mapping into ES + public static mapping: Record = { + title: 'text', + description: 'text', + numLinks: 'integer', + numVertices: 'integer', + version: 'integer', + wsState: 'json', + }; + // Order these fields to the top, the rest are alphabetical + public static fieldOrder = ['title', 'description']; + public static searchSource = false; + + public wsState?: string; + + constructor(id: string) { + // Gives our SavedWorkspace the properties of a SavedObject + super({ + type: SavedWorkspaceClass.type, + mapping: SavedWorkspaceClass.mapping, + searchSource: SavedWorkspaceClass.searchSource, + extractReferences, + injectReferences, + // if this is null/undefined then the SavedObject will be assigned the defaults + id, + // default values that will get assigned if the doc is new + defaults: { + title: i18n.translate('xpack.graph.savedWorkspace.workspaceNameTitle', { + defaultMessage: 'New Graph Workspace', + }), + numLinks: 0, + numVertices: 0, + wsState: '{}', + version: 1, + }, + }); + } + // Overwrite the default getDisplayName function which uses type and which is not very + // user friendly for this object. + getDisplayName = () => { + return 'graph workspace'; + }; + } + return SavedWorkspaceClass; +} diff --git a/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.test.js b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.test.ts similarity index 91% rename from x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.test.js rename to x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.test.ts index 01eb7f9ead1f0..716520cb83aa1 100644 --- a/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.test.js +++ b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.test.ts @@ -5,6 +5,7 @@ */ import { extractReferences, injectReferences } from './saved_workspace_references'; +import { SavedWorkspace } from './saved_workspace'; describe('extractReferences', () => { test('extracts references from wsState', () => { @@ -19,6 +20,7 @@ describe('extractReferences', () => { }) ), }, + references: [], }; const updatedDoc = extractReferences(doc); expect(updatedDoc).toMatchInlineSnapshot(` @@ -48,6 +50,7 @@ Object { }) ), }, + references: [], }; expect(() => extractReferences(doc)).toThrowErrorMatchingInlineSnapshot( `"indexPattern attribute is missing in \\"wsState\\""` @@ -59,12 +62,12 @@ describe('injectReferences', () => { test('injects references into context', () => { const context = { id: '1', - foo: true, + title: 'test', wsState: JSON.stringify({ indexPatternRefName: 'indexPattern_0', bar: true, }), - }; + } as SavedWorkspace; const references = [ { name: 'indexPattern_0', @@ -75,8 +78,8 @@ describe('injectReferences', () => { injectReferences(context, references); expect(context).toMatchInlineSnapshot(` Object { - "foo": true, "id": "1", + "title": "test", "wsState": "{\\"bar\\":true,\\"indexPattern\\":\\"pattern*\\"}", } `); @@ -85,13 +88,13 @@ Object { test('skips when wsState is not a string', () => { const context = { id: '1', - foo: true, - }; + title: 'test', + } as SavedWorkspace; injectReferences(context, []); expect(context).toMatchInlineSnapshot(` Object { - "foo": true, "id": "1", + "title": "test", } `); }); @@ -100,7 +103,7 @@ Object { const context = { id: '1', wsState: JSON.stringify({ bar: true }), - }; + } as SavedWorkspace; injectReferences(context, []); expect(context).toMatchInlineSnapshot(` Object { @@ -116,7 +119,7 @@ Object { wsState: JSON.stringify({ indexPatternRefName: 'indexPattern_0', }), - }; + } as SavedWorkspace; expect(() => injectReferences(context, [])).toThrowErrorMatchingInlineSnapshot( `"Could not find reference \\"indexPattern_0\\""` ); diff --git a/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.js b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.ts similarity index 73% rename from x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.js rename to x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.ts index a1b4254685c40..3a596b8068655 100644 --- a/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.js +++ b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.ts @@ -4,9 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -export function extractReferences({ attributes, references = [] }) { +import { SavedObjectAttributes, SavedObjectReference } from 'kibana/public'; +import { SavedWorkspace } from './saved_workspace'; + +export function extractReferences({ + attributes, + references = [], +}: { + attributes: SavedObjectAttributes; + references: SavedObjectReference[]; +}) { // For some reason, wsState comes in stringified 2x - const state = JSON.parse(JSON.parse(attributes.wsState)); + const state = JSON.parse(JSON.parse(String(attributes.wsState))); const { indexPattern } = state; if (!indexPattern) { throw new Error('indexPattern attribute is missing in "wsState"'); @@ -20,7 +29,7 @@ export function extractReferences({ attributes, references = [] }) { name: 'indexPattern_0', type: 'index-pattern', id: indexPattern, - } + }, ], attributes: { ...attributes, @@ -29,7 +38,7 @@ export function extractReferences({ attributes, references = [] }) { }; } -export function injectReferences(savedObject, references) { +export function injectReferences(savedObject: SavedWorkspace, references: SavedObjectReference[]) { // Skip if wsState is missing, at the time of development of this, there is no guarantee each // saved object has wsState. if (typeof savedObject.wsState !== 'string') { @@ -41,7 +50,9 @@ export function injectReferences(savedObject, references) { if (!state.indexPatternRefName) { return; } - const indexPatternReference = references.find(reference => reference.name === state.indexPatternRefName); + const indexPatternReference = references.find( + reference => reference.name === state.indexPatternRefName + ); if (!indexPatternReference) { // Throw an error as "indexPatternRefName" means the reference exists within // "references" and in this scenario we have bad data. diff --git a/x-pack/legacy/plugins/graph/public/angular/services/saved_workspaces.js b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspaces.js deleted file mode 100644 index 1fef4b7c38c07..0000000000000 --- a/x-pack/legacy/plugins/graph/public/angular/services/saved_workspaces.js +++ /dev/null @@ -1,90 +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 chrome from 'ui/chrome'; -import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry'; -import { SavedObjectsClientProvider } from 'ui/saved_objects'; -import { i18n } from '@kbn/i18n'; - -import { SavedWorkspaceProvider } from './saved_workspace'; - - -export function SavedWorkspacesProvider(kbnUrl, Private, Promise) { - const savedObjectsClient = Private(SavedObjectsClientProvider); - const SavedWorkspace = Private(SavedWorkspaceProvider); - - this.type = SavedWorkspace.type; - this.Class = SavedWorkspace; - - this.loaderProperties = { - name: 'Graph workspace', - noun: i18n.translate('xpack.graph.savedWorkspaces.graphWorkspaceLabel', { - defaultMessage: 'Graph workspace' - }), - nouns: i18n.translate('xpack.graph.savedWorkspaces.graphWorkspacesLabel', { - defaultMessage: 'Graph workspaces' - }) - }; - - // Returns a single dashboard by ID, should be the name of the workspace - this.get = function (id) { - // Returns a promise that contains a workspace which is a subclass of docSource - return (new SavedWorkspace(id)).init(); - }; - - this.urlFor = function (id) { - return chrome.addBasePath(kbnUrl.eval('/app/graph#/workspace/{{id}}', { id })); - }; - - this.delete = function (ids) { - ids = !_.isArray(ids) ? [ids] : ids; - return Promise.map(ids, function (id) { - return (new SavedWorkspace(id)).delete(); - }); - }; - - this.mapHits = function (hit) { - const source = hit.attributes; - source.id = hit.id; - source.url = this.urlFor(hit.id); - source.icon = 'fa-share-alt';// looks like a graph - return source; - }; - - this.find = function (searchString, size = 100) { - let body; - if (searchString) { - body = { - query: { - simple_query_string: { - query: searchString + '*', - fields: ['title^3', 'description'], - default_operator: 'AND' - } - } - }; - } else { - body = { query: { match_all: {} } }; - } - - return savedObjectsClient.find({ - type: SavedWorkspace.type, - search: searchString ? `${searchString}*` : undefined, - perPage: size, - searchFields: ['title^3', 'description'] - }) - .then(resp => { - return { - total: resp.total, - hits: resp.savedObjects.map((hit) => this.mapHits(hit)) - }; - }); - }; -} - -SavedObjectRegistryProvider.register(SavedWorkspacesProvider); diff --git a/x-pack/legacy/plugins/graph/public/angular/services/saved_workspaces.ts b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspaces.ts new file mode 100644 index 0000000000000..e28bb60fb466b --- /dev/null +++ b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspaces.ts @@ -0,0 +1,76 @@ +/* + * 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 { npSetup, npStart } from 'ui/new_platform'; +import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry'; +import { i18n } from '@kbn/i18n'; + +import { createSavedWorkspaceClass } from './saved_workspace'; + +export function SavedWorkspacesProvider() { + const savedObjectsClient = npStart.core.savedObjects.client; + const services = { + savedObjectsClient, + indexPatterns: npStart.plugins.data.indexPatterns, + chrome: npStart.core.chrome, + overlays: npStart.core.overlays, + }; + + const SavedWorkspace = createSavedWorkspaceClass(services); + const urlFor = (id: string) => + npSetup.core.http.basePath.prepend(`/app/graph#/workspace/${encodeURIComponent(id)}`); + const mapHits = (hit: { id: string; attributes: Record }) => { + const source = hit.attributes; + source.id = hit.id; + source.url = urlFor(hit.id); + source.icon = 'fa-share-alt'; // looks like a graph + return source; + }; + + return { + type: SavedWorkspace.type, + Class: SavedWorkspace, + loaderProperties: { + name: 'Graph workspace', + noun: i18n.translate('xpack.graph.savedWorkspaces.graphWorkspaceLabel', { + defaultMessage: 'Graph workspace', + }), + nouns: i18n.translate('xpack.graph.savedWorkspaces.graphWorkspacesLabel', { + defaultMessage: 'Graph workspaces', + }), + }, + // Returns a single dashboard by ID, should be the name of the workspace + get: (id: string) => { + // Returns a promise that contains a workspace which is a subclass of docSource + // @ts-ignore + return new SavedWorkspace(id).init(); + }, + urlFor, + delete: (ids: string | string[]) => { + const idArr = Array.isArray(ids) ? ids : [ids]; + return Promise.all( + idArr.map((id: string) => savedObjectsClient.delete(SavedWorkspace.type, id)) + ); + }, + find: (searchString: string, size: number = 100) => { + return savedObjectsClient + .find({ + type: SavedWorkspace.type, + search: searchString ? `${searchString}*` : undefined, + perPage: size, + searchFields: ['title^3', 'description'], + }) + .then(resp => { + return { + total: resp.total, + hits: resp.savedObjects.map(hit => mapHits(hit)), + }; + }); + }, + }; +} + +SavedObjectRegistryProvider.register(SavedWorkspacesProvider); diff --git a/x-pack/legacy/plugins/graph/public/index.ts b/x-pack/legacy/plugins/graph/public/index.ts index e0ce210328897..600df6d309784 100644 --- a/x-pack/legacy/plugins/graph/public/index.ts +++ b/x-pack/legacy/plugins/graph/public/index.ts @@ -17,6 +17,7 @@ import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_regis import { npSetup, npStart } from 'ui/new_platform'; import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { start as navigation } from '../../../../../src/legacy/core_plugins/navigation/public/legacy'; +import { LicensingPluginSetup } from '../../../../plugins/licensing/public'; import { GraphPlugin } from './plugin'; // @ts-ignore @@ -39,13 +40,17 @@ async function getAngularInjectedDependencies(): Promise { const instance = new GraphPlugin(); instance.setup(npSetup.core, { __LEGACY: { Storage, }, - ...npSetup.plugins, + ...(npSetup.plugins as XpackNpSetupDeps), }); instance.start(npStart.core, { npData: npStart.plugins.data, diff --git a/x-pack/legacy/plugins/graph/public/plugin.ts b/x-pack/legacy/plugins/graph/public/plugin.ts index 4319775147610..1646cf200e374 100644 --- a/x-pack/legacy/plugins/graph/public/plugin.ts +++ b/x-pack/legacy/plugins/graph/public/plugin.ts @@ -9,7 +9,7 @@ import { CoreSetup, CoreStart, Plugin, SavedObjectsClientContract } from 'src/co import { Plugin as DataPlugin } from 'src/plugins/data/public'; import { LegacyAngularInjectedDependencies } from './render_app'; import { NavigationStart } from '../../../../../src/legacy/core_plugins/navigation/public'; -import { LicensingPluginSetup } from '../../../../plugins/licensing/common/types'; +import { LicensingPluginSetup } from '../../../../plugins/licensing/public'; export interface GraphPluginStartDependencies { npData: ReturnType; diff --git a/x-pack/legacy/plugins/graph/public/render_app.ts b/x-pack/legacy/plugins/graph/public/render_app.ts index 2cad8f629f2ab..b07a91e6d6328 100644 --- a/x-pack/legacy/plugins/graph/public/render_app.ts +++ b/x-pack/legacy/plugins/graph/public/render_app.ts @@ -38,7 +38,7 @@ import { IndexPatternsContract, } from '../../../../../src/plugins/data/public'; import { NavigationStart } from '../../../../../src/legacy/core_plugins/navigation/public'; -import { LicensingPluginSetup } from '../../../../plugins/licensing/common/types'; +import { LicensingPluginSetup } from '../../../../plugins/licensing/public'; import { checkLicense } from '../../../../plugins/graph/common/check_license'; /** diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.tsx index cdde03d7e9f56..05dcafcaeba31 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.tsx @@ -162,7 +162,7 @@ export function InnerWorkspacePanel({

{ onChangeIndexPattern(newId); diff --git a/x-pack/legacy/plugins/siem/server/plugin.ts b/x-pack/legacy/plugins/siem/server/plugin.ts index 533b6c23088ec..25fa3bd6cde4c 100644 --- a/x-pack/legacy/plugins/siem/server/plugin.ts +++ b/x-pack/legacy/plugins/siem/server/plugin.ts @@ -45,17 +45,24 @@ export class Plugin { catalogue: ['siem'], privileges: { all: { - api: ['siem'], + api: ['siem', 'actions-read', 'actions-all', 'alerting-read', 'alerting-all'], savedObject: { - all: [noteSavedObjectType, pinnedEventSavedObjectType, timelineSavedObjectType], + all: [ + 'alert', + 'action', + 'action_task_params', + noteSavedObjectType, + pinnedEventSavedObjectType, + timelineSavedObjectType, + ], read: ['config'], }, ui: ['show'], }, read: { - api: ['siem'], + api: ['siem', 'actions-read', 'actions-all', 'alerting-read', 'alerting-all'], savedObject: { - all: [], + all: ['alert', 'action', 'action_task_params'], read: [ 'config', noteSavedObjectType, diff --git a/x-pack/legacy/plugins/uptime/common/runtime_types/common.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/common.ts new file mode 100644 index 0000000000000..84e3ae33294f0 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/common.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 * as t from 'io-ts'; + +export const LocationType = t.partial({ + lat: t.string, + lon: t.string, +}); + +export const CheckGeoType = t.partial({ + name: t.string, + location: LocationType, +}); + +export const SummaryType = t.partial({ + up: t.number, + down: t.number, + geo: CheckGeoType, +}); + +export type Summary = t.TypeOf; +export type CheckGeo = t.TypeOf; +export type Location = t.TypeOf; diff --git a/x-pack/legacy/plugins/uptime/common/runtime_types/index.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/index.ts index a88e28f2e5a09..224892eb91783 100644 --- a/x-pack/legacy/plugins/uptime/common/runtime_types/index.ts +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/index.ts @@ -4,5 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +export * from './common'; export * from './snapshot'; export * from './monitor/monitor_details'; +export * from './monitor/monitor_locations'; diff --git a/x-pack/legacy/plugins/uptime/common/runtime_types/monitor/monitor_locations.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/monitor/monitor_locations.ts new file mode 100644 index 0000000000000..a40453b3671b7 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/monitor/monitor_locations.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 * as t from 'io-ts'; +import { CheckGeoType, SummaryType } from '../common'; + +// IO type for validation +export const MonitorLocationType = t.partial({ + summary: SummaryType, + geo: CheckGeoType, +}); + +// Typescript type for type checking +export type MonitorLocation = t.TypeOf; + +export const MonitorLocationsType = t.intersection([ + t.type({ monitorId: t.string }), + t.partial({ locations: t.array(MonitorLocationType) }), +]); +export type MonitorLocations = t.TypeOf; diff --git a/x-pack/legacy/plugins/uptime/public/apps/index.ts b/x-pack/legacy/plugins/uptime/public/apps/index.ts index 53a74022778f4..06776842aa6de 100644 --- a/x-pack/legacy/plugins/uptime/public/apps/index.ts +++ b/x-pack/legacy/plugins/uptime/public/apps/index.ts @@ -7,6 +7,7 @@ import chrome from 'ui/chrome'; import { npStart } from 'ui/new_platform'; import { Plugin } from './plugin'; +import 'uiExports/embeddableFactories'; new Plugin( { opaqueId: Symbol('uptime'), env: {} as any, config: { get: () => ({} as any) } }, diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_status.bar.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_status.bar.test.tsx.snap index 204dcdbe5b516..4fda42e510bba 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_status.bar.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_status.bar.test.tsx.snap @@ -2,71 +2,67 @@ exports[`MonitorStatusBar component renders duration in ms, not us 1`] = `
-
- -
-
- Up -
+
-
-
-
+
+
- 1234ms -
-
+
+ 1234ms +
+
+ 15 minutes ago +
`; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/__mocks__/mock.ts b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/__mocks__/mock.ts new file mode 100644 index 0000000000000..9b902651690bf --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/__mocks__/mock.ts @@ -0,0 +1,185 @@ +/* + * 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 lowPolyLayerFeatures from '../low_poly_layer.json'; + +export const mockDownPointsLayer = { + id: 'down_points', + label: 'Down Locations', + sourceDescriptor: { + type: 'GEOJSON_FILE', + __featureCollection: { + features: [ + { + type: 'feature', + geometry: { + type: 'Point', + coordinates: [13.399262, 52.487239], + }, + }, + { + type: 'feature', + geometry: { + type: 'Point', + coordinates: [13.399262, 55.487239], + }, + }, + { + type: 'feature', + geometry: { + type: 'Point', + coordinates: [14.399262, 54.487239], + }, + }, + ], + type: 'FeatureCollection', + }, + }, + visible: true, + style: { + type: 'VECTOR', + properties: { + fillColor: { + type: 'STATIC', + options: { + color: '#BC261E', + }, + }, + lineColor: { + type: 'STATIC', + options: { + color: '#fff', + }, + }, + lineWidth: { + type: 'STATIC', + options: { + size: 2, + }, + }, + iconSize: { + type: 'STATIC', + options: { + size: 6, + }, + }, + }, + }, + type: 'VECTOR', +}; + +export const mockUpPointsLayer = { + id: 'up_points', + label: 'Up Locations', + sourceDescriptor: { + type: 'GEOJSON_FILE', + __featureCollection: { + features: [ + { + type: 'feature', + geometry: { + type: 'Point', + coordinates: [13.399262, 52.487239], + }, + }, + { + type: 'feature', + geometry: { + type: 'Point', + coordinates: [13.399262, 55.487239], + }, + }, + { + type: 'feature', + geometry: { + type: 'Point', + coordinates: [14.399262, 54.487239], + }, + }, + ], + type: 'FeatureCollection', + }, + }, + visible: true, + style: { + type: 'VECTOR', + properties: { + fillColor: { + type: 'STATIC', + options: { + color: '#98A2B2', + }, + }, + lineColor: { + type: 'STATIC', + options: { + color: '#fff', + }, + }, + lineWidth: { + type: 'STATIC', + options: { + size: 2, + }, + }, + iconSize: { + type: 'STATIC', + options: { + size: 6, + }, + }, + }, + }, + type: 'VECTOR', +}; + +export const mockLayerList = [ + { + id: 'low_poly_layer', + label: 'World countries', + minZoom: 0, + maxZoom: 24, + alpha: 1, + sourceDescriptor: { + id: 'b7486535-171b-4d3b-bb2e-33c1a0a2854c', + type: 'GEOJSON_FILE', + __featureCollection: lowPolyLayerFeatures, + }, + visible: true, + style: { + type: 'VECTOR', + properties: { + fillColor: { + type: 'STATIC', + options: { + color: '#cad3e4', + }, + }, + lineColor: { + type: 'STATIC', + options: { + color: '#fff', + }, + }, + lineWidth: { + type: 'STATIC', + options: { + size: 0, + }, + }, + iconSize: { + type: 'STATIC', + options: { + size: 6, + }, + }, + }, + }, + type: 'VECTOR', + }, + mockDownPointsLayer, + mockUpPointsLayer, +]; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/embedded_map.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/embedded_map.tsx new file mode 100644 index 0000000000000..a5578d9e05667 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/embedded_map.tsx @@ -0,0 +1,102 @@ +/* + * 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, { useEffect, useState } from 'react'; +import uuid from 'uuid'; +import styled from 'styled-components'; + +import { start } from '../../../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public/legacy'; +import * as i18n from './translations'; +// @ts-ignore +import { MAP_SAVED_OBJECT_TYPE } from '../../../../../../maps/common/constants'; + +import { MapEmbeddable } from './types'; +import { getLayerList } from './map_config'; + +export interface EmbeddedMapProps { + upPoints: LocationPoint[]; + downPoints: LocationPoint[]; +} + +export interface LocationPoint { + lat: string; + lon: string; +} + +const EmbeddedPanel = styled.div` + z-index: auto; + flex: 1; + display: flex; + flex-direction: column; + height: 100%; + position: relative; + .embPanel__content { + display: flex; + flex: 1 1 100%; + z-index: 1; + min-height: 0; // Absolute must for Firefox to scroll contents + } + &&& .mapboxgl-canvas { + animation: none !important; + } +`; + +export const EmbeddedMap = ({ upPoints, downPoints }: EmbeddedMapProps) => { + const [embeddable, setEmbeddable] = useState(); + + useEffect(() => { + async function setupEmbeddable() { + const mapState = { + layerList: getLayerList(upPoints, downPoints), + title: i18n.MAP_TITLE, + }; + // @ts-ignore + const embeddableObject = await factory.createFromState(mapState, input, undefined); + + setEmbeddable(embeddableObject); + } + setupEmbeddable(); + }, []); + + useEffect(() => { + if (embeddable) { + embeddable.setLayerList(getLayerList(upPoints, downPoints)); + } + }, [upPoints, downPoints]); + + useEffect(() => { + if (embeddableRoot.current && embeddable) { + embeddable.render(embeddableRoot.current); + } + }, [embeddable]); + + const factory = start.getEmbeddableFactory(MAP_SAVED_OBJECT_TYPE); + + const input = { + id: uuid.v4(), + filters: [], + hidePanelTitles: true, + query: { query: '', language: 'kuery' }, + refreshConfig: { value: 0, pause: false }, + viewMode: 'view', + isLayerTOCOpen: false, + hideFilterActions: true, + mapCenter: { lon: 11, lat: 47, zoom: 0 }, + disableInteractive: true, + disableTooltipControl: true, + hideToolbarOverlay: true, + }; + + const embeddableRoot: React.RefObject = React.createRef(); + + return ( + +
+ + ); +}; + +EmbeddedMap.displayName = 'EmbeddedMap'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/low_poly_layer.json b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/low_poly_layer.json new file mode 100644 index 0000000000000..7a309cd01ebc7 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/low_poly_layer.json @@ -0,0 +1,2898 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [ + "34.21666", + "31.32333" + ], + [ + "35.98361", + "34.52750" + ], + [ + "34.65943", + "36.80527" + ], + [ + "32.77166", + "36.02888" + ], + [ + "29.67722", + "36.11833" + ], + [ + "27.25500", + "36.96500" + ], + [ + "27.51166", + "40.30555" + ], + [ + "33.33860", + "42.01985" + ], + [ + "38.35582", + "40.91027" + ], + [ + "41.77609", + "41.84193" + ], + [ + "41.59748", + "43.22151" + ], + [ + "45.16512", + "42.70333" + ], + [ + "47.91547", + "41.22499" + ], + [ + "49.76062", + "42.71076" + ], + [ + "49.44831", + "45.53038" + ], + [ + "47.30249", + "50.03194" + ], + [ + "52.34180", + "51.78075" + ], + [ + "55.69249", + "50.53249" + ], + [ + "58.33777", + "51.15610" + ], + [ + "57.97027", + "54.38819" + ], + [ + "59.64166", + "55.55867" + ], + [ + "57.22169", + "56.85096" + ], + [ + "59.44912", + "58.48804" + ], + [ + "59.57756", + "63.93287" + ], + [ + "66.10887", + "67.48123" + ], + [ + "64.52222", + "68.90305" + ], + [ + "67.05498", + "68.85637" + ], + [ + "69.32735", + "72.94540" + ], + [ + "73.52553", + "71.81582" + ], + [ + "80.82610", + "72.08693" + ], + [ + "80.51860", + "73.57346" + ], + [ + "89.25278", + "75.50305" + ], + [ + "97.18359", + "75.92804" + ], + [ + "104.07138", + "77.73221" + ], + [ + "111.10387", + "76.75526" + ], + [ + "113.47054", + "73.50096" + ], + [ + "118.63443", + "73.57166" + ], + [ + "131.53580", + "70.87776" + ], + [ + "137.45190", + "71.34109" + ], + [ + "141.02414", + "72.58582" + ], + [ + "149.18524", + "72.22249" + ], + [ + "152.53830", + "70.83777" + ], + [ + "159.72968", + "69.83472" + ], + [ + "170.61194", + "68.75633" + ], + [ + "170.47189", + "70.13416" + ], + [ + "180.00000", + "68.98010" + ], + [ + "180.00000", + "65.06891" + ], + [ + "179.55373", + "62.61971" + ], + [ + "173.54178", + "61.74430" + ], + [ + "170.64194", + "60.41750" + ], + [ + "163.36023", + "59.82388" + ], + [ + "161.93858", + "58.06763" + ], + [ + "163.34996", + "56.19596" + ], + [ + "156.74524", + "51.07791" + ], + [ + "155.54413", + "55.30360" + ], + [ + "155.94206", + "56.65353" + ], + [ + "161.91248", + "60.41972" + ], + [ + "159.24747", + "61.92222" + ], + [ + "152.35718", + "59.02332" + ], + [ + "143.21109", + "59.37666" + ], + [ + "137.72580", + "56.17500" + ], + [ + "137.29327", + "54.07500" + ], + [ + "141.41483", + "53.29361" + ], + [ + "140.17609", + "48.45013" + ], + [ + "135.42233", + "43.75611" + ], + [ + "133.15485", + "42.68263" + ], + [ + "131.81052", + "43.32555" + ], + [ + "129.70204", + "40.83069" + ], + [ + "127.51763", + "39.73957" + ], + [ + "129.42944", + "37.05986" + ], + [ + "129.23749", + "35.18990" + ], + [ + "126.37556", + "34.79138" + ], + [ + "126.38860", + "37.88721" + ], + [ + "124.32395", + "39.91589" + ], + [ + "121.64804", + "38.99638" + ], + [ + "121.17747", + "40.92194" + ], + [ + "118.11053", + "38.14639" + ], + [ + "120.82054", + "36.64527" + ], + [ + "120.24873", + "34.31145" + ], + [ + "121.84693", + "30.85305" + ], + [ + "120.93526", + "27.98222" + ], + [ + "119.58074", + "25.67996" + ], + [ + "116.48172", + "22.93902" + ], + [ + "112.28194", + "21.70139" + ], + [ + "107.36693", + "21.26527" + ], + [ + "105.63857", + "18.89065" + ], + [ + "108.82916", + "15.42194" + ], + [ + "109.46186", + "12.86097" + ], + [ + "109.02168", + "11.36225" + ], + [ + "104.79893", + "8.79222" + ], + [ + "104.98177", + "10.10444" + ], + [ + "100.97635", + "13.46281" + ], + [ + "99.15082", + "10.36472" + ], + [ + "100.57809", + "7.22014" + ], + [ + "103.18192", + "5.28278" + ], + [ + "103.37455", + "1.53347" + ], + [ + "101.28574", + "2.84354" + ], + [ + "100.35553", + "5.96389" + ], + [ + "98.27415", + "8.27444" + ], + [ + "98.74720", + "11.67486" + ], + [ + "97.72457", + "15.84666" + ], + [ + "95.42859", + "15.72972" + ], + [ + "93.72436", + "19.93243" + ], + [ + "91.70444", + "22.48055" + ], + [ + "86.96332", + "21.38194" + ], + [ + "86.42123", + "19.98493" + ], + [ + "80.27943", + "15.69917" + ], + [ + "79.85811", + "10.28583" + ], + [ + "76.99860", + "8.36527" + ], + [ + "74.85526", + "12.75500" + ], + [ + "73.44748", + "16.05861" + ], + [ + "72.56485", + "21.37506" + ], + [ + "70.82513", + "20.69597" + ], + [ + "66.50005", + "25.40381" + ], + [ + "61.76083", + "25.03208" + ], + [ + "57.31909", + "25.77146" + ], + [ + "56.80888", + "27.12361" + ], + [ + "54.78846", + "26.49041" + ], + [ + "51.43027", + "27.93777" + ], + [ + "50.63916", + "29.47042" + ], + [ + "47.95943", + "30.03305" + ], + [ + "48.83887", + "27.61972" + ], + [ + "51.28236", + "24.30000" + ], + [ + "53.58777", + "24.04417" + ], + [ + "55.85944", + "25.72042" + ], + [ + "57.17131", + "23.93444" + ], + [ + "59.82861", + "22.29166" + ], + [ + "57.80569", + "18.97097" + ], + [ + "55.03194", + "17.01472" + ], + [ + "52.18916", + "15.60528" + ], + [ + "45.04232", + "12.75239" + ], + [ + "43.47888", + "12.67500" + ], + [ + "42.78933", + "16.46083" + ], + [ + "40.75694", + "19.76417" + ], + [ + "39.17486", + "21.10402" + ], + [ + "39.06277", + "22.58333" + ], + [ + "35.16055", + "28.05666" + ], + [ + "34.21666", + "31.32333" + ] + ] + ], + [ + [ + [ + "-169.69496", + "66.06806" + ], + [ + "-173.67308", + "64.34679" + ], + [ + "-179.32083", + "65.53012" + ], + [ + "-180.00000", + "65.06891" + ], + [ + "-180.00000", + "68.98010" + ], + [ + "-169.69496", + "66.06806" + ] + ] + ], + [ + [ + [ + "139.93851", + "40.42860" + ], + [ + "142.06970", + "39.54666" + ], + [ + "140.95358", + "38.14805" + ], + [ + "140.33218", + "35.12985" + ], + [ + "137.02879", + "34.56784" + ], + [ + "136.71246", + "36.75139" + ], + [ + "139.42622", + "38.15458" + ], + [ + "139.93851", + "40.42860" + ] + ] + ], + [ + [ + [ + "119.89259", + "15.80112" + ], + [ + "120.58527", + "18.51139" + ], + [ + "122.51833", + "17.04389" + ], + [ + "121.38026", + "15.30250" + ], + [ + "119.89259", + "15.80112" + ] + ] + ], + [ + [ + [ + "122.32916", + "7.30833" + ], + [ + "126.18610", + "9.24277" + ], + [ + "125.37762", + "6.72361" + ], + [ + "123.45888", + "7.81055" + ], + [ + "122.32916", + "7.30833" + ] + ] + ], + [ + [ + [ + "111.89638", + "-3.57389" + ], + [ + "110.23193", + "-2.97111" + ], + [ + "108.84549", + "0.81056" + ], + [ + "109.64857", + "2.07341" + ], + [ + "113.01054", + "3.16055" + ], + [ + "115.37886", + "4.91167" + ], + [ + "116.75417", + "7.01805" + ], + [ + "119.27582", + "5.34500" + ], + [ + "117.27540", + "3.22000" + ], + [ + "117.87192", + "1.87667" + ], + [ + "117.44479", + "-0.52397" + ], + [ + "115.96624", + "-3.60875" + ], + [ + "113.03471", + "-2.98972" + ], + [ + "111.89638", + "-3.57389" + ] + ] + ], + [ + [ + [ + "102.97601", + "0.64348" + ], + [ + "103.36081", + "-0.70222" + ], + [ + "106.05525", + "-3.03139" + ], + [ + "105.72887", + "-5.89826" + ], + [ + "102.32610", + "-4.00611" + ], + [ + "100.90555", + "-2.31944" + ], + [ + "98.70383", + "1.55979" + ], + [ + "95.53108", + "4.68278" + ], + [ + "97.51483", + "5.24944" + ], + [ + "100.41219", + "2.29306" + ], + [ + "102.97601", + "0.64348" + ] + ] + ], + [ + [ + [ + "120.82723", + "1.23406" + ], + [ + "120.01999", + "-0.07528" + ], + [ + "122.47623", + "-3.16090" + ], + [ + "120.32888", + "-5.51208" + ], + [ + "119.35491", + "-5.40007" + ], + [ + "118.88860", + "-2.89319" + ], + [ + "119.77805", + "0.22972" + ], + [ + "120.82723", + "1.23406" + ] + ] + ], + [ + [ + [ + "136.04913", + "-2.69806" + ], + [ + "137.87579", + "-1.47306" + ], + [ + "144.51373", + "-3.82222" + ], + [ + "145.76639", + "-5.48528" + ], + [ + "147.46661", + "-5.97086" + ], + [ + "146.08969", + "-8.09111" + ], + [ + "144.21738", + "-7.79465" + ], + [ + "143.36510", + "-9.01222" + ], + [ + "141.11996", + "-9.23097" + ], + [ + "139.09454", + "-7.56181" + ], + [ + "138.06525", + "-5.40896" + ], + [ + "135.20468", + "-4.45972" + ], + [ + "132.72275", + "-2.81722" + ], + [ + "131.25555", + "-0.82278" + ], + [ + "134.02950", + "-0.96694" + ], + [ + "134.99495", + "-3.33653" + ], + [ + "136.04913", + "-2.69806" + ] + ] + ], + [ + [ + [ + "110.05640", + "-7.89751" + ], + [ + "106.56721", + "-7.41694" + ], + [ + "106.07582", + "-5.88194" + ], + [ + "110.39360", + "-6.97903" + ], + [ + "110.05640", + "-7.89751" + ] + ] + ] + ] + }, + "properties": { + "CONTINENT": "Asia" + } + }, + { + "type": "Feature", + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [ + "-25.28167", + "71.39166" + ], + [ + "-23.56056", + "70.10609" + ], + [ + "-26.36333", + "68.66748" + ], + [ + "-31.99916", + "68.09526" + ], + [ + "-34.71999", + "66.33832" + ], + [ + "-41.15541", + "64.96235" + ], + [ + "-43.08722", + "60.10027" + ], + [ + "-47.68986", + "61.00680" + ], + [ + "-50.31562", + "62.49430" + ], + [ + "-53.23333", + "65.68283" + ], + [ + "-53.62778", + "67.81470" + ], + [ + "-50.58930", + "69.92373" + ], + [ + "-54.68694", + "72.36721" + ], + [ + "-58.15958", + "75.50860" + ], + [ + "-68.50056", + "76.08693" + ], + [ + "-72.55222", + "78.52110" + ], + [ + "-60.80666", + "81.87997" + ], + [ + "-30.38833", + "83.60220" + ], + [ + "-16.00500", + "80.72859" + ], + [ + "-22.03695", + "77.68568" + ], + [ + "-19.33681", + "75.40207" + ], + [ + "-24.46305", + "73.53581" + ], + [ + "-25.28167", + "71.39166" + ] + ] + ], + [ + [ + [ + "-87.64890", + "76.33804" + ], + [ + "-86.47916", + "79.76167" + ], + [ + "-90.43666", + "81.88750" + ], + [ + "-70.26001", + "83.11388" + ], + [ + "-61.07639", + "82.32083" + ], + [ + "-78.78194", + "76.57221" + ], + [ + "-87.64890", + "76.33804" + ] + ] + ], + [ + [ + [ + "-123.83389", + "73.70027" + ], + [ + "-115.31903", + "73.47707" + ], + [ + "-123.29306", + "71.14610" + ], + [ + "-123.83389", + "73.70027" + ] + ] + ], + [ + [ + [ + "-65.32806", + "62.66610" + ], + [ + "-68.61583", + "62.26389" + ], + [ + "-77.33667", + "65.17609" + ], + [ + "-72.25835", + "67.24803" + ], + [ + "-77.30506", + "69.83395" + ], + [ + "-85.87465", + "70.07943" + ], + [ + "-89.90348", + "71.35304" + ], + [ + "-89.03958", + "73.25499" + ], + [ + "-81.57251", + "73.71971" + ], + [ + "-67.21986", + "69.94081" + ], + [ + "-67.23819", + "68.35790" + ], + [ + "-61.26458", + "66.62609" + ], + [ + "-65.56204", + "64.73154" + ], + [ + "-65.32806", + "62.66610" + ] + ] + ], + [ + [ + [ + "-105.02444", + "72.21999" + ], + [ + "-100.99973", + "70.17276" + ], + [ + "-101.85139", + "68.98442" + ], + [ + "-113.04173", + "68.49374" + ], + [ + "-116.53221", + "69.40887" + ], + [ + "-119.13445", + "71.77457" + ], + [ + "-114.66666", + "73.37247" + ], + [ + "-105.02444", + "72.21999" + ] + ] + ], + [ + [ + [ + "-77.36667", + "8.67500" + ], + [ + "-77.88972", + "7.22889" + ], + [ + "-79.69778", + "8.86666" + ], + [ + "-81.73862", + "8.16250" + ], + [ + "-85.65668", + "9.90500" + ], + [ + "-85.66959", + "11.05500" + ], + [ + "-87.93779", + "13.15639" + ], + [ + "-91.38474", + "13.97889" + ], + [ + "-93.93861", + "16.09389" + ], + [ + "-96.47612", + "15.64361" + ], + [ + "-103.45001", + "18.31361" + ], + [ + "-105.67834", + "20.38305" + ], + [ + "-105.18945", + "21.43750" + ], + [ + "-106.91570", + "23.86514" + ], + [ + "-109.43750", + "25.82027" + ], + [ + "-109.44431", + "26.71555" + ], + [ + "-112.16195", + "28.97139" + ], + [ + "-113.09167", + "31.22972" + ], + [ + "-115.69667", + "29.77423" + ], + [ + "-117.40944", + "33.24416" + ], + [ + "-120.60583", + "34.55860" + ], + [ + "-124.33118", + "40.27246" + ], + [ + "-124.52444", + "42.86610" + ], + [ + "-123.87161", + "45.52898" + ], + [ + "-124.71431", + "48.39708" + ], + [ + "-124.03510", + "49.91801" + ], + [ + "-127.17315", + "50.92221" + ], + [ + "-130.88640", + "55.70791" + ], + [ + "-133.81302", + "57.97293" + ], + [ + "-136.65891", + "58.21652" + ], + [ + "-140.40335", + "59.69804" + ], + [ + "-146.75543", + "60.95249" + ], + [ + "-154.23567", + "58.13069" + ], + [ + "-157.55139", + "58.38777" + ], + [ + "-165.42244", + "60.55215" + ], + [ + "-164.40112", + "63.21499" + ], + [ + "-168.13196", + "65.66296" + ], + [ + "-161.66779", + "67.02054" + ], + [ + "-166.82362", + "68.34873" + ], + [ + "-156.59673", + "71.35144" + ], + [ + "-151.22986", + "70.37296" + ], + [ + "-143.21555", + "70.11026" + ], + [ + "-137.25500", + "68.94832" + ], + [ + "-127.18096", + "70.27638" + ], + [ + "-114.06652", + "68.46970" + ], + [ + "-112.39584", + "67.67915" + ], + [ + "-98.11124", + "67.83887" + ], + [ + "-90.43639", + "68.87442" + ], + [ + "-85.55499", + "69.85970" + ], + [ + "-81.33570", + "69.18498" + ], + [ + "-81.50222", + "67.00096" + ], + [ + "-85.89726", + "66.16802" + ], + [ + "-87.98736", + "64.18845" + ], + [ + "-92.71001", + "62.46583" + ], + [ + "-94.78972", + "59.09222" + ], + [ + "-92.41875", + "57.33270" + ], + [ + "-88.81500", + "56.82444" + ], + [ + "-85.00195", + "55.29666" + ], + [ + "-82.30777", + "55.14888" + ], + [ + "-82.27390", + "52.95638" + ], + [ + "-78.57945", + "52.11138" + ], + [ + "-79.76181", + "54.65166" + ], + [ + "-76.67979", + "56.03645" + ], + [ + "-78.57299", + "58.62888" + ], + [ + "-77.50835", + "62.56166" + ], + [ + "-73.68346", + "62.47999" + ], + [ + "-70.14848", + "61.08458" + ], + [ + "-67.56610", + "58.22360" + ], + [ + "-64.74538", + "60.23075" + ], + [ + "-61.09055", + "55.84415" + ], + [ + "-57.34969", + "54.57496" + ], + [ + "-56.95160", + "51.42458" + ], + [ + "-60.00500", + "50.24888" + ], + [ + "-66.44903", + "50.26777" + ], + [ + "-64.21167", + "48.88499" + ], + [ + "-64.90430", + "46.84597" + ], + [ + "-63.66708", + "45.81666" + ], + [ + "-70.19187", + "43.57555" + ], + [ + "-70.72610", + "41.72777" + ], + [ + "-74.13390", + "40.70082" + ], + [ + "-75.96083", + "37.15221" + ], + [ + "-76.34326", + "34.88194" + ], + [ + "-78.82750", + "33.73027" + ], + [ + "-81.48843", + "31.11347" + ], + [ + "-80.03534", + "26.79569" + ], + [ + "-81.73659", + "25.95944" + ], + [ + "-84.01098", + "30.09764" + ], + [ + "-88.98083", + "30.41833" + ], + [ + "-94.75417", + "29.36791" + ], + [ + "-97.56041", + "26.84208" + ], + [ + "-97.74223", + "22.01250" + ], + [ + "-95.80112", + "18.74500" + ], + [ + "-94.46918", + "18.14625" + ], + [ + "-90.73167", + "19.36153" + ], + [ + "-90.27972", + "21.06305" + ], + [ + "-86.82973", + "21.42923" + ], + [ + "-88.28250", + "17.62389" + ], + [ + "-88.13696", + "15.68285" + ], + [ + "-84.26015", + "15.82597" + ], + [ + "-83.18695", + "14.32389" + ], + [ + "-83.84751", + "11.17458" + ], + [ + "-82.24278", + "9.00236" + ], + [ + "-79.53445", + "9.62014" + ], + [ + "-77.36667", + "8.67500" + ] + ] + ], + [ + [ + [ + "-55.19333", + "46.98499" + ], + [ + "-59.40361", + "47.89423" + ], + [ + "-56.68250", + "51.33943" + ], + [ + "-55.56114", + "49.36818" + ], + [ + "-52.83465", + "48.09965" + ], + [ + "-55.19333", + "46.98499" + ] + ] + ], + [ + [ + [ + "-73.03644", + "18.45622" + ], + [ + "-72.79834", + "19.94278" + ], + [ + "-69.94932", + "19.67680" + ], + [ + "-68.89528", + "18.39639" + ], + [ + "-73.03644", + "18.45622" + ] + ] + ] + ] + }, + "properties": { + "CONTINENT": "North America" + } + }, + { + "type": "Feature", + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [ + "64.52222", + "68.90305" + ], + [ + "66.10887", + "67.48123" + ], + [ + "59.57756", + "63.93287" + ], + [ + "59.44912", + "58.48804" + ], + [ + "57.22169", + "56.85096" + ], + [ + "59.64166", + "55.55867" + ], + [ + "57.97027", + "54.38819" + ], + [ + "58.33777", + "51.15610" + ], + [ + "55.69249", + "50.53249" + ], + [ + "52.34180", + "51.78075" + ], + [ + "47.30249", + "50.03194" + ], + [ + "49.44831", + "45.53038" + ], + [ + "49.76062", + "42.71076" + ], + [ + "47.91547", + "41.22499" + ], + [ + "45.16512", + "42.70333" + ], + [ + "41.59748", + "43.22151" + ], + [ + "39.94553", + "43.39693" + ], + [ + "34.70249", + "46.17582" + ], + [ + "30.83277", + "46.54832" + ], + [ + "28.78083", + "44.66096" + ], + [ + "28.01305", + "41.98222" + ], + [ + "26.36041", + "40.95388" + ], + [ + "22.59500", + "40.01221" + ], + [ + "23.96055", + "38.28166" + ], + [ + "22.15246", + "37.01854" + ], + [ + "19.30721", + "40.64531" + ], + [ + "19.59771", + "41.80611" + ], + [ + "15.15167", + "44.19639" + ], + [ + "13.02958", + "41.26014" + ], + [ + "8.74722", + "44.42805" + ], + [ + "6.16528", + "43.05055" + ], + [ + "4.05625", + "43.56277" + ], + [ + "3.20167", + "41.89278" + ], + [ + "0.99306", + "41.04805" + ], + [ + "0.20722", + "38.73221" + ], + [ + "-2.12292", + "36.73347" + ], + [ + "-5.61361", + "36.00610" + ], + [ + "-6.95992", + "37.22184" + ], + [ + "-8.98924", + "37.02631" + ], + [ + "-9.49083", + "38.79388" + ], + [ + "-8.66014", + "40.69111" + ], + [ + "-9.16972", + "43.18583" + ], + [ + "-1.44389", + "43.64055" + ], + [ + "-1.11463", + "46.31658" + ], + [ + "-2.68528", + "48.50166" + ], + [ + "1.43875", + "50.10083" + ], + [ + "5.59917", + "53.30028" + ], + [ + "13.80854", + "53.85479" + ], + [ + "21.24506", + "54.95506" + ], + [ + "21.05223", + "56.81749" + ], + [ + "23.43159", + "59.95382" + ], + [ + "21.42416", + "60.57930" + ], + [ + "21.58500", + "64.43971" + ], + [ + "17.09861", + "61.60278" + ], + [ + "19.07264", + "59.73819" + ], + [ + "16.37982", + "56.66333" + ], + [ + "12.46007", + "56.29666" + ], + [ + "10.51569", + "59.30624" + ], + [ + "8.12750", + "58.09888" + ], + [ + "5.50847", + "58.66764" + ], + [ + "4.94944", + "61.41041" + ], + [ + "9.54528", + "63.76611" + ], + [ + "15.28833", + "68.03055" + ], + [ + "21.30000", + "70.24693" + ], + [ + "28.20778", + "71.07999" + ], + [ + "32.80605", + "69.30277" + ], + [ + "43.75180", + "67.31152" + ], + [ + "53.60437", + "68.90818" + ], + [ + "64.52222", + "68.90305" + ] + ] + ], + [ + [ + [ + "-13.49944", + "65.06915" + ], + [ + "-18.77500", + "63.39139" + ], + [ + "-22.04556", + "64.04666" + ], + [ + "-22.42167", + "66.43332" + ], + [ + "-16.41736", + "66.27603" + ], + [ + "-13.49944", + "65.06915" + ] + ] + ], + [ + [ + [ + "-4.19667", + "57.48583" + ], + [ + "-0.07931", + "54.11340" + ], + [ + "0.25389", + "50.73861" + ], + [ + "-3.43722", + "50.60500" + ], + [ + "-4.19639", + "53.20611" + ], + [ + "-2.89979", + "53.72499" + ], + [ + "-6.22778", + "56.69722" + ], + [ + "-4.19667", + "57.48583" + ] + ] + ], + [ + [ + [ + "12.44167", + "37.80611" + ], + [ + "15.64794", + "38.26458" + ], + [ + "15.08139", + "36.64916" + ], + [ + "12.44167", + "37.80611" + ] + ] + ] + ] + }, + "properties": { + "CONTINENT": "Europe" + } + }, + { + "type": "Feature", + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [ + "34.21666", + "31.32333" + ], + [ + "34.90380", + "29.48671" + ], + [ + "33.93833", + "26.65528" + ], + [ + "36.88625", + "22.05319" + ], + [ + "37.43569", + "18.85389" + ], + [ + "38.58902", + "18.06680" + ], + [ + "39.71805", + "15.08805" + ], + [ + "41.17222", + "14.63069" + ], + [ + "43.32750", + "12.47673" + ], + [ + "44.27833", + "10.44778" + ], + [ + "50.09319", + "11.51458" + ], + [ + "51.14555", + "10.63361" + ], + [ + "48.00055", + "4.52306" + ], + [ + "46.02555", + "2.43722" + ], + [ + "43.48861", + "0.65000" + ], + [ + "40.12548", + "-3.26569" + ], + [ + "38.77611", + "-6.03972" + ], + [ + "40.38777", + "-11.31778" + ], + [ + "40.57833", + "-15.49889" + ], + [ + "34.89069", + "-19.86042" + ], + [ + "35.45611", + "-24.16945" + ], + [ + "32.81111", + "-25.61209" + ], + [ + "32.39444", + "-28.53139" + ], + [ + "27.90000", + "-33.04056" + ], + [ + "24.82472", + "-34.20167" + ], + [ + "22.53916", + "-34.01118" + ], + [ + "20.00000", + "-34.82200" + ], + [ + "17.84750", + "-32.83083" + ], + [ + "18.21791", + "-31.73458" + ], + [ + "15.09500", + "-26.73528" + ], + [ + "14.51139", + "-22.55278" + ], + [ + "11.76764", + "-17.98820" + ], + [ + "11.73125", + "-15.85070" + ], + [ + "13.84944", + "-10.95611" + ], + [ + "13.39180", + "-8.39375" + ], + [ + "11.77417", + "-4.54264" + ], + [ + "9.70250", + "-2.44792" + ], + [ + "9.29833", + "-0.37167" + ], + [ + "9.96514", + "3.08521" + ], + [ + "8.89861", + "4.58833" + ], + [ + "5.93583", + "4.33833" + ], + [ + "4.41021", + "6.35993" + ], + [ + "1.46889", + "6.18639" + ], + [ + "-2.05889", + "4.73083" + ], + [ + "-4.46806", + "5.29556" + ], + [ + "-7.43639", + "4.34917" + ], + [ + "-9.23889", + "5.12278" + ], + [ + "-12.50417", + "7.38861" + ], + [ + "-13.49313", + "9.56008" + ], + [ + "-15.00542", + "10.77194" + ], + [ + "-17.17556", + "14.65444" + ], + [ + "-16.03945", + "17.73458" + ], + [ + "-16.91625", + "21.94542" + ], + [ + "-12.96271", + "27.92048" + ], + [ + "-11.51195", + "28.30375" + ], + [ + "-9.64097", + "30.16500" + ], + [ + "-8.53833", + "33.25055" + ], + [ + "-6.84306", + "34.01861" + ], + [ + "-5.91874", + "35.79065" + ], + [ + "-1.97972", + "35.07333" + ], + [ + "1.18250", + "36.51221" + ], + [ + "9.85868", + "37.32833" + ], + [ + "11.12667", + "35.24194" + ], + [ + "11.17430", + "33.21006" + ], + [ + "15.16583", + "32.39861" + ], + [ + "15.75430", + "31.38972" + ], + [ + "18.95750", + "30.27639" + ], + [ + "20.56763", + "32.56091" + ], + [ + "29.03500", + "30.82417" + ], + [ + "30.35545", + "31.50284" + ], + [ + "34.21666", + "31.32333" + ] + ] + ], + [ + [ + [ + "48.03140", + "-14.06341" + ], + [ + "49.94333", + "-13.03945" + ], + [ + "50.48277", + "-15.40583" + ], + [ + "49.36833", + "-18.35139" + ], + [ + "47.13305", + "-24.92806" + ], + [ + "44.01708", + "-24.98083" + ], + [ + "43.23888", + "-22.28250" + ], + [ + "44.48277", + "-19.96584" + ], + [ + "43.93139", + "-17.50056" + ], + [ + "44.87360", + "-16.21028" + ], + [ + "48.03140", + "-14.06341" + ] + ] + ] + ] + }, + "properties": { + "CONTINENT": "Africa" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + "-77.88972", + "7.22889" + ], + [ + "-77.36667", + "8.67500" + ], + [ + "-75.63432", + "9.44819" + ], + [ + "-74.86081", + "11.12549" + ], + [ + "-68.84368", + "11.44708" + ], + [ + "-68.11424", + "10.48493" + ], + [ + "-61.87959", + "10.72833" + ], + [ + "-61.61987", + "9.90528" + ], + [ + "-57.51919", + "6.27077" + ], + [ + "-52.97320", + "5.47305" + ], + [ + "-51.25931", + "4.15250" + ], + [ + "-49.90320", + "1.17444" + ], + [ + "-51.92751", + "-1.33486" + ], + [ + "-48.42722", + "-1.66028" + ], + [ + "-47.28556", + "-0.59917" + ], + [ + "-42.23584", + "-2.83778" + ], + [ + "-39.99875", + "-2.84653" + ], + [ + "-37.17445", + "-4.91861" + ], + [ + "-35.47973", + "-5.16611" + ], + [ + "-34.83129", + "-6.98180" + ], + [ + "-35.32751", + "-9.22889" + ], + [ + "-39.05709", + "-13.38028" + ], + [ + "-38.87195", + "-15.87417" + ], + [ + "-39.70403", + "-19.42361" + ], + [ + "-42.03445", + "-22.91917" + ], + [ + "-44.67521", + "-23.05570" + ], + [ + "-48.02612", + "-25.01500" + ], + [ + "-48.84251", + "-28.61778" + ], + [ + "-52.21764", + "-31.74500" + ], + [ + "-54.14077", + "-34.66466" + ], + [ + "-56.15834", + "-34.92722" + ], + [ + "-56.67834", + "-36.92361" + ], + [ + "-58.30112", + "-38.48500" + ], + [ + "-62.06875", + "-39.50848" + ], + [ + "-62.39001", + "-40.90195" + ], + [ + "-65.13014", + "-40.84417" + ], + [ + "-65.24945", + "-44.31306" + ], + [ + "-67.58435", + "-46.00030" + ], + [ + "-65.78979", + "-47.96584" + ], + [ + "-68.94112", + "-50.38806" + ], + [ + "-68.99014", + "-51.62445" + ], + [ + "-72.11501", + "-53.68764" + ], + [ + "-74.28924", + "-50.48049" + ], + [ + "-74.74139", + "-47.71146" + ], + [ + "-72.61389", + "-44.47278" + ], + [ + "-73.99432", + "-40.96695" + ], + [ + "-73.22404", + "-39.41688" + ], + [ + "-73.67709", + "-37.34729" + ], + [ + "-71.44667", + "-32.66500" + ], + [ + "-71.69585", + "-30.50667" + ], + [ + "-70.91389", + "-27.62445" + ], + [ + "-70.05334", + "-21.42565" + ], + [ + "-70.31202", + "-18.43750" + ], + [ + "-71.49424", + "-17.30223" + ], + [ + "-75.05139", + "-15.46597" + ], + [ + "-76.39480", + "-13.88417" + ], + [ + "-78.99459", + "-8.21965" + ], + [ + "-81.17473", + "-6.08667" + ], + [ + "-81.27640", + "-4.28083" + ], + [ + "-79.95632", + "-3.20778" + ], + [ + "-80.91279", + "-1.03653" + ], + [ + "-80.10084", + "0.77028" + ], + [ + "-78.88929", + "1.23837" + ], + [ + "-77.43445", + "4.03139" + ], + [ + "-77.88972", + "7.22889" + ] + ] + ] + }, + "properties": { + "CONTINENT": "South America" + } + }, + { + "type": "Feature", + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [ + "177.91779", + "-38.94280" + ], + [ + "175.95523", + "-41.25528" + ], + [ + "173.75165", + "-39.27000" + ], + [ + "174.94025", + "-38.10111" + ], + [ + "177.91779", + "-38.94280" + ] + ] + ], + [ + [ + [ + "171.18524", + "-44.93833" + ], + [ + "169.45801", + "-46.62333" + ], + [ + "166.47690", + "-45.80972" + ], + [ + "168.37233", + "-44.04056" + ], + [ + "171.15166", + "-42.56042" + ], + [ + "172.63025", + "-40.51056" + ], + [ + "174.23636", + "-41.83722" + ], + [ + "171.18524", + "-44.93833" + ] + ] + ] + ] + }, + "properties": { + "CONTINENT": "Oceania" + } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + "151.54025", + "-24.04583" + ], + [ + "153.18192", + "-25.94944" + ], + [ + "153.62419", + "-28.66104" + ], + [ + "152.52969", + "-32.40361" + ], + [ + "151.45456", + "-33.31681" + ], + [ + "149.97163", + "-37.52222" + ], + [ + "146.87357", + "-38.65166" + ], + [ + "143.54295", + "-38.85923" + ], + [ + "140.52997", + "-38.00028" + ], + [ + "138.09225", + "-34.13493" + ], + [ + "135.49586", + "-34.61708" + ], + [ + "134.18414", + "-32.48666" + ], + [ + "131.14859", + "-31.47403" + ], + [ + "125.97227", + "-32.26674" + ], + [ + "123.73499", + "-33.77972" + ], + [ + "120.00499", + "-33.92889" + ], + [ + "117.93414", + "-35.12534" + ], + [ + "115.00895", + "-34.26243" + ], + [ + "115.73998", + "-31.86806" + ], + [ + "113.64346", + "-26.65431" + ], + [ + "113.38971", + "-24.42944" + ], + [ + "114.03027", + "-21.84167" + ], + [ + "116.70749", + "-20.64917" + ], + [ + "121.02748", + "-19.59222" + ], + [ + "122.95623", + "-16.58681" + ], + [ + "126.85790", + "-13.75097" + ], + [ + "129.08942", + "-14.89944" + ], + [ + "130.57927", + "-12.40465" + ], + [ + "132.67198", + "-11.50813" + ], + [ + "135.23135", + "-12.29445" + ], + [ + "135.45135", + "-14.93278" + ], + [ + "136.76581", + "-15.90445" + ], + [ + "140.83330", + "-17.45194" + ], + [ + "141.66553", + "-15.02653" + ], + [ + "141.59412", + "-12.53167" + ], + [ + "142.78830", + "-11.08056" + ], + [ + "143.78220", + "-14.41333" + ], + [ + "145.31580", + "-14.94555" + ], + [ + "146.27762", + "-18.88701" + ], + [ + "147.43192", + "-19.41236" + ], + [ + "150.81912", + "-22.73194" + ], + [ + "151.54025", + "-24.04583" + ] + ] + ] + }, + "properties": { + "CONTINENT": "Australia" + } + } + ] +} \ No newline at end of file diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.test.ts b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.test.ts new file mode 100644 index 0000000000000..1e8e5b6012a79 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.test.ts @@ -0,0 +1,40 @@ +/* + * 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 { getLayerList } from './map_config'; +import { mockLayerList } from './__mocks__/mock'; +import { LocationPoint } from './embedded_map'; + +jest.mock('uuid', () => { + return { + v4: jest.fn(() => 'uuid.v4()'), + }; +}); + +describe('map_config', () => { + let upPoints: LocationPoint[]; + let downPoints: LocationPoint[]; + + beforeEach(() => { + upPoints = [ + { lat: '52.487239', lon: '13.399262' }, + { lat: '55.487239', lon: '13.399262' }, + { lat: '54.487239', lon: '14.399262' }, + ]; + downPoints = [ + { lat: '52.487239', lon: '13.399262' }, + { lat: '55.487239', lon: '13.399262' }, + { lat: '54.487239', lon: '14.399262' }, + ]; + }); + + describe('#getLayerList', () => { + test('it returns the low poly layer', () => { + const layerList = getLayerList(upPoints, downPoints); + expect(layerList).toStrictEqual(mockLayerList); + }); + }); +}); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.ts b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.ts new file mode 100644 index 0000000000000..608df8b235f00 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.ts @@ -0,0 +1,167 @@ +/* + * 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 lowPolyLayerFeatures from './low_poly_layer.json'; +import { LocationPoint } from './embedded_map'; + +/** + * Returns `Source/Destination Point-to-point` Map LayerList configuration, with a source, + * destination, and line layer for each of the provided indexPatterns + * + */ +export const getLayerList = (upPoints: LocationPoint[], downPoints: LocationPoint[]) => { + return [getLowPolyLayer(), getDownPointsLayer(downPoints), getUpPointsLayer(upPoints)]; +}; + +export const getLowPolyLayer = () => { + return { + id: 'low_poly_layer', + label: 'World countries', + minZoom: 0, + maxZoom: 24, + alpha: 1, + sourceDescriptor: { + id: 'b7486535-171b-4d3b-bb2e-33c1a0a2854c', + type: 'GEOJSON_FILE', + __featureCollection: lowPolyLayerFeatures, + }, + visible: true, + style: { + type: 'VECTOR', + properties: { + fillColor: { + type: 'STATIC', + options: { + color: '#cad3e4', + }, + }, + lineColor: { + type: 'STATIC', + options: { + color: '#fff', + }, + }, + lineWidth: { + type: 'STATIC', + options: { + size: 0, + }, + }, + iconSize: { + type: 'STATIC', + options: { + size: 6, + }, + }, + }, + }, + type: 'VECTOR', + }; +}; + +export const getDownPointsLayer = (downPoints: LocationPoint[]) => { + const features = downPoints?.map(point => ({ + type: 'feature', + geometry: { + type: 'Point', + coordinates: [+point.lon, +point.lat], + }, + })); + return { + id: 'down_points', + label: 'Down Locations', + sourceDescriptor: { + type: 'GEOJSON_FILE', + __featureCollection: { + features, + type: 'FeatureCollection', + }, + }, + visible: true, + style: { + type: 'VECTOR', + properties: { + fillColor: { + type: 'STATIC', + options: { + color: '#BC261E', + }, + }, + lineColor: { + type: 'STATIC', + options: { + color: '#fff', + }, + }, + lineWidth: { + type: 'STATIC', + options: { + size: 2, + }, + }, + iconSize: { + type: 'STATIC', + options: { + size: 6, + }, + }, + }, + }, + type: 'VECTOR', + }; +}; + +export const getUpPointsLayer = (upPoints: LocationPoint[]) => { + const features = upPoints?.map(point => ({ + type: 'feature', + geometry: { + type: 'Point', + coordinates: [+point.lon, +point.lat], + }, + })); + return { + id: 'up_points', + label: 'Up Locations', + sourceDescriptor: { + type: 'GEOJSON_FILE', + __featureCollection: { + features, + type: 'FeatureCollection', + }, + }, + visible: true, + style: { + type: 'VECTOR', + properties: { + fillColor: { + type: 'STATIC', + options: { + color: '#98A2B2', + }, + }, + lineColor: { + type: 'STATIC', + options: { + color: '#fff', + }, + }, + lineWidth: { + type: 'STATIC', + options: { + size: 2, + }, + }, + iconSize: { + type: 'STATIC', + options: { + size: 6, + }, + }, + }, + }, + type: 'VECTOR', + }; +}; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/translations.ts b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/translations.ts new file mode 100644 index 0000000000000..a5f68228efb1a --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/translations.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. + */ + +import { i18n } from '@kbn/i18n'; + +export const MAP_TITLE = i18n.translate( + 'xpack.uptime.components.embeddables.embeddedMap.embeddablePanelTitle', + { + defaultMessage: 'Monitor Observer Location Map', + } +); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/types.ts b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/types.ts new file mode 100644 index 0000000000000..5cac204ffb071 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/types.ts @@ -0,0 +1,31 @@ +/* + * 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 { Query } from 'src/plugins/data/common'; +import { TimeRange } from 'src/plugins/data/public'; +import { + EmbeddableInput, + EmbeddableOutput, + IEmbeddable, +} from '../../../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public'; + +import { esFilters } from '../../../../../../../../../src/plugins/data/public'; + +export interface MapEmbeddableInput extends EmbeddableInput { + filters: esFilters.Filter[]; + query: Query; + refreshConfig: { + isPaused: boolean; + interval: number; + }; + timeRange?: TimeRange; +} + +export interface CustomProps { + setLayerList: Function; +} + +export type MapEmbeddable = IEmbeddable & CustomProps; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/index.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/index.tsx new file mode 100644 index 0000000000000..1f4b88b971c4c --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/index.tsx @@ -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 * from './location_map'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_map.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_map.tsx new file mode 100644 index 0000000000000..b271632cb631f --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_map.tsx @@ -0,0 +1,38 @@ +/* + * 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 styled from 'styled-components'; +import { EmbeddedMap, LocationPoint } from './embeddables/embedded_map'; + +const MapPanel = styled.div` + height: 400px; + width: 520px; +`; + +interface LocationMapProps { + monitorLocations: any; +} + +export const LocationMap = ({ monitorLocations }: LocationMapProps) => { + const upPoints: LocationPoint[] = []; + const downPoints: LocationPoint[] = []; + + if (monitorLocations?.locations) { + monitorLocations.locations.forEach((item: any) => { + if (item.summary.down === 0) { + upPoints.push(item.geo.location); + } else { + downPoints.push(item.geo.location); + } + }); + } + return ( + + + + ); +}; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_bar/monitor_status_bar.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_bar/monitor_status_bar.tsx index 7ef6c3ed1e4bf..f36f0dff6745f 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_bar/monitor_status_bar.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_bar/monitor_status_bar.tsx @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiFlexGroup, EuiFlexItem, EuiHealth, EuiLink, EuiPanel } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; +import { EuiFlexGroup, EuiFlexItem, EuiHealth, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { get } from 'lodash'; import moment from 'moment'; @@ -16,6 +15,7 @@ import { monitorStatusBarQuery } from '../../../queries'; import { EmptyStatusBar } from '../empty_status_bar'; import { convertMicrosecondsToMilliseconds } from '../../../lib/helper'; import { MonitorSSLCertificate } from './monitor_ssl_certificate'; +import * as labels from './translations'; interface MonitorStatusBarQueryResult { monitorStatus?: Ping[]; @@ -28,58 +28,33 @@ interface MonitorStatusBarProps { type Props = MonitorStatusBarProps & UptimeGraphQLQueryProps; export const MonitorStatusBarComponent = ({ data, monitorId }: Props) => { - if (data && data.monitorStatus && data.monitorStatus.length) { + if (data?.monitorStatus?.length) { const { monitor, timestamp, tls } = data.monitorStatus[0]; const duration: number | undefined = get(monitor, 'duration.us', undefined); const status = get<'up' | 'down'>(monitor, 'status', 'down'); const full = get(data.monitorStatus[0], 'url.full'); return ( - + <> - {status === 'up' - ? i18n.translate('xpack.uptime.monitorStatusBar.healthStatusMessage.upLabel', { - defaultMessage: 'Up', - }) - : i18n.translate('xpack.uptime.monitorStatusBar.healthStatusMessage.downLabel', { - defaultMessage: 'Down', - })} + {status === 'up' ? labels.upLabel : labels.downLabel} - + {full} {!!duration && ( - + { /> )} - + {moment(new Date(timestamp).valueOf()).fromNow()} - + ); } - return ( - - ); + return ; }; export const MonitorStatusBar = withUptimeGraphQL< diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_bar/translations.ts b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_bar/translations.ts new file mode 100644 index 0000000000000..1c2844f4f6ccf --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_bar/translations.ts @@ -0,0 +1,49 @@ +/* + * 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'; + +export const healthStatusMessageAriaLabel = i18n.translate( + 'xpack.uptime.monitorStatusBar.healthStatusMessageAriaLabel', + { + defaultMessage: 'Monitor status', + } +); + +export const upLabel = i18n.translate('xpack.uptime.monitorStatusBar.healthStatusMessage.upLabel', { + defaultMessage: 'Up', +}); + +export const downLabel = i18n.translate( + 'xpack.uptime.monitorStatusBar.healthStatusMessage.downLabel', + { + defaultMessage: 'Down', + } +); + +export const monitorUrlLinkAriaLabel = i18n.translate( + 'xpack.uptime.monitorStatusBar.monitorUrlLinkAriaLabel', + { + defaultMessage: 'Monitor URL link', + } +); + +export const durationTextAriaLabel = i18n.translate( + 'xpack.uptime.monitorStatusBar.durationTextAriaLabel', + { + defaultMessage: 'Monitor duration in milliseconds', + } +); + +export const timestampFromNowTextAriaLabel = i18n.translate( + 'xpack.uptime.monitorStatusBar.timestampFromNowTextAriaLabel', + { + defaultMessage: 'Time since last check', + } +); + +export const loadingMessage = i18n.translate('xpack.uptime.monitorStatusBar.loadingMessage', { + defaultMessage: 'Loading…', +}); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/index.ts b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/index.ts new file mode 100644 index 0000000000000..234586e0b51f1 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/index.ts @@ -0,0 +1,34 @@ +/* + * 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 { connect } from 'react-redux'; +import { AppState } from '../../../state'; +import { getMonitorLocations } from '../../../state/selectors'; +import { fetchMonitorLocations } from '../../../state/actions/monitor'; +import { MonitorStatusDetailsComponent } from './monitor_status_details'; + +const mapStateToProps = (state: AppState, { monitorId }: any) => ({ + monitorLocations: getMonitorLocations(state, monitorId), +}); + +const mapDispatchToProps = (dispatch: any, ownProps: any) => ({ + loadMonitorLocations: () => { + const { dateStart, dateEnd, monitorId } = ownProps; + dispatch( + fetchMonitorLocations({ + monitorId, + dateStart, + dateEnd, + }) + ); + }, +}); + +export const MonitorStatusDetails = connect( + mapStateToProps, + mapDispatchToProps +)(MonitorStatusDetailsComponent); + +export * from './monitor_status_details'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_details.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_details.tsx new file mode 100644 index 0000000000000..cf337eaec4bbc --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_details.tsx @@ -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 React, { useEffect } from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui'; +import { LocationMap } from '../location_map'; +import { MonitorStatusBar } from '../monitor_status_bar'; + +interface MonitorStatusBarProps { + monitorId: string; + variables: any; + loadMonitorLocations: any; + monitorLocations: any; + dateStart: any; + dateEnd: any; +} + +export const MonitorStatusDetailsComponent = ({ + monitorId, + variables, + loadMonitorLocations, + monitorLocations, + dateStart, + dateEnd, +}: MonitorStatusBarProps) => { + useEffect(() => { + loadMonitorLocations(monitorId); + }, [monitorId, dateStart, dateEnd]); + + return ( + + + + + + + + + + + ); +}; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/translations.ts b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/translations.ts new file mode 100644 index 0000000000000..1c2844f4f6ccf --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/translations.ts @@ -0,0 +1,49 @@ +/* + * 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'; + +export const healthStatusMessageAriaLabel = i18n.translate( + 'xpack.uptime.monitorStatusBar.healthStatusMessageAriaLabel', + { + defaultMessage: 'Monitor status', + } +); + +export const upLabel = i18n.translate('xpack.uptime.monitorStatusBar.healthStatusMessage.upLabel', { + defaultMessage: 'Up', +}); + +export const downLabel = i18n.translate( + 'xpack.uptime.monitorStatusBar.healthStatusMessage.downLabel', + { + defaultMessage: 'Down', + } +); + +export const monitorUrlLinkAriaLabel = i18n.translate( + 'xpack.uptime.monitorStatusBar.monitorUrlLinkAriaLabel', + { + defaultMessage: 'Monitor URL link', + } +); + +export const durationTextAriaLabel = i18n.translate( + 'xpack.uptime.monitorStatusBar.durationTextAriaLabel', + { + defaultMessage: 'Monitor duration in milliseconds', + } +); + +export const timestampFromNowTextAriaLabel = i18n.translate( + 'xpack.uptime.monitorStatusBar.timestampFromNowTextAriaLabel', + { + defaultMessage: 'Time since last check', + } +); + +export const loadingMessage = i18n.translate('xpack.uptime.monitorStatusBar.loadingMessage', { + defaultMessage: 'Loading…', +}); diff --git a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx index 86a0a9e4b0f0b..8c5fced2f2864 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx @@ -4,26 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - // @ts-ignore No typings for EuiSpacer - EuiSpacer, -} from '@elastic/eui'; +import { EuiSpacer } from '@elastic/eui'; import { ApolloQueryResult, OperationVariables, QueryOptions } from 'apollo-client'; import gql from 'graphql-tag'; import React, { Fragment, useContext, useEffect, useState } from 'react'; import { getMonitorPageBreadcrumb } from '../breadcrumbs'; -import { - MonitorCharts, - MonitorPageTitle, - MonitorStatusBar, - PingList, -} from '../components/functional'; +import { MonitorCharts, MonitorPageTitle, PingList } from '../components/functional'; import { UMUpdateBreadcrumbs } from '../lib/lib'; import { UptimeSettingsContext } from '../contexts'; import { useUrlParams } from '../hooks'; import { stringifyUrlParams } from '../lib/helper/stringify_url_params'; import { useTrackPageview } from '../../../infra/public'; import { getTitle } from '../lib/helper/get_title'; +import { MonitorStatusDetails } from '../components/functional/monitor_status_details'; interface MonitorPageProps { logMonitorPageLoad: () => void; @@ -92,7 +85,12 @@ export const MonitorPage = ({ - + => { + const url = getApiPath(`/api/uptime/monitor/locations`, basePath); + + const params = { + dateStart, + dateEnd, + monitorId, + }; + const urlParams = new URLSearchParams(params).toString(); + const response = await fetch(`${url}?${urlParams}`); + + if (!response.ok) { + throw new Error(response.statusText); + } + return response.json().then(data => { + ThrowReporter.report(MonitorLocationsType.decode(data)); + return data; + }); +}; diff --git a/x-pack/legacy/plugins/uptime/public/state/effects/monitor.ts b/x-pack/legacy/plugins/uptime/public/state/effects/monitor.ts index 529b9041c9093..210004bb343bb 100644 --- a/x-pack/legacy/plugins/uptime/public/state/effects/monitor.ts +++ b/x-pack/legacy/plugins/uptime/public/state/effects/monitor.ts @@ -10,8 +10,11 @@ import { FETCH_MONITOR_DETAILS, FETCH_MONITOR_DETAILS_SUCCESS, FETCH_MONITOR_DETAILS_FAIL, + FETCH_MONITOR_LOCATIONS, + FETCH_MONITOR_LOCATIONS_SUCCESS, + FETCH_MONITOR_LOCATIONS_FAIL, } from '../actions/monitor'; -import { fetchMonitorDetails } from '../api'; +import { fetchMonitorDetails, fetchMonitorLocations } from '../api'; import { getBasePath } from '../selectors'; function* monitorDetailsEffect(action: Action) { @@ -25,6 +28,18 @@ function* monitorDetailsEffect(action: Action) { } } +function* monitorLocationsEffect(action: Action) { + const payload = action.payload; + try { + const basePath = yield select(getBasePath); + const response = yield call(fetchMonitorLocations, { basePath, ...payload }); + yield put({ type: FETCH_MONITOR_LOCATIONS_SUCCESS, payload: response }); + } catch (error) { + yield put({ type: FETCH_MONITOR_LOCATIONS_FAIL, payload: error.message }); + } +} + export function* fetchMonitorDetailsEffect() { yield takeLatest(FETCH_MONITOR_DETAILS, monitorDetailsEffect); + yield takeLatest(FETCH_MONITOR_LOCATIONS, monitorLocationsEffect); } diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/monitor.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/monitor.ts index 4cacb6f8cab9e..220ab0b205462 100644 --- a/x-pack/legacy/plugins/uptime/public/state/reducers/monitor.ts +++ b/x-pack/legacy/plugins/uptime/public/state/reducers/monitor.ts @@ -10,16 +10,24 @@ import { FETCH_MONITOR_DETAILS, FETCH_MONITOR_DETAILS_SUCCESS, FETCH_MONITOR_DETAILS_FAIL, + FETCH_MONITOR_LOCATIONS, + FETCH_MONITOR_LOCATIONS_SUCCESS, + FETCH_MONITOR_LOCATIONS_FAIL, } from '../actions/monitor'; +import { MonitorLocations } from '../../../common/runtime_types'; + +type MonitorLocationsList = Map; export interface MonitorState { monitorDetailsList: MonitorDetailsState[]; + monitorLocationsList: MonitorLocationsList; loading: boolean; errors: any[]; } const initialState: MonitorState = { monitorDetailsList: [], + monitorLocationsList: new Map(), loading: false, errors: [], }; @@ -42,10 +50,27 @@ export function monitorReducer(state = initialState, action: MonitorActionTypes) loading: false, }; case FETCH_MONITOR_DETAILS_FAIL: - const error = action.payload; return { ...state, - errors: [...state.errors, error], + errors: [...state.errors, action.payload], + }; + case FETCH_MONITOR_LOCATIONS: + return { + ...state, + loading: true, + }; + case FETCH_MONITOR_LOCATIONS_SUCCESS: + const monLocations = state.monitorLocationsList; + monLocations.set(action.payload.monitorId, action.payload); + return { + ...state, + monitorLocationsList: monLocations, + loading: false, + }; + case FETCH_MONITOR_LOCATIONS_FAIL: + return { + ...state, + errors: [...state.errors, action.payload], }; default: return state; diff --git a/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts b/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts index 70cd2b19860ba..b61ed83663435 100644 --- a/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts +++ b/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts @@ -11,6 +11,7 @@ describe('state selectors', () => { const state: AppState = { monitor: { monitorDetailsList: [], + monitorLocationsList: new Map(), loading: false, errors: [], }, diff --git a/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts b/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts index 245b45a939950..1792c84c45220 100644 --- a/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts +++ b/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts @@ -14,3 +14,7 @@ export const isIntegrationsPopupOpen = ({ ui: { integrationsPopoverOpen } }: App export const getMonitorDetails = (state: AppState, summary: any) => { return state.monitor.monitorDetailsList[summary.monitor_id]; }; + +export const getMonitorLocations = (state: AppState, monitorId: string) => { + return state.monitor.monitorLocationsList?.get(monitorId); +}; diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/adapter_types.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/adapter_types.ts index f6ac587b0ceec..1191eb813a214 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/adapter_types.ts +++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/adapter_types.ts @@ -17,4 +17,10 @@ export interface UMMonitorsAdapter { getFilterBar(request: any, dateRangeStart: string, dateRangeEnd: string): Promise; getMonitorPageTitle(request: any, monitorId: string): Promise; getMonitorDetails(request: any, monitorId: string): Promise; + getMonitorLocations( + request: any, + monitorId: string, + dateStart: string, + dateEnd: string + ): Promise; } diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts index c7ebc77af3567..4009a4b1331fa 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts +++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts @@ -16,7 +16,12 @@ import { import { getHistogramIntervalFormatted } from '../../helper'; import { DatabaseAdapter } from '../database'; import { UMMonitorsAdapter } from './adapter_types'; -import { MonitorDetails, MonitorError } from '../../../../common/runtime_types'; +import { + MonitorDetails, + MonitorError, + MonitorLocations, + MonitorLocation, +} from '../../../../common/runtime_types'; const formatStatusBuckets = (time: any, buckets: any, docCount: any) => { let up = null; @@ -273,6 +278,11 @@ export class ElasticsearchMonitorsAdapter implements UMMonitorsAdapter { }; } + /** + * Fetch data for the monitor page title. + * @param request Kibana server request + * @param monitorId the ID to query + */ public async getMonitorDetails(request: any, monitorId: string): Promise { const params = { index: INDEX_NAMES.HEARTBEAT, @@ -320,4 +330,100 @@ export class ElasticsearchMonitorsAdapter implements UMMonitorsAdapter { timestamp: errorTimeStamp, }; } + + /** + * Fetch data for the monitor page title. + * @param request Kibana server request + * @param monitorId the ID to query + */ + public async getMonitorLocations( + request: any, + monitorId: string, + dateStart: string, + dateEnd: string + ): Promise { + const params = { + index: INDEX_NAMES.HEARTBEAT, + body: { + size: 0, + query: { + bool: { + filter: [ + { + match: { + 'monitor.id': monitorId, + }, + }, + { + exists: { + field: 'summary', + }, + }, + { + range: { + '@timestamp': { + gte: dateStart, + lte: dateEnd, + }, + }, + }, + ], + }, + }, + aggs: { + location: { + terms: { + field: 'observer.geo.name', + missing: '__location_missing__', + }, + aggs: { + most_recent: { + top_hits: { + size: 1, + sort: { + '@timestamp': { + order: 'desc', + }, + }, + _source: ['monitor', 'summary', 'observer'], + }, + }, + }, + }, + }, + }, + }; + + const result = await this.database.search(request, params); + const locations = result?.aggregations?.location?.buckets ?? []; + + const getGeo = (locGeo: any) => { + const { name, location } = locGeo; + const latLon = location.trim().split(','); + return { + name, + location: { + lat: latLon[0], + lon: latLon[1], + }, + }; + }; + + const monLocs: MonitorLocation[] = []; + locations.forEach((loc: any) => { + if (loc?.key !== '__location_missing__') { + const mostRecentLocation = loc.most_recent.hits.hits[0]._source; + const location: MonitorLocation = { + summary: mostRecentLocation?.summary, + geo: getGeo(mostRecentLocation?.observer?.geo), + }; + monLocs.push(location); + } + }); + + return { + monitorId, + locations: monLocs, + }; + } } diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/index.ts b/x-pack/legacy/plugins/uptime/server/rest_api/index.ts index 2810982fb0c6c..f18b9e8e44c36 100644 --- a/x-pack/legacy/plugins/uptime/server/rest_api/index.ts +++ b/x-pack/legacy/plugins/uptime/server/rest_api/index.ts @@ -9,7 +9,7 @@ import { createGetIndexPatternRoute } from './index_pattern'; import { createLogMonitorPageRoute, createLogOverviewPageRoute } from './telemetry'; import { createGetSnapshotCount } from './snapshot'; import { UMRestApiRouteCreator } from './types'; -import { createGetMonitorDetailsRoute } from './monitors'; +import { createGetMonitorDetailsRoute, createGetMonitorLocationsRoute } from './monitors'; export * from './types'; export { createRouteWithAuth } from './create_route_with_auth'; @@ -17,6 +17,7 @@ export const restApiRoutes: UMRestApiRouteCreator[] = [ createGetAllRoute, createGetIndexPatternRoute, createGetMonitorDetailsRoute, + createGetMonitorLocationsRoute, createGetSnapshotCount, createLogMonitorPageRoute, createLogOverviewPageRoute, diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/monitors/index.ts b/x-pack/legacy/plugins/uptime/server/rest_api/monitors/index.ts index 2c4b9e9fb1f3e..2279233d49a09 100644 --- a/x-pack/legacy/plugins/uptime/server/rest_api/monitors/index.ts +++ b/x-pack/legacy/plugins/uptime/server/rest_api/monitors/index.ts @@ -5,3 +5,4 @@ */ export { createGetMonitorDetailsRoute } from './monitors_details'; +export { createGetMonitorLocationsRoute } from './monitor_locations'; diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/monitors/monitor_locations.ts b/x-pack/legacy/plugins/uptime/server/rest_api/monitors/monitor_locations.ts new file mode 100644 index 0000000000000..4a91255bd19f2 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/server/rest_api/monitors/monitor_locations.ts @@ -0,0 +1,33 @@ +/* + * 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 { schema } from '@kbn/config-schema'; +import { UMServerLibs } from '../../lib/lib'; +import { UMRestApiRouteCreator } from '../types'; + +export const createGetMonitorLocationsRoute: UMRestApiRouteCreator = (libs: UMServerLibs) => ({ + method: 'GET', + path: '/api/uptime/monitor/locations', + validate: { + query: schema.object({ + monitorId: schema.string(), + dateStart: schema.string(), + dateEnd: schema.string(), + }), + }, + options: { + tags: ['access:uptime'], + }, + handler: async (_context, request, response): Promise => { + const { monitorId, dateStart, dateEnd } = request.query; + + return response.ok({ + body: { + ...(await libs.monitors.getMonitorLocations(request, monitorId, dateStart, dateEnd)), + }, + }); + }, +}); diff --git a/x-pack/plugins/graph/public/plugin.ts b/x-pack/plugins/graph/public/plugin.ts index cb997ff427543..c0cec14e04d61 100644 --- a/x-pack/plugins/graph/public/plugin.ts +++ b/x-pack/plugins/graph/public/plugin.ts @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import { CoreSetup, CoreStart } from 'kibana/public'; import { Plugin } from 'src/core/public'; import { toggleNavLink } from './services/toggle_nav_link'; -import { LicensingPluginSetup } from '../../licensing/common/types'; +import { LicensingPluginSetup } from '../../licensing/public'; import { checkLicense } from '../common/check_license'; import { FeatureCatalogueCategory, diff --git a/x-pack/plugins/graph/server/plugin.ts b/x-pack/plugins/graph/server/plugin.ts index 4b5a17707641f..c7ada3af31b76 100644 --- a/x-pack/plugins/graph/server/plugin.ts +++ b/x-pack/plugins/graph/server/plugin.ts @@ -5,7 +5,7 @@ */ import { Plugin, CoreSetup } from 'src/core/server'; -import { LicensingPluginSetup } from '../../licensing/common/types'; +import { LicensingPluginSetup } from '../../licensing/server'; import { LicenseState } from './lib/license_state'; import { registerSearchRoute } from './routes/search'; import { registerExploreRoute } from './routes/explore'; diff --git a/x-pack/test/accessibility/apps/login_page.ts b/x-pack/test/accessibility/apps/login_page.ts index bce6a67745377..5b18b6be9e3a4 100644 --- a/x-pack/test/accessibility/apps/login_page.ts +++ b/x-pack/test/accessibility/apps/login_page.ts @@ -17,7 +17,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { describe('Login Page', () => { before(async () => { await esArchiver.load('empty_kibana'); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); after(async () => { @@ -25,7 +25,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { }); afterEach(async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); it('meets a11y requirements', async () => { diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions/index.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions/index.ts index 6ef30a6f933ff..73279cd0c2ff0 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions/index.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions/index.ts @@ -32,6 +32,30 @@ export default function(kibana: any) { require: ['actions'], name: NAME, init: (server: Hapi.Server) => { + server.plugins.xpack_main.registerFeature({ + id: 'actions', + name: 'Actions', + app: ['actions', 'kibana'], + privileges: { + all: { + savedObject: { + all: ['action', 'action_task_params'], + read: [], + }, + ui: [], + api: ['actions-read', 'actions-all'], + }, + read: { + savedObject: { + all: ['action_task_params'], + read: ['action'], + }, + ui: [], + api: ['actions-read'], + }, + }, + }); + initSlack(server, getExternalServiceSimulatorPath(ExternalServiceSimulator.SLACK)); initWebhook(server, getExternalServiceSimulatorPath(ExternalServiceSimulator.WEBHOOK)); initPagerduty(server, getExternalServiceSimulatorPath(ExternalServiceSimulator.PAGERDUTY)); diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/index.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/index.ts index 30b235a784c22..ebe741df71d79 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/index.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/index.ts @@ -14,6 +14,30 @@ export default function(kibana: any) { require: ['actions', 'alerting', 'elasticsearch'], name: 'alerts', init(server: any) { + server.plugins.xpack_main.registerFeature({ + id: 'alerting', + name: 'Alerting', + app: ['alerting', 'kibana'], + privileges: { + all: { + savedObject: { + all: ['alert'], + read: [], + }, + ui: [], + api: ['alerting-read', 'alerting-all'], + }, + read: { + savedObject: { + all: [], + read: ['alert'], + }, + ui: [], + api: ['alerting-read'], + }, + }, + }); + // Action types const noopActionType: ActionType = { id: 'test.noop', diff --git a/x-pack/test/api_integration/apis/features/features/features.ts b/x-pack/test/api_integration/apis/features/features/features.ts index a24155943b45c..f613473dd87fb 100644 --- a/x-pack/test/api_integration/apis/features/features/features.ts +++ b/x-pack/test/api_integration/apis/features/features/features.ts @@ -114,8 +114,6 @@ export default function({ getService }: FtrProviderContext) { 'maps', 'uptime', 'siem', - 'alerting', - 'actions', ].sort() ); }); diff --git a/x-pack/test/api_integration/apis/security/privileges.ts b/x-pack/test/api_integration/apis/security/privileges.ts index d6ad1608f3688..d4c8a3e68c50e 100644 --- a/x-pack/test/api_integration/apis/security/privileges.ts +++ b/x-pack/test/api_integration/apis/security/privileges.ts @@ -37,8 +37,6 @@ export default function({ getService }: FtrProviderContext) { uptime: ['all', 'read'], apm: ['all', 'read'], siem: ['all', 'read'], - actions: ['all', 'read'], - alerting: ['all', 'read'], }, global: ['all', 'read'], space: ['all', 'read'], diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts index d60b286e3337a..f148d62421ff8 100644 --- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts +++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts @@ -46,7 +46,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { full_name: 'test user', }); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login( 'global_advanced_settings_all_user', 'global_advanced_settings_all_user-password', @@ -62,7 +62,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await Promise.all([ security.role.delete('global_advanced_settings_all_role'), security.user.delete('global_advanced_settings_all_user'), - PageObjects.security.logout(), + PageObjects.security.forceLogout(), ]); }); diff --git a/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts b/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts index e9e1436241308..a58eb61ec4ca2 100644 --- a/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts +++ b/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts @@ -45,7 +45,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { full_name: 'test user', }); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login( 'global_canvas_all_user', @@ -60,7 +60,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await Promise.all([ security.role.delete('global_canvas_all_role'), security.user.delete('global_canvas_all_user'), - PageObjects.security.logout(), + PageObjects.security.forceLogout(), ]); }); diff --git a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js index 9e5447919c6d0..8acb875e1d7b4 100644 --- a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js +++ b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js @@ -110,11 +110,11 @@ export default function ({ getService, getPageObjects }) { }); after('logout', async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); it('shows only the dashboard app link', async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login('dashuser', '123456'); const appLinks = await appsMenu.readLinks(); @@ -194,7 +194,7 @@ export default function ({ getService, getPageObjects }) { }); it('is loaded for a user who is assigned a non-dashboard mode role', async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login('mixeduser', '123456'); if (await appsMenu.linkExists('Management')) { @@ -203,7 +203,7 @@ export default function ({ getService, getPageObjects }) { }); it('is not loaded for a user who is assigned a superuser role', async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login('mysuperuser', '123456'); if (!await appsMenu.linkExists('Management')) { diff --git a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts index f5ceae689ead2..553ce459ebb18 100644 --- a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts +++ b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts @@ -33,14 +33,14 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await esArchiver.loadIfNeeded('logstash_functional'); // ensure we're logged out so we can login as the appropriate users - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); after(async () => { await esArchiver.unload('discover/feature_controls/security'); // logout, so the other tests don't accidentally run as the custom users we're testing below - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); describe('global discover all privileges', () => { diff --git a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts index cce5ededf2cf3..4929bb52c170c 100644 --- a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts +++ b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts @@ -46,7 +46,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { full_name: 'test user', }); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login( 'global_index_patterns_all_user', @@ -64,7 +64,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await Promise.all([ security.role.delete('global_index_patterns_all_role'), security.user.delete('global_index_patterns_all_user'), - PageObjects.security.logout(), + PageObjects.security.forceLogout(), ]); }); diff --git a/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts b/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts index 08cb5b3951ee4..8b2df502dc100 100644 --- a/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts +++ b/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts @@ -29,7 +29,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); // ensure we're logged out so we can login as the appropriate users - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); after(async () => { @@ -37,7 +37,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await security.role.delete('global_all_role'); // logout, so the other tests don't accidentally run as the custom users we're testing below - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); describe('machine_learning_user', () => { diff --git a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts index 2543eec76340f..cf31f445a96f3 100644 --- a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts +++ b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts @@ -49,7 +49,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { full_name: 'test user', }); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login('global_maps_all_user', 'global_maps_all_user-password', { expectSpaceSelector: false, @@ -60,7 +60,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await Promise.all([ security.role.delete('global_maps_all_role'), security.user.delete('global_maps_all_user'), - PageObjects.security.logout(), + PageObjects.security.forceLogout(), ]); }); diff --git a/x-pack/test/functional/apps/monitoring/_get_lifecycle_methods.js b/x-pack/test/functional/apps/monitoring/_get_lifecycle_methods.js index c1faa25ed9c70..58756c657347d 100644 --- a/x-pack/test/functional/apps/monitoring/_get_lifecycle_methods.js +++ b/x-pack/test/functional/apps/monitoring/_get_lifecycle_methods.js @@ -35,7 +35,7 @@ export const getLifecycleMethods = (getService, getPageObjects) => { }, async tearDown() { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await security.user.delete('basic_monitoring_user'); return esArchiver.unload(_archive); } diff --git a/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_spaces.ts b/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_spaces.ts index 60aa40d0b5904..80f33ff6175c5 100644 --- a/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_spaces.ts +++ b/x-pack/test/functional/apps/monitoring/feature_controls/monitoring_spaces.ts @@ -21,7 +21,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { after(async () => { await esArchiver.unload('empty_kibana'); await PageObjects.common.navigateToApp('home'); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); describe('space with no features disabled', () => { diff --git a/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts b/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts index 619a85c616b2e..53da2b80454e4 100644 --- a/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts +++ b/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts @@ -44,7 +44,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { full_name: 'test user', }); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login('global_all_user', 'global_all_user-password', { expectSpaceSelector: false, @@ -55,7 +55,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await Promise.all([ security.role.delete('global_all_role'), security.user.delete('global_all_user'), - PageObjects.security.logout(), + PageObjects.security.forceLogout(), ]); }); @@ -162,7 +162,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { full_name: 'test user', }); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login('global_som_read_user', 'global_som_read_user-password', { expectSpaceSelector: false, @@ -173,7 +173,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await Promise.all([ security.role.delete('global_som_read_role'), security.user.delete('global_som_read_user'), - PageObjects.security.logout(), + PageObjects.security.forceLogout(), ]); }); @@ -281,7 +281,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { full_name: 'test user', }); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login( 'global_visualize_all_user', @@ -296,7 +296,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await Promise.all([ security.role.delete('global_visualize_all_role'), security.user.delete('global_visualize_all_user'), - PageObjects.security.logout(), + PageObjects.security.forceLogout(), ]); }); diff --git a/x-pack/test/functional/apps/security/doc_level_security_roles.js b/x-pack/test/functional/apps/security/doc_level_security_roles.js index 9dac150b9a0e6..8a4184daf4d23 100644 --- a/x-pack/test/functional/apps/security/doc_level_security_roles.js +++ b/x-pack/test/functional/apps/security/doc_level_security_roles.js @@ -66,7 +66,7 @@ export default function ({ getService, getPageObjects }) { }); it('user East should only see EAST doc', async function () { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login('userEast', 'changeme'); await PageObjects.common.navigateToApp('discover'); await retry.try(async () => { @@ -77,7 +77,7 @@ export default function ({ getService, getPageObjects }) { expect(rowData).to.be('name:ABC Company region:EAST _id:doc1 _type: - _index:dlstest _score:0'); }); after('logout', async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); }); } diff --git a/x-pack/test/functional/apps/security/field_level_security.js b/x-pack/test/functional/apps/security/field_level_security.js index 2939805d70859..8bcc49e7dd554 100644 --- a/x-pack/test/functional/apps/security/field_level_security.js +++ b/x-pack/test/functional/apps/security/field_level_security.js @@ -89,7 +89,7 @@ export default function ({ getService, getPageObjects }) { }); it('user customer1 should see ssn', async function () { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login('customer1', 'changeme'); await PageObjects.common.navigateToApp('discover'); await retry.tryForTime(10000, async () => { @@ -102,7 +102,7 @@ export default function ({ getService, getPageObjects }) { }); it('user customer2 should not see ssn', async function () { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login('customer2', 'changeme'); await PageObjects.common.navigateToApp('discover'); await retry.tryForTime(10000, async () => { @@ -114,7 +114,7 @@ export default function ({ getService, getPageObjects }) { }); after(async function () { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); }); diff --git a/x-pack/test/functional/apps/security/rbac_phase1.js b/x-pack/test/functional/apps/security/rbac_phase1.js index 3f9f2f6bdbe87..cf81af54c6d02 100644 --- a/x-pack/test/functional/apps/security/rbac_phase1.js +++ b/x-pack/test/functional/apps/security/rbac_phase1.js @@ -79,7 +79,7 @@ export default function ({ getService, getPageObjects }) { expect(user.roles).to.eql(['rbac_read']); expect(user.fullname).to.eql('kibanareadonlyFirst kibanareadonlyLast'); expect(user.reserved).to.be(false); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); @@ -100,11 +100,11 @@ export default function ({ getService, getPageObjects }) { await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.visualize.waitForVisualization(); await PageObjects.visualize.saveVisualizationExpectSuccess(vizName1); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); after(async function () { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); }); diff --git a/x-pack/test/functional/apps/security/secure_roles_perm.js b/x-pack/test/functional/apps/security/secure_roles_perm.js index 4f725d04ce034..0c84a34e0bf89 100644 --- a/x-pack/test/functional/apps/security/secure_roles_perm.js +++ b/x-pack/test/functional/apps/security/secure_roles_perm.js @@ -60,7 +60,7 @@ export default function ({ getService, getPageObjects }) { expect(users.Rashmi.roles).to.eql(['logstash_reader', 'kibana_user']); expect(users.Rashmi.fullname).to.eql('RashmiFirst RashmiLast'); expect(users.Rashmi.reserved).to.be(false); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login('Rashmi', 'changeme'); }); @@ -83,7 +83,7 @@ export default function ({ getService, getPageObjects }) { }); after(async function () { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); }); diff --git a/x-pack/test/functional/apps/security/security.js b/x-pack/test/functional/apps/security/security.js index 537491185d9ef..ca7aa893d14e1 100644 --- a/x-pack/test/functional/apps/security/security.js +++ b/x-pack/test/functional/apps/security/security.js @@ -16,7 +16,7 @@ export default function ({ getService, getPageObjects }) { describe('Login Page', () => { before(async () => { await esArchiver.load('empty_kibana'); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); after(async () => { @@ -24,7 +24,7 @@ export default function ({ getService, getPageObjects }) { }); afterEach(async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); it('can login', async () => { diff --git a/x-pack/test/functional/apps/security/user_email.js b/x-pack/test/functional/apps/security/user_email.js index 538066d19ff1f..c04a8031a0379 100644 --- a/x-pack/test/functional/apps/security/user_email.js +++ b/x-pack/test/functional/apps/security/user_email.js @@ -30,7 +30,7 @@ export default function ({ getService, getPageObjects }) { expect(users.newuser.fullname).to.eql('newuserFirst newuserLast'); expect(users.newuser.email).to.eql('newuser@myEmail.com'); expect(users.newuser.reserved).to.be(false); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); it('login as new user and verify email', async function () { @@ -41,7 +41,7 @@ export default function ({ getService, getPageObjects }) { it('click changepassword link, change the password and re-login', async function () { await PageObjects.accountSetting.verifyAccountSettings('newuser@myEmail.com', 'newuser'); await PageObjects.accountSetting.changePassword('changeme', 'mechange'); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); @@ -51,7 +51,7 @@ export default function ({ getService, getPageObjects }) { }); after(async function () { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); }); } diff --git a/x-pack/test/functional/apps/spaces/enter_space.ts b/x-pack/test/functional/apps/spaces/enter_space.ts index 017d252b166cc..b931a5cb0ca63 100644 --- a/x-pack/test/functional/apps/spaces/enter_space.ts +++ b/x-pack/test/functional/apps/spaces/enter_space.ts @@ -19,7 +19,7 @@ export default function enterSpaceFunctonalTests({ after(async () => await esArchiver.unload('spaces/enter_space')); afterEach(async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); it('allows user to navigate to different spaces, respecting the configured default route', async () => { diff --git a/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts b/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts index 1e74322d0676d..46f0be1e6f6d6 100644 --- a/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts +++ b/x-pack/test/functional/apps/spaces/feature_controls/spaces_security.ts @@ -39,7 +39,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { full_name: 'test user', }); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login('global_all_user', 'global_all_user-password', { expectSpaceSelector: false, @@ -50,7 +50,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await Promise.all([ security.role.delete('global_all_role'), security.user.delete('global_all_user'), - PageObjects.security.logout(), + PageObjects.security.forceLogout(), ]); }); @@ -111,7 +111,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { full_name: 'test user', }); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login( 'default_space_all_user', @@ -126,7 +126,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await Promise.all([ security.role.delete('default_space_all_role'), security.user.delete('default_space_all_user'), - PageObjects.security.logout(), + PageObjects.security.forceLogout(), ]); }); diff --git a/x-pack/test/functional/apps/spaces/spaces_selection.ts b/x-pack/test/functional/apps/spaces/spaces_selection.ts index 9b4c99334dd67..3d1ef40262b1d 100644 --- a/x-pack/test/functional/apps/spaces/spaces_selection.ts +++ b/x-pack/test/functional/apps/spaces/spaces_selection.ts @@ -26,7 +26,7 @@ export default function spaceSelectorFunctonalTests({ after(async () => await esArchiver.unload('spaces/selector')); afterEach(async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); it('allows user to navigate to different spaces', async () => { @@ -87,7 +87,7 @@ export default function spaceSelectorFunctonalTests({ hash: sampleDataHash, }); await PageObjects.home.removeSampleDataSet('logs'); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await esArchiver.unload('spaces/selector'); }); diff --git a/x-pack/test/functional/apps/status_page/status_page.ts b/x-pack/test/functional/apps/status_page/status_page.ts index ffd87ff74588c..58551aaaf4112 100644 --- a/x-pack/test/functional/apps/status_page/status_page.ts +++ b/x-pack/test/functional/apps/status_page/status_page.ts @@ -18,7 +18,7 @@ export default function statusPageFunctonalTests({ after(async () => await esArchiver.unload('empty_kibana')); it('allows user to navigate without authentication', async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.statusPage.navigateToPage(); await PageObjects.statusPage.expectStatusPage(); }); diff --git a/x-pack/test/functional/apps/timelion/feature_controls/timelion_security.ts b/x-pack/test/functional/apps/timelion/feature_controls/timelion_security.ts index 073d54b9088bb..64fb218a62c80 100644 --- a/x-pack/test/functional/apps/timelion/feature_controls/timelion_security.ts +++ b/x-pack/test/functional/apps/timelion/feature_controls/timelion_security.ts @@ -41,7 +41,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { full_name: 'test user', }); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login( 'global_timelion_all_user', @@ -53,7 +53,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await security.role.delete('global_timelion_all_role'); await security.user.delete('global_timelion_all_user'); }); @@ -107,7 +107,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await security.role.delete('global_timelion_read_role'); await security.user.delete('global_timelion_read_user'); }); @@ -151,7 +151,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { full_name: 'test user', }); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login( 'no_timelion_privileges_user', @@ -163,7 +163,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await security.role.delete('no_timelion_privileges_role'); await security.user.delete('no_timelion_privileges_user'); }); diff --git a/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts b/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts index d85271fe166b1..86fe606ecafad 100644 --- a/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts +++ b/x-pack/test/functional/apps/visualize/feature_controls/visualize_security.ts @@ -56,7 +56,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { full_name: 'test user', }); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await PageObjects.security.login( 'global_visualize_all_user', @@ -68,7 +68,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await security.role.delete('global_visualize_all_role'); await security.user.delete('global_visualize_all_user'); }); @@ -184,7 +184,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await security.role.delete('global_visualize_read_role'); await security.user.delete('global_visualize_read_user'); }); @@ -294,7 +294,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); await security.role.delete('no_visualize_privileges_role'); await security.user.delete('no_visualize_privileges_user'); }); diff --git a/x-pack/test/visual_regression/tests/login_page.js b/x-pack/test/visual_regression/tests/login_page.js index 003a23086c7b6..04f6dff5fcaec 100644 --- a/x-pack/test/visual_regression/tests/login_page.js +++ b/x-pack/test/visual_regression/tests/login_page.js @@ -15,7 +15,7 @@ export default function ({ getService, getPageObjects }) { describe('Login Page', () => { before(async () => { await esArchiver.load('empty_kibana'); - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); after(async () => { @@ -23,7 +23,7 @@ export default function ({ getService, getPageObjects }) { }); afterEach(async () => { - await PageObjects.security.logout(); + await PageObjects.security.forceLogout(); }); it('renders login page', async () => {