-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
46 changed files
with
1,142 additions
and
228 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
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
177 changes: 177 additions & 0 deletions
177
src/plugins/data_views/server/rest_api_routes/public/swap_references.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,177 @@ | ||
/* | ||
* 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 { UsageCounter } from '@kbn/usage-collection-plugin/server'; | ||
import { schema } from '@kbn/config-schema'; | ||
import { IRouter, StartServicesAccessor, SavedObjectsFindOptions } from '@kbn/core/server'; | ||
import { DataViewsService } from '../../../common'; | ||
import { handleErrors } from './util/handle_errors'; | ||
import type { | ||
DataViewsServerPluginStartDependencies, | ||
DataViewsServerPluginStart, | ||
} from '../../types'; | ||
import { DATA_VIEW_SWAP_REFERENCES_PATH, INITIAL_REST_VERSION } from '../../constants'; | ||
import { DATA_VIEW_SAVED_OBJECT_TYPE } from '../../../common/constants'; | ||
|
||
interface GetDataViewArgs { | ||
dataViewsService: DataViewsService; | ||
usageCollection?: UsageCounter; | ||
counterName: string; | ||
id: string; | ||
} | ||
|
||
interface SwapRefResponse { | ||
result: Array<{ id: string; type: string }>; | ||
preview: boolean; | ||
deleteSuccess?: boolean; | ||
} | ||
|
||
export const swapReference = async ({ | ||
dataViewsService, | ||
usageCollection, | ||
counterName, | ||
id, | ||
}: GetDataViewArgs) => { | ||
usageCollection?.incrementCounter({ counterName }); | ||
return dataViewsService.get(id); | ||
}; | ||
|
||
const idSchema = schema.string(); | ||
|
||
export const swapReferencesRoute = ( | ||
router: IRouter, | ||
getStartServices: StartServicesAccessor< | ||
DataViewsServerPluginStartDependencies, | ||
DataViewsServerPluginStart | ||
>, | ||
usageCollection?: UsageCounter | ||
) => { | ||
router.versioned.post({ path: DATA_VIEW_SWAP_REFERENCES_PATH, access: 'public' }).addVersion( | ||
{ | ||
version: INITIAL_REST_VERSION, | ||
validate: { | ||
request: { | ||
body: schema.object({ | ||
from_id: idSchema, | ||
from_type: schema.maybe(schema.string()), | ||
to_id: idSchema, | ||
for_id: schema.maybe(schema.oneOf([idSchema, schema.arrayOf(idSchema)])), | ||
for_type: schema.maybe(schema.string()), | ||
preview: schema.maybe(schema.boolean()), | ||
delete: schema.maybe(schema.boolean()), | ||
}), | ||
}, | ||
response: { | ||
200: { | ||
body: schema.object({ | ||
result: schema.arrayOf(schema.object({ id: idSchema, type: schema.string() })), | ||
preview: schema.boolean(), | ||
deleteSuccess: schema.maybe(schema.boolean()), | ||
}), | ||
}, | ||
}, | ||
}, | ||
}, | ||
router.handleLegacyErrors( | ||
handleErrors(async (ctx, req, res) => { | ||
const savedObjectsClient = (await ctx.core).savedObjects.client; | ||
const [core] = await getStartServices(); | ||
const types = core.savedObjects.getTypeRegistry().getAllTypes(); | ||
const type = req.body.from_type || DATA_VIEW_SAVED_OBJECT_TYPE; | ||
const preview = req.body.preview !== undefined ? req.body.preview : true; | ||
const searchId = | ||
!Array.isArray(req.body.for_id) && req.body.for_id !== undefined | ||
? [req.body.for_id] | ||
: req.body.for_id; | ||
|
||
usageCollection?.incrementCounter({ counterName: 'swap_references' }); | ||
|
||
// verify 'to' object actually exists | ||
try { | ||
await savedObjectsClient.get(type, req.body.to_id); | ||
} catch (e) { | ||
throw new Error(`Could not find object with type ${type} and id ${req.body.to_id}`); | ||
} | ||
|
||
// assemble search params | ||
const findParams: SavedObjectsFindOptions = { | ||
type: types.map((t) => t.name), | ||
hasReference: { type, id: req.body.from_id }, | ||
}; | ||
|
||
if (req.body.for_type) { | ||
findParams.type = [req.body.for_type]; | ||
} | ||
|
||
const { saved_objects: savedObjects } = await savedObjectsClient.find(findParams); | ||
|
||
const filteredSavedObjects = searchId | ||
? savedObjects.filter((so) => searchId?.includes(so.id)) | ||
: savedObjects; | ||
|
||
// create summary of affected objects | ||
const resultSummary = filteredSavedObjects.map((savedObject) => ({ | ||
id: savedObject.id, | ||
type: savedObject.type, | ||
})); | ||
|
||
const body: SwapRefResponse = { | ||
result: resultSummary, | ||
preview, | ||
}; | ||
|
||
// bail if preview | ||
if (preview) { | ||
return res.ok({ | ||
headers: { | ||
'content-type': 'application/json', | ||
}, | ||
body, | ||
}); | ||
} | ||
|
||
// iterate over list and update references | ||
for (const savedObject of filteredSavedObjects) { | ||
const updatedRefs = savedObject.references.map((ref) => { | ||
if (ref.type === type && ref.id === req.body.from_id) { | ||
return { ...ref, id: req.body.to_id }; | ||
} else { | ||
return ref; | ||
} | ||
}); | ||
|
||
await savedObjectsClient.update( | ||
savedObject.type, | ||
savedObject.id, | ||
{}, | ||
{ | ||
references: updatedRefs, | ||
} | ||
); | ||
} | ||
|
||
if (req.body.delete) { | ||
const verifyNoMoreRefs = await savedObjectsClient.find(findParams); | ||
if (verifyNoMoreRefs.total > 0) { | ||
body.deleteSuccess = false; | ||
} else { | ||
await savedObjectsClient.delete(type, req.body.from_id); | ||
body.deleteSuccess = true; | ||
} | ||
} | ||
|
||
return res.ok({ | ||
headers: { | ||
'content-type': 'application/json', | ||
}, | ||
body, | ||
}); | ||
}) | ||
) | ||
); | ||
}; |
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
40 changes: 40 additions & 0 deletions
40
test/api_integration/apis/data_views/swap_references/errors.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,40 @@ | ||
/* | ||
* 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 expect from '@kbn/expect'; | ||
import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; | ||
import { INITIAL_REST_VERSION } from '@kbn/data-views-plugin/server/constants'; | ||
import { FtrProviderContext } from '../../../ftr_provider_context'; | ||
import { dataViewConfig } from '../constants'; | ||
|
||
export default function ({ getService }: FtrProviderContext) { | ||
const supertest = getService('supertest'); | ||
|
||
describe('errors', () => { | ||
it('returns 404 error on non-existing index_pattern', async () => { | ||
const id = `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-${Date.now()}`; | ||
const response = await supertest | ||
.get(`${dataViewConfig.path}/${id}`) | ||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION); | ||
|
||
expect(response.status).to.be(404); | ||
}); | ||
|
||
it('returns error when ID is too long', async () => { | ||
const id = `xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx`; | ||
const response = await supertest | ||
.get(`${dataViewConfig.path}/${id}`) | ||
.set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION); | ||
|
||
expect(response.status).to.be(400); | ||
expect(response.body.message).to.be( | ||
'[request params.id]: value has length [1759] but it must have a maximum length of [1000].' | ||
); | ||
}); | ||
}); | ||
} |
16 changes: 16 additions & 0 deletions
16
test/api_integration/apis/data_views/swap_references/index.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,16 @@ | ||
/* | ||
* 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 { FtrProviderContext } from '../../../ftr_provider_context'; | ||
|
||
export default function ({ loadTestFile }: FtrProviderContext) { | ||
describe('swap_references', () => { | ||
loadTestFile(require.resolve('./errors')); | ||
loadTestFile(require.resolve('./main')); | ||
}); | ||
} |
Oops, something went wrong.