Skip to content

Commit

Permalink
Add unit tests for consuming permissions in repository
Browse files Browse the repository at this point in the history
Signed-off-by: gaobinlong <gbinlong@amazon.com>
  • Loading branch information
gaobinlong committed Oct 9, 2023
1 parent fb47a13 commit ffedcb4
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 21 deletions.
3 changes: 2 additions & 1 deletion src/core/server/saved_objects/serialization/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export class SavedObjectsSerializer {
*/
public rawToSavedObject(doc: SavedObjectsRawDoc): SavedObjectSanitizedDoc {
const { _id, _source, _seq_no, _primary_term } = doc;
const { type, namespace, namespaces, originId } = _source;
const { type, namespace, namespaces, originId, permissions } = _source;

const version =
_seq_no != null || _primary_term != null
Expand All @@ -86,6 +86,7 @@ export class SavedObjectsSerializer {
...(namespace && this.registry.isSingleNamespace(type) && { namespace }),
...(namespaces && this.registry.isMultiNamespace(type) && { namespaces }),
...(originId && { originId }),
...(permissions && { permissions }),
attributes: _source[type],
references: _source.references || [],
...(_source.migrationVersion && { migrationVersion: _source.migrationVersion }),
Expand Down
179 changes: 163 additions & 16 deletions src/core/server/saved_objects/service/lib/repository.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ describe('SavedObjectsRepository', () => {
});

const getMockGetResponse = (
{ type, id, references, namespace: objectNamespace, originId },
{ type, id, references, namespace: objectNamespace, originId, permissions },
namespace
) => {
const namespaceId = objectNamespace === 'default' ? undefined : objectNamespace ?? namespace;
Expand All @@ -183,6 +183,7 @@ describe('SavedObjectsRepository', () => {
...(registry.isSingleNamespace(type) && { namespace: namespaceId }),
...(registry.isMultiNamespace(type) && { namespaces: [namespaceId ?? 'default'] }),
...(originId && { originId }),
...(permissions && { permissions }),
type,
[type]: { title: 'Testing' },
references,
Expand Down Expand Up @@ -444,24 +445,35 @@ describe('SavedObjectsRepository', () => {
references: [{ name: 'ref_0', type: 'test', id: '2' }],
};
const namespace = 'foo-namespace';
const permissions = {
read: {
users: ['user1'],
},
write: {
groups: ['groups1'],
},
};

const getMockBulkCreateResponse = (objects, namespace) => {
return {
items: objects.map(({ type, id, originId, attributes, references, migrationVersion }) => ({
create: {
_id: `${namespace ? `${namespace}:` : ''}${type}:${id}`,
_source: {
[type]: attributes,
type,
namespace,
...(originId && { originId }),
references,
...mockTimestampFields,
migrationVersion: migrationVersion || { [type]: '1.1.1' },
items: objects.map(
({ type, id, originId, attributes, references, migrationVersion, permissions }) => ({
create: {
_id: `${namespace ? `${namespace}:` : ''}${type}:${id}`,
_source: {
[type]: attributes,
type,
namespace,
...(originId && { originId }),
...(permissions && { permissions }),
references,
...mockTimestampFields,
migrationVersion: migrationVersion || { [type]: '1.1.1' },
},
...mockVersionProps,
},
...mockVersionProps,
},
})),
})
),
};
};

Expand Down Expand Up @@ -730,6 +742,18 @@ describe('SavedObjectsRepository', () => {
await bulkCreateSuccess(objects, { namespace });
expectClientCallArgsAction(objects, { method: 'create', getId });
});

it(`accepts permissions property when providing permissions info`, async () => {
const objects = [obj1, obj2].map((obj) => ({ ...obj, permissions: permissions }));
await bulkCreateSuccess(objects);
const expected = expect.objectContaining({ permissions });
const body = [expect.any(Object), expected, expect.any(Object), expected];
expect(client.bulk).toHaveBeenCalledWith(
expect.objectContaining({ body }),
expect.anything()
);
client.bulk.mockClear();
});
});

describe('errors', () => {
Expand Down Expand Up @@ -1000,6 +1024,17 @@ describe('SavedObjectsRepository', () => {
);
expect(result.saved_objects[1].id).toEqual(obj2.id);
});

it(`includes permissions property if present`, async () => {
const objects = [obj1, obj2].map((obj) => ({ ...obj, permissions: permissions }));
const result = await bulkCreateSuccess(objects);
expect(result).toEqual({
saved_objects: [
expect.objectContaining({ permissions }),
expect.objectContaining({ permissions }),
],
});
});
});
});

Expand Down Expand Up @@ -1219,6 +1254,22 @@ describe('SavedObjectsRepository', () => {
],
});
});

