Verify access to related catalog entities for all techdocs api routes
Signed-off-by: Joe Porpeglia <josephp@spotify.com> Co-authored-by: Nataliya Issayeva <nissayeva@users.noreply.github.com>
This commit is contained in:
committed by
Joe Porpeglia
parent
6680853e0c
commit
b76fec242d
@@ -18,7 +18,7 @@ import {
|
||||
PluginCacheManager,
|
||||
} from '@backstage/backend-common';
|
||||
import { CatalogClient } from '@backstage/catalog-client';
|
||||
import { Entity, stringifyEntityRef } from '@backstage/catalog-model';
|
||||
import { stringifyEntityRef } from '@backstage/catalog-model';
|
||||
import { Config } from '@backstage/config';
|
||||
import { NotFoundError, NotModifiedError } from '@backstage/errors';
|
||||
import {
|
||||
@@ -27,7 +27,6 @@ import {
|
||||
PreparerBuilder,
|
||||
PublisherBase,
|
||||
} from '@backstage/techdocs-common';
|
||||
import fetch from 'node-fetch';
|
||||
import express, { Response } from 'express';
|
||||
import Router from 'express-promise-router';
|
||||
import { Knex } from 'knex';
|
||||
@@ -107,6 +106,16 @@ export async function createRouter(
|
||||
router.get('/metadata/techdocs/:namespace/:kind/:name', async (req, res) => {
|
||||
const { kind, namespace, name } = req.params;
|
||||
const entityName = { kind, namespace, name };
|
||||
const token = getBearerToken(req.headers.authorization);
|
||||
|
||||
// Verify that the related entity exists and the current user has permission to view it.
|
||||
const entity = await catalogClient.getEntityByName(entityName, { token });
|
||||
|
||||
if (!entity) {
|
||||
throw new NotFoundError(
|
||||
`Unable to get metadata for '${stringifyEntityRef(entityName)}'`,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const techdocsMetadata = await publisher.fetchTechDocsMetadata(
|
||||
@@ -128,23 +137,19 @@ export async function createRouter(
|
||||
});
|
||||
|
||||
router.get('/metadata/entity/:namespace/:kind/:name', async (req, res) => {
|
||||
const catalogUrl = await discovery.getBaseUrl('catalog');
|
||||
|
||||
const { kind, namespace, name } = req.params;
|
||||
const entityName = { kind, namespace, name };
|
||||
const token = getBearerToken(req.headers.authorization);
|
||||
|
||||
const entity = await catalogClient.getEntityByName(entityName, { token });
|
||||
|
||||
if (!entity) {
|
||||
throw new NotFoundError(
|
||||
`Unable to get metadata for '${stringifyEntityRef(entityName)}'`,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const token = getBearerToken(req.headers.authorization);
|
||||
// TODO: Consider using the catalog client here
|
||||
const entity = (await (
|
||||
await fetch(
|
||||
`${catalogUrl}/entities/by-name/${kind}/${namespace}/${name}`,
|
||||
{
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
},
|
||||
)
|
||||
).json()) as Entity;
|
||||
|
||||
const locationMetadata = getLocationForEntity(entity, scmIntegrations);
|
||||
res.json({ ...entity, locationMetadata });
|
||||
} catch (err) {
|
||||
@@ -226,6 +231,23 @@ export async function createRouter(
|
||||
);
|
||||
});
|
||||
|
||||
// Ensures that the related entity exists and the current user has permission to view it.
|
||||
router.use('/static/docs/:namespace/:kind/:name', async (req, _res, next) => {
|
||||
const { kind, namespace, name } = req.params;
|
||||
const entityName = { kind, namespace, name };
|
||||
const token = getBearerToken(req.headers.authorization);
|
||||
|
||||
const entity = await catalogClient.getEntityByName(entityName, { token });
|
||||
|
||||
if (!entity) {
|
||||
throw new NotFoundError(
|
||||
`Entity not found for ${stringifyEntityRef(entityName)}`,
|
||||
);
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
// If a cache manager was provided, attach the cache middleware.
|
||||
if (cache) {
|
||||
router.use(createCacheMiddleware({ logger, cache }));
|
||||
|
||||
Reference in New Issue
Block a user