Merge branch 'master' into feat/dynatrace-plugin-synthetics
Signed-off-by: Isaiah Thiessen <isaiah.thiessen@telus.com>
This commit is contained in:
@@ -14,10 +14,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Knex from 'knex';
|
||||
import Knex, { Knex as KnexType } from 'knex';
|
||||
import { DatabaseKeyStore } from './DatabaseKeyStore';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
function createDatabaseManager(
|
||||
client: KnexType,
|
||||
skipMigrations: boolean = false,
|
||||
) {
|
||||
return {
|
||||
getClient: async () => client,
|
||||
migrations: {
|
||||
skip: skipMigrations,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function createDB() {
|
||||
const knex = Knex({
|
||||
client: 'better-sqlite3',
|
||||
@@ -38,8 +50,10 @@ const keyBase = {
|
||||
|
||||
describe('DatabaseKeyStore', () => {
|
||||
it('should store a key', async () => {
|
||||
const database = createDB();
|
||||
const store = await DatabaseKeyStore.create({ database });
|
||||
const client = createDB();
|
||||
const store = await DatabaseKeyStore.create({
|
||||
database: createDatabaseManager(client),
|
||||
});
|
||||
|
||||
const key = {
|
||||
kid: '123',
|
||||
@@ -59,8 +73,10 @@ describe('DatabaseKeyStore', () => {
|
||||
});
|
||||
|
||||
it('should remove stored keys', async () => {
|
||||
const database = createDB();
|
||||
const store = await DatabaseKeyStore.create({ database });
|
||||
const client = createDB();
|
||||
const store = await DatabaseKeyStore.create({
|
||||
database: createDatabaseManager(client),
|
||||
});
|
||||
|
||||
const key1 = { kid: '1', ...keyBase };
|
||||
const key2 = { kid: '2', ...keyBase };
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { resolvePackagePath } from '@backstage/backend-common';
|
||||
import {
|
||||
PluginDatabaseManager,
|
||||
resolvePackagePath,
|
||||
} from '@backstage/backend-common';
|
||||
import { Knex } from 'knex';
|
||||
import { DateTime } from 'luxon';
|
||||
import { AnyJWK, KeyStore, StoredKey } from './types';
|
||||
@@ -33,7 +36,7 @@ type Row = {
|
||||
};
|
||||
|
||||
type Options = {
|
||||
database: Knex;
|
||||
database: PluginDatabaseManager;
|
||||
};
|
||||
|
||||
const parseDate = (date: string | Date) => {
|
||||
@@ -54,29 +57,32 @@ const parseDate = (date: string | Date) => {
|
||||
export class DatabaseKeyStore implements KeyStore {
|
||||
static async create(options: Options): Promise<DatabaseKeyStore> {
|
||||
const { database } = options;
|
||||
const client = await database.getClient();
|
||||
|
||||
await database.migrate.latest({
|
||||
directory: migrationsDir,
|
||||
});
|
||||
if (!database.migrations?.skip) {
|
||||
await client.migrate.latest({
|
||||
directory: migrationsDir,
|
||||
});
|
||||
}
|
||||
|
||||
return new DatabaseKeyStore(options);
|
||||
return new DatabaseKeyStore(client);
|
||||
}
|
||||
|
||||
private readonly database: Knex;
|
||||
private readonly client: Knex;
|
||||
|
||||
private constructor(options: Options) {
|
||||
this.database = options.database;
|
||||
private constructor(client: Knex) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
async addKey(key: AnyJWK): Promise<void> {
|
||||
await this.database<Row>(TABLE).insert({
|
||||
await this.client<Row>(TABLE).insert({
|
||||
kid: key.kid,
|
||||
key: JSON.stringify(key),
|
||||
});
|
||||
}
|
||||
|
||||
async listKeys(): Promise<{ items: StoredKey[] }> {
|
||||
const rows = await this.database<Row>(TABLE).select();
|
||||
const rows = await this.client<Row>(TABLE).select();
|
||||
|
||||
return {
|
||||
items: rows.map(row => ({
|
||||
@@ -87,6 +93,6 @@ export class DatabaseKeyStore implements KeyStore {
|
||||
}
|
||||
|
||||
async removeKeys(kids: string[]): Promise<void> {
|
||||
await this.database(TABLE).delete().whereIn('kid', kids);
|
||||
await this.client(TABLE).delete().whereIn('kid', kids);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,9 +53,7 @@ export class KeyStores {
|
||||
throw new Error('This KeyStore provider requires a database');
|
||||
}
|
||||
|
||||
return await DatabaseKeyStore.create({
|
||||
database: await database.getClient(),
|
||||
});
|
||||
return await DatabaseKeyStore.create({ database });
|
||||
}
|
||||
|
||||
if (provider === 'memory') {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
```ts
|
||||
/// <reference types="node" />
|
||||
|
||||
import { BackendRegistrable } from '@backstage/backend-plugin-api';
|
||||
import { BackendFeature } from '@backstage/backend-plugin-api';
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
import { CatalogEntityDocument } from '@backstage/plugin-catalog-common';
|
||||
import { CatalogProcessor } from '@backstage/plugin-catalog-node';
|
||||
@@ -224,7 +224,7 @@ export type CatalogPermissionRule<TParams extends unknown[] = unknown[]> =
|
||||
PermissionRule<Entity, EntitiesSearchFilter, 'catalog-entity', TParams>;
|
||||
|
||||
// @alpha
|
||||
export const catalogPlugin: (option: unknown) => BackendRegistrable;
|
||||
export const catalogPlugin: (options?: unknown) => BackendFeature;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface CatalogProcessingEngine {
|
||||
|
||||
@@ -27,7 +27,7 @@ import { CatalogBuilder } from './CatalogBuilder';
|
||||
import {
|
||||
CatalogProcessor,
|
||||
CatalogProcessingExtensionPoint,
|
||||
catalogProcessingExtentionPoint,
|
||||
catalogProcessingExtensionPoint,
|
||||
EntityProvider,
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
|
||||
@@ -62,7 +62,7 @@ export const catalogPlugin = createBackendPlugin({
|
||||
const processingExtensions = new CatalogExtensionPointImpl();
|
||||
// plugins depending on this API will be initialized before this plugins init method is executed.
|
||||
env.registerExtensionPoint(
|
||||
catalogProcessingExtentionPoint,
|
||||
catalogProcessingExtensionPoint,
|
||||
processingExtensions,
|
||||
);
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
import { CompoundEntityRef } from '@backstage/catalog-model';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { ExtensionPoint } from '@backstage/backend-plugin-api';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
import { ServiceRef } from '@backstage/backend-plugin-api';
|
||||
|
||||
// @alpha (undocumented)
|
||||
export interface CatalogProcessingExtensionPoint {
|
||||
@@ -19,7 +19,7 @@ export interface CatalogProcessingExtensionPoint {
|
||||
}
|
||||
|
||||
// @alpha (undocumented)
|
||||
export const catalogProcessingExtentionPoint: ServiceRef<CatalogProcessingExtensionPoint>;
|
||||
export const catalogProcessingExtensionPoint: ExtensionPoint<CatalogProcessingExtensionPoint>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type CatalogProcessor = {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { createServiceRef } from '@backstage/backend-plugin-api';
|
||||
import { createExtensionPoint } from '@backstage/backend-plugin-api';
|
||||
import { EntityProvider } from './api';
|
||||
import { CatalogProcessor } from './api/processor';
|
||||
|
||||
@@ -28,7 +28,7 @@ export interface CatalogProcessingExtensionPoint {
|
||||
/**
|
||||
* @alpha
|
||||
*/
|
||||
export const catalogProcessingExtentionPoint =
|
||||
createServiceRef<CatalogProcessingExtensionPoint>({
|
||||
export const catalogProcessingExtensionPoint =
|
||||
createExtensionPoint<CatalogProcessingExtensionPoint>({
|
||||
id: 'catalog.processing',
|
||||
});
|
||||
|
||||
@@ -21,6 +21,6 @@
|
||||
*/
|
||||
|
||||
export type { CatalogProcessingExtensionPoint } from './extensions';
|
||||
export { catalogProcessingExtentionPoint } from './extensions';
|
||||
export { catalogProcessingExtensionPoint } from './extensions';
|
||||
export * from './api';
|
||||
export * from './processing';
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import { ApiRef } from '@backstage/core-plugin-api';
|
||||
import { BackstagePlugin } from '@backstage/core-plugin-api';
|
||||
import { DiscoveryApi } from '@backstage/core-plugin-api';
|
||||
import { FetchApi } from '@backstage/core-plugin-api';
|
||||
import { RouteRef } from '@backstage/core-plugin-api';
|
||||
|
||||
// Warning: (ae-missing-release-tag) "CodeClimateApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
@@ -74,7 +75,8 @@ export const mockData: CodeClimateData;
|
||||
//
|
||||
// @public (undocumented)
|
||||
export class ProductionCodeClimateApi implements CodeClimateApi {
|
||||
constructor(discoveryApi: DiscoveryApi);
|
||||
// Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts
|
||||
constructor(options: Options);
|
||||
// (undocumented)
|
||||
fetchAllData(options: {
|
||||
apiUrl: string;
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
CodeClimateIssuesData,
|
||||
} from './code-climate-data';
|
||||
import { CodeClimateApi } from './code-climate-api';
|
||||
import { DiscoveryApi } from '@backstage/core-plugin-api';
|
||||
import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';
|
||||
import { Duration } from 'luxon';
|
||||
import humanizeDuration from 'humanize-duration';
|
||||
|
||||
@@ -34,8 +34,19 @@ const codeSmellsQuery = `${basicIssuesOptions}&${categoriesFilter}=Complexity`;
|
||||
const duplicationQuery = `${basicIssuesOptions}&${categoriesFilter}=Duplication`;
|
||||
const otherIssuesQuery = `${basicIssuesOptions}&${categoriesFilter}=Bug%20Risk`;
|
||||
|
||||
type Options = {
|
||||
discoveryApi: DiscoveryApi;
|
||||
fetchApi: FetchApi;
|
||||
};
|
||||
|
||||
export class ProductionCodeClimateApi implements CodeClimateApi {
|
||||
constructor(private readonly discoveryApi: DiscoveryApi) {}
|
||||
private readonly discoveryApi: DiscoveryApi;
|
||||
private readonly fetchApi: FetchApi;
|
||||
|
||||
constructor(options: Options) {
|
||||
this.discoveryApi = options.discoveryApi;
|
||||
this.fetchApi = options.fetchApi;
|
||||
}
|
||||
|
||||
async fetchAllData(options: {
|
||||
apiUrl: string;
|
||||
@@ -44,7 +55,6 @@ export class ProductionCodeClimateApi implements CodeClimateApi {
|
||||
testReportID: string;
|
||||
}): Promise<any> {
|
||||
const { apiUrl, repoID, snapshotID, testReportID } = options;
|
||||
|
||||
const [
|
||||
maintainabilityResponse,
|
||||
testCoverageResponse,
|
||||
@@ -52,15 +62,19 @@ export class ProductionCodeClimateApi implements CodeClimateApi {
|
||||
duplicationResponse,
|
||||
otherIssuesResponse,
|
||||
] = await Promise.all([
|
||||
await fetch(`${apiUrl}/repos/${repoID}/snapshots/${snapshotID}`),
|
||||
await fetch(`${apiUrl}/repos/${repoID}/test_reports/${testReportID}`),
|
||||
await fetch(
|
||||
await this.fetchApi.fetch(
|
||||
`${apiUrl}/repos/${repoID}/snapshots/${snapshotID}`,
|
||||
),
|
||||
await this.fetchApi.fetch(
|
||||
`${apiUrl}/repos/${repoID}/test_reports/${testReportID}`,
|
||||
),
|
||||
await this.fetchApi.fetch(
|
||||
`${apiUrl}/repos/${repoID}/snapshots/${snapshotID}/issues?${codeSmellsQuery}`,
|
||||
),
|
||||
await fetch(
|
||||
await this.fetchApi.fetch(
|
||||
`${apiUrl}/repos/${repoID}/snapshots/${snapshotID}/issues?${duplicationQuery}`,
|
||||
),
|
||||
await fetch(
|
||||
await this.fetchApi.fetch(
|
||||
`${apiUrl}/repos/${repoID}/snapshots/${snapshotID}/issues?${otherIssuesQuery}`,
|
||||
),
|
||||
]);
|
||||
@@ -109,7 +123,7 @@ export class ProductionCodeClimateApi implements CodeClimateApi {
|
||||
'proxy',
|
||||
)}/codeclimate/api`;
|
||||
|
||||
const repoResponse = await fetch(`${apiUrl}/repos/${repoID}`);
|
||||
const repoResponse = await this.fetchApi.fetch(`${apiUrl}/repos/${repoID}`);
|
||||
|
||||
if (!repoResponse.ok) {
|
||||
throw new Error('Failed fetching Code Climate info');
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
createPlugin,
|
||||
createRouteRef,
|
||||
discoveryApiRef,
|
||||
identityApiRef,
|
||||
fetchApiRef,
|
||||
createComponentExtension,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
@@ -37,9 +37,10 @@ export const codeClimatePlugin = createPlugin({
|
||||
api: codeClimateApiRef,
|
||||
deps: {
|
||||
discoveryApi: discoveryApiRef,
|
||||
identityApi: identityApiRef,
|
||||
fetchApi: fetchApiRef,
|
||||
},
|
||||
factory: ({ discoveryApi }) => new ProductionCodeClimateApi(discoveryApi),
|
||||
factory: ({ discoveryApi, fetchApi }) =>
|
||||
new ProductionCodeClimateApi({ discoveryApi, fetchApi }),
|
||||
}),
|
||||
],
|
||||
routes: {
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
"prepack": "backstage-cli package prepack",
|
||||
"postpack": "backstage-cli package postpack"
|
||||
},
|
||||
"prettier": "@spotify/prettier-config",
|
||||
"dependencies": {
|
||||
"@backstage/catalog-model": "^1.0.3",
|
||||
"@backstage/core-components": "^0.11.0-next.2",
|
||||
@@ -44,7 +43,6 @@
|
||||
"@backstage/core-app-api": "^1.0.5-next.0",
|
||||
"@backstage/dev-utils": "^1.0.5-next.1",
|
||||
"@backstage/test-utils": "^1.1.3-next.0",
|
||||
"@spotify/prettier-config": "^14.0.0",
|
||||
"@testing-library/jest-dom": "^5.10.1",
|
||||
"@testing-library/react": "^12.1.3",
|
||||
"@testing-library/user-event": "^14.0.0",
|
||||
@@ -52,8 +50,7 @@
|
||||
"@types/node": "*",
|
||||
"@types/react": "^16.13.1 || ^17.0.0",
|
||||
"cross-fetch": "^3.1.5",
|
||||
"msw": "^0.44.0",
|
||||
"prettier": "^2.7.1"
|
||||
"msw": "^0.44.0"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
|
||||
@@ -22,7 +22,9 @@ import { GraphQLEndpoint } from '../../lib/api';
|
||||
import { BackstageTheme } from '@backstage/theme';
|
||||
import { Progress } from '@backstage/core-components';
|
||||
|
||||
const GraphiQL = React.lazy(() => import('graphiql'));
|
||||
const GraphiQL = React.lazy(() =>
|
||||
import('graphiql').then(m => ({ default: m.GraphiQL })),
|
||||
);
|
||||
|
||||
const useStyles = makeStyles<BackstageTheme>(theme => ({
|
||||
root: {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
```ts
|
||||
/// <reference types="node" />
|
||||
|
||||
import { BackendRegistrable } from '@backstage/backend-plugin-api';
|
||||
import { BackendFeature } from '@backstage/backend-plugin-api';
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
import { CatalogProcessor } from '@backstage/plugin-catalog-backend';
|
||||
import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend';
|
||||
@@ -566,7 +566,7 @@ export type RunCommandOptions = {
|
||||
};
|
||||
|
||||
// @alpha
|
||||
export const scaffolderCatalogModule: (option: unknown) => BackendRegistrable;
|
||||
export const scaffolderCatalogModule: (options?: unknown) => BackendFeature;
|
||||
|
||||
// @public (undocumented)
|
||||
export class ScaffolderEntitiesProcessor implements CatalogProcessor {
|
||||
|
||||
@@ -14,27 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BackendInitRegistry } from '@backstage/backend-plugin-api';
|
||||
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node';
|
||||
import { ScaffolderEntitiesProcessor } from '../processor';
|
||||
import { scaffolderCatalogModule } from './ScaffolderCatalogModule';
|
||||
import { startTestBackend } from '@backstage/backend-test-utils';
|
||||
|
||||
describe('ScaffolderCatalogModule', () => {
|
||||
it('should register the extension point', () => {
|
||||
// TODO(jhaals): clean this up and add test helpers for backend system.
|
||||
const ext = scaffolderCatalogModule({});
|
||||
expect(ext.id).toBe('catalog.scaffolder.module');
|
||||
const registry: jest.Mocked<BackendInitRegistry> = {
|
||||
registerInit: jest.fn(),
|
||||
} as any;
|
||||
ext.register(registry);
|
||||
|
||||
const extensionPoint = {
|
||||
addProcessor: jest.fn(),
|
||||
};
|
||||
|
||||
registry.registerInit.mock.calls[0][0].init({
|
||||
catalogProcessingExtensionPoint: extensionPoint,
|
||||
it('should register the extension point', async () => {
|
||||
const extensionPoint = { addProcessor: jest.fn() };
|
||||
await startTestBackend({
|
||||
extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]],
|
||||
features: [scaffolderCatalogModule({})],
|
||||
});
|
||||
|
||||
expect(extensionPoint.addProcessor).toHaveBeenCalledWith(
|
||||
new ScaffolderEntitiesProcessor(),
|
||||
);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { createBackendModule } from '@backstage/backend-plugin-api';
|
||||
import { catalogProcessingExtentionPoint } from '@backstage/plugin-catalog-node';
|
||||
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node';
|
||||
import { ScaffolderEntitiesProcessor } from '../processor';
|
||||
|
||||
/**
|
||||
@@ -27,12 +27,10 @@ export const scaffolderCatalogModule = createBackendModule({
|
||||
register(env) {
|
||||
env.registerInit({
|
||||
deps: {
|
||||
catalogProcessingExtensionPoint: catalogProcessingExtentionPoint,
|
||||
catalog: catalogProcessingExtensionPoint,
|
||||
},
|
||||
async init({ catalogProcessingExtensionPoint }) {
|
||||
catalogProcessingExtensionPoint.addProcessor(
|
||||
new ScaffolderEntitiesProcessor(),
|
||||
);
|
||||
async init({ catalog }) {
|
||||
catalog.addProcessor(new ScaffolderEntitiesProcessor());
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
@@ -267,6 +267,57 @@ describe('createRouter', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should not throw when an invalid authorization header is passed', async () => {
|
||||
const broker = taskBroker.dispatch as jest.Mocked<TaskBroker>['dispatch'];
|
||||
const mockToken = 'blob.eyJzdWIiOiIiLCJuYW1lIjoiSm9obiBEb2UifQ.blob';
|
||||
|
||||
await request(app)
|
||||
.post('/v2/tasks')
|
||||
.set('Authorization', `Bearer ${mockToken}`)
|
||||
.send({
|
||||
templateRef: stringifyEntityRef({
|
||||
kind: 'template',
|
||||
name: 'create-react-app-template',
|
||||
}),
|
||||
values: {
|
||||
required: 'required-value',
|
||||
},
|
||||
});
|
||||
expect(broker).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
createdBy: undefined,
|
||||
secrets: {
|
||||
backstageToken: undefined,
|
||||
},
|
||||
|
||||
spec: {
|
||||
apiVersion: mockTemplate.apiVersion,
|
||||
steps: mockTemplate.spec.steps.map((step, index) => ({
|
||||
...step,
|
||||
id: step.id ?? `step-${index + 1}`,
|
||||
name: step.name ?? step.action,
|
||||
})),
|
||||
output: mockTemplate.spec.output ?? {},
|
||||
parameters: {
|
||||
required: 'required-value',
|
||||
},
|
||||
user: {
|
||||
entity: undefined,
|
||||
ref: undefined,
|
||||
},
|
||||
templateInfo: {
|
||||
entityRef: stringifyEntityRef({
|
||||
kind: 'Template',
|
||||
namespace: 'Default',
|
||||
name: mockTemplate.metadata?.name,
|
||||
}),
|
||||
baseUrl: 'https://dev.azure.com',
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should not decorate a user when no backstage auth is passed', async () => {
|
||||
const broker = taskBroker.dispatch as jest.Mocked<TaskBroker>['dispatch'];
|
||||
|
||||
|
||||
@@ -146,7 +146,10 @@ export async function createRouter(
|
||||
'/v2/templates/:namespace/:kind/:name/parameter-schema',
|
||||
async (req, res) => {
|
||||
const { namespace, kind, name } = req.params;
|
||||
const { token } = parseBearerToken(req.headers.authorization);
|
||||
const { token } = parseBearerToken({
|
||||
header: req.headers.authorization,
|
||||
logger,
|
||||
});
|
||||
const template = await findTemplate({
|
||||
catalogApi: catalogClient,
|
||||
entityRef: { kind, namespace, name },
|
||||
@@ -187,9 +190,10 @@ export async function createRouter(
|
||||
const { kind, namespace, name } = parseEntityRef(templateRef, {
|
||||
defaultKind: 'template',
|
||||
});
|
||||
const { token, entityRef: userEntityRef } = parseBearerToken(
|
||||
req.headers.authorization,
|
||||
);
|
||||
const { token, entityRef: userEntityRef } = parseBearerToken({
|
||||
header: req.headers.authorization,
|
||||
logger,
|
||||
});
|
||||
|
||||
const userEntity = userEntityRef
|
||||
? await catalogClient.getEntityByRef(userEntityRef, { token })
|
||||
@@ -389,7 +393,10 @@ export async function createRouter(
|
||||
throw new InputError('Input template is not a template');
|
||||
}
|
||||
|
||||
const { token } = parseBearerToken(req.headers.authorization);
|
||||
const { token } = parseBearerToken({
|
||||
header: req.headers.authorization,
|
||||
logger,
|
||||
});
|
||||
|
||||
for (const parameters of [template.spec.parameters ?? []].flat()) {
|
||||
const result = validate(body.values, parameters);
|
||||
@@ -440,7 +447,13 @@ export async function createRouter(
|
||||
return app;
|
||||
}
|
||||
|
||||
function parseBearerToken(header?: string): {
|
||||
function parseBearerToken({
|
||||
header,
|
||||
logger,
|
||||
}: {
|
||||
header?: string;
|
||||
logger: Logger;
|
||||
}): {
|
||||
token?: string;
|
||||
entityRef?: string;
|
||||
} {
|
||||
@@ -472,8 +485,12 @@ function parseBearerToken(header?: string): {
|
||||
throw new TypeError('Expected string sub claim');
|
||||
}
|
||||
|
||||
// Check that it's a valid ref, otherwise this will throw.
|
||||
parseEntityRef(sub);
|
||||
|
||||
return { entityRef: sub, token };
|
||||
} catch (e) {
|
||||
throw new InputError(`Invalid authorization header: ${stringifyError(e)}`);
|
||||
logger.error(`Invalid authorization header: ${stringifyError(e)}`);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user