it(`includes permissions property if present`, async () => {
const permissions = {
read: {
users: ['user1'],
},
write: {
groups: ['groups1'],
},
};
const obj = { id: 'three', type: MULTI_NAMESPACE_TYPE, permissions: permissions };
const result = await bulkGetSuccess([obj]);
expect(result).toEqual({
saved_objects: [expect.objectContaining({ permissions: permissions })],
});
});
});
});

Expand All @@ -1236,6 +1287,14 @@ describe('SavedObjectsRepository', () => {
const references = [{ name: 'ref_0', type: 'test', id: '1' }];
const originId = 'some-origin-id';
const namespace = 'foo-namespace';
const permissions = {
read: {
users: ['user1'],
},
write: {
groups: ['groups1'],
},
};

const getMockBulkUpdateResponse = (objects, options, includeOriginId) => ({
items: objects.map(({ type, id }) => ({
Expand Down Expand Up @@ -1496,6 +1555,20 @@ describe('SavedObjectsRepository', () => {
await bulkUpdateSuccess([{ ..._obj2, namespace }]);
expectClientCallArgsAction([_obj2], { method: 'update', getId, overrides }, 2);
});

it(`accepts permissions property when providing permissions info`, async () => {
const objects = [obj1, obj2].map((obj) => ({ ...obj, permissions: permissions }));
await bulkUpdateSuccess(objects);
const doc = {
doc: expect.objectContaining({ permissions }),
};
const body = [expect.any(Object), doc, expect.any(Object), doc];
expect(client.bulk).toHaveBeenCalledWith(
expect.objectContaining({ body }),
expect.anything()
);
client.bulk.mockClear();
});
});

describe('errors', () => {
Expand Down Expand Up @@ -1688,6 +1761,14 @@ describe('SavedObjectsRepository', () => {
],
});
});

it(`includes permissions property if present`, async () => {
const obj = { type: MULTI_NAMESPACE_TYPE, id: 'three', permissions: permissions };
const result = await bulkUpdateSuccess([obj1, obj], {}, true);
expect(result).toEqual({
saved_objects: [expect.anything(), expect.objectContaining({ permissions })],
});
});
});
});

Expand Down Expand Up @@ -1843,6 +1924,14 @@ describe('SavedObjectsRepository', () => {
id: '123',
},
];
const permissions = {
read: {
users: ['user1'],
},
write: {
groups: ['groups1'],
},
};

const createSuccess = async (type, attributes, options) => {
const result = await savedObjectsRepository.create(type, attributes, options);
Expand Down Expand Up @@ -2040,6 +2129,16 @@ describe('SavedObjectsRepository', () => {
expect.anything()
);
});

it(`accepts permissions property`, async () => {
await createSuccess(type, attributes, { id, permissions });
expect(client.create).toHaveBeenCalledWith(
expect.objectContaining({
body: expect.objectContaining({ permissions }),
}),
expect.anything()
);
});
});

