From 94ccd772d4796008aff3d218b8ed77b4d1977ed6 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 11 Mar 2022 18:57:09 +0000 Subject: [PATCH] search-backend: filter out authorization property in api responses Signed-off-by: Mike Lewis --- .changeset/empty-pens-invent.md | 5 ++ .../search-backend/src/service/router.test.ts | 54 +++++++++++++++++-- plugins/search-backend/src/service/router.ts | 14 ++++- 3 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 .changeset/empty-pens-invent.md diff --git a/.changeset/empty-pens-invent.md b/.changeset/empty-pens-invent.md new file mode 100644 index 0000000000..4f94028fc0 --- /dev/null +++ b/.changeset/empty-pens-invent.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend': patch +--- + +Filter out `authorization` property before returning API responses. diff --git a/plugins/search-backend/src/service/router.test.ts b/plugins/search-backend/src/service/router.test.ts index bdf46a240b..2efab91256 100644 --- a/plugins/search-backend/src/service/router.test.ts +++ b/plugins/search-backend/src/service/router.test.ts @@ -19,7 +19,6 @@ import { ConfigReader } from '@backstage/config'; import { PermissionAuthorizer } from '@backstage/plugin-permission-common'; import { IndexBuilder, - LunrSearchEngine, SearchEngine, } from '@backstage/plugin-search-backend-node'; import express from 'express'; @@ -39,8 +38,19 @@ describe('createRouter', () => { beforeAll(async () => { const logger = getVoidLogger(); - const searchEngine = new LunrSearchEngine({ logger }); - const indexBuilder = new IndexBuilder({ logger, searchEngine }); + mockSearchEngine = { + getIndexer: jest.fn(), + setTranslator: jest.fn(), + query: jest.fn().mockResolvedValue({ + results: [], + nextPageCursor: '', + previousPageCursor: '', + }), + }; + const indexBuilder = new IndexBuilder({ + logger, + searchEngine: mockSearchEngine, + }); const router = await createRouter({ engine: indexBuilder.getSearchEngine(), @@ -56,7 +66,7 @@ describe('createRouter', () => { }); beforeEach(() => { - jest.resetAllMocks(); + jest.clearAllMocks(); }); describe('GET /query', () => { @@ -101,6 +111,42 @@ describe('createRouter', () => { }); }); + it('removes backend-only properties from search documents', async () => { + mockSearchEngine.query.mockResolvedValue({ + results: [ + { + type: 'software-catalog', + document: { + text: 'foo', + title: 'bar baz', + location: '/catalog/default/component/example', + authorization: { + resourceRef: 'component:default/example', + }, + }, + }, + ], + nextPageCursor: '', + previousPageCursor: '', + }); + + const response = await request(app).get('/query'); + + expect(response.status).toEqual(200); + expect(response.body).toMatchObject({ + results: [ + { + type: 'software-catalog', + document: { + text: 'foo', + title: 'bar baz', + location: '/catalog/default/component/example', + }, + }, + ], + }); + }); + describe('search result filtering', () => { beforeAll(async () => { const logger = getVoidLogger(); diff --git a/plugins/search-backend/src/service/router.ts b/plugins/search-backend/src/service/router.ts index 92e4e5526f..ff91465cf4 100644 --- a/plugins/search-backend/src/service/router.ts +++ b/plugins/search-backend/src/service/router.ts @@ -26,6 +26,7 @@ import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-no import { PermissionAuthorizer } from '@backstage/plugin-permission-common'; import { DocumentTypeInfo, + IndexableResultSet, SearchResultSet, } from '@backstage/plugin-search-common'; import { SearchEngine } from '@backstage/plugin-search-backend-node'; @@ -89,6 +90,17 @@ export async function createRouter( }), }); + const toSearchResults = (resultSet: IndexableResultSet): SearchResultSet => ({ + ...resultSet, + results: resultSet.results.map(result => ({ + ...result, + document: { + ...result.document, + authorization: undefined, + }, + })), + }); + const router = Router(); router.get( '/query', @@ -116,7 +128,7 @@ export async function createRouter( try { const resultSet = await engine?.query(query, { token }); - res.send(filterResultSet(resultSet)); + res.send(filterResultSet(toSearchResults(resultSet))); } catch (err) { throw new Error( `There was a problem performing the search query. ${err}`,