From b76fa489280da71ee72d3014ae85d4d42a409509 Mon Sep 17 00:00:00 2001 From: Debsmita Santra Date: Tue, 23 Jul 2024 15:59:10 +0530 Subject: [PATCH] Create backend plugin test-plugin-backend-2 --- .../.eslintrc.js | 1 + .../test-plugin-backend-2-backend/README.md | 21 ++++++++ .../dev/index.ts | 9 ++++ .../package.json | 51 +++++++++++++++++++ .../src/index.ts | 2 + .../src/plugin.ts | 40 +++++++++++++++ .../src/service/router.test.ts | 41 +++++++++++++++ .../src/service/router.ts | 39 ++++++++++++++ .../src/setupTests.ts | 1 + 9 files changed, 205 insertions(+) create mode 100644 plugins/test-plugin-backend-2-backend/.eslintrc.js create mode 100644 plugins/test-plugin-backend-2-backend/README.md create mode 100644 plugins/test-plugin-backend-2-backend/dev/index.ts create mode 100644 plugins/test-plugin-backend-2-backend/package.json create mode 100644 plugins/test-plugin-backend-2-backend/src/index.ts create mode 100644 plugins/test-plugin-backend-2-backend/src/plugin.ts create mode 100644 plugins/test-plugin-backend-2-backend/src/service/router.test.ts create mode 100644 plugins/test-plugin-backend-2-backend/src/service/router.ts create mode 100644 plugins/test-plugin-backend-2-backend/src/setupTests.ts diff --git a/plugins/test-plugin-backend-2-backend/.eslintrc.js b/plugins/test-plugin-backend-2-backend/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/test-plugin-backend-2-backend/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/test-plugin-backend-2-backend/README.md b/plugins/test-plugin-backend-2-backend/README.md new file mode 100644 index 0000000000..3f20036dbd --- /dev/null +++ b/plugins/test-plugin-backend-2-backend/README.md @@ -0,0 +1,21 @@ +# test-plugin-backend-2 + +Welcome to the test-plugin-backend-2 backend plugin! + +_This plugin was created through the Backstage CLI_ + +## Getting started + +Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn +start` in the root directory, wait the server to start and then acessing the plugin endpoints: + +* [/test-plugin-backend-2/health](http://localhost:7007/api/test-plugin-backend-2/health): This endpoint will simply return a JSON with content `{"status" : "ok"}` and requires no authentication; +* [/test-plugin-backend-2/hello](http://localhost:7007/api/test-plugin-backend-2/hello): This endpoint will thrown a 401 error if not authenticated and can be called setting the `Authorization` header with the proper token. Once authenticated it will return a JSON with content `{"message": "Hello User"}`, where User is the authenticated user. Here's an example to call it using the `curl` utility: + +``` +curl -vH "Authorization: Bearer ${RHDH_TOKEN}" http://localhost:7007/api/test-plugin-backend-2/hello +``` + +You can also serve the plugin in isolation by running `yarn start` in the plugin directory. +This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads. +It is only meant for local development, and the setup for it can be found inside the [/dev](/dev) directory. \ No newline at end of file diff --git a/plugins/test-plugin-backend-2-backend/dev/index.ts b/plugins/test-plugin-backend-2-backend/dev/index.ts new file mode 100644 index 0000000000..9d74c82508 --- /dev/null +++ b/plugins/test-plugin-backend-2-backend/dev/index.ts @@ -0,0 +1,9 @@ +import { createBackend } from '@backstage/backend-defaults'; + +const backend = createBackend(); + +backend.add(import('@backstage/plugin-auth-backend')); +backend.add(import('@backstage/plugin-auth-backend-module-guest-provider')); +backend.add(import('../src')); + +backend.start(); diff --git a/plugins/test-plugin-backend-2-backend/package.json b/plugins/test-plugin-backend-2-backend/package.json new file mode 100644 index 0000000000..d217169ef2 --- /dev/null +++ b/plugins/test-plugin-backend-2-backend/package.json @@ -0,0 +1,51 @@ +{ + "name": "@internal/backstage-plugin-test-plugin-backend-2-backend", + "version": "0.1.1", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "private": true, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "export-dynamic": "janus-cli package export-dynamic-plugin --clean" + }, + "dependencies": { + "@backstage/backend-common": "^0.21.7", + "@backstage/backend-defaults": "^0.3.3", + "@backstage/backend-plugin-api": "0.6.18", + "@backstage/config": "^1.2.0", + "@types/express": "^4.17.6", + "express": "^4.17.1", + "express-promise-router": "^4.1.0", + "winston": "^3.2.1", + "node-fetch": "^2.6.7", + "yn": "^4.0.0" + }, + "devDependencies": { + "@backstage/backend-test-utils": "^0.4.3", + "@backstage/cli": "^0.26.10", + "@backstage/plugin-auth-backend": "^0.22.8", + "@backstage/plugin-auth-backend-module-guest-provider": "^0.1.7", + "@janus-idp/cli": "^1.11.1", + "@types/supertest": "^2.0.12", + "supertest": "^6.2.4", + "msw": "^1.0.0" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/test-plugin-backend-2-backend/src/index.ts b/plugins/test-plugin-backend-2-backend/src/index.ts new file mode 100644 index 0000000000..872e3e8a93 --- /dev/null +++ b/plugins/test-plugin-backend-2-backend/src/index.ts @@ -0,0 +1,2 @@ +export * from './service/router'; +export { plugin as default } from './plugin'; \ No newline at end of file diff --git a/plugins/test-plugin-backend-2-backend/src/plugin.ts b/plugins/test-plugin-backend-2-backend/src/plugin.ts new file mode 100644 index 0000000000..f97585ef3a --- /dev/null +++ b/plugins/test-plugin-backend-2-backend/src/plugin.ts @@ -0,0 +1,40 @@ +import { + coreServices, + createBackendPlugin, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './service/router'; + +/** + * test-plugin-backend-2Plugin backend plugin + * + * @public + */ +export const plugin = createBackendPlugin({ + pluginId: 'test-plugin-backend-2', + register(env) { + env.registerInit({ + deps: { + httpRouter: coreServices.httpRouter, + logger: coreServices.logger, + config: coreServices.rootConfig, + httpAuth: coreServices.httpAuth, + discovery: coreServices.discovery, + }, + async init({ httpRouter, logger, config, httpAuth, discovery }) { + logger.info('test-plugin-backend-2 plugin :: init'); + httpRouter.use( + await createRouter({ + logger, + config, + httpAuth, + discovery + }), + ); + httpRouter.addAuthPolicy({ + path: '/health', + allow: 'unauthenticated', + }); + }, + }); + }, +}); diff --git a/plugins/test-plugin-backend-2-backend/src/service/router.test.ts b/plugins/test-plugin-backend-2-backend/src/service/router.test.ts new file mode 100644 index 0000000000..abb902fdfe --- /dev/null +++ b/plugins/test-plugin-backend-2-backend/src/service/router.test.ts @@ -0,0 +1,41 @@ +import { mockServices } from '@backstage/backend-test-utils'; +import express from 'express'; +import request from 'supertest'; + +import { createRouter } from './router'; + +describe('createRouter', () => { + let app: express.Express; + + beforeAll(async () => { + const router = await createRouter({ + logger: mockServices.logger.mock(), + config: mockServices.rootConfig(), + discovery: mockServices.discovery(), + httpAuth: mockServices.httpAuth(), + }); + app = express().use(router); + }); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + describe('GET /health', () => { + it('returns ok', async () => { + const response = await request(app).get('/health'); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ status: 'ok' }); + }); + }); + + describe('GET /hello', () => { + it('returns 200', async () => { + const response = await request(app).get('/hello'); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ message: 'Hello user:default/mock' }); + }); + }); +}); diff --git a/plugins/test-plugin-backend-2-backend/src/service/router.ts b/plugins/test-plugin-backend-2-backend/src/service/router.ts new file mode 100644 index 0000000000..94d4cbf6e0 --- /dev/null +++ b/plugins/test-plugin-backend-2-backend/src/service/router.ts @@ -0,0 +1,39 @@ +// TODO: We should use the MiddlewareFactory from @backstage/backend-defaults/rootHttpRouter, but it is not available in RHDH 1.2.x +import { MiddlewareFactory } from '@backstage/backend-app-api'; +import { createLegacyAuthAdapters } from '@backstage/backend-common'; +import { + DiscoveryService, + HttpAuthService, + LoggerService, +} from '@backstage/backend-plugin-api'; +import { Config } from '@backstage/config'; +import express from 'express'; +import Router from 'express-promise-router'; + +export interface RouterOptions { + logger: LoggerService; + config: Config; + discovery: DiscoveryService; + httpAuth?: HttpAuthService; +} + +export async function createRouter( + options: RouterOptions, +): Promise { + const { logger, config } = options; + const { httpAuth } = createLegacyAuthAdapters(options); + + const router = Router(); + router.use(express.json()); + router.get('/health', async (_, res) => res.json({ status: 'ok' })); + + router.get('/hello', async (req, res) => { + const caller = await httpAuth.credentials(req, { allow: ['user'] }); + res.json({ message: `Hello ${caller.principal.userEntityRef}` }); + }); + + const middleware = MiddlewareFactory.create({ logger, config }); + + router.use(middleware.error()); + return router; +} diff --git a/plugins/test-plugin-backend-2-backend/src/setupTests.ts b/plugins/test-plugin-backend-2-backend/src/setupTests.ts new file mode 100644 index 0000000000..cb0ff5c3b5 --- /dev/null +++ b/plugins/test-plugin-backend-2-backend/src/setupTests.ts @@ -0,0 +1 @@ +export {};