-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Cases] Add import/export functionality (#110148)
* Working export but not import * Adding user action import flag * Adding a few integration tests * Adding connector test * Finishing integration tests * Removing connector after each test to restore original state * Bumping migration version for comment so Co-authored-by: Kibana Machine <[email protected]>
- Loading branch information
1 parent
65eb7b9
commit 2567c4f
Showing
10 changed files
with
369 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
114 changes: 114 additions & 0 deletions
114
x-pack/plugins/cases/server/saved_object_types/import_export/export.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
* 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 { | ||
CoreSetup, | ||
Logger, | ||
SavedObject, | ||
SavedObjectsClientContract, | ||
SavedObjectsExportTransformContext, | ||
} from 'kibana/server'; | ||
import { | ||
CaseUserActionAttributes, | ||
CASE_COMMENT_SAVED_OBJECT, | ||
CASE_SAVED_OBJECT, | ||
CASE_USER_ACTION_SAVED_OBJECT, | ||
CommentAttributes, | ||
MAX_DOCS_PER_PAGE, | ||
SAVED_OBJECT_TYPES, | ||
} from '../../../common'; | ||
import { createCaseError, defaultSortField } from '../../common'; | ||
import { ESCaseAttributes } from '../../services/cases/types'; | ||
|
||
export async function handleExport({ | ||
context, | ||
objects, | ||
coreSetup, | ||
logger, | ||
}: { | ||
context: SavedObjectsExportTransformContext; | ||
objects: Array<SavedObject<ESCaseAttributes>>; | ||
coreSetup: CoreSetup; | ||
logger: Logger; | ||
}): Promise<Array<SavedObject<ESCaseAttributes | CommentAttributes | CaseUserActionAttributes>>> { | ||
try { | ||
if (objects.length <= 0) { | ||
return []; | ||
} | ||
|
||
const [{ savedObjects }] = await coreSetup.getStartServices(); | ||
const savedObjectsClient = savedObjects.getScopedClient(context.request, { | ||
includedHiddenTypes: SAVED_OBJECT_TYPES, | ||
}); | ||
|
||
const caseIds = objects.map((caseObject) => caseObject.id); | ||
const attachmentsAndUserActionsForCases = await getAttachmentsAndUserActionsForCases( | ||
savedObjectsClient, | ||
caseIds | ||
); | ||
|
||
return [...objects, ...attachmentsAndUserActionsForCases.flat()]; | ||
} catch (error) { | ||
throw createCaseError({ | ||
message: `Failed to retrieve associated objects for exporting of cases: ${error}`, | ||
error, | ||
logger, | ||
}); | ||
} | ||
} | ||
|
||
async function getAttachmentsAndUserActionsForCases( | ||
savedObjectsClient: SavedObjectsClientContract, | ||
caseIds: string[] | ||
): Promise<Array<SavedObject<CommentAttributes | CaseUserActionAttributes>>> { | ||
const [attachments, userActions] = await Promise.all([ | ||
getAssociatedObjects<CommentAttributes>({ | ||
savedObjectsClient, | ||
caseIds, | ||
sortField: defaultSortField, | ||
type: CASE_COMMENT_SAVED_OBJECT, | ||
}), | ||
getAssociatedObjects<CaseUserActionAttributes>({ | ||
savedObjectsClient, | ||
caseIds, | ||
sortField: 'action_at', | ||
type: CASE_USER_ACTION_SAVED_OBJECT, | ||
}), | ||
]); | ||
|
||
return [...attachments, ...userActions]; | ||
} | ||
|
||
async function getAssociatedObjects<T>({ | ||
savedObjectsClient, | ||
caseIds, | ||
sortField, | ||
type, | ||
}: { | ||
savedObjectsClient: SavedObjectsClientContract; | ||
caseIds: string[]; | ||
sortField: string; | ||
type: string; | ||
}): Promise<Array<SavedObject<T>>> { | ||
const references = caseIds.map((id) => ({ type: CASE_SAVED_OBJECT, id })); | ||
|
||
const finder = savedObjectsClient.createPointInTimeFinder<T>({ | ||
type, | ||
hasReferenceOperator: 'OR', | ||
hasReference: references, | ||
perPage: MAX_DOCS_PER_PAGE, | ||
sortField, | ||
sortOrder: 'asc', | ||
}); | ||
|
||
let result: Array<SavedObject<T>> = []; | ||
for await (const findResults of finder.find()) { | ||
result = result.concat(findResults.saved_objects); | ||
} | ||
|
||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
...egration/common/fixtures/saved_object_exports/single_case_user_actions_one_comment.ndjson
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{"attributes":{"closed_at":null,"closed_by":null,"connector":{"fields":[],"name":"none","type":".none"},"created_at":"2021-08-26T19:48:01.292Z","created_by":{"email":null,"full_name":null,"username":"elastic"},"description":"a description","external_service":null,"owner":"securitySolution","settings":{"syncAlerts":true},"status":"open","tags":["some tags"],"title":"A case to export","type":"individual","updated_at":"2021-08-26T19:48:30.151Z","updated_by":{"email":null,"full_name":null,"username":"elastic"}},"coreMigrationVersion":"8.0.0","id":"85541260-06a6-11ec-b3f9-3d05c48a7d46","migrationVersion":{"cases":"7.15.0"},"references":[],"type":"cases","updated_at":"2021-08-26T19:48:30.162Z","version":"WzM0NDEsMV0="} | ||
{"attributes":{"action":"create","action_at":"2021-08-26T19:48:01.292Z","action_by":{"email":null,"full_name":null,"username":"elastic"},"action_field":["description","status","tags","title","connector","settings","owner"],"new_value":"{\"type\":\"individual\",\"title\":\"A case to export\",\"tags\":[\"some tags\"],\"description\":\"a description\",\"connector\":{\"id\":\"none\",\"name\":\"none\",\"type\":\".none\",\"fields\":null},\"settings\":{\"syncAlerts\":true},\"owner\":\"securitySolution\"}","old_value":null,"owner":"securitySolution"},"coreMigrationVersion":"8.0.0","id":"8cb85070-06a6-11ec-b3f9-3d05c48a7d46","migrationVersion":{"cases-user-actions":"7.14.0"},"references":[{"id":"85541260-06a6-11ec-b3f9-3d05c48a7d46","name":"associated-cases","type":"cases"}],"score":null,"sort":[1630007281292,7288],"type":"cases-user-actions","updated_at":"2021-08-26T19:48:13.687Z","version":"WzIzODIsMV0="} | ||
{"attributes":{"associationType":"case","comment":"A comment for my case","created_at":"2021-08-26T19:48:30.151Z","created_by":{"email":null,"full_name":null,"username":"elastic"},"owner":"securitySolution","pushed_at":null,"pushed_by":null,"type":"user","updated_at":null,"updated_by":null},"coreMigrationVersion":"8.0.0","id":"9687c220-06a6-11ec-b3f9-3d05c48a7d46","migrationVersion":{"cases-comments":"7.16.0"},"references":[{"id":"85541260-06a6-11ec-b3f9-3d05c48a7d46","name":"associated-cases","type":"cases"}],"score":null,"sort":[1630007310151,9470],"type":"cases-comments","updated_at":"2021-08-26T19:48:30.161Z","version":"WzM0NDIsMV0="} | ||
{"attributes":{"action":"create","action_at":"2021-08-26T19:48:30.151Z","action_by":{"email":null,"full_name":null,"username":"elastic"},"action_field":["comment"],"new_value":"{\"comment\":\"A comment for my case\",\"type\":\"user\",\"owner\":\"securitySolution\"}","old_value":null,"owner":"securitySolution"},"coreMigrationVersion":"8.0.0","id":"9710c840-06a6-11ec-b3f9-3d05c48a7d46","migrationVersion":{"cases-user-actions":"7.14.0"},"references":[{"id":"85541260-06a6-11ec-b3f9-3d05c48a7d46","name":"associated-cases","type":"cases"},{"id":"9687c220-06a6-11ec-b3f9-3d05c48a7d46","name":"associated-cases-comments","type":"cases-comments"}],"score":null,"sort":[1630007310151,9542],"type":"cases-user-actions","updated_at":"2021-08-26T19:48:31.044Z","version":"WzM1MTIsMV0="} | ||
{"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":4,"missingRefCount":0,"missingReferences":[]} |
6 changes: 6 additions & 0 deletions
6
...ion/common/fixtures/saved_object_exports/single_case_with_connector_update_to_none.ndjson
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{"attributes":{"actionTypeId":".jira","config":{"apiUrl":"https://cases-testing.atlassian.net","projectKey":"TPN"},"isMissingSecrets":true,"name":"A jira connector"},"coreMigrationVersion":"8.0.0","id":"1cd34740-06ad-11ec-babc-0b08808e8e01","migrationVersion":{"action":"7.14.0"},"references":[],"type":"action","updated_at":"2021-08-26T20:35:12.447Z","version":"WzM1ODQsMV0="} | ||
{"attributes":{"closed_at":null,"closed_by":null,"connector":{"fields":[],"name":"none","type":".none"},"created_at":"2021-08-26T20:35:42.131Z","created_by":{"email":null,"full_name":null,"username":"elastic"},"description":"super description","external_service":{"connector_name":"A jira connector","external_id":"10125","external_title":"TPN-118","external_url":"https://cases-testing.atlassian.net/browse/TPN-118","pushed_at":"2021-08-26T20:35:44.302Z","pushed_by":{"email":null,"full_name":null,"username":"elastic"}},"owner":"securitySolution","settings":{"syncAlerts":true},"status":"open","tags":["other tags"],"title":"A case with a connector","type":"individual","updated_at":"2021-08-26T20:36:35.536Z","updated_by":{"email":null,"full_name":null,"username":"elastic"}},"coreMigrationVersion":"8.0.0","id":"2e85c3f0-06ad-11ec-babc-0b08808e8e01","migrationVersion":{"cases":"7.15.0"},"references":[{"id":"1cd34740-06ad-11ec-babc-0b08808e8e01","name":"pushConnectorId","type":"action"}],"type":"cases","updated_at":"2021-08-26T20:36:35.537Z","version":"WzM1OTIsMV0="} | ||
{"attributes":{"action":"create","action_at":"2021-08-26T20:35:42.131Z","action_by":{"email":null,"full_name":null,"username":"elastic"},"action_field":["description","status","tags","title","connector","settings","owner"],"new_value":"{\"type\":\"individual\",\"title\":\"A case with a connector\",\"tags\":[\"other tags\"],\"description\":\"super description\",\"connector\":{\"id\":\"1cd34740-06ad-11ec-babc-0b08808e8e01\",\"name\":\"A jira connector\",\"type\":\".jira\",\"fields\":{\"issueType\":\"10002\",\"parent\":null,\"priority\":\"High\"}},\"settings\":{\"syncAlerts\":true},\"owner\":\"securitySolution\"}","old_value":null,"owner":"securitySolution"},"coreMigrationVersion":"8.0.0","id":"2e9db8c0-06ad-11ec-babc-0b08808e8e01","migrationVersion":{"cases-user-actions":"7.14.0"},"references":[{"id":"2e85c3f0-06ad-11ec-babc-0b08808e8e01","name":"associated-cases","type":"cases"}],"score":null,"sort":[1630010142131,4024],"type":"cases-user-actions","updated_at":"2021-08-26T20:35:42.284Z","version":"WzM1ODksMV0="} | ||
{"attributes":{"action":"push-to-service","action_at":"2021-08-26T20:35:44.302Z","action_by":{"email":null,"full_name":null,"username":"elastic"},"action_field":["pushed"],"new_value":"{\"pushed_at\":\"2021-08-26T20:35:44.302Z\",\"pushed_by\":{\"username\":\"elastic\",\"full_name\":null,\"email\":null},\"connector_id\":\"1cd34740-06ad-11ec-babc-0b08808e8e01\",\"connector_name\":\"A jira connector\",\"external_id\":\"10125\",\"external_title\":\"TPN-118\",\"external_url\":\"https://cases-testing.atlassian.net/browse/TPN-118\"}","old_value":null,"owner":"securitySolution"},"coreMigrationVersion":"8.0.0","id":"2fd1cbf0-06ad-11ec-babc-0b08808e8e01","migrationVersion":{"cases-user-actions":"7.14.0"},"references":[{"id":"2e85c3f0-06ad-11ec-babc-0b08808e8e01","name":"associated-cases","type":"cases"}],"score":null,"sort":[1630010144302,4029],"type":"cases-user-actions","updated_at":"2021-08-26T20:35:44.303Z","version":"WzM1OTAsMV0="} | ||
{"attributes":{"action":"update","action_at":"2021-08-26T20:36:35.536Z","action_by":{"email":null,"full_name":null,"username":"elastic"},"action_field":["connector"],"new_value":"{\"id\":\"none\",\"name\":\"none\",\"type\":\".none\",\"fields\":null}","old_value":"{\"id\":\"1cd34740-06ad-11ec-babc-0b08808e8e01\",\"name\":\"A jira connector\",\"type\":\".jira\",\"fields\":{\"issueType\":\"10002\",\"parent\":null,\"priority\":\"High\"}}","owner":"securitySolution"},"coreMigrationVersion":"8.0.0","id":"4ee9b250-06ad-11ec-babc-0b08808e8e01","migrationVersion":{"cases-user-actions":"7.14.0"},"references":[{"id":"2e85c3f0-06ad-11ec-babc-0b08808e8e01","name":"associated-cases","type":"cases"}],"score":null,"sort":[1630010195536,4033],"type":"cases-user-actions","updated_at":"2021-08-26T20:36:36.469Z","version":"WzM1OTMsMV0="} | ||
{"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":5,"missingRefCount":0,"missingReferences":[]} |
Oops, something went wrong.