From 5bbffa60be3ce136c67f23181b8673bf4231e7e8 Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Thu, 27 Jan 2022 16:26:43 +0000 Subject: [PATCH 1/2] catalog-backend: pass token to locationService in location routes Signed-off-by: MT Lewis --- .changeset/thirty-houses-juggle.md | 5 ++ .../src/service/createRouter.test.ts | 46 +++++++++++++++---- .../src/service/createRouter.ts | 18 ++++++-- 3 files changed, 56 insertions(+), 13 deletions(-) create mode 100644 .changeset/thirty-houses-juggle.md diff --git a/.changeset/thirty-houses-juggle.md b/.changeset/thirty-houses-juggle.md new file mode 100644 index 0000000000..c54ab5526f --- /dev/null +++ b/.changeset/thirty-houses-juggle.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Pass authorization token to location service inside location api routes diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index a747a4cf23..240cc022c6 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -250,8 +250,14 @@ describe('createRouter readonly disabled', () => { ]; locationService.listLocations.mockResolvedValueOnce(locations); - const response = await request(app).get('/locations'); + const response = await request(app) + .get('/locations') + .set('authorization', 'Bearer someauthtoken'); + expect(locationService.listLocations).toHaveBeenCalledTimes(1); + expect(locationService.listLocations).toHaveBeenCalledWith({ + authorizationToken: 'someauthtoken', + }); expect(response.status).toEqual(200); expect(response.body).toEqual([ { data: { id: 'foo', target: 'example.com', type: 'url' } }, @@ -266,7 +272,10 @@ describe('createRouter readonly disabled', () => { target: 'c', } as unknown as LocationSpec; - const response = await request(app).post('/locations').send(spec); + const response = await request(app) + .post('/locations') + .set('authorization', 'Bearer someauthtoken') + .send(spec); expect(locationService.createLocation).not.toHaveBeenCalled(); expect(response.status).toEqual(400); @@ -283,10 +292,15 @@ describe('createRouter readonly disabled', () => { entities: [], }); - const response = await request(app).post('/locations').send(spec); + const response = await request(app) + .post('/locations') + .set('authorization', 'Bearer someauthtoken') + .send(spec); expect(locationService.createLocation).toHaveBeenCalledTimes(1); - expect(locationService.createLocation).toHaveBeenCalledWith(spec, false); + expect(locationService.createLocation).toHaveBeenCalledWith(spec, false, { + authorizationToken: 'someauthtoken', + }); expect(response.status).toEqual(201); expect(response.body).toEqual( expect.objectContaining({ @@ -308,10 +322,13 @@ describe('createRouter readonly disabled', () => { const response = await request(app) .post('/locations?dryRun=true') + .set('authorization', 'Bearer someauthtoken') .send(spec); expect(locationService.createLocation).toHaveBeenCalledTimes(1); - expect(locationService.createLocation).toHaveBeenCalledWith(spec, true); + expect(locationService.createLocation).toHaveBeenCalledWith(spec, true, { + authorizationToken: 'someauthtoken', + }); expect(response.status).toEqual(201); expect(response.body).toEqual( expect.objectContaining({ @@ -397,7 +414,14 @@ describe('createRouter readonly enabled', () => { ]; locationService.listLocations.mockResolvedValueOnce(locations); - const response = await request(app).get('/locations'); + const response = await request(app) + .get('/locations') + .set('authorization', 'Bearer someauthtoken'); + + expect(locationService.listLocations).toHaveBeenCalledTimes(1); + expect(locationService.listLocations).toHaveBeenCalledWith({ + authorizationToken: 'someauthtoken', + }); expect(response.status).toEqual(200); expect(response.body).toEqual([ @@ -413,7 +437,10 @@ describe('createRouter readonly enabled', () => { target: 'c', }; - const response = await request(app).post('/locations').send(spec); + const response = await request(app) + .post('/locations') + .set('authorization', 'Bearer someauthtoken') + .send(spec); expect(locationService.createLocation).not.toHaveBeenCalled(); expect(response.status).toEqual(403); @@ -433,10 +460,13 @@ describe('createRouter readonly enabled', () => { const response = await request(app) .post('/locations?dryRun=true') + .set('authorization', 'Bearer someauthtoken') .send(spec); expect(locationService.createLocation).toHaveBeenCalledTimes(1); - expect(locationService.createLocation).toHaveBeenCalledWith(spec, true); + expect(locationService.createLocation).toHaveBeenCalledWith(spec, true, { + authorizationToken: 'someauthtoken', + }); expect(response.status).toEqual(201); expect(response.body).toEqual( expect.objectContaining({ diff --git a/plugins/catalog-backend/src/service/createRouter.ts b/plugins/catalog-backend/src/service/createRouter.ts index fc60577141..ab123238c7 100644 --- a/plugins/catalog-backend/src/service/createRouter.ts +++ b/plugins/catalog-backend/src/service/createRouter.ts @@ -174,24 +174,32 @@ export async function createRouter( disallowReadonlyMode(readonlyEnabled); } - const output = await locationService.createLocation(input, dryRun); + const output = await locationService.createLocation(input, dryRun, { + authorizationToken: getBearerToken(req.header('authorization')), + }); res.status(201).json(output); }) - .get('/locations', async (_req, res) => { - const locations = await locationService.listLocations(); + .get('/locations', async (req, res) => { + const locations = await locationService.listLocations({ + authorizationToken: getBearerToken(req.header('authorization')), + }); res.status(200).json(locations.map(l => ({ data: l }))); }) .get('/locations/:id', async (req, res) => { const { id } = req.params; - const output = await locationService.getLocation(id); + const output = await locationService.getLocation(id, { + authorizationToken: getBearerToken(req.header('authorization')), + }); res.status(200).json(output); }) .delete('/locations/:id', async (req, res) => { disallowReadonlyMode(readonlyEnabled); const { id } = req.params; - await locationService.deleteLocation(id); + await locationService.deleteLocation(id, { + authorizationToken: getBearerToken(req.header('authorization')), + }); res.status(204).end(); }); } From fef8fc92c53de7f730f636889f68ed0c959c6153 Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Thu, 27 Jan 2022 17:48:15 +0000 Subject: [PATCH 2/2] catalog-backend: add some missing location unit tests Signed-off-by: MT Lewis --- .../src/service/createRouter.test.ts | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index 240cc022c6..205be01b42 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -265,6 +265,33 @@ describe('createRouter readonly disabled', () => { }); }); + describe('GET /locations/:id', () => { + it('happy path: gets location by id', async () => { + const location: Location = { + id: 'foo', + type: 'url', + target: 'example.com', + }; + locationService.getLocation.mockResolvedValueOnce(location); + + const response = await request(app) + .get('/locations/foo') + .set('authorization', 'Bearer someauthtoken'); + + expect(locationService.getLocation).toHaveBeenCalledTimes(1); + expect(locationService.getLocation).toHaveBeenCalledWith('foo', { + authorizationToken: 'someauthtoken', + }); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ + id: 'foo', + target: 'example.com', + type: 'url', + }); + }); + }); + describe('POST /locations', () => { it('rejects malformed locations', async () => { const spec = { @@ -337,6 +364,23 @@ describe('createRouter readonly disabled', () => { ); }); }); + + describe('DELETE /locations', () => { + it('deletes the location', async () => { + locationService.deleteLocation.mockResolvedValueOnce(undefined); + + const response = await request(app) + .delete('/locations/foo') + .set('authorization', 'Bearer someauthtoken'); + + expect(locationService.deleteLocation).toHaveBeenCalledTimes(1); + expect(locationService.deleteLocation).toHaveBeenCalledWith('foo', { + authorizationToken: 'someauthtoken', + }); + + expect(response.status).toEqual(204); + }); + }); }); describe('createRouter readonly enabled', () => { @@ -430,6 +474,33 @@ describe('createRouter readonly enabled', () => { }); }); + describe('GET /locations/:id', () => { + it('happy path: gets location by id', async () => { + const location: Location = { + id: 'foo', + type: 'url', + target: 'example.com', + }; + locationService.getLocation.mockResolvedValueOnce(location); + + const response = await request(app) + .get('/locations/foo') + .set('authorization', 'Bearer someauthtoken'); + + expect(locationService.getLocation).toHaveBeenCalledTimes(1); + expect(locationService.getLocation).toHaveBeenCalledWith('foo', { + authorizationToken: 'someauthtoken', + }); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ + id: 'foo', + target: 'example.com', + type: 'url', + }); + }); + }); + describe('POST /locations', () => { it('is not allowed', async () => { const spec: LocationSpec = { @@ -475,6 +546,17 @@ describe('createRouter readonly enabled', () => { ); }); }); + + describe('DELETE /locations', () => { + it('is not allowed', async () => { + const response = await request(app) + .delete('/locations/foo') + .set('authorization', 'Bearer someauthtoken'); + + expect(locationService.deleteLocation).not.toHaveBeenCalled(); + expect(response.status).toEqual(403); + }); + }); }); describe('NextRouter permissioning', () => {