Skip to content

Commit 3a28421

Browse files
committed
Fix tests + swap_references API
1 parent 6f51d1e commit 3a28421

File tree

3 files changed

+110
-5
lines changed

3 files changed

+110
-5
lines changed

src/core/packages/saved-objects/api-server-internal/src/lib/repository.security_extension.test.ts

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import {
6262
generateIndexPatternSearchResults,
6363
setupAuthorizeFunc,
6464
setupAuthorizeFind,
65+
HIDDEN_TYPE,
6566
} from '../test_helpers/repository.test.common';
6667
import { savedObjectsExtensionsMock } from '../mocks/saved_objects_extensions.mock';
6768
import { arrayMapsAreEqual } from '@kbn/core-saved-objects-utils-server';
@@ -845,14 +846,108 @@ describe('SavedObjectsRepository Security Extension', () => {
845846
});
846847
});
847848

849+
test(`returns empty authorization map for partially authorized if the authorized types are not part of the query`, async () => {
850+
setupAuthorizeFind(mockSecurityExt, 'partially_authorized');
851+
setupRedactPassthrough(mockSecurityExt);
852+
853+
await findSuccess(
854+
client,
855+
repository,
856+
{
857+
type: [type, NAMESPACE_AGNOSTIC_TYPE],
858+
namespaces: [namespace, 'ns-1'],
859+
}, // include multiple types and spaces
860+
namespace
861+
);
862+
863+
expect(mockGetSearchDsl.mock.calls[0].length).toBe(3); // Find success verifies this is called once, this should always pass
864+
const {
865+
typeToNamespacesMap: actualMap,
866+
}: { typeToNamespacesMap: Map<string, string[] | undefined> } =
867+
mockGetSearchDsl.mock.calls[0][2];
868+
869+
expect(actualMap).not.toBeUndefined();
870+
const expectedMap = new Map<string, string[] | undefined>();
871+
872+
expect(arrayMapsAreEqual(actualMap, expectedMap)).toBeTruthy();
873+
});
874+
875+
test(`returns empty authorization map for fully authorized if the authorized types are not part of the query`, async () => {
876+
setupAuthorizeFind(mockSecurityExt, 'fully_authorized');
877+
setupRedactPassthrough(mockSecurityExt);
878+
879+
await findSuccess(
880+
client,
881+
repository,
882+
{
883+
type: [type, NAMESPACE_AGNOSTIC_TYPE],
884+
namespaces: [namespace, 'ns-1'],
885+
}, // include multiple types and spaces
886+
namespace
887+
);
888+
889+
expect(mockGetSearchDsl.mock.calls[0].length).toBe(3); // Find success verifies this is called once, this should always pass
890+
const {
891+
typeToNamespacesMap: actualMap,
892+
}: { typeToNamespacesMap: Map<string, string[] | undefined> } =
893+
mockGetSearchDsl.mock.calls[0][2];
894+
895+
expect(actualMap).not.toBeUndefined();
896+
const expectedMap = new Map<string, string[] | undefined>();
897+
898+
expect(arrayMapsAreEqual(actualMap, expectedMap)).toBeTruthy();
899+
});
900+
848901
test(`uses the authorization map when partially authorized`, async () => {
849902
setupAuthorizeFind(mockSecurityExt, 'partially_authorized');
850903
setupRedactPassthrough(mockSecurityExt);
851904

852905
await findSuccess(
853906
client,
854907
repository,
855-
{ type: [type, NAMESPACE_AGNOSTIC_TYPE], namespaces: [namespace, 'ns-1'] }, // include multiple types and spaces
908+
{
909+
type: [
910+
type,
911+
'foo',
912+
// Explicitly request the hidden type despite the repository not having access to it to confirm that it's not authorized.
913+
HIDDEN_TYPE,
914+
NAMESPACE_AGNOSTIC_TYPE,
915+
],
916+
namespaces: [namespace, 'ns-1'],
917+
}, // include multiple types and spaces
918+
namespace
919+
);
920+
921+
expect(mockGetSearchDsl.mock.calls[0].length).toBe(3); // Find success verifies this is called once, this should always pass
922+
const {
923+
typeToNamespacesMap: actualMap,
924+
}: { typeToNamespacesMap: Map<string, string[] | undefined> } =
925+
mockGetSearchDsl.mock.calls[0][2];
926+
927+
expect(actualMap).not.toBeUndefined();
928+
const expectedMap = new Map<string, string[] | undefined>();
929+
expectedMap.set('foo', ['bar']); // this is what is hard-coded in authMap
930+
931+
expect(arrayMapsAreEqual(actualMap, expectedMap)).toBeTruthy();
932+
});
933+
934+
test(`uses the authorization map when fully authorized`, async () => {
935+
setupAuthorizeFind(mockSecurityExt, 'fully_authorized');
936+
setupRedactPassthrough(mockSecurityExt);
937+
938+
await findSuccess(
939+
client,
940+
repository,
941+
{
942+
type: [
943+
type,
944+
'foo',
945+
// Explicitly request the hidden type despite the repository not having access to it to confirm that it's not authorized.
946+
HIDDEN_TYPE,
947+
NAMESPACE_AGNOSTIC_TYPE,
948+
],
949+
namespaces: [namespace, 'ns-1'],
950+
}, // include multiple types and spaces
856951
namespace
857952
);
858953

src/core/packages/saved-objects/api-server-internal/src/test_helpers/repository.test.common.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,13 @@ export const mappings: SavedObjectsTypeMappingDefinition = {
233233
export const authRecord: Record<string, AuthorizationTypeEntry> = {
234234
find: { authorizedSpaces: ['bar'] },
235235
};
236-
export const authMap = Object.freeze(new Map([['foo', authRecord]]));
236+
export const authMap = Object.freeze(
237+
new Map([
238+
['foo', authRecord],
239+
// The user is authorized to read hidden types but tests will confirm that repositories without that hidden type listed, won't show this as authorized.
240+
[HIDDEN_TYPE, authRecord],
241+
])
242+
);
237243

238244
export const checkAuthError = SavedObjectsErrorHelpers.createBadRequestError(
239245
'Failed to check authorization'
@@ -344,6 +350,7 @@ export const createType = (
344350

345351
export const createRegistry = () => {
346352
const registry = new SavedObjectTypeRegistry();
353+
registry.registerType(createType('foo'));
347354
registry.registerType(createType('config'));
348355
registry.registerType(createType('index-pattern'));
349356
registry.registerType(

src/platform/plugins/shared/data_views/server/rest_api_routes/public/swap_references.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,12 @@ export const swapReferencesRoute =
113113
},
114114
router.handleLegacyErrors(
115115
handleErrors(async (ctx, req, res) => {
116-
const savedObjectsClient = (await ctx.core).savedObjects.client;
117-
const [core] = await getStartServices();
118-
const types = core.savedObjects.getTypeRegistry().getAllTypes();
116+
const savedObjectsContract = (await ctx.core).savedObjects;
117+
const types = savedObjectsContract.typeRegistry.getAllTypes();
118+
const savedObjectsClient = savedObjectsContract.getClient({
119+
// Make sure to search through all the hidden types as well.
120+
includedHiddenTypes: types.filter((t) => t.hidden).map((t) => t.name),
121+
});
119122
const type = req.body.fromType || DATA_VIEW_SAVED_OBJECT_TYPE;
120123
const searchId =
121124
!Array.isArray(req.body.forId) && req.body.forId !== undefined

0 commit comments

Comments
 (0)