Merge branch 'master' into feat/githubMultiOrgReaderProcessor
This commit is contained in:
@@ -1,5 +1,36 @@
|
||||
# @backstage/plugin-api-docs
|
||||
|
||||
## 0.6.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- d719926d2: **BREAKING CHANGE** Remove deprecated route registrations, meaning that it is no longer enough to only import the plugin in the app and the exported page extension must be used instead.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 48c9fcd33: Migrated to use the new `@backstage/core-*` packages rather than `@backstage/core`.
|
||||
- 7bd46b19d: Move `EntityTypePicker` to be consistent with `CatalogPage` and remove `api:` prefix from entity names
|
||||
- Updated dependencies
|
||||
- @backstage/plugin-catalog@0.6.4
|
||||
- @backstage/core-plugin-api@0.1.3
|
||||
- @backstage/catalog-model@0.8.4
|
||||
- @backstage/plugin-catalog-react@0.2.4
|
||||
|
||||
## 0.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 2ebc430c4: Rework `ApiExplorerPage` to utilize `EntityListProvider` to provide a consistent UI with the `CatalogIndexPage` which now exposes support for starring entities, pagination, and customizing columns.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 14ce64b4f: Add pagination to ApiExplorerTable
|
||||
- Updated dependencies
|
||||
- @backstage/plugin-catalog-react@0.2.3
|
||||
- @backstage/plugin-catalog@0.6.3
|
||||
- @backstage/catalog-model@0.8.3
|
||||
- @backstage/core@0.7.13
|
||||
|
||||
## 0.4.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
## API Report File for "@backstage/plugin-api-docs"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
|
||||
import { ApiEntity } from '@backstage/catalog-model';
|
||||
import { ApiRef } from '@backstage/core-plugin-api';
|
||||
import { BackstagePlugin } from '@backstage/core-plugin-api';
|
||||
import { CatalogTableRow } from '@backstage/plugin-catalog';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { ExternalRouteRef } from '@backstage/core-plugin-api';
|
||||
import { default as React_2 } from 'react';
|
||||
import { RouteRef } from '@backstage/core-plugin-api';
|
||||
import { TableColumn } from '@backstage/core-components';
|
||||
import { UserListFilterKind } from '@backstage/plugin-catalog-react';
|
||||
|
||||
// @public (undocumented)
|
||||
export const ApiDefinitionCard: (_: Props) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export type ApiDefinitionWidget = {
|
||||
type: string;
|
||||
title: string;
|
||||
component: (definition: string) => React_2.ReactElement;
|
||||
rawLanguage?: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export const apiDocsConfigRef: ApiRef<ApiDocsConfig>;
|
||||
|
||||
// @public (undocumented)
|
||||
const apiDocsPlugin: BackstagePlugin<{
|
||||
root: RouteRef<undefined>;
|
||||
}, {
|
||||
createComponent: ExternalRouteRef<undefined, true>;
|
||||
}>;
|
||||
|
||||
export { apiDocsPlugin }
|
||||
|
||||
export { apiDocsPlugin as plugin }
|
||||
|
||||
// @public (undocumented)
|
||||
export const ApiExplorerPage: ({ initiallySelectedFilter, columns, }: ApiExplorerPageProps) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export const ApiTypeTitle: ({ apiEntity }: {
|
||||
apiEntity: ApiEntity;
|
||||
}) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export const AsyncApiDefinitionWidget: ({ definition }: Props_5) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export const ConsumedApisCard: ({ variant }: Props_2) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export const ConsumingComponentsCard: ({ variant }: Props_6) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export function defaultDefinitionWidgets(): ApiDefinitionWidget[];
|
||||
|
||||
// @public (undocumented)
|
||||
export const EntityApiDefinitionCard: (_: {
|
||||
apiEntity?: ApiEntity | undefined;
|
||||
}) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export const EntityConsumedApisCard: ({ variant }: {
|
||||
entity?: Entity| undefined;
|
||||
variant?: "gridItem" | undefined;
|
||||
}) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export const EntityConsumingComponentsCard: ({ variant }: {
|
||||
entity?: Entity| undefined;
|
||||
variant?: "gridItem" | undefined;
|
||||
}) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export const EntityHasApisCard: ({ variant }: {
|
||||
variant?: "gridItem" | undefined;
|
||||
}) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export const EntityProvidedApisCard: ({ variant }: {
|
||||
entity?: Entity| undefined;
|
||||
variant?: "gridItem" | undefined;
|
||||
}) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export const EntityProvidingComponentsCard: ({ variant }: {
|
||||
entity?: Entity| undefined;
|
||||
variant?: "gridItem" | undefined;
|
||||
}) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export const HasApisCard: ({ variant }: Props_3) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export const OpenApiDefinitionWidget: ({ definition }: Props_8) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export const PlainApiDefinitionWidget: ({ definition, language }: Props_9) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export const ProvidedApisCard: ({ variant }: Props_4) => JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export const ProvidingComponentsCard: ({ variant }: Props_7) => JSX.Element;
|
||||
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
|
||||
```
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
import { ApiEntity, Entity } from '@backstage/catalog-model';
|
||||
import { Content, Header, Page } from '@backstage/core';
|
||||
import { createDevApp } from '@backstage/dev-utils';
|
||||
import { catalogApiRef, EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import React from 'react';
|
||||
@@ -29,6 +28,14 @@ import asyncapiApiEntity from './asyncapi-example-api.yaml';
|
||||
import graphqlApiEntity from './graphql-example-api.yaml';
|
||||
import openapiApiEntity from './openapi-example-api.yaml';
|
||||
import otherApiEntity from './other-example-api.yaml';
|
||||
import { Content, Header, Page } from '@backstage/core-components';
|
||||
|
||||
const mockEntities = ([
|
||||
openapiApiEntity,
|
||||
asyncapiApiEntity,
|
||||
graphqlApiEntity,
|
||||
otherApiEntity,
|
||||
] as unknown) as Entity[];
|
||||
|
||||
createDevApp()
|
||||
.registerApi({
|
||||
@@ -38,14 +45,12 @@ createDevApp()
|
||||
(({
|
||||
async getEntities() {
|
||||
return {
|
||||
items: [
|
||||
openapiApiEntity,
|
||||
asyncapiApiEntity,
|
||||
graphqlApiEntity,
|
||||
otherApiEntity,
|
||||
],
|
||||
items: mockEntities.slice(),
|
||||
};
|
||||
},
|
||||
async getEntityByName(name: string) {
|
||||
return mockEntities.find(e => e.metadata.name === name);
|
||||
},
|
||||
} as unknown) as typeof catalogApiRef.T),
|
||||
})
|
||||
.registerApi({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-api-docs",
|
||||
"version": "0.4.15",
|
||||
"version": "0.6.0",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
@@ -30,9 +30,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@asyncapi/react-component": "^0.23.0",
|
||||
"@backstage/catalog-model": "^0.8.2",
|
||||
"@backstage/core": "^0.7.11",
|
||||
"@backstage/plugin-catalog-react": "^0.2.2",
|
||||
"@backstage/catalog-model": "^0.8.4",
|
||||
"@backstage/core-components": "^0.1.3",
|
||||
"@backstage/core-plugin-api": "^0.1.3",
|
||||
"@backstage/plugin-catalog": "^0.6.4",
|
||||
"@backstage/plugin-catalog-react": "^0.2.4",
|
||||
"@backstage/theme": "^0.2.8",
|
||||
"@material-icons/font": "^1.0.2",
|
||||
"@material-ui/core": "^4.11.0",
|
||||
@@ -49,9 +51,10 @@
|
||||
"swagger-ui-react": "^3.37.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.7.0",
|
||||
"@backstage/dev-utils": "^0.1.17",
|
||||
"@backstage/test-utils": "^0.1.13",
|
||||
"@backstage/cli": "^0.7.2",
|
||||
"@backstage/core-app-api": "^0.1.3",
|
||||
"@backstage/dev-utils": "^0.2.0",
|
||||
"@backstage/test-utils": "^0.1.14",
|
||||
"@testing-library/jest-dom": "^5.10.1",
|
||||
"@testing-library/react": "^11.2.5",
|
||||
"@testing-library/user-event": "^13.1.8",
|
||||
@@ -59,7 +62,7 @@
|
||||
"@types/node": "^14.14.32",
|
||||
"@types/swagger-ui-react": "^3.23.3",
|
||||
"cross-fetch": "^3.0.6",
|
||||
"msw": "^0.21.2"
|
||||
"msw": "^0.29.0"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
import { ApiEntity } from '@backstage/catalog-model';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { waitFor } from '@testing-library/react';
|
||||
@@ -23,6 +22,7 @@ import React from 'react';
|
||||
import { ApiDocsConfig, apiDocsConfigRef } from '../../config';
|
||||
import { OpenApiDefinitionWidget } from '../OpenApiDefinitionWidget';
|
||||
import { ApiDefinitionCard } from './ApiDefinitionCard';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
|
||||
|
||||
describe('<ApiDefinitionCard />', () => {
|
||||
const apiDocsConfig: jest.Mocked<ApiDocsConfig> = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
|
||||
import { ApiEntity } from '@backstage/catalog-model';
|
||||
import { CardTab, TabbedCard, useApi } from '@backstage/core';
|
||||
import { useEntity } from '@backstage/plugin-catalog-react';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import React from 'react';
|
||||
import { apiDocsConfigRef } from '../../config';
|
||||
import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget';
|
||||
|
||||
import { CardTab, TabbedCard } from '@backstage/core-components';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
|
||||
type Props = {
|
||||
/** @deprecated The entity is now grabbed from context instead */
|
||||
apiEntity?: ApiEntity;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -15,11 +15,11 @@
|
||||
*/
|
||||
|
||||
import { ApiEntity } from '@backstage/catalog-model';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import React from 'react';
|
||||
import { ApiDocsConfig, apiDocsConfigRef } from '../../config';
|
||||
import { ApiTypeTitle } from './ApiTypeTitle';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
|
||||
|
||||
describe('<ApiTypeTitle />', () => {
|
||||
const apiDocsConfig: jest.Mocked<ApiDocsConfig> = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -15,9 +15,9 @@
|
||||
*/
|
||||
|
||||
import { ApiEntity } from '@backstage/catalog-model';
|
||||
import { useApi } from '@backstage/core';
|
||||
import React from 'react';
|
||||
import { apiDocsConfigRef } from '../../config';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
|
||||
export const ApiTypeTitle = ({ apiEntity }: { apiEntity: ApiEntity }) => {
|
||||
const config = useApi(apiDocsConfigRef);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -14,9 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Header, Page, useApi, configApiRef } from '@backstage/core';
|
||||
import React from 'react';
|
||||
|
||||
import { Header, Page } from '@backstage/core-components';
|
||||
import { useApi, configApiRef } from '@backstage/core-plugin-api';
|
||||
|
||||
type Props = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -14,15 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import {
|
||||
ApiProvider,
|
||||
ApiRegistry,
|
||||
storageApiRef,
|
||||
ConfigApi,
|
||||
configApiRef,
|
||||
ConfigReader,
|
||||
} from '@backstage/core';
|
||||
import { Entity, RELATION_MEMBER_OF } from '@backstage/catalog-model';
|
||||
import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react';
|
||||
import { MockStorageApi, wrapInTestApp } from '@backstage/test-utils';
|
||||
import { render } from '@testing-library/react';
|
||||
@@ -30,6 +22,17 @@ import React from 'react';
|
||||
import { apiDocsConfigRef } from '../../config';
|
||||
import { ApiExplorerPage } from './ApiExplorerPage';
|
||||
|
||||
import {
|
||||
ApiProvider,
|
||||
ApiRegistry,
|
||||
ConfigReader,
|
||||
} from '@backstage/core-app-api';
|
||||
import {
|
||||
storageApiRef,
|
||||
ConfigApi,
|
||||
configApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
describe('ApiCatalogPage', () => {
|
||||
const catalogApi: Partial<CatalogApi> = {
|
||||
getEntities: () =>
|
||||
@@ -55,6 +58,19 @@ describe('ApiCatalogPage', () => {
|
||||
}),
|
||||
getLocationByEntity: () =>
|
||||
Promise.resolve({ id: 'id', type: 'github', target: 'url' }),
|
||||
getEntityByName: async entityName => {
|
||||
return {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'User',
|
||||
metadata: { name: entityName.name },
|
||||
relations: [
|
||||
{
|
||||
type: RELATION_MEMBER_OF,
|
||||
target: { namespace: 'default', kind: 'Group', name: 'tools' },
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
const configApi: ConfigApi = new ConfigReader({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -14,40 +14,61 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
EntityKindPicker,
|
||||
EntityLifecyclePicker,
|
||||
EntityListProvider,
|
||||
EntityOwnerPicker,
|
||||
EntityTagPicker,
|
||||
EntityTypePicker,
|
||||
UserListFilterKind,
|
||||
UserListPicker,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { CatalogTable, CatalogTableRow } from '@backstage/plugin-catalog';
|
||||
import { Button, makeStyles } from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import { createComponentRouteRef } from '../../routes';
|
||||
import { ApiExplorerLayout } from './ApiExplorerLayout';
|
||||
|
||||
import {
|
||||
Content,
|
||||
ContentHeader,
|
||||
SupportButton,
|
||||
useApi,
|
||||
useRouteRef,
|
||||
} from '@backstage/core';
|
||||
import { catalogApiRef } from '@backstage/plugin-catalog-react';
|
||||
import { Button } from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import { useAsync } from 'react-use';
|
||||
import { createComponentRouteRef } from '../../routes';
|
||||
import { ApiExplorerTable } from '../ApiExplorerTable';
|
||||
import { ApiExplorerLayout } from './ApiExplorerLayout';
|
||||
TableColumn,
|
||||
} from '@backstage/core-components';
|
||||
import { useRouteRef } from '@backstage/core-plugin-api';
|
||||
|
||||
export const ApiExplorerPage = () => {
|
||||
const useStyles = makeStyles(theme => ({
|
||||
contentWrapper: {
|
||||
display: 'grid',
|
||||
gridTemplateAreas: "'filters' 'table'",
|
||||
gridTemplateColumns: '250px 1fr',
|
||||
gridColumnGap: theme.spacing(2),
|
||||
},
|
||||
}));
|
||||
|
||||
const defaultColumns: TableColumn<CatalogTableRow>[] = [
|
||||
CatalogTable.columns.createNameColumn({ defaultKind: 'API' }),
|
||||
CatalogTable.columns.createSystemColumn(),
|
||||
CatalogTable.columns.createOwnerColumn(),
|
||||
CatalogTable.columns.createSpecTypeColumn(),
|
||||
CatalogTable.columns.createSpecLifecycleColumn(),
|
||||
CatalogTable.columns.createMetadataDescriptionColumn(),
|
||||
CatalogTable.columns.createTagsColumn(),
|
||||
];
|
||||
|
||||
export type ApiExplorerPageProps = {
|
||||
initiallySelectedFilter?: UserListFilterKind;
|
||||
columns?: TableColumn<CatalogTableRow>[];
|
||||
};
|
||||
|
||||
export const ApiExplorerPage = ({
|
||||
initiallySelectedFilter = 'all',
|
||||
columns,
|
||||
}: ApiExplorerPageProps) => {
|
||||
const styles = useStyles();
|
||||
const createComponentLink = useRouteRef(createComponentRouteRef);
|
||||
const catalogApi = useApi(catalogApiRef);
|
||||
const { loading, error, value: catalogResponse } = useAsync(() => {
|
||||
return catalogApi.getEntities({
|
||||
filter: { kind: 'API' },
|
||||
fields: [
|
||||
'apiVersion',
|
||||
'kind',
|
||||
'metadata',
|
||||
'relations',
|
||||
'spec.lifecycle',
|
||||
'spec.owner',
|
||||
'spec.type',
|
||||
'spec.system',
|
||||
],
|
||||
});
|
||||
}, [catalogApi]);
|
||||
|
||||
return (
|
||||
<ApiExplorerLayout>
|
||||
@@ -65,11 +86,19 @@ export const ApiExplorerPage = () => {
|
||||
)}
|
||||
<SupportButton>All your APIs</SupportButton>
|
||||
</ContentHeader>
|
||||
<ApiExplorerTable
|
||||
entities={catalogResponse?.items ?? []}
|
||||
loading={loading}
|
||||
error={error}
|
||||
/>
|
||||
<div className={styles.contentWrapper}>
|
||||
<EntityListProvider>
|
||||
<div>
|
||||
<EntityKindPicker initialFilter="api" hidden />
|
||||
<EntityTypePicker />
|
||||
<UserListPicker initialFilter={initiallySelectedFilter} />
|
||||
<EntityOwnerPicker />
|
||||
<EntityLifecyclePicker />
|
||||
<EntityTagPicker />
|
||||
</div>
|
||||
<CatalogTable columns={columns || defaultColumns} />
|
||||
</EntityListProvider>
|
||||
</div>
|
||||
</Content>
|
||||
</ApiExplorerLayout>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 { Entity } from '@backstage/catalog-model';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core';
|
||||
import { wrapInTestApp } from '@backstage/test-utils';
|
||||
import { render } from '@testing-library/react';
|
||||
import * as React from 'react';
|
||||
import { apiDocsConfigRef } from '../../config';
|
||||
import { ApiExplorerTable } from './ApiExplorerTable';
|
||||
|
||||
const entities: Entity[] = [
|
||||
{
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'API',
|
||||
metadata: { name: 'api1' },
|
||||
spec: { type: 'openapi' },
|
||||
},
|
||||
{
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'API',
|
||||
metadata: { name: 'api2' },
|
||||
spec: { type: 'openapi' },
|
||||
},
|
||||
{
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'API',
|
||||
metadata: { name: 'api3' },
|
||||
spec: { type: 'grpc' },
|
||||
},
|
||||
];
|
||||
|
||||
const apiRegistry = ApiRegistry.with(apiDocsConfigRef, {
|
||||
getApiDefinitionWidget: () => undefined,
|
||||
});
|
||||
|
||||
describe('ApiCatalogTable component', () => {
|
||||
it('should render error message when error is passed in props', async () => {
|
||||
const rendered = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apiRegistry}>
|
||||
<ApiExplorerTable
|
||||
entities={[]}
|
||||
loading={false}
|
||||
error={{ code: 'error' }}
|
||||
/>
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
const errorMessage = await rendered.findByText(
|
||||
/Could not fetch catalog entities./,
|
||||
);
|
||||
expect(errorMessage).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display entity names when loading has finished and no error occurred', async () => {
|
||||
const rendered = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apiRegistry}>
|
||||
<ApiExplorerTable entities={entities} loading={false} />
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
expect(rendered.getByText(/api1/)).toBeInTheDocument();
|
||||
expect(rendered.getByText(/api2/)).toBeInTheDocument();
|
||||
expect(rendered.getByText(/api3/)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,214 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 {
|
||||
ApiEntityV1alpha1,
|
||||
Entity,
|
||||
EntityName,
|
||||
RELATION_OWNED_BY,
|
||||
RELATION_PART_OF,
|
||||
} from '@backstage/catalog-model';
|
||||
import {
|
||||
CodeSnippet,
|
||||
OverflowTooltip,
|
||||
Table,
|
||||
TableColumn,
|
||||
TableFilter,
|
||||
TableState,
|
||||
useQueryParamState,
|
||||
WarningPanel,
|
||||
} from '@backstage/core';
|
||||
import {
|
||||
EntityRefLink,
|
||||
EntityRefLinks,
|
||||
formatEntityRefTitle,
|
||||
getEntityRelations,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { Chip } from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { ApiTypeTitle } from '../ApiDefinitionCard';
|
||||
|
||||
type EntityRow = {
|
||||
entity: ApiEntityV1alpha1;
|
||||
resolved: {
|
||||
name: string;
|
||||
partOfSystemRelationTitle?: string;
|
||||
partOfSystemRelations: EntityName[];
|
||||
ownedByRelationsTitle?: string;
|
||||
ownedByRelations: EntityName[];
|
||||
};
|
||||
};
|
||||
|
||||
const columns: TableColumn<EntityRow>[] = [
|
||||
{
|
||||
title: 'Name',
|
||||
field: 'resolved.name',
|
||||
highlight: true,
|
||||
render: ({ entity }) => (
|
||||
<EntityRefLink entityRef={entity} defaultKind="API" />
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'System',
|
||||
field: 'resolved.partOfSystemRelationTitle',
|
||||
render: ({ resolved }) => (
|
||||
<EntityRefLinks
|
||||
entityRefs={resolved.partOfSystemRelations}
|
||||
defaultKind="system"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Owner',
|
||||
field: 'resolved.ownedByRelationsTitle',
|
||||
render: ({ resolved }) => (
|
||||
<EntityRefLinks
|
||||
entityRefs={resolved.ownedByRelations}
|
||||
defaultKind="group"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Lifecycle',
|
||||
field: 'entity.spec.lifecycle',
|
||||
},
|
||||
{
|
||||
title: 'Type',
|
||||
field: 'entity.spec.type',
|
||||
render: ({ entity }) => <ApiTypeTitle apiEntity={entity} />,
|
||||
},
|
||||
{
|
||||
title: 'Description',
|
||||
field: 'entity.metadata.description',
|
||||
render: ({ entity }) => (
|
||||
<OverflowTooltip
|
||||
text={entity.metadata.description}
|
||||
placement="bottom-start"
|
||||
/>
|
||||
),
|
||||
width: 'auto',
|
||||
},
|
||||
{
|
||||
title: 'Tags',
|
||||
field: 'entity.metadata.tags',
|
||||
cellStyle: {
|
||||
padding: '0px 16px 0px 20px',
|
||||
},
|
||||
render: ({ entity }) => (
|
||||
<>
|
||||
{entity.metadata.tags &&
|
||||
entity.metadata.tags.map(t => (
|
||||
<Chip
|
||||
key={t}
|
||||
label={t}
|
||||
size="small"
|
||||
variant="outlined"
|
||||
style={{ marginBottom: '0px' }}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const filters: TableFilter[] = [
|
||||
{
|
||||
column: 'Owner',
|
||||
type: 'select',
|
||||
},
|
||||
{
|
||||
column: 'Type',
|
||||
type: 'multiple-select',
|
||||
},
|
||||
{
|
||||
column: 'Lifecycle',
|
||||
type: 'multiple-select',
|
||||
},
|
||||
{
|
||||
column: 'Tags',
|
||||
type: 'checkbox-tree',
|
||||
},
|
||||
];
|
||||
|
||||
type ExplorerTableProps = {
|
||||
entities: Entity[];
|
||||
loading: boolean;
|
||||
error?: any;
|
||||
};
|
||||
|
||||
export const ApiExplorerTable = ({
|
||||
entities,
|
||||
loading,
|
||||
error,
|
||||
}: ExplorerTableProps) => {
|
||||
const [queryParamState, setQueryParamState] = useQueryParamState<TableState>(
|
||||
'apiTable',
|
||||
);
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<WarningPanel severity="error" title="Could not fetch catalog entities.">
|
||||
<CodeSnippet language="text" text={error.toString()} />
|
||||
</WarningPanel>
|
||||
);
|
||||
}
|
||||
|
||||
const rows = entities.map(entity => {
|
||||
const partOfSystemRelations = getEntityRelations(entity, RELATION_PART_OF, {
|
||||
kind: 'system',
|
||||
});
|
||||
const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);
|
||||
|
||||
return {
|
||||
entity: entity as ApiEntityV1alpha1,
|
||||
resolved: {
|
||||
name: formatEntityRefTitle(entity, {
|
||||
defaultKind: 'API',
|
||||
}),
|
||||
ownedByRelationsTitle: ownedByRelations
|
||||
.map(r => formatEntityRefTitle(r, { defaultKind: 'group' }))
|
||||
.join(', '),
|
||||
ownedByRelations,
|
||||
partOfSystemRelationTitle: partOfSystemRelations
|
||||
.map(r =>
|
||||
formatEntityRefTitle(r, {
|
||||
defaultKind: 'system',
|
||||
}),
|
||||
)
|
||||
.join(', '),
|
||||
partOfSystemRelations,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<Table<EntityRow>
|
||||
isLoading={loading}
|
||||
columns={columns}
|
||||
options={{
|
||||
paging: false,
|
||||
actionsColumnIndex: -1,
|
||||
loadingType: 'linear',
|
||||
padding: 'dense',
|
||||
showEmptyDataSourceMessage: !loading,
|
||||
}}
|
||||
data={rows}
|
||||
filters={filters}
|
||||
initialState={queryParamState}
|
||||
onStateChange={setQueryParamState}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
import { Entity, RELATION_CONSUMES_API } from '@backstage/catalog-model';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core';
|
||||
import {
|
||||
CatalogApi,
|
||||
catalogApiRef,
|
||||
@@ -26,6 +25,7 @@ import { waitFor } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { ApiDocsConfig, apiDocsConfigRef } from '../../config';
|
||||
import { ConsumedApisCard } from './ConsumedApisCard';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
|
||||
|
||||
describe('<ConsumedApisCard />', () => {
|
||||
const apiDocsConfig: jest.Mocked<ApiDocsConfig> = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -19,13 +19,6 @@ import {
|
||||
Entity,
|
||||
RELATION_CONSUMES_API,
|
||||
} from '@backstage/catalog-model';
|
||||
import {
|
||||
CodeSnippet,
|
||||
InfoCard,
|
||||
Link,
|
||||
Progress,
|
||||
WarningPanel,
|
||||
} from '@backstage/core';
|
||||
import { Typography } from '@material-ui/core';
|
||||
import {
|
||||
EntityTable,
|
||||
@@ -34,6 +27,13 @@ import {
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import React from 'react';
|
||||
import { apiEntityColumns } from './presets';
|
||||
import {
|
||||
CodeSnippet,
|
||||
InfoCard,
|
||||
Link,
|
||||
Progress,
|
||||
WarningPanel,
|
||||
} from '@backstage/core-components';
|
||||
|
||||
type Props = {
|
||||
/** @deprecated The entity is now grabbed from context instead */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
import { Entity, RELATION_HAS_PART } from '@backstage/catalog-model';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core';
|
||||
import {
|
||||
CatalogApi,
|
||||
catalogApiRef,
|
||||
@@ -26,6 +25,7 @@ import { waitFor } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { ApiDocsConfig, apiDocsConfigRef } from '../../config';
|
||||
import { HasApisCard } from './HasApisCard';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
|
||||
|
||||
describe('<HasApisCard />', () => {
|
||||
const apiDocsConfig: jest.Mocked<ApiDocsConfig> = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -15,14 +15,6 @@
|
||||
*/
|
||||
|
||||
import { ApiEntity, RELATION_HAS_PART } from '@backstage/catalog-model';
|
||||
import {
|
||||
CodeSnippet,
|
||||
InfoCard,
|
||||
Link,
|
||||
Progress,
|
||||
TableColumn,
|
||||
WarningPanel,
|
||||
} from '@backstage/core';
|
||||
import { Typography } from '@material-ui/core';
|
||||
import {
|
||||
EntityTable,
|
||||
@@ -31,6 +23,14 @@ import {
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import React from 'react';
|
||||
import { createSpecApiTypeColumn } from './presets';
|
||||
import {
|
||||
CodeSnippet,
|
||||
InfoCard,
|
||||
Link,
|
||||
Progress,
|
||||
TableColumn,
|
||||
WarningPanel,
|
||||
} from '@backstage/core-components';
|
||||
|
||||
type Props = {
|
||||
variant?: 'gridItem';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
import { Entity, RELATION_PROVIDES_API } from '@backstage/catalog-model';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core';
|
||||
import {
|
||||
CatalogApi,
|
||||
catalogApiRef,
|
||||
@@ -26,6 +25,7 @@ import { waitFor } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { ApiDocsConfig, apiDocsConfigRef } from '../../config';
|
||||
import { ProvidedApisCard } from './ProvidedApisCard';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
|
||||
|
||||
describe('<ProvidedApisCard />', () => {
|
||||
const apiDocsConfig: jest.Mocked<ApiDocsConfig> = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -19,13 +19,6 @@ import {
|
||||
Entity,
|
||||
RELATION_PROVIDES_API,
|
||||
} from '@backstage/catalog-model';
|
||||
import {
|
||||
CodeSnippet,
|
||||
InfoCard,
|
||||
Link,
|
||||
Progress,
|
||||
WarningPanel,
|
||||
} from '@backstage/core';
|
||||
import { Typography } from '@material-ui/core';
|
||||
import {
|
||||
EntityTable,
|
||||
@@ -34,6 +27,13 @@ import {
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import React from 'react';
|
||||
import { apiEntityColumns } from './presets';
|
||||
import {
|
||||
CodeSnippet,
|
||||
InfoCard,
|
||||
Link,
|
||||
Progress,
|
||||
WarningPanel,
|
||||
} from '@backstage/core-components';
|
||||
|
||||
type Props = {
|
||||
/** @deprecated The entity is now grabbed from context instead */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -15,10 +15,10 @@
|
||||
*/
|
||||
|
||||
import { ApiEntity } from '@backstage/catalog-model';
|
||||
import { TableColumn } from '@backstage/core';
|
||||
import { EntityTable } from '@backstage/plugin-catalog-react';
|
||||
import React from 'react';
|
||||
import { ApiTypeTitle } from '../ApiDefinitionCard';
|
||||
import { TableColumn } from '@backstage/core-components';
|
||||
|
||||
export function createSpecApiTypeColumn(): TableColumn<ApiEntity> {
|
||||
return {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
import { Entity, RELATION_API_CONSUMED_BY } from '@backstage/catalog-model';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core';
|
||||
import {
|
||||
CatalogApi,
|
||||
catalogApiRef,
|
||||
@@ -25,6 +24,7 @@ import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { waitFor } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { ConsumingComponentsCard } from './ConsumingComponentsCard';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
|
||||
|
||||
describe('<ConsumingComponentsCard />', () => {
|
||||
const catalogApi: jest.Mocked<CatalogApi> = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -19,13 +19,6 @@ import {
|
||||
Entity,
|
||||
RELATION_API_CONSUMED_BY,
|
||||
} from '@backstage/catalog-model';
|
||||
import {
|
||||
CodeSnippet,
|
||||
InfoCard,
|
||||
Link,
|
||||
Progress,
|
||||
WarningPanel,
|
||||
} from '@backstage/core';
|
||||
import { Typography } from '@material-ui/core';
|
||||
import {
|
||||
EntityTable,
|
||||
@@ -33,6 +26,13 @@ import {
|
||||
useRelatedEntities,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import React from 'react';
|
||||
import {
|
||||
CodeSnippet,
|
||||
InfoCard,
|
||||
Link,
|
||||
Progress,
|
||||
WarningPanel,
|
||||
} from '@backstage/core-components';
|
||||
|
||||
type Props = {
|
||||
/** @deprecated The entity is now grabbed from context instead */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
import { Entity, RELATION_API_PROVIDED_BY } from '@backstage/catalog-model';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core';
|
||||
import {
|
||||
CatalogApi,
|
||||
catalogApiRef,
|
||||
@@ -25,6 +24,7 @@ import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { waitFor } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { ProvidingComponentsCard } from './ProvidingComponentsCard';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
|
||||
|
||||
describe('<ProvidingComponentsCard />', () => {
|
||||
const catalogApi: jest.Mocked<CatalogApi> = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -19,13 +19,6 @@ import {
|
||||
Entity,
|
||||
RELATION_API_PROVIDED_BY,
|
||||
} from '@backstage/catalog-model';
|
||||
import {
|
||||
CodeSnippet,
|
||||
InfoCard,
|
||||
Link,
|
||||
Progress,
|
||||
WarningPanel,
|
||||
} from '@backstage/core';
|
||||
import { Typography } from '@material-ui/core';
|
||||
import {
|
||||
EntityTable,
|
||||
@@ -33,6 +26,13 @@ import {
|
||||
useRelatedEntities,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import React from 'react';
|
||||
import {
|
||||
CodeSnippet,
|
||||
InfoCard,
|
||||
Link,
|
||||
Progress,
|
||||
WarningPanel,
|
||||
} from '@backstage/core-components';
|
||||
|
||||
type Props = {
|
||||
/** @deprecated The entity is now grabbed from context instead */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -14,12 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Progress } from '@backstage/core';
|
||||
import { BackstageTheme } from '@backstage/theme';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import 'graphiql/graphiql.css';
|
||||
import { buildSchema } from 'graphql';
|
||||
import React, { Suspense } from 'react';
|
||||
import { Progress } from '@backstage/core-components';
|
||||
|
||||
const GraphiQL = React.lazy(() => import('graphiql'));
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -14,8 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { CodeSnippet } from '@backstage/core';
|
||||
import React from 'react';
|
||||
import { CodeSnippet } from '@backstage/core-components';
|
||||
|
||||
type Props = {
|
||||
definition: any;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
|
||||
import { ApiEntity } from '@backstage/catalog-model';
|
||||
import { createApiRef } from '@backstage/core';
|
||||
import { ApiDefinitionWidget } from './components/ApiDefinitionCard/ApiDefinitionWidget';
|
||||
import { createApiRef } from '@backstage/core-plugin-api';
|
||||
|
||||
export const apiDocsConfigRef = createApiRef<ApiDocsConfig>({
|
||||
id: 'plugin.api-docs.config',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -15,16 +15,15 @@
|
||||
*/
|
||||
|
||||
import { ApiEntity } from '@backstage/catalog-model';
|
||||
import { defaultDefinitionWidgets } from './components/ApiDefinitionCard';
|
||||
import { apiDocsConfigRef } from './config';
|
||||
import { createComponentRouteRef, rootRoute } from './routes';
|
||||
import {
|
||||
createApiFactory,
|
||||
createComponentExtension,
|
||||
createPlugin,
|
||||
createRoutableExtension,
|
||||
} from '@backstage/core';
|
||||
import { defaultDefinitionWidgets } from './components/ApiDefinitionCard';
|
||||
import { ApiExplorerPage as Page } from './components/ApiExplorerPage/ApiExplorerPage';
|
||||
import { apiDocsConfigRef } from './config';
|
||||
import { createComponentRouteRef, rootRoute } from './routes';
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
export const apiDocsPlugin = createPlugin({
|
||||
id: 'api-docs',
|
||||
@@ -48,9 +47,6 @@ export const apiDocsPlugin = createPlugin({
|
||||
externalRoutes: {
|
||||
createComponent: createComponentRouteRef,
|
||||
},
|
||||
register({ router }) {
|
||||
router.addRoute(rootRoute, Page);
|
||||
},
|
||||
});
|
||||
|
||||
export const ApiExplorerPage = apiDocsPlugin.provide(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -14,7 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createExternalRouteRef, createRouteRef } from '@backstage/core';
|
||||
import {
|
||||
createExternalRouteRef,
|
||||
createRouteRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
const NoIcon = () => null;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @backstage/plugin-app-backend
|
||||
|
||||
## 0.3.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 3108ff7bf: Make `yarn dev` respect the `PLUGIN_PORT` environment variable.
|
||||
- Updated dependencies
|
||||
- @backstage/backend-common@0.8.3
|
||||
- @backstage/config-loader@0.6.4
|
||||
|
||||
## 0.3.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
## API Report File for "@backstage/plugin-app-backend"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
|
||||
import { Config } from '@backstage/config';
|
||||
import express from 'express';
|
||||
import { Logger } from 'winston';
|
||||
|
||||
// @public (undocumented)
|
||||
export function createRouter(options: RouterOptions): Promise<express.Router>;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface RouterOptions {
|
||||
appPackageName: string;
|
||||
// (undocumented)
|
||||
config: Config;
|
||||
disableConfigInjection?: boolean;
|
||||
// (undocumented)
|
||||
logger: Logger;
|
||||
staticFallbackHandler?: express.Handler;
|
||||
}
|
||||
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-app-backend",
|
||||
"version": "0.3.13",
|
||||
"version": "0.3.14",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
@@ -29,8 +29,8 @@
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.8.2",
|
||||
"@backstage/config-loader": "^0.6.1",
|
||||
"@backstage/backend-common": "^0.8.3",
|
||||
"@backstage/config-loader": "^0.6.4",
|
||||
"@backstage/config": "^0.1.5",
|
||||
"@types/express": "^4.17.6",
|
||||
"express": "^4.17.1",
|
||||
@@ -40,9 +40,9 @@
|
||||
"yn": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.7.0",
|
||||
"@backstage/cli": "^0.7.1",
|
||||
"@types/supertest": "^2.0.8",
|
||||
"msw": "^0.20.5",
|
||||
"msw": "^0.29.0",
|
||||
"supertest": "^6.1.3"
|
||||
},
|
||||
"files": [
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -38,7 +38,9 @@ export async function startStandaloneServer(
|
||||
appPackageName: 'example-app',
|
||||
});
|
||||
|
||||
const service = createServiceBuilder(module).addRouter('', router);
|
||||
const service = createServiceBuilder(module)
|
||||
.setPort(options.port)
|
||||
.addRouter('', router);
|
||||
|
||||
return await service.start().catch(err => {
|
||||
logger.error(err);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,46 @@
|
||||
# @backstage/plugin-auth-backend
|
||||
|
||||
## 0.3.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 36e9a4084: Don't export the `defaultGoogleAuthProvider`
|
||||
- c467cc4b9: Adds support for custom sign-in resolvers and profile transformations for the
|
||||
Google auth provider.
|
||||
|
||||
Adds an `ent` claim in Backstage tokens, with a list of
|
||||
[entity references](https://backstage.io/docs/features/software-catalog/references)
|
||||
related to your signed-in user's identities and groups across multiple systems.
|
||||
|
||||
Adds an optional `providerFactories` argument to the `createRouter` exported by
|
||||
the `auth-backend` plugin.
|
||||
|
||||
Updates `BackstageIdentity` so that
|
||||
|
||||
- `idToken` is deprecated in favor of `token`
|
||||
- An optional `entity` field is added which represents the entity that the user is represented by within Backstage.
|
||||
|
||||
More information:
|
||||
|
||||
- [The identity resolver documentation](https://backstage.io/docs/auth/identity-resolver)
|
||||
explains the concepts and shows how to implement your own.
|
||||
- The [From Identity to Ownership](https://github.com/backstage/backstage/issues/4089)
|
||||
RFC contains details about how this affects ownership in the catalog
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/catalog-client@0.3.14
|
||||
- @backstage/catalog-model@0.8.4
|
||||
- @backstage/test-utils@0.1.14
|
||||
|
||||
## 0.3.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1aa31f0af: Add support for refreshing GitLab auth sessions.
|
||||
- Updated dependencies
|
||||
- @backstage/backend-common@0.8.3
|
||||
- @backstage/catalog-model@0.8.3
|
||||
|
||||
## 0.3.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
## API Report File for "@backstage/plugin-auth-backend"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
import { Config } from '@backstage/config';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import express from 'express';
|
||||
import { JSONWebKey } from 'jose';
|
||||
import { Logger } from 'winston';
|
||||
import { PluginDatabaseManager } from '@backstage/backend-common';
|
||||
import { PluginEndpointDiscovery } from '@backstage/backend-common';
|
||||
import { Profile } from 'passport';
|
||||
import { UserEntity } from '@backstage/catalog-model';
|
||||
|
||||
// @public (undocumented)
|
||||
export type AuthProviderFactory = (options: AuthProviderFactoryOptions) => AuthProviderRouteHandlers;
|
||||
|
||||
// @public (undocumented)
|
||||
export type AuthProviderFactoryOptions = {
|
||||
providerId: string;
|
||||
globalConfig: AuthProviderConfig;
|
||||
config: Config;
|
||||
logger: Logger;
|
||||
tokenIssuer: TokenIssuer;
|
||||
discovery: PluginEndpointDiscovery;
|
||||
catalogApi: CatalogApi;
|
||||
identityResolver?: ExperimentalIdentityResolver;
|
||||
};
|
||||
|
||||
// @public
|
||||
export interface AuthProviderRouteHandlers {
|
||||
frameHandler(req: express.Request, res: express.Response): Promise<void>;
|
||||
logout?(req: express.Request, res: express.Response): Promise<void>;
|
||||
refresh?(req: express.Request, res: express.Response): Promise<void>;
|
||||
start(req: express.Request, res: express.Response): Promise<void>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type AuthResponse<ProviderInfo> = {
|
||||
providerInfo: ProviderInfo;
|
||||
profile: ProfileInfo;
|
||||
backstageIdentity?: BackstageIdentity;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type BackstageIdentity = {
|
||||
id: string;
|
||||
idToken?: string;
|
||||
token?: string;
|
||||
entity?: Entity;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export const createGoogleProvider: (options?: GoogleProviderOptions | undefined) => AuthProviderFactory;
|
||||
|
||||
// @public (undocumented)
|
||||
export function createRouter({ logger, config, discovery, database, providerFactories, }: RouterOptions): Promise<express.Router>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const defaultAuthProviderFactories: {
|
||||
[providerId: string]: AuthProviderFactory;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export const encodeState: (state: OAuthState) => string;
|
||||
|
||||
// @public (undocumented)
|
||||
export const ensuresXRequestedWith: (req: express.Request) => boolean;
|
||||
|
||||
// @public (undocumented)
|
||||
export const googleEmailSignInResolver: SignInResolver<OAuthResult>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type GoogleProviderOptions = {
|
||||
authHandler?: AuthHandler<OAuthResult>;
|
||||
signIn?: {
|
||||
resolver?: SignInResolver<OAuthResult>;
|
||||
};
|
||||
};
|
||||
|
||||
// @public
|
||||
export class IdentityClient {
|
||||
constructor(options: {
|
||||
discovery: PluginEndpointDiscovery;
|
||||
issuer: string;
|
||||
});
|
||||
authenticate(token: string | undefined): Promise<BackstageIdentity>;
|
||||
static getBearerToken(authorizationHeader: string | undefined): string | undefined;
|
||||
listPublicKeys(): Promise<{
|
||||
keys: JSONWebKey[];
|
||||
}>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export class OAuthAdapter implements AuthProviderRouteHandlers {
|
||||
constructor(handlers: OAuthHandlers, options: Options);
|
||||
// (undocumented)
|
||||
frameHandler(req: express.Request, res: express.Response): Promise<void>;
|
||||
// (undocumented)
|
||||
static fromConfig(config: AuthProviderConfig, handlers: OAuthHandlers, options: Pick<Options, 'providerId' | 'persistScopes' | 'disableRefresh' | 'tokenIssuer'>): OAuthAdapter;
|
||||
// (undocumented)
|
||||
logout(req: express.Request, res: express.Response): Promise<void>;
|
||||
// (undocumented)
|
||||
refresh(req: express.Request, res: express.Response): Promise<void>;
|
||||
// (undocumented)
|
||||
start(req: express.Request, res: express.Response): Promise<void>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export class OAuthEnvironmentHandler implements AuthProviderRouteHandlers {
|
||||
constructor(handlers: Map<string, AuthProviderRouteHandlers>);
|
||||
// (undocumented)
|
||||
frameHandler(req: express.Request, res: express.Response): Promise<void>;
|
||||
// (undocumented)
|
||||
logout(req: express.Request, res: express.Response): Promise<void>;
|
||||
// (undocumented)
|
||||
static mapConfig(config: Config, factoryFunc: (envConfig: Config) => AuthProviderRouteHandlers): OAuthEnvironmentHandler;
|
||||
// (undocumented)
|
||||
refresh(req: express.Request, res: express.Response): Promise<void>;
|
||||
// (undocumented)
|
||||
start(req: express.Request, res: express.Response): Promise<void>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface OAuthHandlers {
|
||||
handler(req: express.Request): Promise<{
|
||||
response: AuthResponse<OAuthProviderInfo>;
|
||||
refreshToken?: string;
|
||||
}>;
|
||||
logout?(): Promise<void>;
|
||||
refresh?(req: OAuthRefreshRequest): Promise<AuthResponse<OAuthProviderInfo>>;
|
||||
start(req: OAuthStartRequest): Promise<RedirectInfo>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type OAuthProviderInfo = {
|
||||
accessToken: string;
|
||||
idToken?: string;
|
||||
expiresInSeconds?: number;
|
||||
scope: string;
|
||||
refreshToken?: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
export type OAuthProviderOptions = {
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
callbackUrl: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type OAuthRefreshRequest = express.Request<{}> & {
|
||||
scope: string;
|
||||
refreshToken: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type OAuthResponse = AuthResponse<OAuthProviderInfo>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type OAuthResult = {
|
||||
fullProfile: Profile;
|
||||
params: {
|
||||
id_token?: string;
|
||||
scope: string;
|
||||
expires_in: number;
|
||||
};
|
||||
accessToken: string;
|
||||
refreshToken?: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type OAuthStartRequest = express.Request<{}> & {
|
||||
scope: string;
|
||||
state: OAuthState;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type OAuthState = {
|
||||
nonce: string;
|
||||
env: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export const postMessageResponse: (res: express.Response, appOrigin: string, response: WebMessageResponse) => void;
|
||||
|
||||
// @public
|
||||
export type ProfileInfo = {
|
||||
email?: string;
|
||||
displayName?: string;
|
||||
picture?: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export const readState: (stateString: string) => OAuthState;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface RouterOptions {
|
||||
// (undocumented)
|
||||
config: Config;
|
||||
// (undocumented)
|
||||
database: PluginDatabaseManager;
|
||||
// (undocumented)
|
||||
discovery: PluginEndpointDiscovery;
|
||||
// (undocumented)
|
||||
logger: Logger;
|
||||
// (undocumented)
|
||||
providerFactories?: ProviderFactories;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export const verifyNonce: (req: express.Request, providerId: string) => void;
|
||||
|
||||
// @public
|
||||
export type WebMessageResponse = {
|
||||
type: 'authorization_response';
|
||||
response: AuthResponse<unknown>;
|
||||
} | {
|
||||
type: 'authorization_response';
|
||||
error: Error;
|
||||
};
|
||||
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
|
||||
```
|
||||
Vendored
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-auth-backend",
|
||||
"version": "0.3.12",
|
||||
"version": "0.3.14",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
@@ -29,12 +29,12 @@
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.8.2",
|
||||
"@backstage/catalog-client": "^0.3.13",
|
||||
"@backstage/catalog-model": "^0.8.2",
|
||||
"@backstage/backend-common": "^0.8.3",
|
||||
"@backstage/catalog-client": "^0.3.14",
|
||||
"@backstage/catalog-model": "^0.8.4",
|
||||
"@backstage/config": "^0.1.5",
|
||||
"@backstage/errors": "^0.1.1",
|
||||
"@backstage/test-utils": "^0.1.12",
|
||||
"@backstage/test-utils": "^0.1.14",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/passport": "^1.0.3",
|
||||
"compression": "^1.7.4",
|
||||
@@ -68,7 +68,7 @@
|
||||
"yn": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.7.0",
|
||||
"@backstage/cli": "^0.7.2",
|
||||
"@types/body-parser": "^1.19.0",
|
||||
"@types/cookie-parser": "^1.4.2",
|
||||
"@types/express-session": "^1.17.2",
|
||||
@@ -79,7 +79,7 @@
|
||||
"@types/passport-saml": "^1.1.2",
|
||||
"@types/passport-strategy": "^0.2.35",
|
||||
"@types/xml2js": "^0.4.7",
|
||||
"msw": "^0.21.2"
|
||||
"msw": "^0.29.0"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -67,13 +67,14 @@ export class TokenFactory implements TokenIssuer {
|
||||
|
||||
const iss = this.issuer;
|
||||
const sub = params.claims.sub;
|
||||
const ent = params.claims.ent;
|
||||
const aud = 'backstage';
|
||||
const iat = Math.floor(Date.now() / MS_IN_S);
|
||||
const exp = iat + this.keyDurationSeconds;
|
||||
|
||||
this.logger.info(`Issuing token for ${sub}`);
|
||||
this.logger.info(`Issuing token for ${sub}, with entities ${ent ?? []}`);
|
||||
|
||||
return JWS.sign({ iss, sub, aud, iat, exp }, key, {
|
||||
return JWS.sign({ iss, sub, aud, iat, exp, ent }, key, {
|
||||
alg: key.alg,
|
||||
kid: key.kid,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -28,6 +28,8 @@ export type TokenParams = {
|
||||
claims: {
|
||||
/** The token subject, i.e. User ID */
|
||||
sub: string;
|
||||
/** A list of entity references that the user claims ownership through */
|
||||
ent?: string[];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
import { UserEntity } from '@backstage/catalog-model';
|
||||
import { TokenIssuer } from '../../identity';
|
||||
import { CatalogIdentityClient } from './CatalogIdentityClient';
|
||||
|
||||
describe('CatalogIdentityClient', () => {
|
||||
@@ -29,25 +30,36 @@ describe('CatalogIdentityClient', () => {
|
||||
getLocationByEntity: jest.fn(),
|
||||
removeEntityByUid: jest.fn(),
|
||||
};
|
||||
const tokenIssuer: jest.Mocked<TokenIssuer> = {
|
||||
issueToken: jest.fn(),
|
||||
listPublicKeys: jest.fn(),
|
||||
};
|
||||
|
||||
afterEach(() => jest.resetAllMocks());
|
||||
|
||||
it('passes through the correct search params', async () => {
|
||||
catalogApi.getEntities.mockResolvedValueOnce({ items: [{} as UserEntity] });
|
||||
tokenIssuer.issueToken.mockResolvedValue('my-token');
|
||||
const client = new CatalogIdentityClient({
|
||||
catalogApi: catalogApi as CatalogApi,
|
||||
catalogApi: catalogApi,
|
||||
tokenIssuer: tokenIssuer,
|
||||
});
|
||||
|
||||
client.findUser({ annotations: { key: 'value' } });
|
||||
await client.findUser({ annotations: { key: 'value' } });
|
||||
|
||||
expect(catalogApi.getEntities).toBeCalledWith(
|
||||
expect(catalogApi.getEntities).toHaveBeenCalledWith(
|
||||
{
|
||||
filter: {
|
||||
kind: 'user',
|
||||
'metadata.annotations.key': 'value',
|
||||
},
|
||||
},
|
||||
undefined,
|
||||
{ token: 'my-token' },
|
||||
);
|
||||
expect(tokenIssuer.issueToken).toHaveBeenCalledWith({
|
||||
claims: {
|
||||
sub: 'backstage.io/auth-backend',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -17,6 +17,7 @@
|
||||
import { ConflictError, NotFoundError } from '@backstage/errors';
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
import { UserEntity } from '@backstage/catalog-model';
|
||||
import { TokenIssuer } from '../../identity';
|
||||
|
||||
type UserQuery = {
|
||||
annotations: Record<string, string>;
|
||||
@@ -27,9 +28,11 @@ type UserQuery = {
|
||||
*/
|
||||
export class CatalogIdentityClient {
|
||||
private readonly catalogApi: CatalogApi;
|
||||
private readonly tokenIssuer: TokenIssuer;
|
||||
|
||||
constructor(options: { catalogApi: CatalogApi }) {
|
||||
constructor(options: { catalogApi: CatalogApi; tokenIssuer: TokenIssuer }) {
|
||||
this.catalogApi = options.catalogApi;
|
||||
this.tokenIssuer = options.tokenIssuer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,10 +40,7 @@ export class CatalogIdentityClient {
|
||||
*
|
||||
* Throws a NotFoundError or ConflictError if 0 or multiple users are found.
|
||||
*/
|
||||
async findUser(
|
||||
query: UserQuery,
|
||||
options?: { token?: string },
|
||||
): Promise<UserEntity> {
|
||||
async findUser(query: UserQuery): Promise<UserEntity> {
|
||||
const filter: Record<string, string> = {
|
||||
kind: 'user',
|
||||
};
|
||||
@@ -48,7 +48,11 @@ export class CatalogIdentityClient {
|
||||
filter[`metadata.annotations.${key}`] = value;
|
||||
}
|
||||
|
||||
const { items } = await this.catalogApi.getEntities({ filter }, options);
|
||||
// TODO(Rugvip): cache the token
|
||||
const token = await this.tokenIssuer.issueToken({
|
||||
claims: { sub: 'backstage.io/auth-backend' },
|
||||
});
|
||||
const { items } = await this.catalogApi.getEntities({ filter }, { token });
|
||||
|
||||
if (items.length !== 1) {
|
||||
if (items.length > 1) {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2021 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 {
|
||||
RELATION_MEMBER_OF,
|
||||
stringifyEntityRef,
|
||||
UserEntity,
|
||||
} from '@backstage/catalog-model';
|
||||
import { TokenParams } from '../../identity';
|
||||
|
||||
export function getEntityClaims(entity: UserEntity): TokenParams['claims'] {
|
||||
const userRef = stringifyEntityRef(entity);
|
||||
|
||||
const membershipRefs =
|
||||
entity.relations
|
||||
?.filter(
|
||||
r =>
|
||||
r.type === RELATION_MEMBER_OF &&
|
||||
r.target.kind.toLocaleLowerCase('en-US') === 'group',
|
||||
)
|
||||
.map(r => stringifyEntityRef(r.target)) ?? [];
|
||||
|
||||
return {
|
||||
sub: userRef,
|
||||
ent: [userRef, ...membershipRefs],
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
@@ -15,3 +15,4 @@
|
||||
*/
|
||||
|
||||
export { CatalogIdentityClient } from './CatalogIdentityClient';
|
||||
export { getEntityClaims } from './helpers';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
* Copyright 2021 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
* Copyright 2021 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
* Copyright 2020 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.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user