diff --git a/.changeset/dirty-apes-divide.md b/.changeset/dirty-apes-divide.md
new file mode 100644
index 0000000000..e90bc7f5e1
--- /dev/null
+++ b/.changeset/dirty-apes-divide.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-search-backend-module-elasticsearch': patch
+'@backstage/plugin-search-backend-module-pg': patch
+---
+
+Start importing `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` from the `@backstage/plugin-search-backend-node`.
diff --git a/.changeset/odd-toys-wonder.md b/.changeset/odd-toys-wonder.md
new file mode 100644
index 0000000000..aedd915c6e
--- /dev/null
+++ b/.changeset/odd-toys-wonder.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-search-common': patch
+---
+
+Deprecate `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` in favor of the types exported from `@backstage/plugin-search-backend-node`.
diff --git a/.changeset/six-grapes-sniff.md b/.changeset/six-grapes-sniff.md
new file mode 100644
index 0000000000..095e96dd77
--- /dev/null
+++ b/.changeset/six-grapes-sniff.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-search-backend': patch
+---
+
+Update the router to use the new `auth` services, it now accepts an optional discovery service option to get credentials for the permission service.
diff --git a/.changeset/violet-rocks-rescue.md b/.changeset/violet-rocks-rescue.md
new file mode 100644
index 0000000000..91fbcdd871
--- /dev/null
+++ b/.changeset/violet-rocks-rescue.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-search-backend-node': patch
+---
+
+Exports `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` types. These new types were extracted from the `@backstage/plugin-search-common` package and the `token` property was deprecated in favor of the a new credentials one.
diff --git a/packages/backend/package.json b/packages/backend/package.json
index e6102b69cf..e2b8c5d50f 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -72,7 +72,6 @@
"@backstage/plugin-search-backend-module-pg": "workspace:^",
"@backstage/plugin-search-backend-module-techdocs": "workspace:^",
"@backstage/plugin-search-backend-node": "workspace:^",
- "@backstage/plugin-search-common": "workspace:^",
"@backstage/plugin-signals-backend": "workspace:^",
"@backstage/plugin-signals-node": "workspace:^",
"@backstage/plugin-tech-insights-backend": "workspace:^",
diff --git a/packages/backend/src/plugins/search.ts b/packages/backend/src/plugins/search.ts
index 7babfe7e1f..a5b976ec9d 100644
--- a/packages/backend/src/plugins/search.ts
+++ b/packages/backend/src/plugins/search.ts
@@ -23,9 +23,9 @@ import { ElasticSearchSearchEngine } from '@backstage/plugin-search-backend-modu
import { PgSearchEngine } from '@backstage/plugin-search-backend-module-pg';
import {
IndexBuilder,
+ SearchEngine,
LunrSearchEngine,
} from '@backstage/plugin-search-backend-node';
-import { SearchEngine } from '@backstage/plugin-search-common';
import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-search-backend-module-techdocs';
import { Router } from 'express';
import { PluginEnvironment } from '../types';
@@ -117,6 +117,7 @@ export default async function createPlugin(
return await createRouter({
engine: indexBuilder.getSearchEngine(),
types: indexBuilder.getDocumentTypes(),
+ discovery: env.discovery,
permissions: env.permissions,
config: env.config,
logger: env.logger,
diff --git a/plugins/search-backend-module-elasticsearch/api-report.md b/plugins/search-backend-module-elasticsearch/api-report.md
index 7de3a1857b..053c267f29 100644
--- a/plugins/search-backend-module-elasticsearch/api-report.md
+++ b/plugins/search-backend-module-elasticsearch/api-report.md
@@ -17,7 +17,7 @@ import { IndexableResultSet } from '@backstage/plugin-search-common';
import { Logger } from 'winston';
import { LoggerService } from '@backstage/backend-plugin-api';
import { Readable } from 'stream';
-import { SearchEngine } from '@backstage/plugin-search-common';
+import { SearchEngine } from '@backstage/plugin-search-backend-node';
import { SearchQuery } from '@backstage/plugin-search-common';
import { TransportRequestPromise } from '@opensearch-project/opensearch/lib/Transport';
import { TransportRequestPromise as TransportRequestPromise_2 } from '@elastic/elasticsearch/lib/Transport';
diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts
index 8ccbe9a4ec..f8c996df51 100644
--- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts
+++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts
@@ -18,9 +18,9 @@ import {
IndexableDocument,
IndexableResult,
IndexableResultSet,
- SearchEngine,
SearchQuery,
} from '@backstage/plugin-search-common';
+import { SearchEngine } from '@backstage/plugin-search-backend-node';
import { isEmpty, isNumber, isNaN as nan } from 'lodash';
import { AwsSigv4Signer } from '@opensearch-project/opensearch/aws';
diff --git a/plugins/search-backend-module-pg/api-report.md b/plugins/search-backend-module-pg/api-report.md
index 3c6096090e..21f2d7737d 100644
--- a/plugins/search-backend-module-pg/api-report.md
+++ b/plugins/search-backend-module-pg/api-report.md
@@ -10,7 +10,7 @@ import { IndexableResultSet } from '@backstage/plugin-search-common';
import { Knex } from 'knex';
import { Logger } from 'winston';
import { PluginDatabaseManager } from '@backstage/backend-common';
-import { SearchEngine } from '@backstage/plugin-search-common';
+import { SearchEngine } from '@backstage/plugin-search-backend-node';
import { SearchQuery } from '@backstage/plugin-search-common';
// @public
diff --git a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts
index 1a27b9f981..b6513a0a97 100644
--- a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts
+++ b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts
@@ -15,7 +15,7 @@
*/
import { PluginDatabaseManager } from '@backstage/backend-common';
-import { SearchEngine } from '@backstage/plugin-search-common';
+import { SearchEngine } from '@backstage/plugin-search-backend-node';
import {
SearchQuery,
IndexableResultSet,
diff --git a/plugins/search-backend-node/api-report-alpha.md b/plugins/search-backend-node/api-report-alpha.md
index 74b7a4b4bc..c8e5cbb65d 100644
--- a/plugins/search-backend-node/api-report-alpha.md
+++ b/plugins/search-backend-node/api-report-alpha.md
@@ -7,7 +7,7 @@ import { DocumentTypeInfo } from '@backstage/plugin-search-common';
import { ExtensionPoint } from '@backstage/backend-plugin-api';
import { RegisterCollatorParameters } from '@backstage/plugin-search-backend-node';
import { RegisterDecoratorParameters } from '@backstage/plugin-search-backend-node';
-import { SearchEngine } from '@backstage/plugin-search-common';
+import { SearchEngine } from '@backstage/plugin-search-backend-node';
import { ServiceRef } from '@backstage/backend-plugin-api';
// @alpha
diff --git a/plugins/search-backend-node/api-report.md b/plugins/search-backend-node/api-report.md
index 734bf6e1c0..4109b12cf5 100644
--- a/plugins/search-backend-node/api-report.md
+++ b/plugins/search-backend-node/api-report.md
@@ -5,6 +5,7 @@
```ts
///
+import { BackstageCredentials } from '@backstage/backend-plugin-api';
import { Config } from '@backstage/config';
import { DocumentCollatorFactory } from '@backstage/plugin-search-common';
import { DocumentDecoratorFactory } from '@backstage/plugin-search-common';
@@ -14,9 +15,7 @@ import { IndexableResultSet } from '@backstage/plugin-search-common';
import { Logger } from 'winston';
import { default as lunr_2 } from 'lunr';
import { Permission } from '@backstage/plugin-permission-common';
-import { QueryTranslator } from '@backstage/plugin-search-common';
import { Readable } from 'stream';
-import { SearchEngine } from '@backstage/plugin-search-common';
import { SearchQuery } from '@backstage/plugin-search-common';
import { TaskFunction } from '@backstage/backend-tasks';
import { TaskRunner } from '@backstage/backend-tasks';
@@ -144,6 +143,18 @@ export type NewlineDelimitedJsonCollatorFactoryOptions = {
visibilityPermission?: Permission;
};
+// @public
+export type QueryRequestOptions =
+ | {
+ token?: string;
+ }
+ | {
+ credentials: BackstageCredentials;
+ };
+
+// @public
+export type QueryTranslator = (query: SearchQuery) => unknown;
+
// @public
export interface RegisterCollatorParameters {
factory: DocumentCollatorFactory;
@@ -170,6 +181,16 @@ export type ScheduleTaskParameters = {
scheduledRunner: TaskRunner;
};
+// @public
+export interface SearchEngine {
+ getIndexer(type: string): Promise;
+ query(
+ query: SearchQuery,
+ options?: QueryRequestOptions,
+ ): Promise;
+ setTranslator(translator: QueryTranslator): void;
+}
+
// @public
export class TestPipeline {
execute(): Promise;
diff --git a/plugins/search-backend-node/src/IndexBuilder.test.ts b/plugins/search-backend-node/src/IndexBuilder.test.ts
index 4a2760dde1..70d00f6974 100644
--- a/plugins/search-backend-node/src/IndexBuilder.test.ts
+++ b/plugins/search-backend-node/src/IndexBuilder.test.ts
@@ -19,11 +19,10 @@ import { TaskInvocationDefinition, TaskRunner } from '@backstage/backend-tasks';
import {
DocumentCollatorFactory,
DocumentDecoratorFactory,
- SearchEngine,
} from '@backstage/plugin-search-common';
import { Readable, Transform } from 'stream';
import { IndexBuilder } from './IndexBuilder';
-import { LunrSearchEngine } from './index';
+import { LunrSearchEngine, SearchEngine } from './index';
class TestDocumentCollatorFactory implements DocumentCollatorFactory {
readonly type: string = 'anything';
diff --git a/plugins/search-backend-node/src/IndexBuilder.ts b/plugins/search-backend-node/src/IndexBuilder.ts
index 907519f289..98c6853cb1 100644
--- a/plugins/search-backend-node/src/IndexBuilder.ts
+++ b/plugins/search-backend-node/src/IndexBuilder.ts
@@ -17,12 +17,12 @@
import {
DocumentDecoratorFactory,
DocumentTypeInfo,
- SearchEngine,
} from '@backstage/plugin-search-common';
import { Transform, pipeline } from 'stream';
import { Logger } from 'winston';
import { Scheduler } from './Scheduler';
import {
+ SearchEngine,
IndexBuilderOptions,
RegisterCollatorParameters,
RegisterDecoratorParameters,
diff --git a/plugins/search-backend-node/src/alpha.ts b/plugins/search-backend-node/src/alpha.ts
index 943e11b580..272bef7f84 100644
--- a/plugins/search-backend-node/src/alpha.ts
+++ b/plugins/search-backend-node/src/alpha.ts
@@ -22,10 +22,7 @@ import {
coreServices,
} from '@backstage/backend-plugin-api';
import { loggerToWinstonLogger } from '@backstage/backend-common';
-import {
- DocumentTypeInfo,
- SearchEngine,
-} from '@backstage/plugin-search-common';
+import { DocumentTypeInfo } from '@backstage/plugin-search-common';
import { createExtensionPoint } from '@backstage/backend-plugin-api';
import {
@@ -33,7 +30,10 @@ import {
RegisterDecoratorParameters,
} from '@backstage/plugin-search-backend-node';
-import { IndexBuilder } from './IndexBuilder';
+import {
+ SearchEngine,
+ IndexBuilder,
+} from '@backstage/plugin-search-backend-node';
/**
* @alpha
diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts
index 55c18cd6fc..e5347b3cb1 100644
--- a/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts
+++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts
@@ -16,10 +16,7 @@
import { getVoidLogger } from '@backstage/backend-common';
import lunr from 'lunr';
-import {
- IndexableDocument,
- SearchEngine,
-} from '@backstage/plugin-search-common';
+import { IndexableDocument } from '@backstage/plugin-search-common';
import {
ConcreteLunrQuery,
LunrSearchEngine,
@@ -28,6 +25,7 @@ import {
parseHighlightFields,
} from './LunrSearchEngine';
import { LunrSearchEngineIndexer } from './LunrSearchEngineIndexer';
+import { SearchEngine } from '../types';
import { TestPipeline } from '../test-utils';
/**
diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts
index 27cfae3fdf..a2db52f960 100644
--- a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts
+++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts
@@ -18,9 +18,8 @@ import {
IndexableDocument,
IndexableResultSet,
SearchQuery,
- QueryTranslator,
- SearchEngine,
} from '@backstage/plugin-search-common';
+import { SearchEngine, QueryTranslator } from '../types';
import { MissingIndexError } from '../errors';
import lunr from 'lunr';
import { v4 as uuid } from 'uuid';
diff --git a/plugins/search-backend-node/src/index.ts b/plugins/search-backend-node/src/index.ts
index a188509c1c..78e4880305 100644
--- a/plugins/search-backend-node/src/index.ts
+++ b/plugins/search-backend-node/src/index.ts
@@ -33,6 +33,9 @@ export type {
IndexBuilderOptions,
RegisterCollatorParameters,
RegisterDecoratorParameters,
+ SearchEngine,
+ QueryRequestOptions,
+ QueryTranslator,
} from './types';
export * from './errors';
export * from './indexing';
diff --git a/plugins/search-backend-node/src/types.ts b/plugins/search-backend-node/src/types.ts
index dfcf4d12ce..742d575ed3 100644
--- a/plugins/search-backend-node/src/types.ts
+++ b/plugins/search-backend-node/src/types.ts
@@ -14,12 +14,15 @@
* limitations under the License.
*/
+import { BackstageCredentials } from '@backstage/backend-plugin-api';
import { TaskRunner } from '@backstage/backend-tasks';
import {
DocumentCollatorFactory,
DocumentDecoratorFactory,
- SearchEngine,
+ IndexableResultSet,
+ SearchQuery,
} from '@backstage/plugin-search-common';
+import { Writable } from 'stream';
import { Logger } from 'winston';
/**
@@ -57,3 +60,55 @@ export interface RegisterDecoratorParameters {
*/
factory: DocumentDecoratorFactory;
}
+
+/**
+ * A type of function responsible for translating an abstract search query into
+ * a concrete query relevant to a particular search engine.
+ * @public
+ */
+export type QueryTranslator = (query: SearchQuery) => unknown;
+
+/**
+ * Options when querying a search engine.
+ * @public
+ */
+export type QueryRequestOptions =
+ | {
+ /** @deprecated use the `credentials` option instead. */
+ token?: string;
+ }
+ | {
+ credentials: BackstageCredentials;
+ };
+
+/**
+ * Interface that must be implemented by specific search engines, responsible
+ * for performing indexing and querying and translating abstract queries into
+ * concrete, search engine-specific queries.
+ * @public
+ */
+export interface SearchEngine {
+ /**
+ * Override the default translator provided by the SearchEngine.
+ */
+ setTranslator(translator: QueryTranslator): void;
+
+ /**
+ * Factory method for getting a search engine indexer for a given document
+ * type.
+ *
+ * @param type - The type or name of the document set for which an indexer
+ * should be retrieved. This corresponds to the `type` property on the
+ * document collator/decorator factories and will most often be used to
+ * identify an index or group to which documents should be written.
+ */
+ getIndexer(type: string): Promise;
+
+ /**
+ * Perform a search query against the SearchEngine.
+ */
+ query(
+ query: SearchQuery,
+ options?: QueryRequestOptions,
+ ): Promise;
+}
diff --git a/plugins/search-backend/api-report.md b/plugins/search-backend/api-report.md
index d6274d9a94..4f99632f28 100644
--- a/plugins/search-backend/api-report.md
+++ b/plugins/search-backend/api-report.md
@@ -3,13 +3,16 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
+import { AuthService } from '@backstage/backend-plugin-api';
import { Config } from '@backstage/config';
+import { DiscoveryService } from '@backstage/backend-plugin-api';
import { DocumentTypeInfo } from '@backstage/plugin-search-common';
import express from 'express';
+import { HttpAuthService } from '@backstage/backend-plugin-api';
import { Logger } from 'winston';
import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
-import { SearchEngine } from '@backstage/plugin-search-common';
+import { SearchEngine } from '@backstage/plugin-search-backend-node';
// @public (undocumented)
export function createRouter(options: RouterOptions): Promise;
@@ -18,8 +21,11 @@ export function createRouter(options: RouterOptions): Promise;
export type RouterOptions = {
engine: SearchEngine;
types: Record;
+ discovery?: DiscoveryService;
permissions: PermissionEvaluator | PermissionAuthorizer;
config: Config;
logger: Logger;
+ auth?: AuthService;
+ httpAuth?: HttpAuthService;
};
```
diff --git a/plugins/search-backend/src/alpha.ts b/plugins/search-backend/src/alpha.ts
index 8a9d4498bc..86bbcdeebe 100644
--- a/plugins/search-backend/src/alpha.ts
+++ b/plugins/search-backend/src/alpha.ts
@@ -22,6 +22,7 @@ import { loggerToWinstonLogger } from '@backstage/backend-common';
import {
RegisterCollatorParameters,
RegisterDecoratorParameters,
+ SearchEngine,
LunrSearchEngine,
} from '@backstage/plugin-search-backend-node';
import {
@@ -33,7 +34,6 @@ import {
} from '@backstage/plugin-search-backend-node/alpha';
import { createRouter } from './service/router';
-import { SearchEngine } from '@backstage/plugin-search-common';
class SearchIndexRegistry implements SearchIndexRegistryExtensionPoint {
private collators: RegisterCollatorParameters[] = [];
@@ -94,11 +94,23 @@ export default createBackendPlugin({
deps: {
logger: coreServices.logger,
config: coreServices.rootConfig,
+ discovery: coreServices.discovery,
permissions: coreServices.permissions,
+ auth: coreServices.auth,
http: coreServices.httpRouter,
+ httpAuth: coreServices.httpAuth,
searchIndexService: searchIndexServiceRef,
},
- async init({ config, logger, permissions, http, searchIndexService }) {
+ async init({
+ config,
+ logger,
+ discovery,
+ permissions,
+ auth,
+ http,
+ httpAuth,
+ searchIndexService,
+ }) {
let searchEngine = searchEngineRegistry.getSearchEngine();
if (!searchEngine) {
searchEngine = new LunrSearchEngine({
@@ -117,7 +129,10 @@ export default createBackendPlugin({
const router = await createRouter({
config,
+ discovery,
permissions,
+ auth,
+ httpAuth,
logger: loggerToWinstonLogger(logger),
engine: searchEngine,
types: searchIndexService.getDocumentTypes(),
diff --git a/plugins/search-backend/src/service/AuthorizedSearchEngine.test.ts b/plugins/search-backend/src/service/AuthorizedSearchEngine.test.ts
index b2355a7239..420af5744b 100644
--- a/plugins/search-backend/src/service/AuthorizedSearchEngine.test.ts
+++ b/plugins/search-backend/src/service/AuthorizedSearchEngine.test.ts
@@ -25,8 +25,8 @@ import {
import {
DocumentTypeInfo,
IndexableDocument,
- SearchEngine,
} from '@backstage/plugin-search-common';
+import { SearchEngine } from '@backstage/plugin-search-backend-node';
import {
encodePageCursor,
decodePageCursor,
diff --git a/plugins/search-backend/src/service/AuthorizedSearchEngine.ts b/plugins/search-backend/src/service/AuthorizedSearchEngine.ts
index 8d285d053e..defb535f42 100644
--- a/plugins/search-backend/src/service/AuthorizedSearchEngine.ts
+++ b/plugins/search-backend/src/service/AuthorizedSearchEngine.ts
@@ -23,21 +23,23 @@ import {
EvaluatePermissionRequest,
EvaluatePermissionResponse,
isResourcePermission,
- PermissionEvaluator,
QueryPermissionRequest,
} from '@backstage/plugin-permission-common';
import {
DocumentTypeInfo,
IndexableResult,
IndexableResultSet,
+ SearchQuery,
+} from '@backstage/plugin-search-common';
+import {
QueryRequestOptions,
QueryTranslator,
SearchEngine,
- SearchQuery,
-} from '@backstage/plugin-search-common';
+} from '@backstage/plugin-search-backend-node';
import { Config } from '@backstage/config';
import { InputError } from '@backstage/errors';
import { Writable } from 'stream';
+import { PermissionsService } from '@backstage/backend-plugin-api';
export function decodePageCursor(pageCursor?: string): { page: number } {
if (!pageCursor) {
@@ -68,7 +70,7 @@ export class AuthorizedSearchEngine implements SearchEngine {
constructor(
private readonly searchEngine: SearchEngine,
private readonly types: Record,
- private readonly permissions: PermissionEvaluator,
+ private readonly permissions: PermissionsService,
config: Config,
) {
this.queryLatencyBudgetMs =
diff --git a/plugins/search-backend/src/service/router.test.ts b/plugins/search-backend/src/service/router.test.ts
index 401488dcbf..7c89a8c750 100644
--- a/plugins/search-backend/src/service/router.test.ts
+++ b/plugins/search-backend/src/service/router.test.ts
@@ -14,16 +14,22 @@
* limitations under the License.
*/
-import { getVoidLogger } from '@backstage/backend-common';
+import {
+ PluginEndpointDiscovery,
+ getVoidLogger,
+} from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
-import { IndexBuilder } from '@backstage/plugin-search-backend-node';
-import { SearchEngine } from '@backstage/plugin-search-common';
+import {
+ IndexBuilder,
+ SearchEngine,
+} from '@backstage/plugin-search-backend-node';
import express from 'express';
import request from 'supertest';
import { createRouter } from './router';
import { wrapInOpenApiTestServer } from '@backstage/backend-openapi-utils';
import { Server } from 'http';
+import { mockCredentials, mockServices } from '@backstage/backend-test-utils';
const mockPermissionEvaluator: PermissionEvaluator = {
authorize: () => {
@@ -38,6 +44,16 @@ describe('createRouter', () => {
let app: express.Express | Server;
let mockSearchEngine: jest.Mocked;
+ const mockBaseUrl = 'http://backstage:9191/api/proxy';
+ const discovery: PluginEndpointDiscovery = {
+ async getBaseUrl() {
+ return mockBaseUrl;
+ },
+ async getExternalBaseUrl() {
+ return mockBaseUrl;
+ },
+ };
+
beforeAll(async () => {
const logger = getVoidLogger();
mockSearchEngine = {
@@ -65,7 +81,10 @@ describe('createRouter', () => {
search: { maxPageLimit: 200, maxTermLength: 20 },
}),
permissions: mockPermissionEvaluator,
+ discovery,
logger,
+ auth: mockServices.auth(),
+ httpAuth: mockServices.httpAuth(),
});
app = wrapInOpenApiTestServer(express().use(router));
});
@@ -227,7 +246,11 @@ describe('createRouter', () => {
unknownKey2: 'unknownValue1',
};
const secondArg = {
- token: undefined,
+ credentials: mockCredentials.user(),
+ token: mockCredentials.service.token({
+ onBehalfOf: mockCredentials.user(),
+ targetPluginId: 'search',
+ }),
};
expect(response.status).toEqual(200);
expect(mockSearchEngine.query).toHaveBeenCalledWith(firstArg, secondArg);
@@ -251,6 +274,7 @@ describe('createRouter', () => {
types: indexBuilder.getDocumentTypes(),
config: new ConfigReader({ permissions: { enabled: false } }),
permissions: mockPermissionEvaluator,
+ discovery,
logger,
});
app = express().use(router);
diff --git a/plugins/search-backend/src/service/router.ts b/plugins/search-backend/src/service/router.ts
index 876cb5d103..ae470ba40e 100644
--- a/plugins/search-backend/src/service/router.ts
+++ b/plugins/search-backend/src/service/router.ts
@@ -17,11 +17,14 @@
import express from 'express';
import { Logger } from 'winston';
import { z } from 'zod';
-import { errorHandler } from '@backstage/backend-common';
+import {
+ HostDiscovery,
+ createLegacyAuthAdapters,
+ errorHandler,
+} from '@backstage/backend-common';
import { InputError } from '@backstage/errors';
import { Config } from '@backstage/config';
import { JsonObject, JsonValue } from '@backstage/types';
-import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node';
import {
PermissionAuthorizer,
PermissionEvaluator,
@@ -32,9 +35,14 @@ import {
IndexableResultSet,
SearchResultSet,
} from '@backstage/plugin-search-common';
-import { SearchEngine } from '@backstage/plugin-search-common';
+import { SearchEngine } from '@backstage/plugin-search-backend-node';
import { AuthorizedSearchEngine } from './AuthorizedSearchEngine';
import { createOpenApiRouter } from '../schema/openapi.generated';
+import {
+ AuthService,
+ DiscoveryService,
+ HttpAuthService,
+} from '@backstage/backend-plugin-api';
const jsonObjectSchema: z.ZodSchema = z.lazy(() => {
const jsonValueSchema: z.ZodSchema = z.lazy(() =>
@@ -57,9 +65,12 @@ const jsonObjectSchema: z.ZodSchema = z.lazy(() => {
export type RouterOptions = {
engine: SearchEngine;
types: Record;
+ discovery?: DiscoveryService;
permissions: PermissionEvaluator | PermissionAuthorizer;
config: Config;
logger: Logger;
+ auth?: AuthService;
+ httpAuth?: HttpAuthService;
};
const defaultMaxPageLimit = 100;
@@ -73,7 +84,19 @@ export async function createRouter(
options: RouterOptions,
): Promise {
const router = await createOpenApiRouter();
- const { engine: inputEngine, types, permissions, config, logger } = options;
+ const {
+ engine: inputEngine,
+ types,
+ permissions,
+ config,
+ logger,
+ discovery = HostDiscovery.fromConfig(config),
+ } = options;
+
+ const { auth, httpAuth } = createLegacyAuthAdapters({
+ ...options,
+ discovery,
+ });
const maxPageLimit =
config.getOptionalNumber('search.maxPageLimit') ?? defaultMaxPageLimit;
@@ -169,12 +192,16 @@ export async function createRouter(
}`,
);
- const token = getBearerTokenFromAuthorizationHeader(
- req.header('authorization'),
- );
-
try {
- const resultSet = await engine?.query(query, { token });
+ const credentials = await httpAuth.credentials(req);
+ const { token } = await auth.getPluginRequestToken({
+ onBehalfOf: credentials,
+ targetPluginId: 'search',
+ });
+ const resultSet = await engine?.query(query, {
+ token,
+ credentials,
+ });
res.json(filterResultSet(toSearchResults(resultSet)));
} catch (error) {
diff --git a/plugins/search-backend/src/service/standaloneServer.ts b/plugins/search-backend/src/service/standaloneServer.ts
index 9e4294d39f..09fa4f87ee 100644
--- a/plugins/search-backend/src/service/standaloneServer.ts
+++ b/plugins/search-backend/src/service/standaloneServer.ts
@@ -57,6 +57,7 @@ export async function startStandaloneServer(
const router = await createRouter({
engine: indexBuilder.getSearchEngine(),
types: indexBuilder.getDocumentTypes(),
+ discovery,
permissions,
config,
logger,
diff --git a/plugins/search-common/api-report.md b/plugins/search-common/api-report.md
index 2006689ab9..497defc46d 100644
--- a/plugins/search-common/api-report.md
+++ b/plugins/search-common/api-report.md
@@ -42,12 +42,12 @@ export type IndexableResult = Result;
// @public (undocumented)
export type IndexableResultSet = ResultSet;
-// @public
+// @public @deprecated
export type QueryRequestOptions = {
token?: string;
};
-// @public
+// @public @deprecated
export type QueryTranslator = (query: SearchQuery) => unknown;
// @public (undocumented)
@@ -87,7 +87,7 @@ export interface SearchDocument {
title: string;
}
-// @public
+// @public @deprecated
export interface SearchEngine {
getIndexer(type: string): Promise;
query(
diff --git a/plugins/search-common/src/deprecated.ts b/plugins/search-common/src/deprecated.ts
new file mode 100644
index 0000000000..8d76d3a22d
--- /dev/null
+++ b/plugins/search-common/src/deprecated.ts
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2024 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Writable } from 'stream';
+import { SearchQuery, IndexableResultSet } from './types';
+
+/**
+ * A type of function responsible for translating an abstract search query into
+ * a concrete query relevant to a particular search engine.
+ * @public
+ * @deprecated Import from `@backstage/plugin-search-backend-node` instead
+ */
+export type QueryTranslator = (query: SearchQuery) => unknown;
+
+/**
+ * Options when querying a search engine.
+ * @public
+ * @deprecated Import from `@backstage/plugin-search-backend-node` instead
+ */
+export type QueryRequestOptions = {
+ token?: string;
+};
+
+/**
+ * Interface that must be implemented by specific search engines, responsible
+ * for performing indexing and querying and translating abstract queries into
+ * concrete, search engine-specific queries.
+ * @public
+ * @deprecated Import from `@backstage/plugin-search-backend-node` instead
+ */
+export interface SearchEngine {
+ /**
+ * Override the default translator provided by the SearchEngine.
+ */
+ setTranslator(translator: QueryTranslator): void;
+
+ /**
+ * Factory method for getting a search engine indexer for a given document
+ * type.
+ *
+ * @param type - The type or name of the document set for which an indexer
+ * should be retrieved. This corresponds to the `type` property on the
+ * document collator/decorator factories and will most often be used to
+ * identify an index or group to which documents should be written.
+ */
+ getIndexer(type: string): Promise;
+
+ /**
+ * Perform a search query against the SearchEngine.
+ */
+ query(
+ query: SearchQuery,
+ options?: QueryRequestOptions,
+ ): Promise;
+}
diff --git a/plugins/search-common/src/index.ts b/plugins/search-common/src/index.ts
index e71f8cd660..5d8ae2d42f 100644
--- a/plugins/search-common/src/index.ts
+++ b/plugins/search-common/src/index.ts
@@ -21,3 +21,4 @@
*/
export * from './types';
+export * from './deprecated';
diff --git a/plugins/search-common/src/types.ts b/plugins/search-common/src/types.ts
index 2ea4a490ca..9d1f9aa887 100644
--- a/plugins/search-common/src/types.ts
+++ b/plugins/search-common/src/types.ts
@@ -16,7 +16,7 @@
import { Permission } from '@backstage/plugin-permission-common';
import { JsonObject } from '@backstage/types';
-import { Readable, Transform, Writable } from 'stream';
+import { Readable, Transform } from 'stream';
/**
* @public
@@ -206,50 +206,3 @@ export interface DocumentDecoratorFactory {
*/
getDecorator(): Promise;
}
-
-/**
- * A type of function responsible for translating an abstract search query into
- * a concrete query relevant to a particular search engine.
- * @public
- */
-export type QueryTranslator = (query: SearchQuery) => unknown;
-
-/**
- * Options when querying a search engine.
- * @public
- */
-export type QueryRequestOptions = {
- token?: string;
-};
-
-/**
- * Interface that must be implemented by specific search engines, responsible
- * for performing indexing and querying and translating abstract queries into
- * concrete, search engine-specific queries.
- * @public
- */
-export interface SearchEngine {
- /**
- * Override the default translator provided by the SearchEngine.
- */
- setTranslator(translator: QueryTranslator): void;
-
- /**
- * Factory method for getting a search engine indexer for a given document
- * type.
- *
- * @param type - The type or name of the document set for which an indexer
- * should be retrieved. This corresponds to the `type` property on the
- * document collator/decorator factories and will most often be used to
- * identify an index or group to which documents should be written.
- */
- getIndexer(type: string): Promise;
-
- /**
- * Perform a search query against the SearchEngine.
- */
- query(
- query: SearchQuery,
- options?: QueryRequestOptions,
- ): Promise;
-}
diff --git a/yarn.lock b/yarn.lock
index 9790c4acf5..532c8a4332 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -27538,7 +27538,6 @@ __metadata:
"@backstage/plugin-search-backend-module-pg": "workspace:^"
"@backstage/plugin-search-backend-module-techdocs": "workspace:^"
"@backstage/plugin-search-backend-node": "workspace:^"
- "@backstage/plugin-search-common": "workspace:^"
"@backstage/plugin-signals-backend": "workspace:^"
"@backstage/plugin-signals-node": "workspace:^"
"@backstage/plugin-tech-insights-backend": "workspace:^"