removed backend-common

Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
Fredrik Adelöw
2025-04-15 22:39:03 +02:00
parent f6e3bc9dce
commit edfcd7e04b
12 changed files with 95 additions and 164 deletions
-1
View File
@@ -43,7 +43,6 @@
"test": "backstage-cli package test"
},
"dependencies": {
"@backstage/backend-common": "^0.25.0",
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/catalog-client": "workspace:^",
"@backstage/catalog-model": "workspace:^",
-3
View File
@@ -66,7 +66,6 @@ export const authPlugin = createBackendPlugin({
database: coreServices.database,
discovery: coreServices.discovery,
auth: coreServices.auth,
httpAuth: coreServices.httpAuth,
catalogApi: catalogServiceRef,
},
async init({
@@ -76,7 +75,6 @@ export const authPlugin = createBackendPlugin({
database,
discovery,
auth,
httpAuth,
catalogApi,
}) {
const router = await createRouter({
@@ -85,7 +83,6 @@ export const authPlugin = createBackendPlugin({
database,
discovery,
auth,
httpAuth,
catalogApi,
providerFactories: Object.fromEntries(providers),
ownershipResolver,
@@ -14,12 +14,10 @@
* limitations under the License.
*/
import { DatabaseManager } from '@backstage/backend-common';
import {
DatabaseService,
resolvePackagePath,
} from '@backstage/backend-plugin-api';
import { ConfigReader } from '@backstage/config';
import { Knex } from 'knex';
const migrationsDir = resolvePackagePath(
@@ -39,21 +37,6 @@ export class AuthDatabase {
return new AuthDatabase(database);
}
/** @internal */
static forTesting(): AuthDatabase {
const config = new ConfigReader({
backend: {
database: {
client: 'better-sqlite3',
connection: ':memory:',
useNullAsDefault: true,
},
},
});
const database = DatabaseManager.fromConfig(config).forPlugin('auth');
return new AuthDatabase(database);
}
static async runMigrations(knex: Knex): Promise<void> {
await knex.migrate.latest({
directory: migrationsDir,
@@ -20,9 +20,13 @@ import { DatabaseKeyStore } from './DatabaseKeyStore';
import { FirestoreKeyStore } from './FirestoreKeyStore';
import { KeyStores } from './KeyStores';
import { MemoryKeyStore } from './MemoryKeyStore';
import { mockServices } from '@backstage/backend-test-utils';
import { mockServices, TestDatabases } from '@backstage/backend-test-utils';
jest.setTimeout(60_000);
describe('KeyStores', () => {
const databases = TestDatabases.create();
const defaultConfigOptions = {
auth: {
keyStore: {
@@ -32,65 +36,77 @@ describe('KeyStores', () => {
};
const defaultConfig = new ConfigReader(defaultConfigOptions);
it('reads auth section from config', async () => {
const configSpy = jest.spyOn(defaultConfig, 'getOptionalConfig');
const keyStore = await KeyStores.fromConfig(defaultConfig, {
logger: mockServices.logger.mock(),
database: AuthDatabase.forTesting(),
});
it.each(databases.eachSupportedId())(
'reads auth section from config, %p',
async databaseId => {
const knex = await databases.init(databaseId);
const configSpy = jest.spyOn(defaultConfig, 'getOptionalConfig');
const keyStore = await KeyStores.fromConfig(defaultConfig, {
logger: mockServices.logger.mock(),
database: AuthDatabase.create(mockServices.database({ knex })),
});
expect(keyStore).toBeInstanceOf(MemoryKeyStore);
expect(configSpy).toHaveBeenCalledWith('auth.keyStore');
expect(
defaultConfig
.getOptionalConfig('auth.keyStore')
?.getOptionalString('provider'),
).toBe(defaultConfigOptions.auth.keyStore.provider);
});
expect(keyStore).toBeInstanceOf(MemoryKeyStore);
expect(configSpy).toHaveBeenCalledWith('auth.keyStore');
expect(
defaultConfig
.getOptionalConfig('auth.keyStore')
?.getOptionalString('provider'),
).toBe(defaultConfigOptions.auth.keyStore.provider);
},
);
it('can handle without auth config', async () => {
const keyStore = await KeyStores.fromConfig(new ConfigReader({}), {
logger: mockServices.logger.mock(),
database: AuthDatabase.forTesting(),
});
expect(keyStore).toBeInstanceOf(DatabaseKeyStore);
});
it.each(databases.eachSupportedId())(
'can handle without auth config, %p',
async databaseId => {
const knex = await databases.init(databaseId);
const keyStore = await KeyStores.fromConfig(new ConfigReader({}), {
logger: mockServices.logger.mock(),
database: AuthDatabase.create(mockServices.database({ knex })),
});
expect(keyStore).toBeInstanceOf(DatabaseKeyStore);
},
);
it('can handle additional provider config', async () => {
jest.spyOn(FirestoreKeyStore, 'verifyConnection').mockResolvedValue();
const createSpy = jest.spyOn(FirestoreKeyStore, 'create');
it.each(databases.eachSupportedId())(
'can handle additional provider config, %p',
async databaseId => {
const knex = await databases.init(databaseId);
jest.spyOn(FirestoreKeyStore, 'verifyConnection').mockResolvedValue();
const createSpy = jest.spyOn(FirestoreKeyStore, 'create');
const configOptions = {
auth: {
keyStore: {
provider: 'firestore',
firestore: {
projectId: 'my-project',
keyFilename: 'cred.json',
path: 'my-path',
timeout: 100,
host: 'localhost',
port: 8088,
ssl: false,
const configOptions = {
auth: {
keyStore: {
provider: 'firestore',
firestore: {
projectId: 'my-project',
keyFilename: 'cred.json',
path: 'my-path',
timeout: 100,
host: 'localhost',
port: 8088,
ssl: false,
},
},
},
},
};
const config = new ConfigReader(configOptions);
const keyStore = await KeyStores.fromConfig(config, {
logger: mockServices.logger.mock(),
database: AuthDatabase.forTesting(),
});
};
const config = new ConfigReader(configOptions);
const keyStore = await KeyStores.fromConfig(config, {
logger: mockServices.logger.mock(),
database: AuthDatabase.create(mockServices.database({ knex })),
});
expect(keyStore).toBeInstanceOf(FirestoreKeyStore);
expect(createSpy).toHaveBeenCalledWith(
configOptions.auth.keyStore.firestore,
);
expect(
config
.getOptionalConfig('auth.keyStore')
?.getOptionalConfig('firestore')
?.getOptionalString('projectId'),
).toBe(configOptions.auth.keyStore.firestore.projectId);
});
expect(keyStore).toBeInstanceOf(FirestoreKeyStore);
expect(createSpy).toHaveBeenCalledWith(
configOptions.auth.keyStore.firestore,
);
expect(
config
.getOptionalConfig('auth.keyStore')
?.getOptionalConfig('firestore')
?.getOptionalString('projectId'),
).toBe(configOptions.auth.keyStore.firestore.projectId);
},
);
});
@@ -14,20 +14,16 @@
* limitations under the License.
*/
import { TokenManager } from '@backstage/backend-common';
import {
RELATION_MEMBER_OF,
UserEntityV1alpha1,
} from '@backstage/catalog-model';
import { catalogServiceMock } from '@backstage/plugin-catalog-node/testUtils';
import { CatalogIdentityClient } from './CatalogIdentityClient';
import { mockServices } from '@backstage/backend-test-utils';
import { mockCredentials, mockServices } from '@backstage/backend-test-utils';
describe('CatalogIdentityClient', () => {
const tokenManager: jest.Mocked<TokenManager> = {
getToken: jest.fn(),
authenticate: jest.fn(),
};
const auth = mockServices.auth();
afterEach(() => jest.resetAllMocks());
@@ -48,11 +44,9 @@ describe('CatalogIdentityClient', () => {
});
jest.spyOn(catalogApi, 'getEntities');
tokenManager.getToken.mockResolvedValue({ token: 'my-token' });
const client = new CatalogIdentityClient({
discovery: mockServices.discovery(),
catalogApi,
tokenManager,
auth,
});
await client.findUser({ annotations: { key: 'value' } });
@@ -64,9 +58,13 @@ describe('CatalogIdentityClient', () => {
'metadata.annotations.key': 'value',
},
},
{ token: 'my-token' },
{
token: mockCredentials.service.token({
onBehalfOf: mockCredentials.service('plugin:test'),
targetPluginId: 'catalog',
}),
},
);
expect(tokenManager.getToken).toHaveBeenCalledWith();
});
it('resolveCatalogMembership resolves membership', async () => {
@@ -107,12 +105,10 @@ describe('CatalogIdentityClient', () => {
];
const catalogApi = catalogServiceMock({ entities: mockUsers });
jest.spyOn(catalogApi, 'getEntities');
tokenManager.getToken.mockResolvedValue({ token: 'my-token' });
const client = new CatalogIdentityClient({
discovery: {} as any,
catalogApi,
tokenManager,
auth,
});
const claims = await client.resolveCatalogMembership({
@@ -139,7 +135,12 @@ describe('CatalogIdentityClient', () => {
},
],
},
{ token: 'my-token' },
{
token: mockCredentials.service.token({
onBehalfOf: mockCredentials.service('plugin:test'),
targetPluginId: 'catalog',
}),
},
);
expect(claims).toMatchObject([
@@ -14,12 +14,7 @@
* limitations under the License.
*/
import {
AuthService,
DiscoveryService,
HttpAuthService,
LoggerService,
} from '@backstage/backend-plugin-api';
import { AuthService, LoggerService } from '@backstage/backend-plugin-api';
import { ConflictError, NotFoundError } from '@backstage/errors';
import { CatalogApi } from '@backstage/catalog-client';
import {
@@ -29,38 +24,17 @@ import {
stringifyEntityRef,
UserEntity,
} from '@backstage/catalog-model';
import {
TokenManager,
createLegacyAuthAdapters,
} from '@backstage/backend-common';
/**
* A catalog client tailored for reading out identity data from the catalog.
*
* @public
* @deprecated Use the provided `AuthResolverContext` instead, see https://backstage.io/docs/auth/identity-resolver#building-custom-resolvers
*/
export class CatalogIdentityClient {
private readonly catalogApi: CatalogApi;
private readonly auth: AuthService;
constructor(options: {
catalogApi: CatalogApi;
tokenManager?: TokenManager;
discovery: DiscoveryService;
auth?: AuthService;
httpAuth?: HttpAuthService;
}) {
constructor(options: { catalogApi: CatalogApi; auth: AuthService }) {
this.catalogApi = options.catalogApi;
const { auth } = createLegacyAuthAdapters({
auth: options.auth,
httpAuth: options.httpAuth,
discovery: options.discovery,
tokenManager: options.tokenManager,
});
this.auth = auth;
this.auth = options.auth;
}
/**
@@ -17,7 +17,6 @@
import { CatalogAuthResolverContext } from './CatalogAuthResolverContext';
import { mockServices } from '@backstage/backend-test-utils';
import { TokenIssuer } from '../../identity/types';
import { DiscoveryService } from '@backstage/backend-plugin-api';
import { catalogServiceMock } from '@backstage/plugin-catalog-node/testUtils';
import { NotFoundError } from '@backstage/errors';
@@ -34,9 +33,7 @@ describe('CatalogAuthResolverContext', () => {
logger: mockServices.logger.mock(),
catalogApi,
tokenIssuer: {} as TokenIssuer,
discovery: {} as DiscoveryService,
auth: mockServices.auth(),
httpAuth: mockServices.httpAuth(),
});
await expect(
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import { TokenManager } from '@backstage/backend-common';
import { CatalogApi } from '@backstage/catalog-client';
import {
DEFAULT_NAMESPACE,
@@ -24,12 +23,7 @@ import {
stringifyEntityRef,
} from '@backstage/catalog-model';
import { ConflictError, InputError, NotFoundError } from '@backstage/errors';
import {
AuthService,
DiscoveryService,
HttpAuthService,
LoggerService,
} from '@backstage/backend-plugin-api';
import { AuthService, LoggerService } from '@backstage/backend-plugin-api';
import { TokenIssuer } from '../../identity/types';
import {
AuthOwnershipResolver,
@@ -55,18 +49,12 @@ export class CatalogAuthResolverContext implements AuthResolverContext {
logger: LoggerService;
catalogApi: CatalogApi;
tokenIssuer: TokenIssuer;
tokenManager?: TokenManager;
discovery: DiscoveryService;
auth: AuthService;
httpAuth: HttpAuthService;
ownershipResolver?: AuthOwnershipResolver;
}): CatalogAuthResolverContext {
const catalogIdentityClient = new CatalogIdentityClient({
catalogApi: options.catalogApi,
tokenManager: options.tokenManager,
discovery: options.discovery,
auth: options.auth,
httpAuth: options.httpAuth,
});
return new CatalogAuthResolverContext(
+1 -1
View File
@@ -14,4 +14,4 @@
* limitations under the License.
*/
export { createOriginFilter, type ProviderFactories } from './router';
export { type ProviderFactories } from './router';
@@ -14,11 +14,9 @@
* limitations under the License.
*/
import { TokenManager } from '@backstage/backend-common';
import {
AuthService,
DiscoveryService,
HttpAuthService,
LoggerService,
} from '@backstage/backend-plugin-api';
import { CatalogApi, CatalogClient } from '@backstage/catalog-client';
@@ -50,8 +48,6 @@ export function bindProviderRouters(
logger: LoggerService;
discovery: DiscoveryService;
auth: AuthService;
httpAuth: HttpAuthService;
tokenManager?: TokenManager;
tokenIssuer: TokenIssuer;
ownershipResolver?: AuthOwnershipResolver;
catalogApi?: CatalogApi;
@@ -65,8 +61,6 @@ export function bindProviderRouters(
logger,
discovery,
auth,
httpAuth,
tokenManager,
tokenIssuer,
catalogApi,
ownershipResolver,
@@ -97,10 +91,7 @@ export function bindProviderRouters(
catalogApi:
catalogApi ?? new CatalogClient({ discoveryApi: discovery }),
tokenIssuer,
tokenManager,
discovery,
auth,
httpAuth,
ownershipResolver,
}),
});
@@ -148,10 +139,6 @@ export function bindProviderRouters(
}
}
/**
* @public
* @deprecated this export will be removed
*/
export function createOriginFilter(
config: Config,
): (origin: string) => boolean {
+3 -13
View File
@@ -21,15 +21,10 @@ import {
AuthService,
DatabaseService,
DiscoveryService,
HttpAuthService,
LoggerService,
RootConfigService,
} from '@backstage/backend-plugin-api';
import { AuthOwnershipResolver } from '@backstage/plugin-auth-node';
import {
TokenManager,
createLegacyAuthAdapters,
} from '@backstage/backend-common';
import { NotFoundError } from '@backstage/errors';
import { CatalogApi } from '@backstage/catalog-client';
import {
@@ -53,9 +48,7 @@ export interface RouterOptions {
database: DatabaseService;
config: RootConfigService;
discovery: DiscoveryService;
tokenManager?: TokenManager;
auth?: AuthService;
httpAuth?: HttpAuthService;
auth: AuthService;
tokenFactoryAlgorithm?: string;
providerFactories?: ProviderFactories;
catalogApi?: CatalogApi;
@@ -74,8 +67,6 @@ export async function createRouter(
providerFactories = {},
} = options;
const { auth, httpAuth } = createLegacyAuthAdapters(options);
const router = Router();
const appUrl = config.getString('app.baseUrl');
@@ -147,12 +138,11 @@ export async function createRouter(
baseUrl: authUrl,
tokenIssuer,
...options,
auth,
httpAuth,
auth: options.auth,
});
bindOidcRouter(router, {
auth,
auth: options.auth,
tokenIssuer,
baseUrl: authUrl,
userInfoDatabaseHandler,
-1
View File
@@ -5277,7 +5277,6 @@ __metadata:
version: 0.0.0-use.local
resolution: "@backstage/plugin-auth-backend@workspace:plugins/auth-backend"
dependencies:
"@backstage/backend-common": "npm:^0.25.0"
"@backstage/backend-defaults": "workspace:^"
"@backstage/backend-plugin-api": "workspace:^"
"@backstage/backend-test-utils": "workspace:^"