mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
feat(rca): items management api (#190852)
This commit is contained in:
parent
24b4eb4d18
commit
ca6f3edf0d
39 changed files with 434 additions and 126 deletions
|
@ -6,22 +6,4 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export type * from './src/schema/create';
|
||||
export type * from './src/schema/create_notes';
|
||||
export type * from './src/schema/delete';
|
||||
export type * from './src/schema/find';
|
||||
export type * from './src/schema/get';
|
||||
export type * from './src/schema/get_notes';
|
||||
export type * from './src/schema/origin';
|
||||
export type * from './src/schema/delete_note';
|
||||
export type * from './src/schema/investigation_note';
|
||||
|
||||
export * from './src/schema/create';
|
||||
export * from './src/schema/create_notes';
|
||||
export * from './src/schema/delete';
|
||||
export * from './src/schema/find';
|
||||
export * from './src/schema/get';
|
||||
export * from './src/schema/get_notes';
|
||||
export * from './src/schema/origin';
|
||||
export * from './src/schema/delete_note';
|
||||
export * from './src/schema/investigation_note';
|
||||
export * from './src';
|
||||
|
|
10
packages/kbn-investigation-shared/src/index.ts
Normal file
10
packages/kbn-investigation-shared/src/index.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './rest_specs';
|
||||
export * from './schema';
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import * as t from 'io-ts';
|
||||
import { investigationResponseSchema } from './investigation';
|
||||
import { alertOriginSchema, blankOriginSchema } from './origin';
|
||||
import { alertOriginSchema, blankOriginSchema } from '../schema';
|
||||
|
||||
const createInvestigationParamsSchema = t.type({
|
||||
body: t.type({
|
||||
|
@ -23,9 +23,8 @@ const createInvestigationParamsSchema = t.type({
|
|||
|
||||
const createInvestigationResponseSchema = investigationResponseSchema;
|
||||
|
||||
type CreateInvestigationInput = t.OutputOf<typeof createInvestigationParamsSchema.props.body>; // Raw payload sent by the frontend
|
||||
type CreateInvestigationParams = t.TypeOf<typeof createInvestigationParamsSchema.props.body>; // Parsed payload used by the backend
|
||||
type CreateInvestigationResponse = t.OutputOf<typeof createInvestigationResponseSchema>; // Raw response sent to the frontend
|
||||
type CreateInvestigationParams = t.TypeOf<typeof createInvestigationParamsSchema.props.body>;
|
||||
type CreateInvestigationResponse = t.OutputOf<typeof createInvestigationResponseSchema>;
|
||||
|
||||
export { createInvestigationParamsSchema, createInvestigationResponseSchema };
|
||||
export type { CreateInvestigationInput, CreateInvestigationParams, CreateInvestigationResponse };
|
||||
export type { CreateInvestigationParams, CreateInvestigationResponse };
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { investigationItemsSchema } from '../schema';
|
||||
import { investigationItemResponseSchema } from './investigation_item';
|
||||
|
||||
const createInvestigationItemParamsSchema = t.type({
|
||||
path: t.type({
|
||||
investigationId: t.string,
|
||||
}),
|
||||
body: investigationItemsSchema,
|
||||
});
|
||||
|
||||
const createInvestigationItemResponseSchema = investigationItemResponseSchema;
|
||||
|
||||
type CreateInvestigationItemParams = t.TypeOf<
|
||||
typeof createInvestigationItemParamsSchema.props.body
|
||||
>;
|
||||
type CreateInvestigationItemResponse = t.OutputOf<typeof createInvestigationItemResponseSchema>;
|
||||
|
||||
export { createInvestigationItemParamsSchema, createInvestigationItemResponseSchema };
|
||||
export type { CreateInvestigationItemParams, CreateInvestigationItemResponse };
|
|
@ -11,7 +11,7 @@ import { investigationNoteResponseSchema } from './investigation_note';
|
|||
|
||||
const createInvestigationNoteParamsSchema = t.type({
|
||||
path: t.type({
|
||||
id: t.string,
|
||||
investigationId: t.string,
|
||||
}),
|
||||
body: t.type({
|
||||
content: t.string,
|
||||
|
@ -20,17 +20,10 @@ const createInvestigationNoteParamsSchema = t.type({
|
|||
|
||||
const createInvestigationNoteResponseSchema = investigationNoteResponseSchema;
|
||||
|
||||
type CreateInvestigationNoteInput = t.OutputOf<
|
||||
typeof createInvestigationNoteParamsSchema.props.body
|
||||
>;
|
||||
type CreateInvestigationNoteParams = t.TypeOf<
|
||||
typeof createInvestigationNoteParamsSchema.props.body
|
||||
>;
|
||||
type CreateInvestigationNoteResponse = t.OutputOf<typeof createInvestigationNoteResponseSchema>;
|
||||
|
||||
export { createInvestigationNoteParamsSchema, createInvestigationNoteResponseSchema };
|
||||
export type {
|
||||
CreateInvestigationNoteInput,
|
||||
CreateInvestigationNoteParams,
|
||||
CreateInvestigationNoteResponse,
|
||||
};
|
||||
export type { CreateInvestigationNoteParams, CreateInvestigationNoteResponse };
|
|
@ -10,11 +10,11 @@ import * as t from 'io-ts';
|
|||
|
||||
const deleteInvestigationParamsSchema = t.type({
|
||||
path: t.type({
|
||||
id: t.string,
|
||||
investigationId: t.string,
|
||||
}),
|
||||
});
|
||||
|
||||
type DeleteInvestigationParams = t.TypeOf<typeof deleteInvestigationParamsSchema.props.path>; // Parsed payload used by the backend
|
||||
type DeleteInvestigationParams = t.TypeOf<typeof deleteInvestigationParamsSchema.props.path>;
|
||||
|
||||
export { deleteInvestigationParamsSchema };
|
||||
export type { DeleteInvestigationParams };
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
|
||||
const deleteInvestigationItemParamsSchema = t.type({
|
||||
path: t.type({
|
||||
investigationId: t.string,
|
||||
itemId: t.string,
|
||||
}),
|
||||
});
|
||||
|
||||
type DeleteInvestigationItemParams = t.TypeOf<
|
||||
typeof deleteInvestigationItemParamsSchema.props.path
|
||||
>;
|
||||
|
||||
export { deleteInvestigationItemParamsSchema };
|
||||
export type { DeleteInvestigationItemParams };
|
|
@ -10,14 +10,14 @@ import * as t from 'io-ts';
|
|||
|
||||
const deleteInvestigationNoteParamsSchema = t.type({
|
||||
path: t.type({
|
||||
id: t.string,
|
||||
investigationId: t.string,
|
||||
noteId: t.string,
|
||||
}),
|
||||
});
|
||||
|
||||
type DeleteInvestigationNoteParams = t.TypeOf<
|
||||
typeof deleteInvestigationNoteParamsSchema.props.path
|
||||
>; // Parsed payload used by the backend
|
||||
>;
|
||||
|
||||
export { deleteInvestigationNoteParamsSchema };
|
||||
export type { DeleteInvestigationNoteParams };
|
|
@ -24,8 +24,8 @@ const findInvestigationsResponseSchema = t.type({
|
|||
results: t.array(investigationResponseSchema),
|
||||
});
|
||||
|
||||
type FindInvestigationsParams = t.TypeOf<typeof findInvestigationsParamsSchema.props.query>; // Parsed payload used by the backend
|
||||
type FindInvestigationsResponse = t.OutputOf<typeof findInvestigationsResponseSchema>; // Raw response sent to the frontend
|
||||
type FindInvestigationsParams = t.TypeOf<typeof findInvestigationsParamsSchema.props.query>;
|
||||
type FindInvestigationsResponse = t.OutputOf<typeof findInvestigationsResponseSchema>;
|
||||
|
||||
export { findInvestigationsParamsSchema, findInvestigationsResponseSchema };
|
||||
export type { FindInvestigationsParams, FindInvestigationsResponse };
|
|
@ -11,7 +11,7 @@ import { investigationResponseSchema } from './investigation';
|
|||
|
||||
const getInvestigationParamsSchema = t.type({
|
||||
path: t.type({
|
||||
id: t.string,
|
||||
investigationId: t.string,
|
||||
}),
|
||||
});
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { investigationItemResponseSchema } from './investigation_item';
|
||||
|
||||
const getInvestigationItemsParamsSchema = t.type({
|
||||
path: t.type({
|
||||
investigationId: t.string,
|
||||
}),
|
||||
});
|
||||
|
||||
const getInvestigationItemsResponseSchema = t.array(investigationItemResponseSchema);
|
||||
|
||||
type GetInvestigationItemsResponse = t.OutputOf<typeof getInvestigationItemsResponseSchema>;
|
||||
|
||||
export { getInvestigationItemsParamsSchema, getInvestigationItemsResponseSchema };
|
||||
export type { GetInvestigationItemsResponse };
|
|
@ -11,7 +11,7 @@ import { investigationNoteResponseSchema } from './investigation_note';
|
|||
|
||||
const getInvestigationNotesParamsSchema = t.type({
|
||||
path: t.type({
|
||||
id: t.string,
|
||||
investigationId: t.string,
|
||||
}),
|
||||
});
|
||||
|
31
packages/kbn-investigation-shared/src/rest_specs/index.ts
Normal file
31
packages/kbn-investigation-shared/src/rest_specs/index.ts
Normal file
|
@ -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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export type * from './create';
|
||||
export type * from './create_note';
|
||||
export type * from './delete';
|
||||
export type * from './find';
|
||||
export type * from './get';
|
||||
export type * from './get_notes';
|
||||
export type * from './delete_note';
|
||||
export type * from './investigation_note';
|
||||
export type * from './create_item';
|
||||
export type * from './delete_item';
|
||||
export type * from './get_items';
|
||||
|
||||
export * from './create';
|
||||
export * from './create_note';
|
||||
export * from './delete';
|
||||
export * from './find';
|
||||
export * from './get';
|
||||
export * from './get_notes';
|
||||
export * from './delete_note';
|
||||
export * from './investigation_note';
|
||||
export * from './create_item';
|
||||
export * from './delete_item';
|
||||
export * from './get_items';
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { investigationSchema } from '../schema';
|
||||
|
||||
const investigationResponseSchema = investigationSchema;
|
||||
|
||||
type InvestigationResponse = t.OutputOf<typeof investigationResponseSchema>;
|
||||
|
||||
export { investigationResponseSchema };
|
||||
export type { InvestigationResponse };
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { investigationItemSchema } from '../schema';
|
||||
|
||||
const investigationItemResponseSchema = investigationItemSchema;
|
||||
|
||||
type InvestigationItemResponse = t.OutputOf<typeof investigationItemResponseSchema>;
|
||||
|
||||
export { investigationItemResponseSchema };
|
||||
export type { InvestigationItemResponse };
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { investigationNoteSchema } from '../schema';
|
||||
|
||||
const investigationNoteResponseSchema = investigationNoteSchema;
|
||||
|
||||
type InvestigationNoteResponse = t.OutputOf<typeof investigationNoteResponseSchema>;
|
||||
|
||||
export { investigationNoteResponseSchema };
|
||||
export type { InvestigationNoteResponse };
|
12
packages/kbn-investigation-shared/src/schema/index.ts
Normal file
12
packages/kbn-investigation-shared/src/schema/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './investigation';
|
||||
export * from './investigation_item';
|
||||
export * from './investigation_note';
|
||||
export * from './origin';
|
|
@ -8,9 +8,10 @@
|
|||
|
||||
import * as t from 'io-ts';
|
||||
import { alertOriginSchema, blankOriginSchema } from './origin';
|
||||
import { investigationNoteResponseSchema } from './investigation_note';
|
||||
import { investigationNoteSchema } from './investigation_note';
|
||||
import { investigationItemSchema } from './investigation_item';
|
||||
|
||||
const investigationResponseSchema = t.type({
|
||||
const investigationSchema = t.type({
|
||||
id: t.string,
|
||||
title: t.string,
|
||||
createdAt: t.number,
|
||||
|
@ -20,10 +21,8 @@ const investigationResponseSchema = t.type({
|
|||
}),
|
||||
origin: t.union([alertOriginSchema, blankOriginSchema]),
|
||||
status: t.union([t.literal('ongoing'), t.literal('closed')]),
|
||||
notes: t.array(investigationNoteResponseSchema),
|
||||
notes: t.array(investigationNoteSchema),
|
||||
items: t.array(investigationItemSchema),
|
||||
});
|
||||
|
||||
type InvestigationResponse = t.OutputOf<typeof investigationResponseSchema>;
|
||||
|
||||
export { investigationResponseSchema };
|
||||
export type { InvestigationResponse };
|
||||
export { investigationSchema };
|
||||
|
|
|
@ -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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
|
||||
const esqlItemSchema = t.type({
|
||||
title: t.string,
|
||||
type: t.literal('esql'),
|
||||
params: t.type({
|
||||
esql: t.string,
|
||||
suggestion: t.any,
|
||||
}),
|
||||
});
|
||||
|
||||
const investigationItemsSchema = esqlItemSchema; // replace with union with various item types
|
||||
|
||||
const investigationItemSchema = t.intersection([
|
||||
t.type({ id: t.string, createdAt: t.number, createdBy: t.string }),
|
||||
investigationItemsSchema,
|
||||
]);
|
||||
|
||||
export { investigationItemSchema, investigationItemsSchema, esqlItemSchema };
|
|
@ -8,14 +8,11 @@
|
|||
|
||||
import * as t from 'io-ts';
|
||||
|
||||
const investigationNoteResponseSchema = t.type({
|
||||
const investigationNoteSchema = t.type({
|
||||
id: t.string,
|
||||
content: t.string,
|
||||
createdAt: t.number,
|
||||
createdBy: t.string,
|
||||
});
|
||||
|
||||
type InvestigationNoteResponse = t.OutputOf<typeof investigationNoteResponseSchema>;
|
||||
|
||||
export { investigationNoteResponseSchema };
|
||||
export type { InvestigationNoteResponse };
|
||||
export { investigationNoteSchema };
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { AuthenticatedUser } from '@kbn/core/public';
|
||||
import type { DeepPartial } from 'utility-types';
|
||||
|
||||
export interface GlobalWidgetParameters {
|
||||
|
@ -36,13 +35,12 @@ export interface InvestigateWidget<
|
|||
TData extends Record<string, any> = {}
|
||||
> {
|
||||
id: string;
|
||||
created: number;
|
||||
last_updated: number;
|
||||
createdAt: number;
|
||||
createdBy: string;
|
||||
title: string;
|
||||
type: string;
|
||||
user: AuthenticatedUser;
|
||||
parameters: GlobalWidgetParameters & TParameters;
|
||||
data: TData;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export type InvestigateWidgetCreate<TParameters extends Record<string, any> = {}> = Pick<
|
||||
|
|
|
@ -42,12 +42,11 @@ export async function regenerateItem({
|
|||
});
|
||||
|
||||
return {
|
||||
created: now,
|
||||
createdAt: now,
|
||||
id: v4(),
|
||||
...widget,
|
||||
parameters: nextParameters,
|
||||
data: widgetData,
|
||||
user,
|
||||
last_updated: now,
|
||||
createdBy: user.username,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -25,9 +25,6 @@ function WithPersistedChanges(props: React.ComponentProps<typeof Component>) {
|
|||
return (
|
||||
<Component
|
||||
{...props}
|
||||
onItemsChange={async (nextItems) => {
|
||||
setItems(() => nextItems);
|
||||
}}
|
||||
onItemCopy={async (item) => {
|
||||
setItems((prevItems) =>
|
||||
prevItems.concat({
|
||||
|
|
|
@ -20,14 +20,12 @@ export interface InvestigateWidgetGridItem {
|
|||
|
||||
interface InvestigateWidgetGridProps {
|
||||
items: InvestigateWidgetGridItem[];
|
||||
onItemsChange: (items: InvestigateWidgetGridItem[]) => Promise<void>;
|
||||
onItemCopy: (item: InvestigateWidgetGridItem) => Promise<void>;
|
||||
onItemDelete: (item: InvestigateWidgetGridItem) => Promise<void>;
|
||||
}
|
||||
|
||||
export function InvestigateWidgetGrid({
|
||||
items,
|
||||
onItemsChange,
|
||||
onItemDelete,
|
||||
onItemCopy,
|
||||
}: InvestigateWidgetGridProps) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public';
|
||||
import {
|
||||
CreateInvestigationNoteInput,
|
||||
CreateInvestigationNoteParams,
|
||||
CreateInvestigationNoteResponse,
|
||||
} from '@kbn/investigation-shared';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
|
@ -26,7 +26,7 @@ export function useAddInvestigationNote() {
|
|||
return useMutation<
|
||||
CreateInvestigationNoteResponse,
|
||||
ServerError,
|
||||
{ investigationId: string; note: CreateInvestigationNoteInput },
|
||||
{ investigationId: string; note: CreateInvestigationNoteParams },
|
||||
{ investigationId: string }
|
||||
>(
|
||||
['addInvestigationNote'],
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
import datemath from '@elastic/datemath';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui';
|
||||
import { AuthenticatedUser } from '@kbn/security-plugin/common';
|
||||
import { noop } from 'lodash';
|
||||
import React from 'react';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
import { AddObservationUI } from '../../../../components/add_observation_ui';
|
||||
|
@ -81,9 +80,6 @@ function InvestigationDetailsWithUser({
|
|||
<EuiFlexItem grow={false}>
|
||||
<InvestigateWidgetGrid
|
||||
items={renderableInvestigation.items}
|
||||
onItemsChange={async (nextGridItems) => {
|
||||
noop();
|
||||
}}
|
||||
onItemCopy={async (copiedItem) => {
|
||||
return copyItem(copiedItem.id);
|
||||
}}
|
||||
|
|
|
@ -5,22 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { alertOriginSchema, blankOriginSchema } from '@kbn/investigation-shared';
|
||||
import { investigationSchema } from '@kbn/investigation-shared';
|
||||
import * as t from 'io-ts';
|
||||
import { investigationNoteSchema } from './investigation_note';
|
||||
|
||||
export const investigationSchema = t.type({
|
||||
id: t.string,
|
||||
title: t.string,
|
||||
createdAt: t.number,
|
||||
createdBy: t.string,
|
||||
params: t.type({
|
||||
timeRange: t.type({ from: t.number, to: t.number }),
|
||||
}),
|
||||
origin: t.union([alertOriginSchema, blankOriginSchema]),
|
||||
status: t.union([t.literal('ongoing'), t.literal('closed')]),
|
||||
notes: t.array(investigationNoteSchema),
|
||||
});
|
||||
|
||||
export type Investigation = t.TypeOf<typeof investigationSchema>;
|
||||
export type StoredInvestigation = t.OutputOf<typeof investigationSchema>;
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { investigationItemSchema } from '@kbn/investigation-shared';
|
||||
|
||||
export type InvestigationItem = t.TypeOf<typeof investigationItemSchema>;
|
||||
export type StoredInvestigationItem = t.OutputOf<typeof investigationItemSchema>;
|
|
@ -6,13 +6,7 @@
|
|||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
|
||||
export const investigationNoteSchema = t.type({
|
||||
id: t.string,
|
||||
createdAt: t.number,
|
||||
createdBy: t.string,
|
||||
content: t.string,
|
||||
});
|
||||
import { investigationNoteSchema } from '@kbn/investigation-shared';
|
||||
|
||||
export type InvestigationNote = t.TypeOf<typeof investigationNoteSchema>;
|
||||
export type StoredInvestigationNote = t.OutputOf<typeof investigationNoteSchema>;
|
||||
|
|
|
@ -6,23 +6,29 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
createInvestigationItemParamsSchema,
|
||||
createInvestigationNoteParamsSchema,
|
||||
createInvestigationParamsSchema,
|
||||
deleteInvestigationItemParamsSchema,
|
||||
deleteInvestigationNoteParamsSchema,
|
||||
deleteInvestigationParamsSchema,
|
||||
findInvestigationsParamsSchema,
|
||||
getInvestigationItemsParamsSchema,
|
||||
getInvestigationNotesParamsSchema,
|
||||
getInvestigationParamsSchema,
|
||||
} from '@kbn/investigation-shared';
|
||||
import { createInvestigation } from '../services/create_investigation';
|
||||
import { createInvestigationItem } from '../services/create_investigation_item';
|
||||
import { createInvestigationNote } from '../services/create_investigation_note';
|
||||
import { deleteInvestigation } from '../services/delete_investigation';
|
||||
import { deleteInvestigationItem } from '../services/delete_investigation_item';
|
||||
import { deleteInvestigationNote } from '../services/delete_investigation_note';
|
||||
import { findInvestigations } from '../services/find_investigations';
|
||||
import { getInvestigation } from '../services/get_investigation';
|
||||
import { getInvestigationNotes } from '../services/get_investigation_notes';
|
||||
import { investigationRepositoryFactory } from '../services/investigation_repository';
|
||||
import { createInvestigateAppServerRoute } from './create_investigate_app_server_route';
|
||||
import { deleteInvestigationNote } from '../services/delete_investigation_note';
|
||||
import { getInvestigationItems } from '../services/get_investigation_items';
|
||||
|
||||
const createInvestigationRoute = createInvestigateAppServerRoute({
|
||||
endpoint: 'POST /api/observability/investigations 2023-10-31',
|
||||
|
@ -57,35 +63,35 @@ const findInvestigationsRoute = createInvestigateAppServerRoute({
|
|||
});
|
||||
|
||||
const getInvestigationRoute = createInvestigateAppServerRoute({
|
||||
endpoint: 'GET /api/observability/investigations/{id} 2023-10-31',
|
||||
endpoint: 'GET /api/observability/investigations/{investigationId} 2023-10-31',
|
||||
options: {
|
||||
tags: [],
|
||||
},
|
||||
params: getInvestigationParamsSchema,
|
||||
handler: async (params) => {
|
||||
const soClient = (await params.context.core).savedObjects.client;
|
||||
const repository = investigationRepositoryFactory({ soClient, logger: params.logger });
|
||||
handler: async ({ params, context, logger }) => {
|
||||
const soClient = (await context.core).savedObjects.client;
|
||||
const repository = investigationRepositoryFactory({ soClient, logger });
|
||||
|
||||
return await getInvestigation(params.params.path, repository);
|
||||
return await getInvestigation(params.path, repository);
|
||||
},
|
||||
});
|
||||
|
||||
const deleteInvestigationRoute = createInvestigateAppServerRoute({
|
||||
endpoint: 'DELETE /api/observability/investigations/{id} 2023-10-31',
|
||||
endpoint: 'DELETE /api/observability/investigations/{investigationId} 2023-10-31',
|
||||
options: {
|
||||
tags: [],
|
||||
},
|
||||
params: deleteInvestigationParamsSchema,
|
||||
handler: async (params) => {
|
||||
const soClient = (await params.context.core).savedObjects.client;
|
||||
const repository = investigationRepositoryFactory({ soClient, logger: params.logger });
|
||||
handler: async ({ params, context, logger }) => {
|
||||
const soClient = (await context.core).savedObjects.client;
|
||||
const repository = investigationRepositoryFactory({ soClient, logger });
|
||||
|
||||
return await deleteInvestigation(params.params.path.id, repository);
|
||||
return await deleteInvestigation(params.path.investigationId, repository);
|
||||
},
|
||||
});
|
||||
|
||||
const createInvestigationNoteRoute = createInvestigateAppServerRoute({
|
||||
endpoint: 'POST /api/observability/investigations/{id}/notes 2023-10-31',
|
||||
endpoint: 'POST /api/observability/investigations/{investigationId}/notes 2023-10-31',
|
||||
options: {
|
||||
tags: [],
|
||||
},
|
||||
|
@ -98,26 +104,29 @@ const createInvestigationNoteRoute = createInvestigateAppServerRoute({
|
|||
const soClient = (await context.core).savedObjects.client;
|
||||
const repository = investigationRepositoryFactory({ soClient, logger });
|
||||
|
||||
return await createInvestigationNote(params.path.id, params.body, { repository, user });
|
||||
return await createInvestigationNote(params.path.investigationId, params.body, {
|
||||
repository,
|
||||
user,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const getInvestigationNotesRoute = createInvestigateAppServerRoute({
|
||||
endpoint: 'GET /api/observability/investigations/{id}/notes 2023-10-31',
|
||||
endpoint: 'GET /api/observability/investigations/{investigationId}/notes 2023-10-31',
|
||||
options: {
|
||||
tags: [],
|
||||
},
|
||||
params: getInvestigationNotesParamsSchema,
|
||||
handler: async (params) => {
|
||||
const soClient = (await params.context.core).savedObjects.client;
|
||||
const repository = investigationRepositoryFactory({ soClient, logger: params.logger });
|
||||
handler: async ({ params, context, request, logger }) => {
|
||||
const soClient = (await context.core).savedObjects.client;
|
||||
const repository = investigationRepositoryFactory({ soClient, logger });
|
||||
|
||||
return await getInvestigationNotes(params.params.path.id, repository);
|
||||
return await getInvestigationNotes(params.path.investigationId, repository);
|
||||
},
|
||||
});
|
||||
|
||||
const deleteInvestigationNotesRoute = createInvestigateAppServerRoute({
|
||||
endpoint: 'DELETE /api/observability/investigations/{id}/notes/{noteId} 2023-10-31',
|
||||
endpoint: 'DELETE /api/observability/investigations/{investigationId}/notes/{noteId} 2023-10-31',
|
||||
options: {
|
||||
tags: [],
|
||||
},
|
||||
|
@ -130,7 +139,63 @@ const deleteInvestigationNotesRoute = createInvestigateAppServerRoute({
|
|||
const soClient = (await context.core).savedObjects.client;
|
||||
const repository = investigationRepositoryFactory({ soClient, logger });
|
||||
|
||||
return await deleteInvestigationNote(params.path.id, params.path.noteId, {
|
||||
return await deleteInvestigationNote(params.path.investigationId, params.path.noteId, {
|
||||
repository,
|
||||
user,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const createInvestigationItemRoute = createInvestigateAppServerRoute({
|
||||
endpoint: 'POST /api/observability/investigations/{investigationId}/items 2023-10-31',
|
||||
options: {
|
||||
tags: [],
|
||||
},
|
||||
params: createInvestigationItemParamsSchema,
|
||||
handler: async ({ params, context, request, logger }) => {
|
||||
const user = (await context.core).coreStart.security.authc.getCurrentUser(request);
|
||||
if (!user) {
|
||||
throw new Error('User is not authenticated');
|
||||
}
|
||||
const soClient = (await context.core).savedObjects.client;
|
||||
const repository = investigationRepositoryFactory({ soClient, logger });
|
||||
|
||||
return await createInvestigationItem(params.path.investigationId, params.body, {
|
||||
repository,
|
||||
user,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const getInvestigationItemsRoute = createInvestigateAppServerRoute({
|
||||
endpoint: 'GET /api/observability/investigations/{investigationId}/items 2023-10-31',
|
||||
options: {
|
||||
tags: [],
|
||||
},
|
||||
params: getInvestigationItemsParamsSchema,
|
||||
handler: async ({ params, context, request, logger }) => {
|
||||
const soClient = (await context.core).savedObjects.client;
|
||||
const repository = investigationRepositoryFactory({ soClient, logger });
|
||||
|
||||
return await getInvestigationItems(params.path.investigationId, repository);
|
||||
},
|
||||
});
|
||||
|
||||
const deleteInvestigationItemRoute = createInvestigateAppServerRoute({
|
||||
endpoint: 'DELETE /api/observability/investigations/{investigationId}/items/{itemId} 2023-10-31',
|
||||
options: {
|
||||
tags: [],
|
||||
},
|
||||
params: deleteInvestigationItemParamsSchema,
|
||||
handler: async ({ params, context, request, logger }) => {
|
||||
const user = (await context.core).coreStart.security.authc.getCurrentUser(request);
|
||||
if (!user) {
|
||||
throw new Error('User is not authenticated');
|
||||
}
|
||||
const soClient = (await context.core).savedObjects.client;
|
||||
const repository = investigationRepositoryFactory({ soClient, logger });
|
||||
|
||||
return await deleteInvestigationItem(params.path.investigationId, params.path.itemId, {
|
||||
repository,
|
||||
user,
|
||||
});
|
||||
|
@ -146,6 +211,9 @@ export function getGlobalInvestigateAppServerRouteRepository() {
|
|||
...createInvestigationNoteRoute,
|
||||
...getInvestigationNotesRoute,
|
||||
...deleteInvestigationNotesRoute,
|
||||
...createInvestigationItemRoute,
|
||||
...deleteInvestigationItemRoute,
|
||||
...getInvestigationItemsRoute,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { CreateInvestigationInput, CreateInvestigationResponse } from '@kbn/investigation-shared';
|
||||
import { CreateInvestigationParams, CreateInvestigationResponse } from '@kbn/investigation-shared';
|
||||
import type { AuthenticatedUser } from '@kbn/core-security-common';
|
||||
import { InvestigationRepository } from './investigation_repository';
|
||||
|
||||
|
@ -15,7 +15,7 @@ enum InvestigationStatus {
|
|||
}
|
||||
|
||||
export async function createInvestigation(
|
||||
params: CreateInvestigationInput,
|
||||
params: CreateInvestigationParams,
|
||||
{ repository, user }: { repository: InvestigationRepository; user: AuthenticatedUser }
|
||||
): Promise<CreateInvestigationResponse> {
|
||||
const investigation = {
|
||||
|
@ -24,6 +24,7 @@ export async function createInvestigation(
|
|||
createdBy: user.username,
|
||||
status: InvestigationStatus.ongoing,
|
||||
notes: [],
|
||||
items: [],
|
||||
};
|
||||
await repository.save(investigation);
|
||||
|
||||
|
|
|
@ -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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { AuthenticatedUser } from '@kbn/core-security-common';
|
||||
import {
|
||||
CreateInvestigationItemParams,
|
||||
CreateInvestigationItemResponse,
|
||||
} from '@kbn/investigation-shared';
|
||||
import { v4 } from 'uuid';
|
||||
import { InvestigationRepository } from './investigation_repository';
|
||||
|
||||
export async function createInvestigationItem(
|
||||
investigationId: string,
|
||||
params: CreateInvestigationItemParams,
|
||||
{ repository, user }: { repository: InvestigationRepository; user: AuthenticatedUser }
|
||||
): Promise<CreateInvestigationItemResponse> {
|
||||
const investigation = await repository.findById(investigationId);
|
||||
|
||||
const investigationItem = {
|
||||
id: v4(),
|
||||
createdBy: user.username,
|
||||
createdAt: Date.now(),
|
||||
...params,
|
||||
};
|
||||
investigation.items.push(investigationItem);
|
||||
|
||||
await repository.save(investigation);
|
||||
|
||||
return investigationItem;
|
||||
}
|
|
@ -5,17 +5,17 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { AuthenticatedUser } from '@kbn/core-security-common';
|
||||
import {
|
||||
CreateInvestigationNoteInput,
|
||||
CreateInvestigationNoteParams,
|
||||
CreateInvestigationNoteResponse,
|
||||
} from '@kbn/investigation-shared';
|
||||
import { v4 } from 'uuid';
|
||||
import type { AuthenticatedUser } from '@kbn/core-security-common';
|
||||
import { InvestigationRepository } from './investigation_repository';
|
||||
|
||||
export async function createInvestigationNote(
|
||||
investigationId: string,
|
||||
params: CreateInvestigationNoteInput,
|
||||
params: CreateInvestigationNoteParams,
|
||||
{ repository, user }: { repository: InvestigationRepository; user: AuthenticatedUser }
|
||||
): Promise<CreateInvestigationNoteResponse> {
|
||||
const investigation = await repository.findById(investigationId);
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
import { InvestigationRepository } from './investigation_repository';
|
||||
|
||||
export async function deleteInvestigation(
|
||||
id: string,
|
||||
investigationId: string,
|
||||
repository: InvestigationRepository
|
||||
): Promise<void> {
|
||||
await repository.deleteById(id);
|
||||
await repository.deleteById(investigationId);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { AuthenticatedUser } from '@kbn/core-security-common';
|
||||
import { InvestigationRepository } from './investigation_repository';
|
||||
|
||||
export async function deleteInvestigationItem(
|
||||
investigationId: string,
|
||||
itemId: string,
|
||||
{ repository, user }: { repository: InvestigationRepository; user: AuthenticatedUser }
|
||||
): Promise<void> {
|
||||
const investigation = await repository.findById(investigationId);
|
||||
const item = investigation.items.find((currItem) => currItem.id === itemId);
|
||||
if (!item) {
|
||||
throw new Error('Note not found');
|
||||
}
|
||||
|
||||
if (item.createdBy !== user.username) {
|
||||
throw new Error('User does not have permission to delete note');
|
||||
}
|
||||
|
||||
investigation.items = investigation.items.filter((currItem) => currItem.id !== itemId);
|
||||
await repository.save(investigation);
|
||||
}
|
|
@ -16,7 +16,7 @@ export async function getInvestigation(
|
|||
params: GetInvestigationParams,
|
||||
repository: InvestigationRepository
|
||||
): Promise<GetInvestigationResponse> {
|
||||
const investigation = await repository.findById(params.id);
|
||||
const investigation = await repository.findById(params.investigationId);
|
||||
|
||||
return getInvestigationResponseSchema.encode(investigation);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import {
|
||||
GetInvestigationItemsResponse,
|
||||
getInvestigationItemsResponseSchema,
|
||||
} from '@kbn/investigation-shared';
|
||||
import { InvestigationRepository } from './investigation_repository';
|
||||
|
||||
export async function getInvestigationItems(
|
||||
investigationId: string,
|
||||
repository: InvestigationRepository
|
||||
): Promise<GetInvestigationItemsResponse> {
|
||||
const investigation = await repository.findById(investigationId);
|
||||
|
||||
return getInvestigationItemsResponseSchema.encode(investigation.items);
|
||||
}
|
|
@ -6,10 +6,11 @@
|
|||
*/
|
||||
|
||||
import { Logger, SavedObjectsClientContract } from '@kbn/core/server';
|
||||
import { investigationSchema } from '@kbn/investigation-shared';
|
||||
import { isLeft } from 'fp-ts/lib/Either';
|
||||
import { Investigation, StoredInvestigation, investigationSchema } from '../models/investigation';
|
||||
import { SO_INVESTIGATION_TYPE } from '../saved_objects/investigation';
|
||||
import { Investigation, StoredInvestigation } from '../models/investigation';
|
||||
import { Paginated, Pagination } from '../models/pagination';
|
||||
import { SO_INVESTIGATION_TYPE } from '../saved_objects/investigation';
|
||||
|
||||
export interface InvestigationRepository {
|
||||
save(investigation: Investigation): Promise<void>;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
CreateInvestigationInput,
|
||||
CreateInvestigationParams,
|
||||
CreateInvestigationResponse,
|
||||
FindInvestigationsResponse,
|
||||
} from '@kbn/investigation-shared';
|
||||
|
@ -26,7 +26,7 @@ export function useCreateInvestigation() {
|
|||
return useMutation<
|
||||
CreateInvestigationResponse,
|
||||
ServerError,
|
||||
{ investigation: CreateInvestigationInput },
|
||||
{ investigation: CreateInvestigationParams },
|
||||
{ previousData?: FindInvestigationsResponse; queryKey?: QueryKey }
|
||||
>(
|
||||
['createInvestigation'],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue