diff --git a/packages/backend-test-utils/report.api.md b/packages/backend-test-utils/report.api.md
index 4f6998e1ce..9ebf02d5b8 100644
--- a/packages/backend-test-utils/report.api.md
+++ b/packages/backend-test-utils/report.api.md
@@ -3,12 +3,9 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
-///
///
///
-///
-import type { AuditorOptions } from '@backstage/backend-defaults/auditor';
import { AuditorService } from '@backstage/backend-plugin-api';
import { AuthService } from '@backstage/backend-plugin-api';
import { Backend } from '@backstage/backend-app-api';
@@ -37,6 +34,7 @@ import { ParamsDictionary } from 'express-serve-static-core';
import { ParsedQs } from 'qs';
import { PermissionsRegistryService } from '@backstage/backend-plugin-api';
import { PermissionsService } from '@backstage/backend-plugin-api';
+import type { RootAuditorOptions } from '@backstage/backend-defaults/auditor';
import { RootConfigService } from '@backstage/backend-plugin-api';
import { RootHealthService } from '@backstage/backend-plugin-api';
import { RootHttpRouterService } from '@backstage/backend-plugin-api';
@@ -156,14 +154,14 @@ export function mockErrorHandler(): ErrorRequestHandler<
// @public
export namespace mockServices {
export function auditor(
- options?: Omit & {
+ options?: auditor.Options & {
pluginId?: string;
},
): AuditorService;
// (undocumented)
export namespace auditor {
// (undocumented)
- export type Options = Omit;
+ export type Options = RootAuditorOptions;
const // (undocumented)
factory: (
options?: auditor.Options,
diff --git a/packages/backend-test-utils/src/next/services/MockAuditorService.test.ts b/packages/backend-test-utils/src/next/services/MockAuditorService.test.ts
index 5dfbe560e2..b11f633ea8 100644
--- a/packages/backend-test-utils/src/next/services/MockAuditorService.test.ts
+++ b/packages/backend-test-utils/src/next/services/MockAuditorService.test.ts
@@ -15,7 +15,7 @@
*/
import type { ErrorLike } from '@backstage/errors';
-import { MockAuditorService } from './MockAuditorService';
+import { MockRootAuditorService } from './MockAuditorService';
import { MockAuthService } from './MockAuthService';
import { MockHttpAuthService } from './MockHttpAuthService';
import { mockCredentials } from './mockCredentials';
@@ -25,81 +25,21 @@ describe('MockAuditorService', () => {
jest.resetAllMocks();
});
- it('should error without plugin service', async () => {
- const auditor = MockAuditorService.create();
- await expect(
- auditor.createEvent({
- eventId: 'test-event',
- }),
- ).rejects.toThrow(
- `The core service 'plugin' was not provided during the auditor's instantiation`,
- );
- });
-
- it('should error without auth service', async () => {
- const pluginId = 'test-plugin';
-
- const auditor = MockAuditorService.create().child(
- {},
- {
- plugin: {
- getId: () => pluginId,
- },
- },
- );
-
- await expect(
- auditor.createEvent({
- eventId: 'test-event',
- }),
- ).rejects.toThrow(
- `The core service 'auth' was not provided during the auditor's instantiation`,
- );
- });
-
- it('should error without httpAuth service', async () => {
- const pluginId = 'test-plugin';
-
- const auditor = MockAuditorService.create().child(
- {},
- {
- plugin: {
- getId: () => pluginId,
- },
- auth: new MockAuthService({
- pluginId,
- disableDefaultAuthPolicy: false,
- }),
- },
- );
-
- await expect(
- auditor.createEvent({
- eventId: 'test-event',
- }),
- ).rejects.toThrow(
- `The core service 'httpAuth' was not provided during the auditor's instantiation`,
- );
- });
-
it('should log', async () => {
jest.spyOn(console, 'log').mockImplementation(() => {});
const pluginId = 'test-plugin';
- const auditor = MockAuditorService.create().child(
- {},
- {
- plugin: {
- getId: () => pluginId,
- },
- auth: new MockAuthService({
- pluginId,
- disableDefaultAuthPolicy: false,
- }),
- httpAuth: new MockHttpAuthService(pluginId, mockCredentials.user()),
+ const auditor = MockRootAuditorService.create().forPlugin({
+ plugin: {
+ getId: () => pluginId,
},
- );
+ auth: new MockAuthService({
+ pluginId,
+ disableDefaultAuthPolicy: false,
+ }),
+ httpAuth: new MockHttpAuthService(pluginId, mockCredentials.user()),
+ });
await auditor.createEvent({
eventId: 'test-event',
@@ -113,19 +53,16 @@ describe('MockAuditorService', () => {
const pluginId = 'test-plugin';
- const auditor = MockAuditorService.create().child(
- {},
- {
- plugin: {
- getId: () => pluginId,
- },
- auth: new MockAuthService({
- pluginId,
- disableDefaultAuthPolicy: false,
- }),
- httpAuth: new MockHttpAuthService(pluginId, mockCredentials.user()),
+ const auditor = MockRootAuditorService.create().forPlugin({
+ plugin: {
+ getId: () => pluginId,
},
- );
+ auth: new MockAuthService({
+ pluginId,
+ disableDefaultAuthPolicy: false,
+ }),
+ httpAuth: new MockHttpAuthService(pluginId, mockCredentials.user()),
+ });
await auditor.createEvent({
eventId: 'test-event',
@@ -139,19 +76,16 @@ describe('MockAuditorService', () => {
const pluginId = 'test-plugin';
- const auditor = MockAuditorService.create().child(
- {},
- {
- plugin: {
- getId: () => pluginId,
- },
- auth: new MockAuthService({
- pluginId,
- disableDefaultAuthPolicy: false,
- }),
- httpAuth: new MockHttpAuthService(pluginId, mockCredentials.user()),
+ const auditor = MockRootAuditorService.create().forPlugin({
+ plugin: {
+ getId: () => pluginId,
},
- );
+ auth: new MockAuthService({
+ pluginId,
+ disableDefaultAuthPolicy: false,
+ }),
+ httpAuth: new MockHttpAuthService(pluginId, mockCredentials.user()),
+ });
const auditorEvent = await auditor.createEvent({
eventId: 'test-event',
@@ -167,19 +101,16 @@ describe('MockAuditorService', () => {
const pluginId = 'test-plugin';
- const auditor = MockAuditorService.create().child(
- {},
- {
- plugin: {
- getId: () => pluginId,
- },
- auth: new MockAuthService({
- pluginId,
- disableDefaultAuthPolicy: false,
- }),
- httpAuth: new MockHttpAuthService(pluginId, mockCredentials.user()),
+ const auditor = MockRootAuditorService.create().forPlugin({
+ plugin: {
+ getId: () => pluginId,
},
- );
+ auth: new MockAuthService({
+ pluginId,
+ disableDefaultAuthPolicy: false,
+ }),
+ httpAuth: new MockHttpAuthService(pluginId, mockCredentials.user()),
+ });
const auditorEvent = await auditor.createEvent({
eventId: 'test-event',
diff --git a/packages/backend-test-utils/src/next/services/MockAuditorService.ts b/packages/backend-test-utils/src/next/services/MockAuditorService.ts
index 3e99986758..2d34ffae9e 100644
--- a/packages/backend-test-utils/src/next/services/MockAuditorService.ts
+++ b/packages/backend-test-utils/src/next/services/MockAuditorService.ts
@@ -26,27 +26,47 @@ import type {
HttpAuthService,
PluginMetadataService,
} from '@backstage/backend-plugin-api';
-import { ForwardedError, ServiceUnavailableError } from '@backstage/errors';
+import { ForwardedError } from '@backstage/errors';
import type { JsonObject } from '@backstage/types';
import type { Request } from 'express';
import type { mockServices } from './mockServices';
export class MockAuditorService implements AuditorService {
- readonly #options: mockServices.auditor.Options & {
- auth?: AuthService;
- httpAuth?: HttpAuthService;
- plugin?: PluginMetadataService;
- };
+ private readonly impl: MockRootAuditorService;
+ private readonly auth: AuthService;
+ private readonly httpAuth: HttpAuthService;
+ private readonly plugin: PluginMetadataService;
- static create(options?: mockServices.auditor.Options): MockAuditorService {
- return new MockAuditorService(options ?? {});
+ private constructor(
+ impl: MockRootAuditorService,
+ deps: {
+ auth: AuthService;
+ httpAuth: HttpAuthService;
+ plugin: PluginMetadataService;
+ },
+ ) {
+ this.impl = impl;
+ this.auth = deps.auth;
+ this.httpAuth = deps.httpAuth;
+ this.plugin = deps.plugin;
+ }
+
+ static create(
+ impl: MockRootAuditorService,
+ deps: {
+ auth: AuthService;
+ httpAuth: HttpAuthService;
+ plugin: PluginMetadataService;
+ },
+ ): AuditorService {
+ return new MockAuditorService(impl, deps);
}
private async log(
options: AuditorEventOptions,
): Promise {
const auditEvent = await this.reshapeAuditorEvent(options);
- this.#log(...auditEvent);
+ this.impl.log(auditEvent);
}
async createEvent(
@@ -89,57 +109,25 @@ export class MockAuditorService implements AuditorService {
};
}
- child(
- meta: JsonObject,
- deps?: {
- auth?: AuthService;
- httpAuth?: HttpAuthService;
- plugin?: PluginMetadataService;
- },
- ): AuditorService {
- return new MockAuditorService({
- ...this.#options,
- auth: deps?.auth,
- httpAuth: deps?.httpAuth,
- plugin: deps?.plugin,
- meta: {
- ...this.#options.meta,
- ...meta,
- },
- });
- }
-
private async getActorId(
request?: Request,
): Promise {
- if (!this.#options.auth) {
- throw new ServiceUnavailableError(
- `The core service 'auth' was not provided during the auditor's instantiation`,
- );
- }
-
- if (!this.#options.httpAuth) {
- throw new ServiceUnavailableError(
- `The core service 'httpAuth' was not provided during the auditor's instantiation`,
- );
- }
-
let credentials: BackstageCredentials =
- await this.#options.auth.getOwnServiceCredentials();
+ await this.auth.getOwnServiceCredentials();
if (request) {
try {
- credentials = await this.#options.httpAuth.credentials(request);
+ credentials = await this.httpAuth.credentials(request);
} catch (error) {
throw new ForwardedError('Could not resolve credentials', error);
}
}
- if (this.#options.auth.isPrincipal(credentials, 'user')) {
+ if (this.auth.isPrincipal(credentials, 'user')) {
return credentials.principal.userEntityRef;
}
- if (this.#options.auth.isPrincipal(credentials, 'service')) {
+ if (this.auth.isPrincipal(credentials, 'service')) {
return credentials.principal.subject;
}
@@ -151,14 +139,8 @@ export class MockAuditorService implements AuditorService {
): Promise {
const { eventId, severityLevel = 'low', request, ...rest } = options;
- if (!this.#options.plugin) {
- throw new ServiceUnavailableError(
- `The core service 'plugin' was not provided during the auditor's instantiation`,
- );
- }
-
const auditEvent: AuditorEvent = [
- `${this.#options.plugin.getId()}.${eventId}`,
+ `${this.plugin.getId()}.${eventId}`,
{
severityLevel,
actor: {
@@ -179,15 +161,32 @@ export class MockAuditorService implements AuditorService {
return auditEvent;
}
+}
- private constructor(
- options: mockServices.auditor.Options & {
- auth?: AuthService;
- httpAuth?: HttpAuthService;
- plugin?: PluginMetadataService;
- },
- ) {
- this.#options = options;
+export class MockRootAuditorService {
+ private readonly options: mockServices.auditor.Options;
+
+ private constructor(options?: mockServices.auditor.Options) {
+ this.options = options ?? {};
+ }
+
+ static create(
+ options?: mockServices.auditor.Options,
+ ): MockRootAuditorService {
+ return new MockRootAuditorService(options);
+ }
+
+ async log(auditEvent: AuditorEvent): Promise {
+ this.#log(...auditEvent);
+ }
+
+ forPlugin(deps: {
+ auth: AuthService;
+ httpAuth: HttpAuthService;
+ plugin: PluginMetadataService;
+ }): AuditorService {
+ const impl = new MockRootAuditorService(this.options);
+ return MockAuditorService.create(impl, deps);
}
#log(message: string, meta?: AuditorEvent[1]) {
diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts
index ad1ee24e5b..e5c8db185b 100644
--- a/packages/backend-test-utils/src/next/services/mockServices.ts
+++ b/packages/backend-test-utils/src/next/services/mockServices.ts
@@ -51,7 +51,7 @@ import {
} from '@backstage/plugin-events-node';
import { JsonObject } from '@backstage/types';
import { Knex } from 'knex';
-import { MockAuditorService } from './MockAuditorService';
+import { MockRootAuditorService } from './MockAuditorService';
import { MockAuthService } from './MockAuthService';
import { MockHttpAuthService } from './MockHttpAuthService';
import { MockRootLoggerService } from './MockRootLoggerService';
@@ -228,7 +228,7 @@ export namespace mockServices {
* Creates a mock implementation of the `AuditorService`.
*/
export function auditor(
- options?: Omit & {
+ options?: auditor.Options & {
pluginId?: string;
},
): AuditorService {
@@ -247,18 +247,19 @@ export namespace mockServices {
getId: () => pluginId,
};
- const auditorMock = MockAuditorService.create({
+ const auditorMock = MockRootAuditorService.create({
meta: options?.meta ? { ...options.meta, service } : { service },
});
- return auditorMock.child(
- { pluginId },
- { auth: mockAuth, httpAuth: mockHttpAuth, plugin: mockPlugin },
- );
+ return auditorMock.forPlugin({
+ auth: mockAuth,
+ httpAuth: mockHttpAuth,
+ plugin: mockPlugin,
+ });
}
export namespace auditor {
- export type Options = Omit;
+ export type Options = RootAuditorOptions;
export const factory = (options?: auditor.Options) =>
createServiceFactory({
@@ -271,23 +272,19 @@ export namespace mockServices {
createRootContext() {
const service = 'backstage';
- return MockAuditorService.create({
+ return MockRootAuditorService.create({
meta: options?.meta ? { ...options.meta, service } : { service },
});
},
factory(
- {
- plugin,
+ { auth: mockAuth, httpAuth: mockHttpAuth, plugin: mockPlugin },
+ rootAuditor,
+ ) {
+ return rootAuditor.forPlugin({
auth: mockAuth,
httpAuth: mockHttpAuth,
plugin: mockPlugin,
- },
- rootAuditor,
- ) {
- return rootAuditor.child(
- { plugin: plugin.getId() },
- { auth: mockAuth, httpAuth: mockHttpAuth, plugin: mockPlugin },
- );
+ });
},
});