-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Cases] Migrate connector ID to references #104221
Changes from 23 commits
e6dc819
a62c282
ab586b0
6a0d9e2
d3be649
dbf84dd
adbb016
6c00c6b
54cd2d2
aed1b30
636c586
37ef451
48a449d
68137ea
2029b4e
3b530ba
f653634
a1a01d2
3affb65
b27d7b8
3be7768
d418f91
13d8ffd
17cb102
7689a83
290ec82
7f7a35b
eb94ffd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ import { NumberFromString } from '../saved_object'; | |
import { UserRT } from '../user'; | ||
import { CommentResponseRt } from './comment'; | ||
import { CasesStatusResponseRt, CaseStatusRt } from './status'; | ||
import { CaseConnectorRt, ESCaseConnector } from '../connectors'; | ||
import { CaseConnectorRt } from '../connectors'; | ||
import { SubCaseResponseRt } from './sub_case'; | ||
|
||
const BucketsAggs = rt.array( | ||
|
@@ -87,24 +87,17 @@ const CaseBasicRt = rt.type({ | |
owner: rt.string, | ||
}); | ||
|
||
const CaseExternalServiceBasicRt = rt.type({ | ||
connector_id: rt.string, | ||
export const CaseExternalServiceBasicRt = rt.type({ | ||
connector_id: rt.union([rt.string, rt.null]), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As long as the user cannot set the |
||
connector_name: rt.string, | ||
external_id: rt.string, | ||
external_title: rt.string, | ||
external_url: rt.string, | ||
pushed_at: rt.string, | ||
pushed_by: UserRT, | ||
}); | ||
|
||
const CaseFullExternalServiceRt = rt.union([ | ||
rt.intersection([ | ||
CaseExternalServiceBasicRt, | ||
rt.type({ | ||
pushed_at: rt.string, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved these up into the basic definition above. |
||
pushed_by: UserRT, | ||
}), | ||
]), | ||
rt.null, | ||
]); | ||
const CaseFullExternalServiceRt = rt.union([CaseExternalServiceBasicRt, rt.null]); | ||
|
||
export const CaseAttributesRt = rt.intersection([ | ||
CaseBasicRt, | ||
|
@@ -326,11 +319,6 @@ export type CaseFullExternalService = rt.TypeOf<typeof CaseFullExternalServiceRt | |
export type CaseSettings = rt.TypeOf<typeof SettingsRt>; | ||
export type ExternalServiceResponse = rt.TypeOf<typeof ExternalServiceResponseRt>; | ||
|
||
export type ESCaseAttributes = Omit<CaseAttributes, 'connector'> & { connector: ESCaseConnector }; | ||
export type ESCasePatchRequest = Omit<CasePatchRequest, 'connector'> & { | ||
connector?: ESCaseConnector; | ||
}; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These have been moved into the cases service because they are isolated to the service layer. Other parts of cases no longer need to reference the types. Instead they will always reference the |
||
export type AllTagsFindRequest = rt.TypeOf<typeof AllTagsFindRequestRt>; | ||
export type AllReportersFindRequest = AllTagsFindRequest; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ | |
import * as rt from 'io-ts'; | ||
|
||
import { UserRT } from '../user'; | ||
import { CaseConnectorRt, ConnectorMappingsRt, ESCaseConnector } from '../connectors'; | ||
import { CaseConnectorRt, ConnectorMappingsRt } from '../connectors'; | ||
|
||
// TODO: we will need to add this type rt.literal('close-by-third-party') | ||
const ClosureTypeRT = rt.union([rt.literal('close-by-user'), rt.literal('close-by-pushing')]); | ||
|
@@ -83,8 +83,4 @@ export type CasesConfigureAttributes = rt.TypeOf<typeof CaseConfigureAttributesR | |
export type CasesConfigureResponse = rt.TypeOf<typeof CaseConfigureResponseRt>; | ||
export type CasesConfigurationsResponse = rt.TypeOf<typeof CaseConfigurationsResponseRt>; | ||
|
||
export type ESCasesConfigureAttributes = Omit<CasesConfigureAttributes, 'connector'> & { | ||
connector: ESCaseConnector; | ||
}; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This has been moved into the configure service because it is isolated to the service layer. Other parts of the cases plugin no longer need to reference the type. Instead they will reference the CasesConfigureAttributes type directly. |
||
export type GetConfigureFindRequest = rt.TypeOf<typeof GetConfigureFindRequestRt>; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,6 +73,8 @@ const ConnectorNoneTypeFieldsRt = rt.type({ | |
fields: rt.null, | ||
}); | ||
|
||
export const noneConnectorId: string = 'none'; | ||
|
||
export const ConnectorTypeFieldsRt = rt.union([ | ||
ConnectorJiraTypeFieldsRt, | ||
ConnectorNoneTypeFieldsRt, | ||
|
@@ -102,16 +104,3 @@ export type ConnectorServiceNowSIRTypeFields = rt.TypeOf<typeof ConnectorService | |
|
||
// we need to change these types back and forth for storing in ES (arrays overwrite, objects merge) | ||
export type ConnectorFields = rt.TypeOf<typeof ConnectorFieldsRt>; | ||
|
||
export type ESConnectorFields = Array<{ | ||
key: string; | ||
value: unknown; | ||
}>; | ||
|
||
export type ESCaseConnectorTypes = ConnectorTypes; | ||
export interface ESCaseConnector { | ||
id: string; | ||
name: string; | ||
type: ESCaseConnectorTypes; | ||
fields: ESConnectorFields | null; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These were moved into the service layer as well since they are only referenced by service layer functionality. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -157,10 +157,11 @@ export const getPushedServiceLabelTitle = (action: CaseUserActions, firstPush: b | |
|
||
export const getPushInfo = ( | ||
caseServices: CaseServices, | ||
parsedValue: { connector_id: string; connector_name: string }, | ||
// a JSON parse failure will result in null for parsedValue | ||
parsedValue: { connector_id: string | null; connector_name: string } | null, | ||
index: number | ||
) => | ||
parsedValue != null | ||
parsedValue != null && parsedValue.connector_id != null | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
? { | ||
firstPush: caseServices[parsedValue.connector_id]?.firstPushIndex === index, | ||
parsedConnectorId: parsedValue.connector_id, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,15 +25,9 @@ import { | |
MAX_TITLE_LENGTH, | ||
} from '../../../common'; | ||
import { buildCaseUserActionItem } from '../../services/user_actions/helpers'; | ||
import { getConnectorFromConfiguration } from '../utils'; | ||
|
||
import { Operations } from '../../authorization'; | ||
import { | ||
createCaseError, | ||
flattenCaseSavedObject, | ||
transformCaseConnectorToEsConnector, | ||
transformNewCase, | ||
} from '../../common'; | ||
import { createCaseError, flattenCaseSavedObject, transformNewCase } from '../../common'; | ||
import { CasesClientArgs } from '..'; | ||
|
||
/** | ||
|
@@ -48,7 +42,6 @@ export const create = async ( | |
const { | ||
unsecuredSavedObjectsClient, | ||
caseService, | ||
caseConfigureService, | ||
userActionService, | ||
user, | ||
logger, | ||
|
@@ -90,10 +83,6 @@ export const create = async ( | |
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
const { username, full_name, email } = user; | ||
const createdDate = new Date().toISOString(); | ||
const myCaseConfigure = await caseConfigureService.find({ | ||
unsecuredSavedObjectsClient, | ||
}); | ||
const caseConfigureConnector = getConnectorFromConfiguration(myCaseConfigure); | ||
|
||
const newCase = await caseService.postNewCase({ | ||
unsecuredSavedObjectsClient, | ||
|
@@ -103,7 +92,7 @@ export const create = async ( | |
username, | ||
full_name, | ||
email, | ||
connector: transformCaseConnectorToEsConnector(query.connector ?? caseConfigureConnector), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
connector: query.connector, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
}), | ||
id: savedObjectID, | ||
}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,13 +34,12 @@ import { | |
CommentAttributes, | ||
CommentType, | ||
ENABLE_CASE_CONNECTOR, | ||
ESCaseAttributes, | ||
ESCasePatchRequest, | ||
excess, | ||
MAX_CONCURRENT_SEARCHES, | ||
SUB_CASE_SAVED_OBJECT, | ||
throwErrors, | ||
MAX_TITLE_LENGTH, | ||
CaseAttributes, | ||
} from '../../../common'; | ||
import { buildCaseUserActions } from '../../services/user_actions/helpers'; | ||
import { getCaseToUpdate } from '../utils'; | ||
|
@@ -51,7 +50,6 @@ import { | |
createCaseError, | ||
flattenCaseSavedObject, | ||
isCommentRequestTypeAlertOrGenAlert, | ||
transformCaseConnectorToEsConnector, | ||
} from '../../common'; | ||
import { UpdateAlertRequest } from '../alerts/types'; | ||
import { CasesClientInternal } from '../client_internal'; | ||
|
@@ -62,8 +60,8 @@ import { Operations, OwnerEntity } from '../../authorization'; | |
* Throws an error if any of the requests attempt to update a collection style cases' status field. | ||
*/ | ||
function throwIfUpdateStatusOfCollection( | ||
requests: ESCasePatchRequest[], | ||
casesMap: Map<string, SavedObject<ESCaseAttributes>> | ||
requests: CasePatchRequest[], | ||
casesMap: Map<string, SavedObject<CaseAttributes>> | ||
) { | ||
const requestsUpdatingStatusOfCollection = requests.filter( | ||
(req) => | ||
|
@@ -82,8 +80,8 @@ function throwIfUpdateStatusOfCollection( | |
* Throws an error if any of the requests attempt to update a collection style case to an individual one. | ||
*/ | ||
function throwIfUpdateTypeCollectionToIndividual( | ||
requests: ESCasePatchRequest[], | ||
casesMap: Map<string, SavedObject<ESCaseAttributes>> | ||
requests: CasePatchRequest[], | ||
casesMap: Map<string, SavedObject<CaseAttributes>> | ||
) { | ||
const requestsUpdatingTypeCollectionToInd = requests.filter( | ||
(req) => | ||
|
@@ -102,7 +100,7 @@ function throwIfUpdateTypeCollectionToIndividual( | |
/** | ||
* Throws an error if any of the requests attempt to update the type of a case. | ||
*/ | ||
function throwIfUpdateType(requests: ESCasePatchRequest[]) { | ||
function throwIfUpdateType(requests: CasePatchRequest[]) { | ||
const requestsUpdatingType = requests.filter((req) => req.type !== undefined); | ||
|
||
if (requestsUpdatingType.length > 0) { | ||
|
@@ -118,7 +116,7 @@ function throwIfUpdateType(requests: ESCasePatchRequest[]) { | |
/** | ||
* Throws an error if any of the requests attempt to update the owner of a case. | ||
*/ | ||
function throwIfUpdateOwner(requests: ESCasePatchRequest[]) { | ||
function throwIfUpdateOwner(requests: CasePatchRequest[]) { | ||
const requestsUpdatingOwner = requests.filter((req) => req.owner !== undefined); | ||
|
||
if (requestsUpdatingOwner.length > 0) { | ||
|
@@ -136,11 +134,11 @@ async function throwIfInvalidUpdateOfTypeWithAlerts({ | |
caseService, | ||
unsecuredSavedObjectsClient, | ||
}: { | ||
requests: ESCasePatchRequest[]; | ||
requests: CasePatchRequest[]; | ||
caseService: CasesService; | ||
unsecuredSavedObjectsClient: SavedObjectsClientContract; | ||
}) { | ||
const getAlertsForID = async (caseToUpdate: ESCasePatchRequest) => { | ||
const getAlertsForID = async (caseToUpdate: CasePatchRequest) => { | ||
const alerts = await caseService.getAllCaseComments({ | ||
unsecuredSavedObjectsClient, | ||
id: caseToUpdate.id, | ||
|
@@ -163,7 +161,7 @@ async function throwIfInvalidUpdateOfTypeWithAlerts({ | |
}; | ||
|
||
const requestsUpdatingTypeField = requests.filter((req) => req.type === CaseType.collection); | ||
const getAlertsMapper = async (caseToUpdate: ESCasePatchRequest) => getAlertsForID(caseToUpdate); | ||
const getAlertsMapper = async (caseToUpdate: CasePatchRequest) => getAlertsForID(caseToUpdate); | ||
// Ensuring we don't too many concurrent get running. | ||
const casesAlertTotals = await pMap(requestsUpdatingTypeField, getAlertsMapper, { | ||
concurrency: MAX_CONCURRENT_SEARCHES, | ||
|
@@ -185,7 +183,7 @@ async function throwIfInvalidUpdateOfTypeWithAlerts({ | |
/** | ||
* Throws an error if any of the requests updates a title and the length is over MAX_TITLE_LENGTH. | ||
*/ | ||
function throwIfTitleIsInvalid(requests: ESCasePatchRequest[]) { | ||
function throwIfTitleIsInvalid(requests: CasePatchRequest[]) { | ||
const requestsInvalidTitle = requests.filter( | ||
(req) => req.title !== undefined && req.title.length > MAX_TITLE_LENGTH | ||
); | ||
|
@@ -218,7 +216,7 @@ async function getAlertComments({ | |
caseService, | ||
unsecuredSavedObjectsClient, | ||
}: { | ||
casesToSync: ESCasePatchRequest[]; | ||
casesToSync: CasePatchRequest[]; | ||
caseService: CasesService; | ||
unsecuredSavedObjectsClient: SavedObjectsClientContract; | ||
}): Promise<SavedObjectsFindResponse<CommentAttributes>> { | ||
|
@@ -315,9 +313,9 @@ async function updateAlerts({ | |
unsecuredSavedObjectsClient, | ||
casesClientInternal, | ||
}: { | ||
casesWithSyncSettingChangedToOn: ESCasePatchRequest[]; | ||
casesWithStatusChangedAndSynced: ESCasePatchRequest[]; | ||
casesMap: Map<string, SavedObject<ESCaseAttributes>>; | ||
casesWithSyncSettingChangedToOn: CasePatchRequest[]; | ||
casesWithStatusChangedAndSynced: CasePatchRequest[]; | ||
casesMap: Map<string, SavedObject<CaseAttributes>>; | ||
caseService: CasesService; | ||
unsecuredSavedObjectsClient: SavedObjectsClientContract; | ||
casesClientInternal: CasesClientInternal; | ||
|
@@ -376,7 +374,7 @@ async function updateAlerts({ | |
} | ||
|
||
function partitionPatchRequest( | ||
casesMap: Map<string, SavedObject<ESCaseAttributes>>, | ||
casesMap: Map<string, SavedObject<CaseAttributes>>, | ||
patchReqCases: CasePatchRequest[] | ||
): { | ||
nonExistingCases: CasePatchRequest[]; | ||
|
@@ -441,7 +439,7 @@ export const update = async ( | |
const casesMap = myCases.saved_objects.reduce((acc, so) => { | ||
acc.set(so.id, so); | ||
return acc; | ||
}, new Map<string, SavedObject<ESCaseAttributes>>()); | ||
}, new Map<string, SavedObject<CaseAttributes>>()); | ||
|
||
const { nonExistingCases, conflictedCases, casesToAuthorize } = partitionPatchRequest( | ||
casesMap, | ||
|
@@ -469,17 +467,12 @@ export const update = async ( | |
); | ||
} | ||
|
||
const updateCases: ESCasePatchRequest[] = query.cases.map((updateCase) => { | ||
const updateCases: CasePatchRequest[] = query.cases.map((updateCase) => { | ||
const currentCase = myCases.saved_objects.find((c) => c.id === updateCase.id); | ||
const { connector, ...thisCase } = updateCase; | ||
const { id, version } = updateCase; | ||
return currentCase != null | ||
? getCaseToUpdate(currentCase.attributes, { | ||
...thisCase, | ||
...(connector != null | ||
? { connector: transformCaseConnectorToEsConnector(connector) } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We no longer need to do the transformation here because that functionality/responsibility has been moved to the service layer. |
||
: {}), | ||
}) | ||
: { id: thisCase.id, version: thisCase.version }; | ||
? getCaseToUpdate(currentCase.attributes, updateCase) | ||
: { id, version }; | ||
}); | ||
|
||
const updateFilterCases = updateCases.filter((updateCase) => { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exporting here for use in the service transformation code so I can define a type without the connector_id field.