describe('errors', () => {
Expand Down Expand Up @@ -2120,6 +2219,11 @@ describe('SavedObjectsRepository', () => {
expect(serializer.savedObjectToRaw).toHaveBeenLastCalledWith(migratedDoc);
});

it(`adds permissions to body when providing permissions info`, async () => {
await createSuccess(type, attributes, { id, permissions });
expectMigrationArgs({ permissions });
});

it(`adds namespace to body when providing namespace for single-namespace type`, async () => {
await createSuccess(type, attributes, { id, namespace });
expectMigrationArgs({ namespace });
Expand Down Expand Up @@ -2166,11 +2270,13 @@ describe('SavedObjectsRepository', () => {
namespace,
references,
originId,
permissions,
});
expect(result).toEqual({
type,
id,
originId,
permissions,
...mockTimestampFields,
version: mockVersion,
attributes,
Expand Down Expand Up @@ -2960,14 +3066,15 @@ describe('SavedObjectsRepository', () => {
const namespace = 'foo-namespace';
const originId = 'some-origin-id';

const getSuccess = async (type, id, options, includeOriginId) => {
const getSuccess = async (type, id, options, includeOriginId, permissions) => {
const response = getMockGetResponse(
{
type,
id,
// "includeOriginId" is not an option for the operation; however, if the existing saved object contains an originId attribute, the
// operation will return it in the result. This flag is just used for test purposes to modify the mock cluster call response.
...(includeOriginId && { originId }),
...(permissions && { permissions }),
},
options?.namespace
);
Expand Down Expand Up @@ -3118,6 +3225,21 @@ describe('SavedObjectsRepository', () => {
const result = await getSuccess(type, id, {}, true);
expect(result).toMatchObject({ originId });
});

it(`includes permissions property if present`, async () => {
const permissions = {
read: {
users: ['user1'],
},
write: {
groups: ['groups1'],
},
};
const result = await getSuccess(type, id, { namespace }, undefined, permissions);
expect(result).toMatchObject({
permissions: permissions,
});
});
});
});

Expand Down Expand Up @@ -3719,6 +3841,14 @@ describe('SavedObjectsRepository', () => {
},
];
const originId = 'some-origin-id';
const permissions = {
read: {
users: ['user1'],
},
write: {
groups: ['groups1'],
},
};

const updateSuccess = async (type, id, attributes, options, includeOriginId) => {
if (registry.isMultiNamespace(type)) {
Expand Down Expand Up @@ -3895,6 +4025,18 @@ describe('SavedObjectsRepository', () => {
expect.anything()
);
});

it(`accepts permissions when providing permissions info`, async () => {
await updateSuccess(type, id, attributes, { permissions });
const expected = expect.objectContaining({ permissions });
const body = {
doc: expected,
};
expect(client.update).toHaveBeenCalledWith(
expect.objectContaining({ body }),
expect.anything()
);
});
});

describe('errors', () => {
Expand Down Expand Up @@ -3989,6 +4131,11 @@ describe('SavedObjectsRepository', () => {
const result = await updateSuccess(type, id, attributes, {}, true);
expect(result).toMatchObject({ originId });
});

it(`includes permissions property if present`, async () => {
const result = await updateSuccess(type, id, attributes, { permissions });
expect(result).toMatchObject({ permissions });
});
});
});
});
10 changes: 7 additions & 3 deletions src/core/server/saved_objects/service/lib/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ export class SavedObjectsRepository {
updated_at: time,
references: object.references || [],
originId: object.originId,
...(object.permissions && { permissions: object.permissions }),
}) as SavedObjectSanitizedDoc
),
};
Expand Down Expand Up @@ -1074,6 +1075,7 @@ export class SavedObjectsRepository {
version: encodeHitVersion(body),
namespaces,
...(originId && { originId }),
...(permissions && { permissions }),
references,
attributes,
};
Expand Down Expand Up @@ -1274,7 +1276,7 @@ export class SavedObjectsRepository {
};
}

const { attributes, references, version, namespace: objectNamespace } = object;
const { attributes, references, version, namespace: objectNamespace, permissions } = object;

if (objectNamespace === ALL_NAMESPACES_STRING) {
return {
Expand All @@ -1295,6 +1297,7 @@ export class SavedObjectsRepository {
[type]: attributes,
updated_at: time,
...(Array.isArray(references) && { references }),
...(permissions && { permissions }),
};

const requiresNamespacesCheck = this._registry.isMultiNamespace(object.type);
Expand Down Expand Up @@ -1447,7 +1450,7 @@ export class SavedObjectsRepository {
)[0] as any;

// eslint-disable-next-line @typescript-eslint/naming-convention
const { [type]: attributes, references, updated_at } = documentToSave;
const { [type]: attributes, references, updated_at, permissions } = documentToSave;
if (error) {
return {
id,
Expand All @@ -1466,6 +1469,7 @@ export class SavedObjectsRepository {
version: encodeVersion(seqNo, primaryTerm),
attributes,
references,
...(permissions && { permissions }),
};
}),
};
Expand Down Expand Up @@ -1777,7 +1781,7 @@ function getSavedObjectFromSource<T>(
attributes: doc._source[type],
references: doc._source.references || [],
migrationVersion: doc._source.migrationVersion,
permissions,
...(permissions && { permissions }),
};
}

Expand Down
Loading

0 comments on commit ffedcb4

Please sign in to comment.