Merge pull request #13842 from anicke/bazaar-user-entity
Bazaar plugin: The project member link will now target the user catalog
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-bazaar': patch
|
||||
---
|
||||
|
||||
Link to the user catalog entity of a member
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
'@backstage/plugin-bazaar-backend': minor
|
||||
---
|
||||
|
||||
**BREAKING** The bazaar-backend `createRouter` now requires that the `identityApi` is passed to the router.
|
||||
|
||||
These changes are **required** to `packages/backend/src/plugins/bazaar.ts`
|
||||
|
||||
The user entity ref is now added to the members table and is taken from the requesting user using the `identityApi`.
|
||||
|
||||
```diff
|
||||
import { PluginEnvironment } from '../types';
|
||||
import { createRouter } from '@backstage/plugin-bazaar-backend';
|
||||
import { Router } from 'express';
|
||||
|
||||
export default async function createPlugin(
|
||||
env: PluginEnvironment,
|
||||
): Promise<Router> {
|
||||
return await createRouter({
|
||||
logger: env.logger,
|
||||
config: env.config,
|
||||
database: env.database,
|
||||
+ identity: env.identity,
|
||||
});
|
||||
}
|
||||
```
|
||||
@@ -15,7 +15,7 @@ yarn add --cwd packages/backend @backstage/plugin-bazaar-backend
|
||||
|
||||
You'll need to add the plugin to the router in your `backend` package. You can do this by creating a file called `packages/backend/src/plugins/bazaar.ts`
|
||||
|
||||
```tsx
|
||||
```typescript
|
||||
import { PluginEnvironment } from '../types';
|
||||
import { createRouter } from '@backstage/plugin-bazaar-backend';
|
||||
import { Router } from 'express';
|
||||
@@ -27,6 +27,7 @@ export default async function createPlugin(
|
||||
logger: env.logger,
|
||||
config: env.config,
|
||||
database: env.database,
|
||||
identity: env.identity,
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
```ts
|
||||
import { Config } from '@backstage/config';
|
||||
import express from 'express';
|
||||
import { IdentityApi } from '@backstage/plugin-auth-node';
|
||||
import { Logger } from 'winston';
|
||||
import { PluginDatabaseManager } from '@backstage/backend-common';
|
||||
|
||||
@@ -18,6 +19,8 @@ export interface RouterOptions {
|
||||
// (undocumented)
|
||||
database: PluginDatabaseManager;
|
||||
// (undocumented)
|
||||
identity: IdentityApi;
|
||||
// (undocumented)
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2022 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.
|
||||
*/
|
||||
|
||||
exports.up = async function up(knex) {
|
||||
await knex.schema.alterTable('members', table => {
|
||||
table.string('user_ref').nullable();
|
||||
});
|
||||
};
|
||||
|
||||
exports.down = async function down(knex) {
|
||||
return knex.schema.table('members', table => {
|
||||
table.dropColumn('user_ref');
|
||||
});
|
||||
};
|
||||
@@ -25,6 +25,7 @@
|
||||
"@backstage/backend-common": "workspace:^",
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/config": "workspace:^",
|
||||
"@backstage/plugin-auth-node": "workspace:^",
|
||||
"@types/express": "^4.17.6",
|
||||
"express": "^4.17.1",
|
||||
"express-promise-router": "^4.1.0",
|
||||
|
||||
@@ -75,6 +75,13 @@ describe('DatabaseHandler', () => {
|
||||
responsible: bazaarProject.responsible,
|
||||
});
|
||||
|
||||
// Add a member to the project
|
||||
await knex('members').insert({
|
||||
item_id: 1,
|
||||
user_ref: 'user:default/thehulk',
|
||||
user_id: 'Bruce Banner',
|
||||
});
|
||||
|
||||
const res = await dbHandler.getMetadataByRef('ref1');
|
||||
|
||||
expect(res).toHaveLength(1);
|
||||
@@ -85,6 +92,9 @@ describe('DatabaseHandler', () => {
|
||||
expect(res[0].end_date).toEqual(null);
|
||||
expect(res[0].size).toEqual('small');
|
||||
expect(res[0].responsible).toEqual('r');
|
||||
expect(
|
||||
res[0].members_count === '1' || res[0].members_count === 1,
|
||||
).toBeTruthy();
|
||||
},
|
||||
60_000,
|
||||
);
|
||||
|
||||
@@ -67,11 +67,17 @@ export class DatabaseHandler {
|
||||
return await this.client.select('*').from('members').where({ item_id: id });
|
||||
}
|
||||
|
||||
async addMember(id: number, userId: string, picture?: string) {
|
||||
async addMember(
|
||||
id: number,
|
||||
userId: string,
|
||||
userRef?: string,
|
||||
picture?: string,
|
||||
) {
|
||||
await this.client
|
||||
.insert({
|
||||
item_id: id,
|
||||
user_id: userId,
|
||||
user_ref: userRef,
|
||||
picture: picture,
|
||||
})
|
||||
.into('members');
|
||||
|
||||
@@ -19,6 +19,7 @@ import express from 'express';
|
||||
import Router from 'express-promise-router';
|
||||
import { Logger } from 'winston';
|
||||
import { Config } from '@backstage/config';
|
||||
import { IdentityApi } from '@backstage/plugin-auth-node';
|
||||
import { DatabaseHandler } from './DatabaseHandler';
|
||||
|
||||
/** @public */
|
||||
@@ -26,13 +27,14 @@ export interface RouterOptions {
|
||||
logger: Logger;
|
||||
database: PluginDatabaseManager;
|
||||
config: Config;
|
||||
identity: IdentityApi;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export async function createRouter(
|
||||
options: RouterOptions,
|
||||
): Promise<express.Router> {
|
||||
const { logger, database } = options;
|
||||
const { logger, database, identity } = options;
|
||||
|
||||
const dbHandler = await DatabaseHandler.create({ database });
|
||||
|
||||
@@ -53,7 +55,14 @@ export async function createRouter(
|
||||
|
||||
router.put('/projects/:id/member/:userId', async (request, response) => {
|
||||
const { id, userId } = request.params;
|
||||
await dbHandler.addMember(parseInt(id, 10), userId, request.body?.picture);
|
||||
const user = await identity.getIdentity({ request: request });
|
||||
|
||||
await dbHandler.addMember(
|
||||
parseInt(id, 10),
|
||||
userId,
|
||||
user?.identity.userEntityRef,
|
||||
request.body?.picture,
|
||||
);
|
||||
|
||||
response.json({ status: 'ok' });
|
||||
});
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
loadBackendConfig,
|
||||
useHotMemoize,
|
||||
} from '@backstage/backend-common';
|
||||
import { IdentityApi } from '@backstage/plugin-auth-node';
|
||||
import { Server } from 'http';
|
||||
import { Logger } from 'winston';
|
||||
import { createRouter } from './router';
|
||||
@@ -54,6 +55,7 @@ export async function startStandaloneServer(
|
||||
logger,
|
||||
database: { getClient: async () => db },
|
||||
config: config,
|
||||
identity: {} as IdentityApi,
|
||||
});
|
||||
|
||||
let service = createServiceBuilder(module)
|
||||
|
||||
@@ -23,8 +23,11 @@ import {
|
||||
Typography,
|
||||
GridSize,
|
||||
} from '@material-ui/core';
|
||||
import { parseEntityRef } from '@backstage/catalog-model';
|
||||
import { Avatar, Link } from '@backstage/core-components';
|
||||
import { useRouteRef } from '@backstage/core-plugin-api';
|
||||
import { AboutField } from '@backstage/plugin-catalog';
|
||||
import { entityRouteRef } from '@backstage/plugin-catalog-react';
|
||||
import { StatusTag } from '../StatusTag';
|
||||
import { Member, BazaarProject } from '../../types';
|
||||
|
||||
@@ -49,6 +52,7 @@ export const CardContentFields = ({
|
||||
membersSize,
|
||||
}: Props) => {
|
||||
const classes = useStyles();
|
||||
const catalogEntityRoute = useRouteRef(entityRouteRef);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -111,8 +115,14 @@ export const CardContentFields = ({
|
||||
/>
|
||||
<Link
|
||||
className={classes.break}
|
||||
to={`http://github.com/${member.userId}`}
|
||||
target="_blank"
|
||||
to={
|
||||
member.userRef
|
||||
? `${catalogEntityRoute(
|
||||
parseEntityRef(member.userRef),
|
||||
)}`
|
||||
: `http://github.com/${member.userId}`
|
||||
}
|
||||
>
|
||||
{member?.userId}
|
||||
</Link>
|
||||
|
||||
@@ -19,6 +19,7 @@ export type Member = {
|
||||
userId: string;
|
||||
joinDate?: string;
|
||||
picture?: string;
|
||||
userRef?: string;
|
||||
};
|
||||
|
||||
export type Status = 'ongoing' | 'proposed';
|
||||
|
||||
@@ -37,6 +37,7 @@ export const parseMember = (member: any): Member => {
|
||||
return {
|
||||
itemId: member.item_id,
|
||||
userId: member.user_id,
|
||||
userRef: member.user_ref,
|
||||
joinDate: member.join_date,
|
||||
picture: member.picture,
|
||||
} as Member;
|
||||
|
||||
Reference in New Issue
Block a user