Merge 403 and unsupported type errors into single error
This commit is contained in:
parent
38b402b623
commit
99aea10c0f
|
@ -269,37 +269,6 @@ exports[`Flyout conflicts should handle errors 1`] = `
|
|||
</EuiCallOut>
|
||||
`;
|
||||
|
||||
exports[`Flyout errors should display unsupported type errors properly 1`] = `
|
||||
<EuiCallOut
|
||||
color="warning"
|
||||
iconType="help"
|
||||
size="m"
|
||||
title={
|
||||
<FormattedMessage
|
||||
defaultMessage="Import failed"
|
||||
id="kbn.management.objects.objectsTable.flyout.importFailedTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="Failed to import {failedImportCount} of {totalImportCount} objects. Import failed"
|
||||
id="kbn.management.objects.objectsTable.flyout.importFailedDescription"
|
||||
values={
|
||||
Object {
|
||||
"failedImportCount": 1,
|
||||
"totalImportCount": 1,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
wigwags [id=1] unsupported type
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
`;
|
||||
|
||||
exports[`Flyout legacy conflicts should allow conflict resolution 1`] = `
|
||||
<EuiFlyout
|
||||
closeButtonAriaLabel="Closes this dialog"
|
||||
|
|
|
@ -313,75 +313,6 @@ describe('Flyout', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('errors', () => {
|
||||
const { importFile } = require('../../../../../lib/import_file');
|
||||
const { resolveImportErrors } = require('../../../../../lib/resolve_import_errors');
|
||||
|
||||
it('should display unsupported type errors properly', async () => {
|
||||
const component = shallowWithIntl(<Flyout.WrappedComponent {...defaultProps} />);
|
||||
|
||||
// Ensure all promises resolve
|
||||
await Promise.resolve();
|
||||
// Ensure the state changes are reflected
|
||||
component.update();
|
||||
|
||||
importFile.mockImplementation(() => ({
|
||||
success: false,
|
||||
successCount: 0,
|
||||
errors: [
|
||||
{
|
||||
id: '1',
|
||||
type: 'wigwags',
|
||||
title: 'My Title',
|
||||
error: {
|
||||
type: 'unsupported_type',
|
||||
}
|
||||
},
|
||||
],
|
||||
}));
|
||||
resolveImportErrors.mockImplementation(() => ({
|
||||
status: 'success',
|
||||
importCount: 0,
|
||||
failedImports: [
|
||||
{
|
||||
error: {
|
||||
type: 'unsupported_type',
|
||||
},
|
||||
obj: {
|
||||
id: '1',
|
||||
type: 'wigwags',
|
||||
title: 'My Title',
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
component.setState({ file: mockFile, isLegacyFile: false });
|
||||
|
||||
// Go through the import flow
|
||||
await component.instance().import();
|
||||
component.update();
|
||||
|
||||
// Ensure all promises resolve
|
||||
await Promise.resolve();
|
||||
|
||||
expect(component.state('status')).toBe('success');
|
||||
expect(component.state('failedImports')).toEqual([
|
||||
{
|
||||
error: {
|
||||
type: 'unsupported_type',
|
||||
},
|
||||
obj: {
|
||||
id: '1',
|
||||
type: 'wigwags',
|
||||
title: 'My Title',
|
||||
},
|
||||
},
|
||||
]);
|
||||
expect(component.find('EuiFlyout EuiCallOut')).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('legacy conflicts', () => {
|
||||
const { importLegacyFile } = require('../../../../../lib/import_legacy_file');
|
||||
const {
|
||||
|
|
|
@ -602,17 +602,6 @@ class FlyoutUI extends Component {
|
|||
}
|
||||
);
|
||||
});
|
||||
} else if (error.type === 'unsupported_type') {
|
||||
return intl.formatMessage(
|
||||
{
|
||||
id: 'kbn.management.objects.objectsTable.flyout.importFailedUnsupportedType',
|
||||
defaultMessage: '{type} [id={id}] unsupported type',
|
||||
},
|
||||
{
|
||||
id: obj.id,
|
||||
type: obj.type,
|
||||
},
|
||||
);
|
||||
}
|
||||
return getField(error, 'body.message', error.message || '');
|
||||
}).join(' ')}
|
||||
|
|
|
@ -23,22 +23,28 @@ describe('getSortedObjectsForExport()', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
savedObjectsClient.find.mockReset();
|
||||
savedObjectsClient.bulkGet.mockReset();
|
||||
savedObjectsClient.create.mockReset();
|
||||
savedObjectsClient.bulkCreate.mockReset();
|
||||
savedObjectsClient.delete.mockReset();
|
||||
savedObjectsClient.get.mockReset();
|
||||
savedObjectsClient.update.mockReset();
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
savedObjectsClient.canBulkCreate.mockImplementation((types: string[]) =>
|
||||
types.map(type => ({ type, can: true }))
|
||||
);
|
||||
savedObjectsClient.canBulkGet.mockImplementation((types: string[]) =>
|
||||
types.map(type => ({ type, can: true }))
|
||||
);
|
||||
savedObjectsClient.canFind.mockImplementation((types: string[]) =>
|
||||
types.map(type => ({ type, can: true }))
|
||||
);
|
||||
});
|
||||
|
||||
test('exports selected types and sorts them', async () => {
|
||||
|
@ -66,6 +72,7 @@ describe('getSortedObjectsForExport()', () => {
|
|||
savedObjectsClient,
|
||||
exportSizeLimit: 500,
|
||||
types: ['index-pattern', 'search'],
|
||||
supportedTypes: ['index-pattern', 'search'],
|
||||
});
|
||||
expect(response).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
|
@ -137,6 +144,7 @@ Array [
|
|||
savedObjectsClient,
|
||||
exportSizeLimit: 1,
|
||||
types: ['index-pattern', 'search'],
|
||||
supportedTypes: ['index-pattern', 'search'],
|
||||
})
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`"Can't export more than 1 objects"`);
|
||||
});
|
||||
|
@ -165,6 +173,7 @@ Array [
|
|||
exportSizeLimit: 10000,
|
||||
savedObjectsClient,
|
||||
types: ['index-pattern', 'search'],
|
||||
supportedTypes: ['index-pattern', 'search'],
|
||||
objects: [
|
||||
{
|
||||
type: 'index-pattern',
|
||||
|
@ -249,6 +258,7 @@ Array [
|
|||
exportSizeLimit: 10000,
|
||||
savedObjectsClient,
|
||||
types: ['index-pattern', 'search'],
|
||||
supportedTypes: ['index-pattern', 'search'],
|
||||
objects: [
|
||||
{
|
||||
type: 'search',
|
||||
|
@ -315,6 +325,7 @@ Array [
|
|||
exportSizeLimit: 1,
|
||||
savedObjectsClient,
|
||||
types: ['index-pattern', 'search'],
|
||||
supportedTypes: ['index-pattern', 'search'],
|
||||
objects: [
|
||||
{
|
||||
type: 'index-pattern',
|
||||
|
|
|
@ -33,6 +33,26 @@ interface ExportObjectsOptions {
|
|||
savedObjectsClient: SavedObjectsClient;
|
||||
exportSizeLimit: number;
|
||||
includeReferencesDeep?: boolean;
|
||||
supportedTypes: string[];
|
||||
}
|
||||
|
||||
function throwIfInvalidTypes(
|
||||
action: string,
|
||||
objectTypes: string[],
|
||||
supportedTypes: string[],
|
||||
authorizedTypes: Array<{ type: string; can: boolean }>
|
||||
) {
|
||||
const invalidTypes = new Set([
|
||||
...objectTypes.filter(type => !supportedTypes.includes(type)),
|
||||
...authorizedTypes.filter(resp => resp.can === false).map(resp => resp.type),
|
||||
]);
|
||||
if (invalidTypes.size) {
|
||||
throw Boom.badRequest(
|
||||
`Unable to ${action} ${Array.from(invalidTypes)
|
||||
.sort()
|
||||
.join(',')}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchObjectsToExport({
|
||||
|
@ -40,13 +60,22 @@ async function fetchObjectsToExport({
|
|||
types,
|
||||
exportSizeLimit,
|
||||
savedObjectsClient,
|
||||
supportedTypes,
|
||||
}: {
|
||||
objects?: ObjectToExport[];
|
||||
types?: string[];
|
||||
exportSizeLimit: number;
|
||||
savedObjectsClient: SavedObjectsClient;
|
||||
supportedTypes: string[];
|
||||
}) {
|
||||
if (objects) {
|
||||
const objectTypes = [...new Set(objects.map(obj => obj.type))];
|
||||
throwIfInvalidTypes(
|
||||
'bulk_get',
|
||||
objectTypes,
|
||||
supportedTypes,
|
||||
await savedObjectsClient.canBulkGet(objectTypes)
|
||||
);
|
||||
if (objects.length > exportSizeLimit) {
|
||||
throw Boom.badRequest(`Can't export more than ${exportSizeLimit} objects`);
|
||||
}
|
||||
|
@ -61,6 +90,13 @@ async function fetchObjectsToExport({
|
|||
}
|
||||
return bulkGetResult.saved_objects;
|
||||
}
|
||||
|
||||
throwIfInvalidTypes(
|
||||
'find',
|
||||
types || [],
|
||||
supportedTypes,
|
||||
await savedObjectsClient.canFind(types || [])
|
||||
);
|
||||
const findResponse = await savedObjectsClient.find({
|
||||
type: types,
|
||||
sortField: '_id',
|
||||
|
@ -79,12 +115,14 @@ export async function getSortedObjectsForExport({
|
|||
savedObjectsClient,
|
||||
exportSizeLimit,
|
||||
includeReferencesDeep = false,
|
||||
supportedTypes,
|
||||
}: ExportObjectsOptions) {
|
||||
const objectsToExport = await fetchObjectsToExport({
|
||||
types,
|
||||
objects,
|
||||
savedObjectsClient,
|
||||
exportSizeLimit,
|
||||
supportedTypes,
|
||||
});
|
||||
return sortObjects(
|
||||
includeReferencesDeep
|
||||
|
|
|
@ -114,9 +114,12 @@ describe('injectNestedDependencies', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
|
|
|
@ -27,13 +27,8 @@ describe('collectSavedObjects()', () => {
|
|||
this.push(null);
|
||||
},
|
||||
});
|
||||
const result = await collectSavedObjects({ readStream, objectLimit: 10, supportedTypes: [] });
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"collectedObjects": Array [],
|
||||
"errors": Array [],
|
||||
}
|
||||
`);
|
||||
const result = await collectSavedObjects({ readStream, objectLimit: 10 });
|
||||
expect(result).toMatchInlineSnapshot(`Array []`);
|
||||
});
|
||||
|
||||
test('collects objects from stream', async () => {
|
||||
|
@ -46,19 +41,15 @@ Object {
|
|||
const result = await collectSavedObjects({
|
||||
readStream,
|
||||
objectLimit: 1,
|
||||
supportedTypes: ['a'],
|
||||
});
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"collectedObjects": Array [
|
||||
Object {
|
||||
"foo": true,
|
||||
"migrationVersion": Object {},
|
||||
"type": "a",
|
||||
},
|
||||
],
|
||||
"errors": Array [],
|
||||
}
|
||||
Array [
|
||||
Object {
|
||||
"foo": true,
|
||||
"migrationVersion": Object {},
|
||||
"type": "a",
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
|
@ -72,19 +63,15 @@ Object {
|
|||
const result = await collectSavedObjects({
|
||||
readStream,
|
||||
objectLimit: 1,
|
||||
supportedTypes: ['a'],
|
||||
});
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"collectedObjects": Array [
|
||||
Object {
|
||||
"foo": true,
|
||||
"migrationVersion": Object {},
|
||||
"type": "a",
|
||||
},
|
||||
],
|
||||
"errors": Array [],
|
||||
}
|
||||
Array [
|
||||
Object {
|
||||
"foo": true,
|
||||
"migrationVersion": Object {},
|
||||
"type": "a",
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
|
@ -100,58 +87,6 @@ Object {
|
|||
collectSavedObjects({
|
||||
readStream,
|
||||
objectLimit: 1,
|
||||
supportedTypes: ['a'],
|
||||
})
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`"Can't import more than 1 objects"`);
|
||||
});
|
||||
|
||||
test('unsupported types return as import errors', async () => {
|
||||
const readStream = new Readable({
|
||||
read() {
|
||||
this.push('{"id":"1","type":"a","attributes":{"title":"my title"}}\n');
|
||||
this.push('{"id":"2","type":"b","attributes":{"title":"my title 2"}}\n');
|
||||
this.push(null);
|
||||
},
|
||||
});
|
||||
const result = await collectSavedObjects({ readStream, objectLimit: 2, supportedTypes: ['1'] });
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"collectedObjects": Array [],
|
||||
"errors": Array [
|
||||
Object {
|
||||
"error": Object {
|
||||
"type": "unsupported_type",
|
||||
},
|
||||
"id": "1",
|
||||
"title": "my title",
|
||||
"type": "a",
|
||||
},
|
||||
Object {
|
||||
"error": Object {
|
||||
"type": "unsupported_type",
|
||||
},
|
||||
"id": "2",
|
||||
"title": "my title 2",
|
||||
"type": "b",
|
||||
},
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test('unsupported types still count towards object limit', async () => {
|
||||
const readStream = new Readable({
|
||||
read() {
|
||||
this.push('{"foo":true,"type":"a"}\n');
|
||||
this.push('{"bar":true,"type":"b"}\n');
|
||||
this.push(null);
|
||||
},
|
||||
});
|
||||
await expect(
|
||||
collectSavedObjects({
|
||||
readStream,
|
||||
objectLimit: 1,
|
||||
supportedTypes: ['a'],
|
||||
})
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`"Can't import more than 1 objects"`);
|
||||
});
|
||||
|
|
|
@ -27,22 +27,18 @@ import {
|
|||
} from '../../../utils/streams';
|
||||
import { SavedObject } from '../service';
|
||||
import { createLimitStream } from './create_limit_stream';
|
||||
import { ImportError } from './types';
|
||||
|
||||
interface CollectSavedObjectsOptions {
|
||||
readStream: Readable;
|
||||
objectLimit: number;
|
||||
filter?: (obj: SavedObject) => boolean;
|
||||
supportedTypes: string[];
|
||||
}
|
||||
|
||||
export async function collectSavedObjects({
|
||||
readStream,
|
||||
objectLimit,
|
||||
filter,
|
||||
supportedTypes,
|
||||
}: CollectSavedObjectsOptions) {
|
||||
const errors: ImportError[] = [];
|
||||
const collectedObjects: SavedObject[] = await createPromiseFromStreams([
|
||||
readStream,
|
||||
createSplitStream('\n'),
|
||||
|
@ -53,20 +49,6 @@ export async function collectSavedObjects({
|
|||
}),
|
||||
createFilterStream<SavedObject>(obj => !!obj),
|
||||
createLimitStream(objectLimit),
|
||||
createFilterStream<SavedObject>(obj => {
|
||||
if (supportedTypes.includes(obj.type)) {
|
||||
return true;
|
||||
}
|
||||
errors.push({
|
||||
id: obj.id,
|
||||
type: obj.type,
|
||||
title: obj.attributes.title,
|
||||
error: {
|
||||
type: 'unsupported_type',
|
||||
},
|
||||
});
|
||||
return false;
|
||||
}),
|
||||
createFilterStream<SavedObject>(obj => (filter ? filter(obj) : true)),
|
||||
createMapStream((obj: SavedObject) => {
|
||||
// Ensure migrations execute on every saved object
|
||||
|
@ -74,8 +56,5 @@ export async function collectSavedObjects({
|
|||
}),
|
||||
createConcatStream([]),
|
||||
]);
|
||||
return {
|
||||
errors,
|
||||
collectedObjects,
|
||||
};
|
||||
return collectedObjects;
|
||||
}
|
||||
|
|
|
@ -59,16 +59,28 @@ describe('importSavedObjects()', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
savedObjectsClient.canBulkCreate.mockImplementation((types: string[]) =>
|
||||
types.map(type => ({ type, can: true }))
|
||||
);
|
||||
savedObjectsClient.canBulkGet.mockImplementation((types: string[]) =>
|
||||
types.map(type => ({ type, can: true }))
|
||||
);
|
||||
savedObjectsClient.canFind.mockImplementation((types: string[]) =>
|
||||
types.map(type => ({ type, can: true }))
|
||||
);
|
||||
});
|
||||
|
||||
test('returns early when no objects exist', async () => {
|
||||
|
@ -443,83 +455,14 @@ Object {
|
|||
savedObjectsClient.bulkCreate.mockResolvedValue({
|
||||
saved_objects: savedObjects,
|
||||
});
|
||||
const result = await importSavedObjects({
|
||||
readStream,
|
||||
objectLimit: 5,
|
||||
overwrite: false,
|
||||
savedObjectsClient,
|
||||
supportedTypes: ['index-pattern', 'search', 'visualization', 'dashboard'],
|
||||
});
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"errors": Array [
|
||||
Object {
|
||||
"error": Object {
|
||||
"type": "unsupported_type",
|
||||
},
|
||||
"id": "1",
|
||||
"title": "my title",
|
||||
"type": "wigwags",
|
||||
},
|
||||
],
|
||||
"success": false,
|
||||
"successCount": 4,
|
||||
}
|
||||
`);
|
||||
expect(savedObjectsClient.bulkCreate).toMatchInlineSnapshot(`
|
||||
[MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Array [
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"title": "My Index Pattern",
|
||||
},
|
||||
"id": "1",
|
||||
"migrationVersion": Object {},
|
||||
"references": Array [],
|
||||
"type": "index-pattern",
|
||||
},
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"title": "My Search",
|
||||
},
|
||||
"id": "2",
|
||||
"migrationVersion": Object {},
|
||||
"references": Array [],
|
||||
"type": "search",
|
||||
},
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"title": "My Visualization",
|
||||
},
|
||||
"id": "3",
|
||||
"migrationVersion": Object {},
|
||||
"references": Array [],
|
||||
"type": "visualization",
|
||||
},
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"title": "My Dashboard",
|
||||
},
|
||||
"id": "4",
|
||||
"migrationVersion": Object {},
|
||||
"references": Array [],
|
||||
"type": "dashboard",
|
||||
},
|
||||
],
|
||||
Object {
|
||||
"overwrite": false,
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"type": "return",
|
||||
"value": Promise {},
|
||||
},
|
||||
],
|
||||
}
|
||||
`);
|
||||
await expect(
|
||||
importSavedObjects({
|
||||
readStream,
|
||||
objectLimit: 5,
|
||||
overwrite: false,
|
||||
savedObjectsClient,
|
||||
supportedTypes: ['index-pattern', 'search', 'visualization', 'dashboard'],
|
||||
})
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`"Unable to bulk_create wigwags"`);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import Boom from 'boom';
|
||||
import { Readable } from 'stream';
|
||||
import { SavedObjectsClient } from '../service';
|
||||
import { collectSavedObjects } from './collect_saved_objects';
|
||||
|
@ -48,11 +49,19 @@ export async function importSavedObjects({
|
|||
let errorAccumulator: ImportError[] = [];
|
||||
|
||||
// Get the objects to import
|
||||
const {
|
||||
errors: collectorErrors,
|
||||
collectedObjects: objectsFromStream,
|
||||
} = await collectSavedObjects({ readStream, objectLimit, supportedTypes });
|
||||
errorAccumulator = [...errorAccumulator, ...collectorErrors];
|
||||
const objectsFromStream = await collectSavedObjects({ readStream, objectLimit });
|
||||
|
||||
const objectTypes = [...new Set(objectsFromStream.map(obj => obj.type))];
|
||||
const authorizedTypes = await savedObjectsClient.canBulkCreate(objectTypes);
|
||||
const invalidTypes = [
|
||||
...new Set([
|
||||
...objectTypes.filter(type => !supportedTypes.includes(type)),
|
||||
...authorizedTypes.filter(resp => resp.can === false).map(resp => resp.type),
|
||||
]),
|
||||
];
|
||||
if (invalidTypes.length) {
|
||||
throw Boom.badRequest(`Unable to bulk_create ${invalidTypes.sort().join(',')}`);
|
||||
}
|
||||
|
||||
// Validate references
|
||||
const { filteredObjects, errors: validationErrors } = await validateReferences(
|
||||
|
|
|
@ -65,16 +65,28 @@ describe('resolveImportErrors()', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
savedObjectsClient.canBulkCreate.mockImplementation((types: string[]) =>
|
||||
types.map(type => ({ type, can: true }))
|
||||
);
|
||||
savedObjectsClient.canBulkGet.mockImplementation((types: string[]) =>
|
||||
types.map(type => ({ type, can: true }))
|
||||
);
|
||||
savedObjectsClient.canFind.mockImplementation((types: string[]) =>
|
||||
types.map(type => ({ type, can: true }))
|
||||
);
|
||||
});
|
||||
|
||||
test('works with empty parameters', async () => {
|
||||
|
@ -494,36 +506,21 @@ Object {
|
|||
savedObjectsClient.bulkCreate.mockResolvedValue({
|
||||
saved_objects: [],
|
||||
});
|
||||
const result = await resolveImportErrors({
|
||||
readStream,
|
||||
objectLimit: 5,
|
||||
retries: [
|
||||
{
|
||||
id: 'i',
|
||||
type: 'wigwags',
|
||||
overwrite: false,
|
||||
replaceReferences: [],
|
||||
},
|
||||
],
|
||||
savedObjectsClient,
|
||||
supportedTypes: ['index-pattern', 'search', 'visualization', 'dashboard'],
|
||||
});
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"errors": Array [
|
||||
Object {
|
||||
"error": Object {
|
||||
"type": "unsupported_type",
|
||||
},
|
||||
"id": "1",
|
||||
"title": "my title",
|
||||
"type": "wigwags",
|
||||
},
|
||||
],
|
||||
"success": false,
|
||||
"successCount": 0,
|
||||
}
|
||||
`);
|
||||
expect(savedObjectsClient.bulkCreate).toMatchInlineSnapshot(`[MockFunction]`);
|
||||
await expect(
|
||||
resolveImportErrors({
|
||||
readStream,
|
||||
objectLimit: 5,
|
||||
retries: [
|
||||
{
|
||||
id: '1',
|
||||
type: 'wigwags',
|
||||
overwrite: false,
|
||||
replaceReferences: [],
|
||||
},
|
||||
],
|
||||
savedObjectsClient,
|
||||
supportedTypes: ['index-pattern', 'search', 'visualization', 'dashboard'],
|
||||
})
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`"Unable to bulk_create wigwags"`);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import Boom from 'boom';
|
||||
import { Readable } from 'stream';
|
||||
import { SavedObjectsClient } from '../service';
|
||||
import { collectSavedObjects } from './collect_saved_objects';
|
||||
|
@ -52,15 +53,23 @@ export async function resolveImportErrors({
|
|||
const filter = createObjectsFilter(retries);
|
||||
|
||||
// Get the objects to resolve errors
|
||||
const { errors: collectorErrors, collectedObjects: objectsToResolve } = await collectSavedObjects(
|
||||
{
|
||||
readStream,
|
||||
objectLimit,
|
||||
filter,
|
||||
supportedTypes,
|
||||
}
|
||||
);
|
||||
errorAccumulator = [...errorAccumulator, ...collectorErrors];
|
||||
const objectsToResolve = await collectSavedObjects({
|
||||
readStream,
|
||||
objectLimit,
|
||||
filter,
|
||||
});
|
||||
|
||||
const objectTypes = [...new Set(objectsToResolve.map(obj => obj.type))];
|
||||
const authorizedTypes = await savedObjectsClient.canBulkCreate(objectTypes);
|
||||
const invalidTypes = [
|
||||
...new Set([
|
||||
...objectTypes.filter(type => !supportedTypes.includes(type)),
|
||||
...authorizedTypes.filter(resp => resp.can === false).map(resp => resp.type),
|
||||
]),
|
||||
];
|
||||
if (invalidTypes.length) {
|
||||
throw Boom.badRequest(`Unable to bulk_create ${invalidTypes.sort().join(',')}`);
|
||||
}
|
||||
|
||||
// Create a map of references to replace for each object to avoid iterating through
|
||||
// retries for every object to resolve
|
||||
|
|
|
@ -32,10 +32,6 @@ export interface ConflictError {
|
|||
type: 'conflict';
|
||||
}
|
||||
|
||||
export interface UnsupportedTypeError {
|
||||
type: 'unsupported_type';
|
||||
}
|
||||
|
||||
export interface UnknownError {
|
||||
type: 'unknown';
|
||||
message: string;
|
||||
|
@ -58,5 +54,5 @@ export interface ImportError {
|
|||
id: string;
|
||||
type: string;
|
||||
title?: string;
|
||||
error: ConflictError | UnsupportedTypeError | MissingReferencesError | UnknownError;
|
||||
error: ConflictError | MissingReferencesError | UnknownError;
|
||||
}
|
||||
|
|
|
@ -23,10 +23,13 @@ describe('getNonExistingReferenceAsKeys()', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
@ -223,10 +226,13 @@ describe('validateReferences()', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
|
|
@ -26,10 +26,13 @@ describe('POST /api/saved_objects/_bulk_create', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
|
|
@ -26,10 +26,13 @@ describe('POST /api/saved_objects/_bulk_get', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
|
|
@ -26,10 +26,13 @@ describe('POST /api/saved_objects/{type}', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
|
|
@ -26,10 +26,13 @@ describe('DELETE /api/saved_objects/{type}/{id}', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
|
|
@ -33,10 +33,13 @@ describe('POST /api/saved_objects/_export', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
@ -128,6 +131,9 @@ Array [
|
|||
"savedObjectsClient": Object {
|
||||
"bulkCreate": [MockFunction],
|
||||
"bulkGet": [MockFunction],
|
||||
"canBulkCreate": [MockFunction],
|
||||
"canBulkGet": [MockFunction],
|
||||
"canFind": [MockFunction],
|
||||
"create": [MockFunction],
|
||||
"delete": [MockFunction],
|
||||
"errors": Object {},
|
||||
|
@ -135,6 +141,10 @@ Array [
|
|||
"get": [MockFunction],
|
||||
"update": [MockFunction],
|
||||
},
|
||||
"supportedTypes": Array [
|
||||
"index-pattern",
|
||||
"search",
|
||||
],
|
||||
"types": Array [
|
||||
"search",
|
||||
],
|
||||
|
|
|
@ -51,14 +51,12 @@ export const createExportRoute = (
|
|||
payload: Joi.object()
|
||||
.keys({
|
||||
type: Joi.array()
|
||||
.items(Joi.string().valid(supportedTypes))
|
||||
.items(Joi.string())
|
||||
.single()
|
||||
.optional(),
|
||||
objects: Joi.array()
|
||||
.items({
|
||||
type: Joi.string()
|
||||
.valid(supportedTypes)
|
||||
.required(),
|
||||
type: Joi.string().required(),
|
||||
id: Joi.string().required(),
|
||||
})
|
||||
.max(server.config().get('savedObjects.maxImportExportSize'))
|
||||
|
@ -71,6 +69,7 @@ export const createExportRoute = (
|
|||
async handler(request: ExportRequest, h: Hapi.ResponseToolkit) {
|
||||
const { savedObjectsClient } = request.pre;
|
||||
const docsToExport = await getSortedObjectsForExport({
|
||||
supportedTypes,
|
||||
savedObjectsClient,
|
||||
types: request.payload.type,
|
||||
objects: request.payload.objects,
|
||||
|
|
|
@ -26,10 +26,13 @@ describe('GET /api/saved_objects/_find', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
|
|
@ -26,10 +26,13 @@ describe('GET /api/saved_objects/{type}/{id}', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
|
|
@ -26,10 +26,13 @@ describe('POST /api/saved_objects/_import', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
@ -37,6 +40,15 @@ describe('POST /api/saved_objects/_import', () => {
|
|||
beforeEach(() => {
|
||||
server = createMockServer();
|
||||
jest.resetAllMocks();
|
||||
savedObjectsClient.canBulkCreate.mockImplementation((types: string[]) =>
|
||||
types.map(type => ({ type, can: true }))
|
||||
);
|
||||
savedObjectsClient.canBulkGet.mockImplementation((types: string[]) =>
|
||||
types.map(type => ({ type, can: true }))
|
||||
);
|
||||
savedObjectsClient.canFind.mockImplementation((types: string[]) =>
|
||||
types.map(type => ({ type, can: true }))
|
||||
);
|
||||
|
||||
const prereqs = {
|
||||
getSavedObjectsClient: {
|
||||
|
|
|
@ -26,10 +26,13 @@ describe('POST /api/saved_objects/_resolve_import_errors', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
@ -37,6 +40,15 @@ describe('POST /api/saved_objects/_resolve_import_errors', () => {
|
|||
beforeEach(() => {
|
||||
server = createMockServer();
|
||||
jest.resetAllMocks();
|
||||
savedObjectsClient.canBulkCreate.mockImplementation((types: string[]) =>
|
||||
types.map(type => ({ type, can: true }))
|
||||
);
|
||||
savedObjectsClient.canBulkGet.mockImplementation((types: string[]) =>
|
||||
types.map(type => ({ type, can: true }))
|
||||
);
|
||||
savedObjectsClient.canFind.mockImplementation((types: string[]) =>
|
||||
types.map(type => ({ type, can: true }))
|
||||
);
|
||||
|
||||
const prereqs = {
|
||||
getSavedObjectsClient: {
|
||||
|
|
|
@ -26,10 +26,13 @@ describe('PUT /api/saved_objects/{type}/{id?}', () => {
|
|||
const savedObjectsClient = {
|
||||
errors: {} as any,
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
get: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
|
|
@ -127,14 +127,24 @@ export declare class SavedObjectsClient {
|
|||
objects: Array<BulkCreateObject<T>>,
|
||||
options?: CreateOptions
|
||||
): Promise<BulkCreateResponse<T>>;
|
||||
public canBulkCreate(
|
||||
types: string[]
|
||||
): Promise<
|
||||
Array<{
|
||||
type: string;
|
||||
can: boolean;
|
||||
}>
|
||||
>;
|
||||
public delete(type: string, id: string, options?: BaseOptions): Promise<{}>;
|
||||
public find<T extends SavedObjectAttributes = any>(
|
||||
options: FindOptions
|
||||
): Promise<FindResponse<T>>;
|
||||
public canFind(types: string[]): Promise<Array<{ type: string; can: boolean }>>;
|
||||
public bulkGet<T extends SavedObjectAttributes = any>(
|
||||
objects: BulkGetObjects,
|
||||
options?: BaseOptions
|
||||
): Promise<BulkGetResponse<T>>;
|
||||
public canBulkGet(types: string[]): Promise<Array<{ type: string; can: boolean }>>;
|
||||
public get<T extends SavedObjectAttributes = any>(
|
||||
type: string,
|
||||
id: string,
|
||||
|
|
|
@ -122,6 +122,19 @@ export class SavedObjectsClient {
|
|||
return this._repository.bulkCreate(objects, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function is used to validate if each type of saved object can be created in bulk.
|
||||
*
|
||||
* This is and should only be used by import / export / resolve import errors to merge
|
||||
* invalid types and unauthorized types in a single error response.
|
||||
*
|
||||
* @param {Array<string>} types Types of saved objects
|
||||
* @return [{ type, can }]
|
||||
*/
|
||||
async canBulkCreate(types) {
|
||||
return types.map(type => ({ type, can: true }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an object
|
||||
*
|
||||
|
@ -155,6 +168,19 @@ export class SavedObjectsClient {
|
|||
return this._repository.find(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function is used to validate if each type of saved object can be created used with find.
|
||||
*
|
||||
* This is and should only be used by import / export / resolve import errors to merge
|
||||
* invalid types and unauthorized types in a single error response.
|
||||
*
|
||||
* @param {Array<string>} types Types of saved objects
|
||||
* @return [{ type, can }]
|
||||
*/
|
||||
async canFind(types) {
|
||||
return types.map(type => ({ type, can: true }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of objects by id
|
||||
*
|
||||
|
@ -173,6 +199,19 @@ export class SavedObjectsClient {
|
|||
return this._repository.bulkGet(objects, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function is used to validate if each type of saved object can be created used in bulk get.
|
||||
*
|
||||
* This is and should only be used by import / export / resolve import errors to merge
|
||||
* invalid types and unauthorized types in a single error response.
|
||||
*
|
||||
* @param {Array<string>} types Types of saved objects
|
||||
* @return [{ type, can }]
|
||||
*/
|
||||
async canBulkGet(types) {
|
||||
return types.map(type => ({ type, can: true }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a single object
|
||||
*
|
||||
|
|
|
@ -138,12 +138,7 @@ export default function ({ getService }) {
|
|||
expect(resp.body).to.eql({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: 'child "type" fails because ["type" at position 0 fails because ' +
|
||||
'["0" must be one of [config, index-pattern, visualization, search, dashboard, url]]]',
|
||||
validation: {
|
||||
source: 'payload',
|
||||
keys: ['type.0'],
|
||||
}
|
||||
message: 'Unable to find wigwags',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -112,26 +112,17 @@ export default function ({ getService }) {
|
|||
});
|
||||
});
|
||||
|
||||
it('should return 200 when trying to import unsupported types', async () => {
|
||||
it('should return 400 when trying to import unsupported types', async () => {
|
||||
const fileBuffer = Buffer.from('{"id":"1","type":"wigwags","attributes":{"title":"my title"},"references":[]}', 'utf8');
|
||||
await supertest
|
||||
.post('/api/saved_objects/_import')
|
||||
.attach('file', fileBuffer, 'export.ndjson')
|
||||
.expect(200)
|
||||
.expect(400)
|
||||
.then(resp => {
|
||||
expect(resp.body).to.eql({
|
||||
success: false,
|
||||
successCount: 0,
|
||||
errors: [
|
||||
{
|
||||
id: '1',
|
||||
type: 'wigwags',
|
||||
title: 'my title',
|
||||
error: {
|
||||
type: 'unsupported_type',
|
||||
},
|
||||
},
|
||||
],
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: 'Unable to bulk_create wigwags',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -88,27 +88,18 @@ export default function ({ getService }) {
|
|||
});
|
||||
});
|
||||
|
||||
it('should return 200 when retrying unsupported types', async () => {
|
||||
it('should return 400 when retrying unsupported types', async () => {
|
||||
const fileBuffer = Buffer.from('{"id":"1","type":"wigwags","attributes":{"title":"my title"},"references":[]}', 'utf8');
|
||||
await supertest
|
||||
.post('/api/saved_objects/_resolve_import_errors')
|
||||
.field('retries', JSON.stringify([{ type: 'wigwags', id: '1' }]))
|
||||
.attach('file', fileBuffer, 'export.ndjson')
|
||||
.expect(200)
|
||||
.expect(400)
|
||||
.then(resp => {
|
||||
expect(resp.body).to.eql({
|
||||
success: false,
|
||||
successCount: 0,
|
||||
errors: [
|
||||
{
|
||||
id: '1',
|
||||
type: 'wigwags',
|
||||
title: 'my title',
|
||||
error: {
|
||||
type: 'unsupported_type',
|
||||
},
|
||||
},
|
||||
],
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: 'Unable to bulk_create wigwags',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -48,6 +48,10 @@ export class SecureSavedObjectsClientWrapper {
|
|||
return await this._baseClient.bulkCreate(objects, options);
|
||||
}
|
||||
|
||||
async canBulkCreate(types) {
|
||||
return await this._checkAuthorizedTypes(types, 'bulk_create');
|
||||
}
|
||||
|
||||
async delete(type, id, options) {
|
||||
await this._ensureAuthorized(
|
||||
type,
|
||||
|
@ -68,6 +72,10 @@ export class SecureSavedObjectsClientWrapper {
|
|||
return this._baseClient.find(options);
|
||||
}
|
||||
|
||||
async canFind(types) {
|
||||
return await this._checkAuthorizedTypes(types, 'find');
|
||||
}
|
||||
|
||||
async bulkGet(objects = [], options = {}) {
|
||||
const types = uniq(objects.map(o => o.type));
|
||||
await this._ensureAuthorized(
|
||||
|
@ -79,6 +87,10 @@ export class SecureSavedObjectsClientWrapper {
|
|||
return await this._baseClient.bulkGet(objects, options);
|
||||
}
|
||||
|
||||
async canBulkGet(types) {
|
||||
return await this._checkAuthorizedTypes(types, 'bulk_get');
|
||||
}
|
||||
|
||||
async get(type, id, options = {}) {
|
||||
await this._ensureAuthorized(
|
||||
type,
|
||||
|
@ -108,6 +120,19 @@ export class SecureSavedObjectsClientWrapper {
|
|||
}
|
||||
}
|
||||
|
||||
async _checkAuthorizedTypes(typeOrTypes, action) {
|
||||
const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes];
|
||||
const actionsToTypesMap = new Map(types.map(type => [this._actions.savedObject.get(type, action), type]));
|
||||
const actions = Array.from(actionsToTypesMap.keys());
|
||||
const { privileges } = await this._checkSavedObjectPrivileges(actions);
|
||||
const missingPrivileges = this._getMissingPrivileges(privileges);
|
||||
const invalidTypes = missingPrivileges.map(privilege => actionsToTypesMap.get(privilege));
|
||||
return types.map(type => ({
|
||||
type,
|
||||
can: !invalidTypes.includes(type),
|
||||
}));
|
||||
}
|
||||
|
||||
async _ensureAuthorized(typeOrTypes, action, args) {
|
||||
const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes];
|
||||
const actionsToTypesMap = new Map(types.map(type => [this._actions.savedObject.get(type, action), type]));
|
||||
|
|
|
@ -33,9 +33,12 @@ const createMockClient = () => {
|
|||
return {
|
||||
get: jest.fn(),
|
||||
bulkGet: jest.fn(),
|
||||
canBulkGet: jest.fn(),
|
||||
find: jest.fn(),
|
||||
canFind: jest.fn(),
|
||||
create: jest.fn(),
|
||||
bulkCreate: jest.fn(),
|
||||
canBulkCreate: jest.fn(),
|
||||
update: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
errors,
|
||||
|
|
|
@ -117,6 +117,12 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient {
|
|||
});
|
||||
}
|
||||
|
||||
public async canBulkCreate(types: string[]) {
|
||||
throwErrorIfTypesContainsSpace(types);
|
||||
|
||||
return await this.client.canBulkCreate(types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an object
|
||||
*
|
||||
|
@ -168,6 +174,12 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient {
|
|||
});
|
||||
}
|
||||
|
||||
public async canFind(types: string[]) {
|
||||
throwErrorIfTypesContainsSpace(types);
|
||||
|
||||
return await this.client.canFind(types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of objects by id
|
||||
*
|
||||
|
@ -192,6 +204,12 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient {
|
|||
});
|
||||
}
|
||||
|
||||
public async canBulkGet(types: string[]) {
|
||||
throwErrorIfTypesContainsSpace(types);
|
||||
|
||||
return await this.client.canBulkGet(types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a single object
|
||||
*
|
||||
|
|
|
@ -27,21 +27,21 @@ interface ExportTestDefinition {
|
|||
}
|
||||
|
||||
export function exportTestSuiteFactory(esArchiver: any, supertest: SuperTest<any>) {
|
||||
const createExpectRbacForbidden = (type: string) => (resp: { [key: string]: any }) => {
|
||||
const createExpectBadRequest = (type: string) => (resp: { [key: string]: any }) => {
|
||||
// In export only, the API uses "bulk_get" or "find" depending on the parameters it receives.
|
||||
// The best that could be done here is to have an if statement to ensure at least one of the
|
||||
// two errors has been thrown.
|
||||
if (resp.body.message.indexOf(`bulk_get`) !== -1) {
|
||||
expect(resp.body).to.eql({
|
||||
statusCode: 403,
|
||||
error: 'Forbidden',
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: `Unable to bulk_get ${type}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
expect(resp.body).to.eql({
|
||||
statusCode: 403,
|
||||
error: 'Forbidden',
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: `Unable to find ${type}`,
|
||||
});
|
||||
};
|
||||
|
@ -136,7 +136,7 @@ export function exportTestSuiteFactory(esArchiver: any, supertest: SuperTest<any
|
|||
exportTest.only = makeExportTest(describe.only);
|
||||
|
||||
return {
|
||||
createExpectRbacForbidden,
|
||||
createExpectBadRequest,
|
||||
expectTypeOrObjectsRequired,
|
||||
createExpectVisualizationResults,
|
||||
exportTest,
|
||||
|
|
|
@ -53,28 +53,27 @@ export function importTestSuiteFactory(es: any, esArchiver: any, supertest: Supe
|
|||
});
|
||||
};
|
||||
|
||||
const expectUnknownType = (resp: { [key: string]: any }) => {
|
||||
const expectBadRequest = (resp: { [key: string]: any }) => {
|
||||
expect(resp.body).to.eql({
|
||||
success: false,
|
||||
successCount: 2,
|
||||
errors: [
|
||||
{
|
||||
id: '1',
|
||||
type: 'wigwags',
|
||||
title: 'Wigwags title',
|
||||
error: {
|
||||
type: 'unsupported_type',
|
||||
},
|
||||
},
|
||||
],
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: `Unable to bulk_create dashboard,globaltype`,
|
||||
});
|
||||
};
|
||||
|
||||
const expectRbacForbidden = (resp: { [key: string]: any }) => {
|
||||
const expectBadRequestWithUnknownType = (resp: { [key: string]: any }) => {
|
||||
expect(resp.body).to.eql({
|
||||
statusCode: 403,
|
||||
error: 'Forbidden',
|
||||
message: `Unable to bulk_create dashboard,globaltype`,
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: `Unable to bulk_create dashboard,globaltype,wigwags`,
|
||||
});
|
||||
};
|
||||
|
||||
const expectBadRequestForUnknownType = (resp: { [key: string]: any }) => {
|
||||
expect(resp.body).to.eql({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: `Unable to bulk_create wigwags`,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -135,7 +134,8 @@ export function importTestSuiteFactory(es: any, esArchiver: any, supertest: Supe
|
|||
return {
|
||||
importTest,
|
||||
createExpectResults,
|
||||
expectRbacForbidden,
|
||||
expectUnknownType,
|
||||
expectBadRequest,
|
||||
expectBadRequestWithUnknownType,
|
||||
expectBadRequestForUnknownType,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -57,28 +57,27 @@ export function resolveImportErrorsTestSuiteFactory(
|
|||
});
|
||||
};
|
||||
|
||||
const expectUnknownType = (resp: { [key: string]: any }) => {
|
||||
const expectBadRequest = (resp: { [key: string]: any }) => {
|
||||
expect(resp.body).to.eql({
|
||||
success: false,
|
||||
successCount: 1,
|
||||
errors: [
|
||||
{
|
||||
id: '1',
|
||||
type: 'wigwags',
|
||||
title: 'Wigwags title',
|
||||
error: {
|
||||
type: 'unsupported_type',
|
||||
},
|
||||
},
|
||||
],
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: `Unable to bulk_create dashboard`,
|
||||
});
|
||||
};
|
||||
|
||||
const expectRbacForbidden = (resp: { [key: string]: any }) => {
|
||||
const expectBadRequestWithUnknownType = (resp: { [key: string]: any }) => {
|
||||
expect(resp.body).to.eql({
|
||||
statusCode: 403,
|
||||
error: 'Forbidden',
|
||||
message: `Unable to bulk_create dashboard`,
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: `Unable to bulk_create dashboard,wigwags`,
|
||||
});
|
||||
};
|
||||
|
||||
const expectBadRequestForUnknownType = (resp: { [key: string]: any }) => {
|
||||
expect(resp.body).to.eql({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: `Unable to bulk_create wigwags`,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -163,7 +162,8 @@ export function resolveImportErrorsTestSuiteFactory(
|
|||
return {
|
||||
resolveImportErrorsTest,
|
||||
createExpectResults,
|
||||
expectRbacForbidden,
|
||||
expectUnknownType,
|
||||
expectBadRequest,
|
||||
expectBadRequestWithUnknownType,
|
||||
expectBadRequestForUnknownType,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ export default function({ getService }: TestInvoker) {
|
|||
|
||||
describe('export', () => {
|
||||
const {
|
||||
createExpectRbacForbidden,
|
||||
createExpectBadRequest,
|
||||
expectTypeOrObjectsRequired,
|
||||
createExpectVisualizationResults,
|
||||
exportTest,
|
||||
|
@ -59,9 +59,9 @@ export default function({ getService }: TestInvoker) {
|
|||
spaceId: scenario.spaceId,
|
||||
tests: {
|
||||
spaceAwareType: {
|
||||
description: 'forbidden login and find visualization message',
|
||||
statusCode: 403,
|
||||
response: createExpectRbacForbidden('visualization'),
|
||||
description: 'bad request login and find visualization message',
|
||||
statusCode: 400,
|
||||
response: createExpectBadRequest('visualization'),
|
||||
},
|
||||
noTypeOrObjects: {
|
||||
description: 'bad request, type or object is required',
|
||||
|
@ -93,9 +93,9 @@ export default function({ getService }: TestInvoker) {
|
|||
spaceId: scenario.spaceId,
|
||||
tests: {
|
||||
spaceAwareType: {
|
||||
description: 'forbidden login and find visualization message',
|
||||
statusCode: 403,
|
||||
response: createExpectRbacForbidden('visualization'),
|
||||
description: 'bad request login and find visualization message',
|
||||
statusCode: 400,
|
||||
response: createExpectBadRequest('visualization'),
|
||||
},
|
||||
noTypeOrObjects: {
|
||||
description: 'bad request, type or object is required',
|
||||
|
@ -212,9 +212,9 @@ export default function({ getService }: TestInvoker) {
|
|||
spaceId: scenario.spaceId,
|
||||
tests: {
|
||||
spaceAwareType: {
|
||||
description: 'forbidden login and find visualization message',
|
||||
statusCode: 403,
|
||||
response: createExpectRbacForbidden('visualization'),
|
||||
description: 'bad request login and find visualization message',
|
||||
statusCode: 400,
|
||||
response: createExpectBadRequest('visualization'),
|
||||
},
|
||||
noTypeOrObjects: {
|
||||
description: 'bad request, type or object is required',
|
||||
|
|
|
@ -18,8 +18,9 @@ export default function({ getService }: TestInvoker) {
|
|||
const {
|
||||
importTest,
|
||||
createExpectResults,
|
||||
expectRbacForbidden,
|
||||
expectUnknownType,
|
||||
expectBadRequest,
|
||||
expectBadRequestWithUnknownType,
|
||||
expectBadRequestForUnknownType,
|
||||
} = importTestSuiteFactory(es, esArchiver, supertest);
|
||||
|
||||
describe('_import', () => {
|
||||
|
@ -60,12 +61,12 @@ export default function({ getService }: TestInvoker) {
|
|||
spaceId: scenario.spaceId,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -79,8 +80,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(scenario.spaceId),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -90,12 +91,12 @@ export default function({ getService }: TestInvoker) {
|
|||
spaceId: scenario.spaceId,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -109,8 +110,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(scenario.spaceId),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -120,12 +121,12 @@ export default function({ getService }: TestInvoker) {
|
|||
spaceId: scenario.spaceId,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -139,8 +140,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(scenario.spaceId),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -150,12 +151,12 @@ export default function({ getService }: TestInvoker) {
|
|||
spaceId: scenario.spaceId,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -169,8 +170,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(scenario.spaceId),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -180,12 +181,12 @@ export default function({ getService }: TestInvoker) {
|
|||
spaceId: scenario.spaceId,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -195,12 +196,12 @@ export default function({ getService }: TestInvoker) {
|
|||
spaceId: scenario.spaceId,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -18,8 +18,9 @@ export default function({ getService }: TestInvoker) {
|
|||
const {
|
||||
resolveImportErrorsTest,
|
||||
createExpectResults,
|
||||
expectRbacForbidden,
|
||||
expectUnknownType,
|
||||
expectBadRequest,
|
||||
expectBadRequestWithUnknownType,
|
||||
expectBadRequestForUnknownType,
|
||||
} = resolveImportErrorsTestSuiteFactory(es, esArchiver, supertest);
|
||||
|
||||
describe('_resolve_import_errors', () => {
|
||||
|
@ -60,12 +61,12 @@ export default function({ getService }: TestInvoker) {
|
|||
spaceId: scenario.spaceId,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -79,8 +80,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(scenario.spaceId),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -90,12 +91,12 @@ export default function({ getService }: TestInvoker) {
|
|||
spaceId: scenario.spaceId,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -109,8 +110,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(scenario.spaceId),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -122,12 +123,12 @@ export default function({ getService }: TestInvoker) {
|
|||
spaceId: scenario.spaceId,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -142,8 +143,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(scenario.spaceId),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -153,12 +154,12 @@ export default function({ getService }: TestInvoker) {
|
|||
spaceId: scenario.spaceId,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -174,8 +175,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(scenario.spaceId),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -188,12 +189,12 @@ export default function({ getService }: TestInvoker) {
|
|||
spaceId: scenario.spaceId,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -206,12 +207,12 @@ export default function({ getService }: TestInvoker) {
|
|||
spaceId: scenario.spaceId,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ export default function({ getService }: TestInvoker) {
|
|||
|
||||
describe('export', () => {
|
||||
const {
|
||||
createExpectRbacForbidden,
|
||||
createExpectBadRequest,
|
||||
expectTypeOrObjectsRequired,
|
||||
createExpectVisualizationResults,
|
||||
exportTest,
|
||||
|
@ -25,9 +25,9 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.NOT_A_KIBANA_USER,
|
||||
tests: {
|
||||
spaceAwareType: {
|
||||
description: 'forbidden login and find visualization message',
|
||||
statusCode: 403,
|
||||
response: createExpectRbacForbidden('visualization'),
|
||||
description: 'bad request login and find visualization message',
|
||||
statusCode: 400,
|
||||
response: createExpectBadRequest('visualization'),
|
||||
},
|
||||
noTypeOrObjects: {
|
||||
description: 'bad request, type or object is required',
|
||||
|
@ -57,9 +57,9 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.KIBANA_LEGACY_USER,
|
||||
tests: {
|
||||
spaceAwareType: {
|
||||
description: 'forbidden login and find visualization message',
|
||||
statusCode: 403,
|
||||
response: createExpectRbacForbidden('visualization'),
|
||||
description: 'bad request login and find visualization message',
|
||||
statusCode: 400,
|
||||
response: createExpectBadRequest('visualization'),
|
||||
},
|
||||
noTypeOrObjects: {
|
||||
description: 'bad request, type or object is required',
|
||||
|
@ -138,8 +138,8 @@ export default function({ getService }: TestInvoker) {
|
|||
tests: {
|
||||
spaceAwareType: {
|
||||
description: 'only the visualization',
|
||||
statusCode: 403,
|
||||
response: createExpectRbacForbidden('visualization'),
|
||||
statusCode: 400,
|
||||
response: createExpectBadRequest('visualization'),
|
||||
},
|
||||
noTypeOrObjects: {
|
||||
description: 'bad request, type or object is required',
|
||||
|
@ -154,8 +154,8 @@ export default function({ getService }: TestInvoker) {
|
|||
tests: {
|
||||
spaceAwareType: {
|
||||
description: 'only the visualization',
|
||||
statusCode: 403,
|
||||
response: createExpectRbacForbidden('visualization'),
|
||||
statusCode: 400,
|
||||
response: createExpectBadRequest('visualization'),
|
||||
},
|
||||
noTypeOrObjects: {
|
||||
description: 'bad request, type or object is required',
|
||||
|
@ -170,8 +170,8 @@ export default function({ getService }: TestInvoker) {
|
|||
tests: {
|
||||
spaceAwareType: {
|
||||
description: 'only the visualization',
|
||||
statusCode: 403,
|
||||
response: createExpectRbacForbidden('visualization'),
|
||||
statusCode: 400,
|
||||
response: createExpectBadRequest('visualization'),
|
||||
},
|
||||
noTypeOrObjects: {
|
||||
description: 'bad request, type or object is required',
|
||||
|
@ -186,8 +186,8 @@ export default function({ getService }: TestInvoker) {
|
|||
tests: {
|
||||
spaceAwareType: {
|
||||
description: 'only the visualization',
|
||||
statusCode: 403,
|
||||
response: createExpectRbacForbidden('visualization'),
|
||||
statusCode: 400,
|
||||
response: createExpectBadRequest('visualization'),
|
||||
},
|
||||
noTypeOrObjects: {
|
||||
description: 'bad request, type or object is required',
|
||||
|
|
|
@ -17,8 +17,9 @@ export default function({ getService }: TestInvoker) {
|
|||
const {
|
||||
importTest,
|
||||
createExpectResults,
|
||||
expectRbacForbidden,
|
||||
expectUnknownType,
|
||||
expectBadRequest,
|
||||
expectBadRequestWithUnknownType,
|
||||
expectBadRequestForUnknownType,
|
||||
} = importTestSuiteFactory(es, esArchiver, supertest);
|
||||
|
||||
describe('_import', () => {
|
||||
|
@ -26,12 +27,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.NOT_A_KIBANA_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -44,8 +45,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -54,12 +55,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.KIBANA_LEGACY_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -72,8 +73,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -82,12 +83,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -100,8 +101,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -110,12 +111,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -124,12 +125,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -138,12 +139,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -152,12 +153,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -166,12 +167,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -17,8 +17,9 @@ export default function({ getService }: TestInvoker) {
|
|||
const {
|
||||
resolveImportErrorsTest,
|
||||
createExpectResults,
|
||||
expectRbacForbidden,
|
||||
expectUnknownType,
|
||||
expectBadRequest,
|
||||
expectBadRequestWithUnknownType,
|
||||
expectBadRequestForUnknownType,
|
||||
} = resolveImportErrorsTestSuiteFactory(es, esArchiver, supertest);
|
||||
|
||||
describe('_resolve_import_errors', () => {
|
||||
|
@ -26,12 +27,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.NOT_A_KIBANA_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -44,8 +45,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -54,12 +55,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.KIBANA_LEGACY_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -72,8 +73,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -82,12 +83,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -100,8 +101,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -110,12 +111,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -124,12 +125,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -138,12 +139,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -152,12 +153,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -166,12 +167,12 @@ export default function({ getService }: TestInvoker) {
|
|||
user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER,
|
||||
tests: {
|
||||
default: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequest,
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 403,
|
||||
response: expectRbacForbidden,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestWithUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -14,11 +14,11 @@ export default function({ getService }: TestInvoker) {
|
|||
const esArchiver = getService('esArchiver');
|
||||
const es = getService('es');
|
||||
|
||||
const { importTest, createExpectResults, expectUnknownType } = importTestSuiteFactory(
|
||||
es,
|
||||
esArchiver,
|
||||
supertest
|
||||
);
|
||||
const {
|
||||
importTest,
|
||||
createExpectResults,
|
||||
expectBadRequestForUnknownType,
|
||||
} = importTestSuiteFactory(es, esArchiver, supertest);
|
||||
|
||||
describe('_import', () => {
|
||||
importTest('in the current space (space_1)', {
|
||||
|
@ -29,8 +29,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(SPACES.SPACE_1.spaceId),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -43,8 +43,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(SPACES.DEFAULT.spaceId),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ export default function({ getService }: TestInvoker) {
|
|||
const {
|
||||
resolveImportErrorsTest,
|
||||
createExpectResults,
|
||||
expectUnknownType,
|
||||
expectBadRequestForUnknownType,
|
||||
} = resolveImportErrorsTestSuiteFactory(es, esArchiver, supertest);
|
||||
|
||||
describe('_resolve_import_errors', () => {
|
||||
|
@ -29,8 +29,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(SPACES.SPACE_1.spaceId),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -43,8 +43,8 @@ export default function({ getService }: TestInvoker) {
|
|||
response: createExpectResults(SPACES.DEFAULT.spaceId),
|
||||
},
|
||||
unknownType: {
|
||||
statusCode: 200,
|
||||
response: expectUnknownType,
|
||||
statusCode: 400,
|
||||
response: expectBadRequestForUnknownType,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue