Skip to content
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

Sharing saved-objects phase 1 #54605

Merged
Merged
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
16ec12f
POC
jportner Jan 13, 2020
f7642f4
Fix broken unit tests, add new ones
jportner Jan 29, 2020
17718c4
Use SavedObjectsErrorHelpers for `bulkGet` operation "Not found"
jportner Feb 14, 2020
9465303
Do not allow non-array references in `create` operations
jportner Feb 13, 2020
daf685e
Refactor CheckPrivileges unit tests
jportner Feb 12, 2020
d49e1bd
Support multi-namespace operations
jportner Feb 12, 2020
9736f8b
Simplify CheckSavedObjectsPrivileges
jportner Feb 20, 2020
5fe2720
Rewrite getQueryParams unit tests
jportner Feb 26, 2020
ffd49e5
Update getQueryParams and update unit tests
jportner Feb 26, 2020
5a3fe41
Support encrypted saved objects
jportner Feb 26, 2020
f7d5b81
Improve Repository.bulkGet behavior
jportner Mar 6, 2020
4bd2d00
Fix saved_object_api_integration tests
jportner Mar 10, 2020
a1944f4
Rename methods for checking saved object types
jportner Mar 10, 2020
7b66aa3
node scripts/check_published_api_changes.js --accept
jportner Mar 10, 2020
b0bba09
Fix api_integration tests
jportner Mar 11, 2020
84d8e42
Misc cleanup
jportner Mar 13, 2020
da8417b
Change behavior of addNamespaces API for Saved Objects Client
jportner Mar 15, 2020
4a0f757
Add/update spaces_api_integration tests
jportner Mar 15, 2020
4f06602
Merge branch 'master' into pr/jportner/54605
jportner Mar 15, 2020
720acb0
Address first round of PR review feedback
jportner Mar 17, 2020
3a32b9a
Clean up SpacesSavedObjectsClient unit tests
jportner Mar 18, 2020
1508946
Remove validation callback from `addNamespaces` operation
jportner Mar 18, 2020
70a1ef7
Merge branch 'master' into pr/jportner/54605
jportner Mar 19, 2020
a5070cf
Change `SavedObjectType` to use `namespaceType`
jportner Mar 19, 2020
9f9effb
Fail gracefully when Elasticsearch query cannot execute a script
jportner Mar 20, 2020
7d70162
Merge branch 'master' into pr/jportner/54605
jportner Mar 23, 2020
e60724d
Fix type check failure
jportner Mar 23, 2020
4f12e46
Address second round of PR review feedback
jportner Mar 25, 2020
f2980c7
Fix outdated unit test snapshots
jportner Mar 25, 2020
cd8791a
Merge branch 'master' into pr/jportner/54605
jportner Mar 26, 2020
92e5ccd
Address third round of PR review feedback
jportner Mar 26, 2020
a5e1424
Simplify `addNamespaces` authZ checks
jportner Mar 26, 2020
dee4a94
Remove custom Not Found errors
jportner Mar 26, 2020
b26aa40
Merge branch 'master' into pr/jportner/54605
jportner Mar 31, 2020
fa5f361
Loosen validation for `addNamespaces` and `removeNamespaces`
jportner Mar 31, 2020
8bf57aa
Fix type check error
jportner Apr 1, 2020
4d75956
Address fourth round of PR review feedback
jportner Apr 1, 2020
83d846e
Fix typo in comment
jportner Apr 1, 2020
57df368
Merge branch 'master' into issue-54043-sharing-saved-objects-phase-1
elasticmachine Apr 2, 2020
28b3b1e
Merge branch 'master' into pr/jportner/54605
jportner Apr 6, 2020
a832503
Refactor SavedObjectsRepository discriminated unions
jportner Apr 6, 2020
94d31ec
Clean up preflight checks for bulk operations
jportner Apr 6, 2020
418f1cd
Renamed `addNamespaces` and `removeNamespaces` methods
jportner Apr 6, 2020
e2f5d65
Address remaining items from fifth round of PR review feedback
jportner Apr 6, 2020
c0dd3b0
Fix integration test file names in test suites
jportner Apr 6, 2020
65fac79
Merge branch 'master' into pr/jportner/54605
jportner Apr 7, 2020
ec7fc3e
Address sixth round of PR review feedback
jportner Apr 7, 2020
dbce4e8
WIP
jportner Apr 7, 2020
e3a5416
Address nits on integration tests
jportner Apr 7, 2020
7a8c11b
Merge branch 'master' into pr/jportner/54605
jportner Apr 8, 2020
223ecef
Fix more nits
jportner Apr 8, 2020
c26a49d
Merge branch 'master' into issue-54043-sharing-saved-objects-phase-1
elasticmachine Apr 8, 2020
d24fa35
Merge branch 'master' into pr/jportner/54605
jportner Apr 9, 2020
c4c35c1
Merge branch 'master' into issue-54043-sharing-saved-objects-phase-1
elasticmachine Apr 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 67 additions & 77 deletions src/core/server/saved_objects/service/lib/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,12 @@ import { validateConvertFilterToKueryNode } from './filter_utils';
// so any breaking changes to this repository are considered breaking changes to the SavedObjectsClient.

// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
type Left<T> = {
tag: 'Left';
error: T;
};
type Left = { tag: 'Left'; error: Record<string, any> };
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
type Right<T> = {
tag: 'Right';
value: T;
};

type Either<L, R> = Left<L> | Right<R>;
const isLeft = <L, R>(either: Either<L, R>): either is Left<L> => {
return either.tag === 'Left';
};
type Right = { tag: 'Right'; value: Record<string, any> };
type Either = Left | Right;
const isLeft = (either: Either): either is Left => either.tag === 'Left';
const isRight = (either: Either): either is Right => either.tag === 'Right';

export interface SavedObjectsRepositoryOptions {
index: string;
Expand Down Expand Up @@ -301,7 +293,7 @@ export class SavedObjectsRepository {

let bulkGetRequestIndexCounter = 0;
const bulkGetDocs: object[] = [];
const expectedResults: Array<Either<any, any>> = objects.map(object => {
const expectedResults: Either[] = objects.map(object => {
if (!this._allowedTypes.includes(object.type)) {
return {
tag: 'Left' as 'Left',
Expand Down Expand Up @@ -354,69 +346,67 @@ export class SavedObjectsRepository {

let bulkRequestIndexCounter = 0;
const bulkCreateParams: object[] = [];
const expectedBulkResults: Array<Either<any, any>> = expectedResults.map(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: the diff below this is messy, but code didn't change, just indentation.

expectedBulkGetResult => {
if (isLeft(expectedBulkGetResult)) {
return expectedBulkGetResult;
}
const expectedBulkResults: Either[] = expectedResults.map(expectedBulkGetResult => {
if (isLeft(expectedBulkGetResult)) {
return expectedBulkGetResult;
}

let savedObjectNamespace;
let savedObjectNamespaces;
const { esRequestIndex, object, method } = expectedBulkGetResult.value;
if (esRequestIndex !== undefined) {
const indexFound = bulkGetResponse.status !== 404;
const actualResult = indexFound ? bulkGetResponse.docs[esRequestIndex] : undefined;
const docFound = indexFound && actualResult.found === true;
if (docFound && !this._rawInNamespaces(actualResult, namespace)) {
const { id, type } = object;
return {
tag: 'Left' as 'Left',
error: {
id,
type,
error: SavedObjectsErrorHelpers.createConflictError(type, id).output.payload,
},
};
}
savedObjectNamespaces = getSavedObjectNamespaces(namespace, docFound && actualResult);
} else {
if (this._registry.isSingleNamespace(object.type)) {
savedObjectNamespace = namespace;
} else if (this._registry.isMultiNamespace(object.type)) {
savedObjectNamespaces = getSavedObjectNamespaces(namespace);
}
let savedObjectNamespace;
let savedObjectNamespaces;
const { esRequestIndex, object, method } = expectedBulkGetResult.value;
if (esRequestIndex !== undefined) {
const indexFound = bulkGetResponse.status !== 404;
const actualResult = indexFound ? bulkGetResponse.docs[esRequestIndex] : undefined;
const docFound = indexFound && actualResult.found === true;
if (docFound && !this._rawInNamespaces(actualResult, namespace)) {
const { id, type } = object;
return {
tag: 'Left' as 'Left',
error: {
id,
type,
error: SavedObjectsErrorHelpers.createConflictError(type, id).output.payload,
},
};
}
savedObjectNamespaces = getSavedObjectNamespaces(namespace, docFound && actualResult);
} else {
if (this._registry.isSingleNamespace(object.type)) {
savedObjectNamespace = namespace;
} else if (this._registry.isMultiNamespace(object.type)) {
savedObjectNamespaces = getSavedObjectNamespaces(namespace);
}
}

const expectedResult = {
esRequestIndex: bulkRequestIndexCounter++,
requestedId: object.id,
rawMigratedDoc: this._serializer.savedObjectToRaw(
this._migrator.migrateDocument({
id: object.id,
type: object.type,
attributes: object.attributes,
migrationVersion: object.migrationVersion,
...(savedObjectNamespace && { namespace: savedObjectNamespace }),
...(savedObjectNamespaces && { namespaces: savedObjectNamespaces }),
updated_at: time,
references: object.references || [],
}) as SavedObjectSanitizedDoc
),
};
const expectedResult = {
esRequestIndex: bulkRequestIndexCounter++,
requestedId: object.id,
rawMigratedDoc: this._serializer.savedObjectToRaw(
this._migrator.migrateDocument({
id: object.id,
type: object.type,
attributes: object.attributes,
migrationVersion: object.migrationVersion,
...(savedObjectNamespace && { namespace: savedObjectNamespace }),
...(savedObjectNamespaces && { namespaces: savedObjectNamespaces }),
updated_at: time,
references: object.references || [],
}) as SavedObjectSanitizedDoc
),
};

bulkCreateParams.push(
{
[method]: {
_id: expectedResult.rawMigratedDoc._id,
_index: this.getIndexForType(object.type),
},
bulkCreateParams.push(
{
[method]: {
_id: expectedResult.rawMigratedDoc._id,
_index: this.getIndexForType(object.type),
},
expectedResult.rawMigratedDoc._source
);
},
expectedResult.rawMigratedDoc._source
);

return { tag: 'Right' as 'Right', value: expectedResult };
}
);
return { tag: 'Right' as 'Right', value: expectedResult };
});

const bulkResponse = bulkCreateParams.length
? await this._writeToCluster('bulk', {
Expand All @@ -428,7 +418,7 @@ export class SavedObjectsRepository {
return {
saved_objects: expectedBulkResults.map(expectedResult => {
if (isLeft(expectedResult)) {
return expectedResult.error;
return expectedResult.error as any;
}

const { requestedId, rawMigratedDoc, esRequestIndex } = expectedResult.value;
Expand Down Expand Up @@ -738,7 +728,7 @@ export class SavedObjectsRepository {

let bulkGetRequestIndexCounter = 0;
const bulkGetDocs: object[] = [];
const expectedBulkGetResults: Array<Either<any, any>> = objects.map(object => {
const expectedBulkGetResults: Either[] = objects.map(object => {
const { type, id, fields } = object;

if (!this._allowedTypes.includes(type)) {
Expand Down Expand Up @@ -780,7 +770,7 @@ export class SavedObjectsRepository {
return {
saved_objects: expectedBulkGetResults.map(expectedResult => {
if (isLeft(expectedResult)) {
return expectedResult.error;
return expectedResult.error as any;
}

const { type, id, esRequestIndex } = expectedResult.value;
Expand Down Expand Up @@ -1078,7 +1068,7 @@ export class SavedObjectsRepository {

let bulkGetRequestIndexCounter = 0;
const bulkGetDocs: object[] = [];
const expectedBulkGetResults: Array<Either<any, any>> = objects.map(object => {
const expectedBulkGetResults: Either[] = objects.map(object => {
const { type, id } = object;

if (!this._allowedTypes.includes(type)) {
Expand Down Expand Up @@ -1141,7 +1131,7 @@ export class SavedObjectsRepository {

let bulkUpdateRequestIndexCounter = 0;
const bulkUpdateParams: object[] = [];
const expectedBulkUpdateResults: Array<Either<any, any>> = expectedBulkGetResults.map(
const expectedBulkUpdateResults: Either[] = expectedBulkGetResults.map(
expectedBulkGetResult => {
if (isLeft(expectedBulkGetResult)) {
return expectedBulkGetResult;
Expand Down Expand Up @@ -1204,7 +1194,7 @@ export class SavedObjectsRepository {
return {
saved_objects: expectedBulkUpdateResults.map(expectedResult => {
if (isLeft(expectedResult)) {
return expectedResult.error;
return expectedResult.error as any;
}

const { type, id, namespaces, documentToSave, esRequestIndex } = expectedResult.value;
Expand Down