mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Co-authored-by: Spencer <email@spalger.com>
This commit is contained in:
parent
9918816b0d
commit
da882b900c
31 changed files with 429 additions and 138 deletions
|
@ -104,5 +104,6 @@ module.exports = {
|
|||
'@kbn/eslint/no_async_promise_body': 'error',
|
||||
'@kbn/eslint/no_async_foreach': 'error',
|
||||
'@kbn/eslint/no_trailing_import_slash': 'error',
|
||||
'@kbn/eslint/no_constructor_args_in_property_initializers': 'error',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -20,16 +20,18 @@ export interface Log {
|
|||
}
|
||||
|
||||
export class CliLog implements Log {
|
||||
public toolingLog = new ToolingLog({
|
||||
level: this.silent ? 'silent' : 'info',
|
||||
writeTo: {
|
||||
write: (msg) => {
|
||||
this.write(msg);
|
||||
},
|
||||
},
|
||||
});
|
||||
public toolingLog: ToolingLog;
|
||||
|
||||
constructor(private readonly silent: boolean) {}
|
||||
constructor(private readonly silent: boolean) {
|
||||
this.toolingLog = new ToolingLog({
|
||||
level: this.silent ? 'silent' : 'info',
|
||||
writeTo: {
|
||||
write: (msg) => {
|
||||
this.write(msg);
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
good(label: string, ...args: any[]) {
|
||||
if (this.silent) {
|
||||
|
|
|
@ -16,5 +16,6 @@ module.exports = {
|
|||
no_async_promise_body: require('./rules/no_async_promise_body'),
|
||||
no_async_foreach: require('./rules/no_async_foreach'),
|
||||
no_trailing_import_slash: require('./rules/no_trailing_import_slash'),
|
||||
no_constructor_args_in_property_initializers: require('./rules/no_constructor_args_in_property_initializers'),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -14,14 +14,10 @@ const esTypes = tsEstree.AST_NODE_TYPES;
|
|||
const babelTypes = require('@babel/types');
|
||||
|
||||
/** @typedef {import("eslint").Rule.RuleModule} Rule */
|
||||
/** @typedef {import("@typescript-eslint/parser").ParserServices} ParserServices */
|
||||
/** @typedef {import("@typescript-eslint/typescript-estree").TSESTree.Expression} Expression */
|
||||
/** @typedef {import("@typescript-eslint/typescript-estree").TSESTree.ArrowFunctionExpression} ArrowFunctionExpression */
|
||||
/** @typedef {import("@typescript-eslint/typescript-estree").TSESTree.FunctionExpression} FunctionExpression */
|
||||
/** @typedef {import("@typescript-eslint/typescript-estree").TSESTree.TryStatement} TryStatement */
|
||||
/** @typedef {import("@typescript-eslint/typescript-estree").TSESTree.NewExpression} NewExpression */
|
||||
/** @typedef {import("typescript").ExportDeclaration} ExportDeclaration */
|
||||
/** @typedef {import("eslint").Rule.RuleFixer} Fixer */
|
||||
|
||||
const ERROR_MSG =
|
||||
'Passing an async function to the Promise constructor leads to a hidden promise being created and prevents handling rejections';
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
const tsEstree = require('@typescript-eslint/typescript-estree');
|
||||
const traverse = require('eslint-traverse');
|
||||
const esTypes = tsEstree.AST_NODE_TYPES;
|
||||
|
||||
/** @typedef {import("eslint").Rule.RuleModule} Rule */
|
||||
/** @typedef {import("@typescript-eslint/typescript-estree").TSESTree.Node} Node */
|
||||
/** @typedef {import("@typescript-eslint/typescript-estree").TSESTree.ClassBody} ClassBody */
|
||||
/** @typedef {import("@typescript-eslint/typescript-estree").TSESTree.Parameter} Parameter */
|
||||
/** @typedef {import("@typescript-eslint/typescript-estree").TSESTree.TSParameterProperty} TSParameterProperty */
|
||||
|
||||
/**
|
||||
* @param {Parameter} param
|
||||
* @returns {param is TSParameterProperty}
|
||||
*/
|
||||
function isTsParameterProperty(param) {
|
||||
return param.type === esTypes.TSParameterProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
*/
|
||||
const errorMsg = (arg) =>
|
||||
`The constructor argument "${arg}" can't be used in a class property intializer, define the property in the constructor instead`;
|
||||
|
||||
/** @type {Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
schema: [],
|
||||
},
|
||||
create: (context) => ({
|
||||
ClassBody(_) {
|
||||
const node = /** @type {ClassBody} */ (_);
|
||||
|
||||
const constructor = node.body.find(
|
||||
(n) => n.type === esTypes.MethodDefinition && n.kind === 'constructor'
|
||||
);
|
||||
|
||||
if (!constructor || constructor.type !== esTypes.MethodDefinition) {
|
||||
return;
|
||||
}
|
||||
|
||||
const constructorArgProps = constructor.value.params
|
||||
.filter(isTsParameterProperty)
|
||||
.map((p) => {
|
||||
if (p.parameter.type === esTypes.Identifier) {
|
||||
return p.parameter.name;
|
||||
}
|
||||
|
||||
if (
|
||||
p.parameter.type === esTypes.AssignmentPattern &&
|
||||
p.parameter.left.type === esTypes.Identifier
|
||||
) {
|
||||
return p.parameter.left.name;
|
||||
}
|
||||
});
|
||||
|
||||
if (!constructorArgProps.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const prop of node.body) {
|
||||
if (prop.type !== esTypes.PropertyDefinition) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const visitor = (path) => {
|
||||
/** @type {Node} node */
|
||||
const node = path.node;
|
||||
|
||||
if (
|
||||
node.type === esTypes.FunctionExpression ||
|
||||
node.type === esTypes.ArrowFunctionExpression
|
||||
) {
|
||||
return traverse.STOP;
|
||||
}
|
||||
|
||||
if (
|
||||
node.type === esTypes.MemberExpression &&
|
||||
node.object.type === esTypes.ThisExpression &&
|
||||
node.property.type === esTypes.Identifier &&
|
||||
node.property.name &&
|
||||
constructorArgProps.includes(node.property.name)
|
||||
) {
|
||||
context.report({
|
||||
message: errorMsg(node.property.name),
|
||||
loc: node.property.loc,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
traverse(context, prop, visitor);
|
||||
}
|
||||
},
|
||||
}),
|
||||
};
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
const { RuleTester } = require('eslint');
|
||||
const rule = require('./no_constructor_args_in_property_initializers');
|
||||
const dedent = require('dedent');
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
parser: require.resolve('@typescript-eslint/parser'),
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2018,
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
ruleTester.run('@kbn/eslint/no_constructor_args_in_property_initializers', rule, {
|
||||
valid: [
|
||||
{
|
||||
code: dedent`
|
||||
class Foo {
|
||||
bar = 'baz'
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
code: dedent`
|
||||
class Foo {
|
||||
bar = 'baz'
|
||||
constructor(private readonly foo: Box) {}
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
code: dedent`
|
||||
class Foo {
|
||||
bar = 'baz'
|
||||
constructor(private readonly foo: () => void) {}
|
||||
|
||||
get = () => {
|
||||
return this.foo()
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
],
|
||||
|
||||
invalid: [
|
||||
// no catch
|
||||
{
|
||||
code: dedent`
|
||||
class Foo {
|
||||
bar = this.foo.split().reverse()
|
||||
constructor(private readonly foo: string) {}
|
||||
}
|
||||
`,
|
||||
errors: [
|
||||
{
|
||||
line: 2,
|
||||
message: `The constructor argument "foo" can't be used in a class property intializer, define the property in the constructor instead`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
code: dedent`
|
||||
class Foo {
|
||||
bar = this.foo()
|
||||
constructor(private readonly foo: () => void) {}
|
||||
}
|
||||
`,
|
||||
errors: [
|
||||
{
|
||||
line: 2,
|
||||
message: `The constructor argument "foo" can't be used in a class property intializer, define the property in the constructor instead`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
code: dedent`
|
||||
class Foo {
|
||||
bar = this.foo()
|
||||
constructor(private readonly foo: (() => void) = defaultValue) {}
|
||||
}
|
||||
`,
|
||||
errors: [
|
||||
{
|
||||
line: 2,
|
||||
message: `The constructor argument "foo" can't be used in a class property intializer, define the property in the constructor instead`,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
|
@ -43,10 +43,12 @@ type ModuleFactory = (data: RequestData, callback: Callback<BundleRefModule>) =>
|
|||
export class BundleRefsPlugin {
|
||||
private readonly resolvedRefEntryCache = new Map<BundleRef, Promise<string>>();
|
||||
private readonly resolvedRequestCache = new Map<string, Promise<string | undefined>>();
|
||||
private readonly ignorePrefix = Path.resolve(this.bundle.contextDir) + Path.sep;
|
||||
private readonly ignorePrefix: string;
|
||||
private allowedBundleIds = new Set<string>();
|
||||
|
||||
constructor(private readonly bundle: Bundle, private readonly bundleRefs: BundleRefs) {}
|
||||
constructor(private readonly bundle: Bundle, private readonly bundleRefs: BundleRefs) {
|
||||
this.ignorePrefix = Path.resolve(this.bundle.contextDir) + Path.sep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by webpack when the plugin is passed in the webpack config
|
||||
|
|
|
@ -15,21 +15,27 @@ export type GetArgsType<T extends LifecycleEvent<any>> = T extends LifecycleEven
|
|||
export class LifecycleEvent<Args extends readonly any[]> {
|
||||
private readonly handlers: Array<(...args: Args) => Promise<void> | void> = [];
|
||||
|
||||
private readonly beforeSubj = this.options.singular
|
||||
? new Rx.BehaviorSubject(undefined)
|
||||
: new Rx.Subject<void>();
|
||||
public readonly before$ = this.beforeSubj.asObservable();
|
||||
private readonly beforeSubj: Rx.Subject<void>;
|
||||
public readonly before$: Rx.Observable<void>;
|
||||
|
||||
private readonly afterSubj = this.options.singular
|
||||
? new Rx.BehaviorSubject(undefined)
|
||||
: new Rx.Subject<void>();
|
||||
public readonly after$ = this.afterSubj.asObservable();
|
||||
private readonly afterSubj: Rx.Subject<void>;
|
||||
public readonly after$: Rx.Observable<void>;
|
||||
|
||||
constructor(
|
||||
private readonly options: {
|
||||
singular?: boolean;
|
||||
} = {}
|
||||
) {}
|
||||
) {
|
||||
this.beforeSubj = this.options.singular
|
||||
? new Rx.BehaviorSubject<void>(undefined)
|
||||
: new Rx.Subject<void>();
|
||||
this.before$ = this.beforeSubj.asObservable();
|
||||
|
||||
this.afterSubj = this.options.singular
|
||||
? new Rx.BehaviorSubject<void>(undefined)
|
||||
: new Rx.Subject<void>();
|
||||
this.after$ = this.afterSubj.asObservable();
|
||||
}
|
||||
|
||||
public add(fn: (...args: Args) => Promise<void> | void) {
|
||||
this.handlers.push(fn);
|
||||
|
|
|
@ -19,19 +19,23 @@ export class LifecyclePhase<Args extends readonly any[]> {
|
|||
|
||||
public triggered = false;
|
||||
|
||||
private readonly beforeSubj = new Rx.Subject<void>();
|
||||
public readonly before$ = this.beforeSubj.asObservable();
|
||||
private readonly beforeSubj: Rx.Subject<void>;
|
||||
public readonly before$: Rx.Observable<void>;
|
||||
|
||||
private readonly afterSubj = this.options.singular
|
||||
? new Rx.ReplaySubject<void>(1)
|
||||
: new Rx.Subject<void>();
|
||||
public readonly after$ = this.afterSubj.asObservable();
|
||||
private readonly afterSubj: Rx.Subject<void>;
|
||||
public readonly after$: Rx.Observable<void>;
|
||||
|
||||
constructor(
|
||||
private readonly options: {
|
||||
singular?: boolean;
|
||||
} = {}
|
||||
) {}
|
||||
) {
|
||||
this.beforeSubj = new Rx.Subject<void>();
|
||||
this.before$ = this.beforeSubj.asObservable();
|
||||
|
||||
this.afterSubj = this.options.singular ? new Rx.ReplaySubject<void>(1) : new Rx.Subject<void>();
|
||||
this.after$ = this.afterSubj.asObservable();
|
||||
}
|
||||
|
||||
public add(fn: (...args: Args) => Promise<void> | void) {
|
||||
this.handlers.push(fn);
|
||||
|
|
|
@ -21,10 +21,12 @@ import { ChromeService } from './chrome_service';
|
|||
import { getAppInfo } from '../application/utils';
|
||||
|
||||
class FakeApp implements App {
|
||||
public title = `${this.id} App`;
|
||||
public title: string;
|
||||
public mount = () => () => {};
|
||||
|
||||
constructor(public id: string, public chromeless?: boolean) {}
|
||||
constructor(public id: string, public chromeless?: boolean) {
|
||||
this.title = `${this.id} App`;
|
||||
}
|
||||
}
|
||||
|
||||
const store = new Map();
|
||||
|
|
|
@ -69,11 +69,13 @@ export interface InjectedMetadataParams {
|
|||
* @internal
|
||||
*/
|
||||
export class InjectedMetadataService {
|
||||
private state = deepFreeze(
|
||||
this.params.injectedMetadata
|
||||
) as InjectedMetadataParams['injectedMetadata'];
|
||||
private state: InjectedMetadataParams['injectedMetadata'];
|
||||
|
||||
constructor(private readonly params: InjectedMetadataParams) {}
|
||||
constructor(private readonly params: InjectedMetadataParams) {
|
||||
this.state = deepFreeze(
|
||||
this.params.injectedMetadata
|
||||
) as InjectedMetadataParams['injectedMetadata'];
|
||||
}
|
||||
|
||||
public start(): InjectedMetadataStart {
|
||||
return this.setup();
|
||||
|
|
|
@ -89,10 +89,10 @@ export interface PluginsServiceDiscoverDeps {
|
|||
/** @internal */
|
||||
export class PluginsService implements CoreService<PluginsServiceSetup, PluginsServiceStart> {
|
||||
private readonly log: Logger;
|
||||
private readonly prebootPluginsSystem = new PluginsSystem(this.coreContext, PluginType.preboot);
|
||||
private readonly prebootPluginsSystem: PluginsSystem<PluginType.preboot>;
|
||||
private arePrebootPluginsStopped = false;
|
||||
private readonly prebootUiPluginInternalInfo = new Map<PluginName, InternalPluginInfo>();
|
||||
private readonly standardPluginsSystem = new PluginsSystem(this.coreContext, PluginType.standard);
|
||||
private readonly standardPluginsSystem: PluginsSystem<PluginType.standard>;
|
||||
private readonly standardUiPluginInternalInfo = new Map<PluginName, InternalPluginInfo>();
|
||||
private readonly configService: IConfigService;
|
||||
private readonly config$: Observable<PluginsConfig>;
|
||||
|
@ -105,6 +105,8 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
|
|||
this.config$ = coreContext.configService
|
||||
.atPath<PluginsConfigType>('plugins')
|
||||
.pipe(map((rawConfig) => new PluginsConfig(rawConfig, coreContext.env)));
|
||||
this.prebootPluginsSystem = new PluginsSystem(this.coreContext, PluginType.preboot);
|
||||
this.standardPluginsSystem = new PluginsSystem(this.coreContext, PluginType.standard);
|
||||
}
|
||||
|
||||
public async discover({ environment }: PluginsServiceDiscoverDeps): Promise<DiscoveredPlugins> {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Logger } from '@kbn/logging';
|
||||
import { CoreContext } from '../core_context';
|
||||
import { InternalPrebootServicePreboot } from './types';
|
||||
|
||||
|
@ -14,9 +15,11 @@ export class PrebootService {
|
|||
private readonly promiseList: Array<Promise<{ shouldReloadConfig: boolean } | undefined>> = [];
|
||||
private waitUntilCanSetupPromise?: Promise<{ shouldReloadConfig: boolean }>;
|
||||
private isSetupOnHold = false;
|
||||
private readonly log = this.core.logger.get('preboot');
|
||||
private readonly log: Logger;
|
||||
|
||||
constructor(private readonly core: CoreContext) {}
|
||||
constructor(private readonly core: CoreContext) {
|
||||
this.log = this.core.logger.get('preboot');
|
||||
}
|
||||
|
||||
public preboot(): InternalPrebootServicePreboot {
|
||||
return {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import axios, { AxiosError, AxiosResponse } from 'axios';
|
||||
import axios, { AxiosError, AxiosResponse, AxiosInstance } from 'axios';
|
||||
|
||||
import { createFailError } from '@kbn/dev-utils';
|
||||
|
||||
|
@ -23,16 +23,18 @@ const isRateLimitError = (error: any) =>
|
|||
`${error.response.headers['X-RateLimit-Remaining']}` === '0';
|
||||
|
||||
export class GithubApi {
|
||||
private api = axios.create({
|
||||
baseURL: 'https://api.github.com/',
|
||||
headers: {
|
||||
Accept: 'application/vnd.github.v3+json',
|
||||
'User-Agent': 'kibana/update_prs_cli',
|
||||
...(this.accessToken ? { Authorization: `token ${this.accessToken} ` } : {}),
|
||||
},
|
||||
});
|
||||
private api: AxiosInstance;
|
||||
|
||||
constructor(private accessToken?: string) {}
|
||||
constructor(private accessToken?: string) {
|
||||
this.api = axios.create({
|
||||
baseURL: 'https://api.github.com/',
|
||||
headers: {
|
||||
Accept: 'application/vnd.github.v3+json',
|
||||
'User-Agent': 'kibana/update_prs_cli',
|
||||
...(this.accessToken ? { Authorization: `token ${this.accessToken} ` } : {}),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async getPrInfo(prNumber: number) {
|
||||
try {
|
||||
|
|
|
@ -21,12 +21,14 @@ export class Pr {
|
|||
return parseInt(input, 10);
|
||||
}
|
||||
|
||||
public readonly remoteRef = `pull/${this.number}/head`;
|
||||
public readonly remoteRef: string;
|
||||
|
||||
constructor(
|
||||
public readonly number: number,
|
||||
public readonly targetRef: string,
|
||||
public readonly owner: string,
|
||||
public readonly sourceBranch: string
|
||||
) {}
|
||||
) {
|
||||
this.remoteRef = `pull/${this.number}/head`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,10 +43,16 @@ export class DashboardContainerFactoryDefinition
|
|||
public readonly isContainerType = true;
|
||||
public readonly type = DASHBOARD_CONTAINER_TYPE;
|
||||
|
||||
public inject: EmbeddablePersistableStateService['inject'];
|
||||
public extract: EmbeddablePersistableStateService['extract'];
|
||||
|
||||
constructor(
|
||||
private readonly getStartServices: () => Promise<DashboardContainerServices>,
|
||||
private readonly persistableStateService: EmbeddablePersistableStateService
|
||||
) {}
|
||||
) {
|
||||
this.inject = createInject(this.persistableStateService);
|
||||
this.extract = createExtract(this.persistableStateService);
|
||||
}
|
||||
|
||||
public isEditable = async () => {
|
||||
// Currently unused for dashboards
|
||||
|
@ -91,8 +97,4 @@ export class DashboardContainerFactoryDefinition
|
|||
|
||||
return new DashboardContainerEmbeddable(initialInput, services, parent, controlGroup);
|
||||
};
|
||||
|
||||
public inject = createInject(this.persistableStateService);
|
||||
|
||||
public extract = createExtract(this.persistableStateService);
|
||||
}
|
||||
|
|
|
@ -27,11 +27,14 @@ export interface HomeServerPluginSetupDependencies {
|
|||
}
|
||||
|
||||
export class HomeServerPlugin implements Plugin<HomeServerPluginSetup, HomeServerPluginStart> {
|
||||
constructor(private readonly initContext: PluginInitializerContext) {}
|
||||
private readonly tutorialsRegistry = new TutorialsRegistry();
|
||||
private readonly sampleDataRegistry = new SampleDataRegistry(this.initContext);
|
||||
private readonly sampleDataRegistry: SampleDataRegistry;
|
||||
private customIntegrations?: CustomIntegrationsPluginSetup;
|
||||
|
||||
constructor(private readonly initContext: PluginInitializerContext) {
|
||||
this.sampleDataRegistry = new SampleDataRegistry(this.initContext);
|
||||
}
|
||||
|
||||
public setup(core: CoreSetup, plugins: HomeServerPluginSetupDependencies): HomeServerPluginSetup {
|
||||
this.customIntegrations = plugins.customIntegrations;
|
||||
|
||||
|
|
|
@ -27,7 +27,13 @@ export class ControlGroupContainerFactory implements EmbeddableFactoryDefinition
|
|||
public readonly isContainerType = true;
|
||||
public readonly type = CONTROL_GROUP_TYPE;
|
||||
|
||||
constructor(private persistableStateService: EmbeddablePersistableStateService) {}
|
||||
public inject: EmbeddablePersistableStateService['inject'];
|
||||
public extract: EmbeddablePersistableStateService['extract'];
|
||||
|
||||
constructor(private persistableStateService: EmbeddablePersistableStateService) {
|
||||
this.inject = createControlGroupInject(this.persistableStateService);
|
||||
this.extract = createControlGroupExtract(this.persistableStateService);
|
||||
}
|
||||
|
||||
public isEditable = async () => false;
|
||||
|
||||
|
@ -50,7 +56,4 @@ export class ControlGroupContainerFactory implements EmbeddableFactoryDefinition
|
|||
const { ControlGroupContainer } = await import('./control_group_container');
|
||||
return new ControlGroupContainer(initialInput, parent);
|
||||
};
|
||||
|
||||
public inject = createControlGroupInject(this.persistableStateService);
|
||||
public extract = createControlGroupExtract(this.persistableStateService);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,10 @@ export type ActionDefinitionContext<Context extends object = object> =
|
|||
| Context
|
||||
| ActionExecutionContext<Context>;
|
||||
|
||||
export interface ActionMenuItemProps<Context extends object> {
|
||||
context: ActionExecutionContext<Context>;
|
||||
}
|
||||
|
||||
export interface Action<Context extends object = object>
|
||||
extends Partial<Presentable<ActionExecutionContext<Context>>> {
|
||||
/**
|
||||
|
@ -68,7 +72,7 @@ export interface Action<Context extends object = object>
|
|||
* `UiComponent` to render when displaying this action as a context menu item.
|
||||
* If not provided, `getDisplayName` will be used instead.
|
||||
*/
|
||||
MenuItem?: UiComponent<{ context: ActionExecutionContext<Context> }>;
|
||||
MenuItem?: UiComponent<ActionMenuItemProps<Context>>;
|
||||
|
||||
/**
|
||||
* Returns a promise that resolves to true if this action is compatible given the context,
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
// @ts-ignore
|
||||
import React from 'react';
|
||||
import { Action, ActionContext as Context, ActionDefinition } from './action';
|
||||
import type { UiComponent } from 'src/plugins/kibana_utils/public';
|
||||
import { Action, ActionContext as Context, ActionDefinition, ActionMenuItemProps } from './action';
|
||||
import { Presentable, PresentableGrouping } from '../util/presentable';
|
||||
import { uiToReactComponent } from '../../../kibana_react/public';
|
||||
|
||||
|
@ -18,14 +19,21 @@ import { uiToReactComponent } from '../../../kibana_react/public';
|
|||
export class ActionInternal<A extends ActionDefinition = ActionDefinition>
|
||||
implements Action<Context<A>>, Presentable<Context<A>>
|
||||
{
|
||||
constructor(public readonly definition: A) {}
|
||||
public readonly id: string;
|
||||
public readonly type: string;
|
||||
public readonly order: number;
|
||||
public readonly MenuItem?: UiComponent<ActionMenuItemProps<Context<A>>>;
|
||||
public readonly ReactMenuItem?: React.FC<ActionMenuItemProps<Context<A>>>;
|
||||
public readonly grouping?: PresentableGrouping<Context<A>>;
|
||||
|
||||
public readonly id: string = this.definition.id;
|
||||
public readonly type: string = this.definition.type || '';
|
||||
public readonly order: number = this.definition.order || 0;
|
||||
public readonly MenuItem? = this.definition.MenuItem;
|
||||
public readonly ReactMenuItem? = this.MenuItem ? uiToReactComponent(this.MenuItem) : undefined;
|
||||
public readonly grouping?: PresentableGrouping<Context<A>> = this.definition.grouping;
|
||||
constructor(public readonly definition: A) {
|
||||
this.id = this.definition.id;
|
||||
this.type = this.definition.type || '';
|
||||
this.order = this.definition.order || 0;
|
||||
this.MenuItem = this.definition.MenuItem;
|
||||
this.ReactMenuItem = this.MenuItem ? uiToReactComponent(this.MenuItem) : undefined;
|
||||
this.grouping = this.definition.grouping;
|
||||
}
|
||||
|
||||
public execute(context: Context<A>) {
|
||||
return this.definition.execute(context);
|
||||
|
|
|
@ -38,4 +38,4 @@ export {
|
|||
ACTION_VISUALIZE_GEO_FIELD,
|
||||
ACTION_VISUALIZE_LENS_FIELD,
|
||||
} from './types';
|
||||
export type { ActionExecutionContext, ActionExecutionMeta } from './actions';
|
||||
export type { ActionExecutionContext, ActionExecutionMeta, ActionMenuItemProps } from './actions';
|
||||
|
|
|
@ -25,9 +25,8 @@ class BrowserService extends FtrService {
|
|||
* Keyboard events
|
||||
*/
|
||||
public readonly keys = Key;
|
||||
public readonly isFirefox: boolean = this.browserType === Browsers.Firefox;
|
||||
public readonly isChromium: boolean =
|
||||
this.browserType === Browsers.Chrome || this.browserType === Browsers.ChromiumEdge;
|
||||
public readonly isFirefox: boolean;
|
||||
public readonly isChromium: boolean;
|
||||
|
||||
private readonly log = this.ctx.getService('log');
|
||||
|
||||
|
@ -37,6 +36,9 @@ class BrowserService extends FtrService {
|
|||
private readonly driver: WebDriver
|
||||
) {
|
||||
super(ctx);
|
||||
this.isFirefox = this.browserType === Browsers.Firefox;
|
||||
this.isChromium =
|
||||
this.browserType === Browsers.Chrome || this.browserType === Browsers.ChromiumEdge;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,7 +35,7 @@ const RETRY_CLICK_RETRY_ON_ERRORS = [
|
|||
export class WebElementWrapper {
|
||||
private By = By;
|
||||
private Keys = Key;
|
||||
public isChromium: boolean = [Browsers.Chrome, Browsers.ChromiumEdge].includes(this.browserType);
|
||||
public isChromium: boolean;
|
||||
|
||||
public static create(
|
||||
webElement: WebElement | WebElementWrapper,
|
||||
|
@ -69,7 +69,9 @@ export class WebElementWrapper {
|
|||
private fixedHeaderHeight: number,
|
||||
private logger: ToolingLog,
|
||||
private browserType: Browsers
|
||||
) {}
|
||||
) {
|
||||
this.isChromium = [Browsers.Chrome, Browsers.ChromiumEdge].includes(this.browserType);
|
||||
}
|
||||
|
||||
private async _findWithCustomTimeout(
|
||||
findFunction: () => Promise<Array<WebElement | WebElementWrapper>>,
|
||||
|
|
|
@ -55,17 +55,20 @@ export class SecurityPlugin
|
|||
PluginStartDependencies
|
||||
>
|
||||
{
|
||||
private readonly config = this.initializerContext.config.get<ConfigType>();
|
||||
private readonly config: ConfigType;
|
||||
private sessionTimeout!: SessionTimeout;
|
||||
private readonly authenticationService = new AuthenticationService();
|
||||
private readonly navControlService = new SecurityNavControlService();
|
||||
private readonly securityLicenseService = new SecurityLicenseService();
|
||||
private readonly managementService = new ManagementService();
|
||||
private readonly securityCheckupService = new SecurityCheckupService(this.config, localStorage);
|
||||
private readonly securityCheckupService: SecurityCheckupService;
|
||||
private readonly anonymousAccessService = new AnonymousAccessService();
|
||||
private authc!: AuthenticationServiceSetup;
|
||||
|
||||
constructor(private readonly initializerContext: PluginInitializerContext) {}
|
||||
constructor(private readonly initializerContext: PluginInitializerContext) {
|
||||
this.config = this.initializerContext.config.get<ConfigType>();
|
||||
this.securityCheckupService = new SecurityCheckupService(this.config, localStorage);
|
||||
}
|
||||
|
||||
public setup(
|
||||
core: CoreSetup<PluginStartDependencies>,
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { Logger } from '@kbn/logging';
|
||||
import type { PublicMethodsOf } from '@kbn/utility-types';
|
||||
import type { IBasePath, IClusterClient, LoggerFactory } from 'src/core/server';
|
||||
|
||||
|
@ -196,18 +197,21 @@ export class Authenticator {
|
|||
/**
|
||||
* Session instance.
|
||||
*/
|
||||
private readonly session = this.options.session;
|
||||
private readonly session: AuthenticatorOptions['session'];
|
||||
|
||||
/**
|
||||
* Internal authenticator logger.
|
||||
*/
|
||||
private readonly logger = this.options.loggers.get('authenticator');
|
||||
private readonly logger: Logger;
|
||||
|
||||
/**
|
||||
* Instantiates Authenticator and bootstrap configured providers.
|
||||
* @param options Authenticator options.
|
||||
*/
|
||||
constructor(private readonly options: Readonly<AuthenticatorOptions>) {
|
||||
this.session = this.options.session;
|
||||
this.logger = this.options.loggers.get('authenticator');
|
||||
|
||||
const providerCommonOptions = {
|
||||
client: this.options.clusterClient,
|
||||
basePath: this.options.basePath,
|
||||
|
|
|
@ -18,27 +18,29 @@ import { UIActions } from './ui';
|
|||
* by the various `checkPrivilegesWithRequest` derivatives.
|
||||
*/
|
||||
export class Actions {
|
||||
public readonly api = new ApiActions(this.versionNumber);
|
||||
|
||||
public readonly app = new AppActions(this.versionNumber);
|
||||
|
||||
public readonly cases = new CasesActions(this.versionNumber);
|
||||
|
||||
public readonly login = 'login:';
|
||||
|
||||
public readonly savedObject = new SavedObjectActions(this.versionNumber);
|
||||
|
||||
public readonly alerting = new AlertingActions(this.versionNumber);
|
||||
|
||||
public readonly space = new SpaceActions(this.versionNumber);
|
||||
|
||||
public readonly ui = new UIActions(this.versionNumber);
|
||||
|
||||
public readonly version = `version:${this.versionNumber}`;
|
||||
public readonly api: ApiActions;
|
||||
public readonly app: AppActions;
|
||||
public readonly cases: CasesActions;
|
||||
public readonly login: string;
|
||||
public readonly savedObject: SavedObjectActions;
|
||||
public readonly alerting: AlertingActions;
|
||||
public readonly space: SpaceActions;
|
||||
public readonly ui: UIActions;
|
||||
public readonly version: string;
|
||||
|
||||
constructor(private readonly versionNumber: string) {
|
||||
if (versionNumber === '') {
|
||||
throw new Error(`version can't be an empty string`);
|
||||
}
|
||||
|
||||
this.api = new ApiActions(this.versionNumber);
|
||||
this.app = new AppActions(this.versionNumber);
|
||||
this.cases = new CasesActions(this.versionNumber);
|
||||
this.login = 'login:';
|
||||
this.savedObject = new SavedObjectActions(this.versionNumber);
|
||||
this.alerting = new AlertingActions(this.versionNumber);
|
||||
this.space = new SpaceActions(this.versionNumber);
|
||||
this.ui = new UIActions(this.versionNumber);
|
||||
this.version = `version:${this.versionNumber}`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -153,9 +153,7 @@ export class SecurityPlugin
|
|||
return this.kibanaIndexName;
|
||||
};
|
||||
|
||||
private readonly authenticationService = new AuthenticationService(
|
||||
this.initializerContext.logger.get('authentication')
|
||||
);
|
||||
private readonly authenticationService: AuthenticationService;
|
||||
private authenticationStart?: InternalAuthenticationServiceStart;
|
||||
private readonly getAuthentication = () => {
|
||||
if (!this.authenticationStart) {
|
||||
|
@ -173,19 +171,12 @@ export class SecurityPlugin
|
|||
return this.featureUsageServiceStart;
|
||||
};
|
||||
|
||||
private readonly auditService = new AuditService(this.initializerContext.logger.get('audit'));
|
||||
private readonly auditService: AuditService;
|
||||
private readonly securityLicenseService = new SecurityLicenseService();
|
||||
private readonly authorizationService = new AuthorizationService();
|
||||
private readonly elasticsearchService = new ElasticsearchService(
|
||||
this.initializerContext.logger.get('elasticsearch')
|
||||
);
|
||||
private readonly sessionManagementService = new SessionManagementService(
|
||||
this.initializerContext.logger.get('session')
|
||||
);
|
||||
private readonly anonymousAccessService = new AnonymousAccessService(
|
||||
this.initializerContext.logger.get('anonymous-access'),
|
||||
this.getConfig
|
||||
);
|
||||
private readonly elasticsearchService: ElasticsearchService;
|
||||
private readonly sessionManagementService: SessionManagementService;
|
||||
private readonly anonymousAccessService: AnonymousAccessService;
|
||||
private anonymousAccessStart?: AnonymousAccessServiceStart;
|
||||
private readonly getAnonymousAccess = () => {
|
||||
if (!this.anonymousAccessStart) {
|
||||
|
@ -196,6 +187,21 @@ export class SecurityPlugin
|
|||
|
||||
constructor(private readonly initializerContext: PluginInitializerContext) {
|
||||
this.logger = this.initializerContext.logger.get();
|
||||
|
||||
this.authenticationService = new AuthenticationService(
|
||||
this.initializerContext.logger.get('authentication')
|
||||
);
|
||||
this.auditService = new AuditService(this.initializerContext.logger.get('audit'));
|
||||
this.elasticsearchService = new ElasticsearchService(
|
||||
this.initializerContext.logger.get('elasticsearch')
|
||||
);
|
||||
this.sessionManagementService = new SessionManagementService(
|
||||
this.initializerContext.logger.get('session')
|
||||
);
|
||||
this.anonymousAccessService = new AnonymousAccessService(
|
||||
this.initializerContext.logger.get('anonymous-access'),
|
||||
this.getConfig
|
||||
);
|
||||
}
|
||||
|
||||
public setup(
|
||||
|
|
|
@ -132,7 +132,7 @@ export class SessionIndex {
|
|||
/**
|
||||
* Name of the index to store session information in.
|
||||
*/
|
||||
private readonly indexName = `${this.options.kibanaIndexName}_security_session_${SESSION_INDEX_TEMPLATE_VERSION}`;
|
||||
private readonly indexName: string;
|
||||
|
||||
/**
|
||||
* Promise that tracks session index initialization process. We'll need to get rid of this as soon
|
||||
|
@ -142,7 +142,9 @@ export class SessionIndex {
|
|||
*/
|
||||
private indexInitialization?: Promise<void>;
|
||||
|
||||
constructor(private readonly options: Readonly<SessionIndexOptions>) {}
|
||||
constructor(private readonly options: Readonly<SessionIndexOptions>) {
|
||||
this.indexName = `${this.options.kibanaIndexName}_security_session_${SESSION_INDEX_TEMPLATE_VERSION}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves session value with the specified ID from the index. If session value isn't found
|
||||
|
|
|
@ -44,7 +44,7 @@ const PURPOSE_PRIVILEGE_MAP: Record<
|
|||
export const LEGACY_URL_ALIAS_TYPE = 'legacy-url-alias';
|
||||
|
||||
export class SecureSpacesClientWrapper implements ISpacesClient {
|
||||
private readonly useRbac = this.authorization.mode.useRbacForRequest(this.request);
|
||||
private readonly useRbac: boolean;
|
||||
|
||||
constructor(
|
||||
private readonly spacesClient: ISpacesClient,
|
||||
|
@ -52,7 +52,9 @@ export class SecureSpacesClientWrapper implements ISpacesClient {
|
|||
private readonly authorization: AuthorizationServiceSetup,
|
||||
private readonly auditLogger: AuditLogger,
|
||||
private readonly errors: SavedObjectsClientContract['errors']
|
||||
) {}
|
||||
) {
|
||||
this.useRbac = this.authorization.mode.useRbacForRequest(this.request);
|
||||
}
|
||||
|
||||
public async getAll({
|
||||
purpose = 'any',
|
||||
|
|
|
@ -107,9 +107,7 @@ export class DrilldownManagerState {
|
|||
triggerIncompatible: !this.deps.triggers.find((t) => t === firstTrigger),
|
||||
};
|
||||
};
|
||||
public readonly events$ = new BehaviorSubject<DrilldownTableItem[]>(
|
||||
this.deps.dynamicActionManager.state.get().events.map(this.mapEventToDrilldownItem)
|
||||
);
|
||||
public readonly events$: BehaviorSubject<DrilldownTableItem[]>;
|
||||
|
||||
/**
|
||||
* State for each drilldown type used for new drilldown creation, so when user
|
||||
|
@ -136,6 +134,10 @@ export class DrilldownManagerState {
|
|||
(factory) => !factory.isCompatibleLicense
|
||||
);
|
||||
|
||||
this.events$ = new BehaviorSubject<DrilldownTableItem[]>(
|
||||
this.deps.dynamicActionManager.state.get().events.map(this.mapEventToDrilldownItem)
|
||||
);
|
||||
|
||||
deps.dynamicActionManager.state.state$
|
||||
.pipe(map((state) => state.events.map(this.mapEventToDrilldownItem)))
|
||||
.subscribe(this.events$);
|
||||
|
|
|
@ -5,8 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { UiComponent, CollectConfigProps } from 'src/plugins/kibana_utils/public';
|
||||
import type { MigrateFunctionsObject } from 'src/plugins/kibana_utils/common';
|
||||
import { uiToReactComponent } from '../../../../../src/plugins/kibana_react/public';
|
||||
import type { UiActionsPresentable as Presentable } from '../../../../../src/plugins/ui_actions/public';
|
||||
import type {
|
||||
UiActionsPresentable as Presentable,
|
||||
ActionMenuItemProps,
|
||||
} from '../../../../../src/plugins/ui_actions/public';
|
||||
import type { ActionFactoryDefinition } from './action_factory_definition';
|
||||
import type { Configurable } from '../../../../../src/plugins/kibana_utils/public';
|
||||
import type {
|
||||
|
@ -15,7 +20,7 @@ import type {
|
|||
SerializedAction,
|
||||
SerializedEvent,
|
||||
} from './types';
|
||||
import type { ILicense, LicensingPluginStart } from '../../../licensing/public';
|
||||
import type { ILicense, LicensingPluginStart, LicenseType } from '../../../licensing/public';
|
||||
import type { UiActionsActionDefinition as ActionDefinition } from '../../../../../src/plugins/ui_actions/public';
|
||||
import type { SavedObjectReference } from '../../../../../src/core/types';
|
||||
import type { PersistableState } from '../../../../../src/plugins/kibana_utils/common';
|
||||
|
@ -34,6 +39,20 @@ export class ActionFactory<
|
|||
Configurable<Config, FactoryContext>,
|
||||
PersistableState<SerializedEvent>
|
||||
{
|
||||
public readonly id: string;
|
||||
public readonly isBeta: boolean;
|
||||
public readonly minimalLicense?: LicenseType;
|
||||
public readonly licenseFeatureName?: string;
|
||||
public readonly order: number;
|
||||
public readonly MenuItem?: UiComponent<ActionMenuItemProps<FactoryContext>>;
|
||||
public readonly ReactMenuItem?: React.FC<ActionMenuItemProps<FactoryContext>>;
|
||||
|
||||
public readonly CollectConfig: UiComponent<CollectConfigProps<Config, FactoryContext>>;
|
||||
public readonly ReactCollectConfig: React.FC<CollectConfigProps<Config, FactoryContext>>;
|
||||
public readonly createConfig: (context: FactoryContext) => Config;
|
||||
public readonly isConfigValid: (config: Config, context: FactoryContext) => boolean;
|
||||
public readonly migrations: MigrateFunctionsObject;
|
||||
|
||||
constructor(
|
||||
protected readonly def: ActionFactoryDefinition<Config, ExecutionContext, FactoryContext>,
|
||||
protected readonly deps: ActionFactoryDeps
|
||||
|
@ -43,22 +62,21 @@ export class ActionFactory<
|
|||
`ActionFactory [actionFactory.id = ${def.id}] "licenseFeatureName" is required, if "minimalLicense" is provided`
|
||||
);
|
||||
}
|
||||
|
||||
this.id = this.def.id;
|
||||
this.isBeta = this.def.isBeta ?? false;
|
||||
this.minimalLicense = this.def.minimalLicense;
|
||||
this.licenseFeatureName = this.def.licenseFeatureName;
|
||||
this.order = this.def.order || 0;
|
||||
this.MenuItem = this.def.MenuItem;
|
||||
this.ReactMenuItem = this.MenuItem ? uiToReactComponent(this.MenuItem) : undefined;
|
||||
this.CollectConfig = this.def.CollectConfig;
|
||||
this.ReactCollectConfig = uiToReactComponent(this.CollectConfig);
|
||||
this.createConfig = this.def.createConfig;
|
||||
this.isConfigValid = this.def.isConfigValid;
|
||||
this.migrations = this.def.migrations || {};
|
||||
}
|
||||
|
||||
public readonly id = this.def.id;
|
||||
public readonly isBeta = this.def.isBeta ?? false;
|
||||
public readonly minimalLicense = this.def.minimalLicense;
|
||||
public readonly licenseFeatureName = this.def.licenseFeatureName;
|
||||
public readonly order = this.def.order || 0;
|
||||
public readonly MenuItem? = this.def.MenuItem;
|
||||
public readonly ReactMenuItem? = this.MenuItem ? uiToReactComponent(this.MenuItem) : undefined;
|
||||
|
||||
public readonly CollectConfig = this.def.CollectConfig;
|
||||
public readonly ReactCollectConfig = uiToReactComponent(this.CollectConfig);
|
||||
public readonly createConfig = this.def.createConfig;
|
||||
public readonly isConfigValid = this.def.isConfigValid;
|
||||
public readonly migrations = this.def.migrations || {};
|
||||
|
||||
public getIconType(context: FactoryContext): string | undefined {
|
||||
if (!this.def.getIconType) return undefined;
|
||||
return this.def.getIconType(context);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue