removed backend-common
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
@@ -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:^",
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:^"
|
||||
|
||||
Reference in New Issue
Block a user