Skip to content

Commit 4413eef

Browse files
authored
feat(extensions): update marketplace pluginId to extensions (#762)
* feat(extensions): update extension to extensions * update marketplace pluginId to extensions
1 parent 3939e71 commit 4413eef

24 files changed

Lines changed: 168 additions & 167 deletions
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@red-hat-developer-hub/backstage-plugin-marketplace-backend': patch
3+
'@red-hat-developer-hub/backstage-plugin-marketplace-common': patch
4+
'@red-hat-developer-hub/backstage-plugin-marketplace': patch
5+
---
6+
7+
updated `extension` to `extensions`
8+
update marketplace pluginId to extensions

workspaces/marketplace/plugins/catalog-backend-module-marketplace/src/module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import { MarketplacePackageProvider } from './providers/MarketplacePackageProvid
3333
*/
3434
export const catalogModuleMarketplace = createBackendModule({
3535
pluginId: 'catalog',
36-
moduleId: 'marketplace',
36+
moduleId: 'extensions',
3737
register(reg) {
3838
reg.registerInit({
3939
deps: {

workspaces/marketplace/plugins/marketplace-backend/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
},
1717
"backstage": {
1818
"role": "backend-plugin",
19-
"pluginId": "marketplace",
19+
"pluginId": "extensions",
2020
"pluginPackages": [
2121
"@red-hat-developer-hub/backstage-plugin-marketplace",
2222
"@red-hat-developer-hub/backstage-plugin-marketplace-backend",
@@ -37,6 +37,7 @@
3737
"@backstage/backend-plugin-api": "^1.2.0",
3838
"@backstage/catalog-client": "^1.9.1",
3939
"@backstage/catalog-model": "^1.7.3",
40+
"@backstage/errors": "^1.2.7",
4041
"@backstage/plugin-catalog-node": "^1.16.0",
4142
"@backstage/plugin-permission-common": "^0.8.4",
4243
"@backstage/plugin-permission-node": "^0.8.8",

workspaces/marketplace/plugins/marketplace-backend/src/permissions/rules.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
import { z } from 'zod';
2222
import {
2323
MarketplacePlugin,
24-
RESOURCE_TYPE_EXTENSION_PLUGIN,
24+
RESOURCE_TYPE_EXTENSIONS_PLUGIN,
2525
} from '@red-hat-developer-hub/backstage-plugin-marketplace-common';
2626

2727
export type ExtentionFilter = {
@@ -35,12 +35,12 @@ export type ExtentionFilters =
3535
| { not: ExtentionFilters }
3636
| ExtentionFilter;
3737

38-
export const extensionPermissionResourceRef = createPermissionResourceRef<
38+
export const extensionsPermissionResourceRef = createPermissionResourceRef<
3939
MarketplacePlugin,
4040
ExtentionFilter
4141
>().with({
42-
pluginId: 'marketplace',
43-
resourceType: RESOURCE_TYPE_EXTENSION_PLUGIN,
42+
pluginId: 'extensions',
43+
resourceType: RESOURCE_TYPE_EXTENSIONS_PLUGIN,
4444
});
4545

4646
export type ExtensionParams = {
@@ -52,18 +52,18 @@ export type ExtensionParams = {
5252
const hasPluginName = createPermissionRule({
5353
name: 'HAS_NAME',
5454
description: 'Should allow users to install the plugin with specified name',
55-
resourceRef: extensionPermissionResourceRef,
55+
resourceRef: extensionsPermissionResourceRef,
5656

5757
paramsSchema: z.object({
5858
pluginNames: z
5959
.string()
6060
.array()
6161
.optional()
62-
.describe('List of plugin names to match on'),
62+
.describe('List of plugin names or titles to match on'),
6363
}),
6464
apply: (plugin: MarketplacePlugin, { pluginNames }) => {
6565
return pluginNames && pluginNames.length > 0
66-
? !!pluginNames?.find(
66+
? pluginNames?.some(
6767
name =>
6868
name.toLowerCase() === plugin.metadata.title?.toLowerCase() ||
6969
name.toLowerCase() === plugin.metadata.name.toLowerCase(),
@@ -77,7 +77,7 @@ const hasAnnotation = createPermissionRule({
7777
name: 'HAS_ANNOTATION',
7878
description:
7979
'Should allow users to install the plugin with specified annotation',
80-
resourceRef: extensionPermissionResourceRef,
80+
resourceRef: extensionsPermissionResourceRef,
8181
paramsSchema: z.object({
8282
annotation: z.string().describe('Name of the annotation to match on'),
8383
value: z

workspaces/marketplace/plugins/marketplace-backend/src/plugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import { createRouter } from './router';
3333
* @public
3434
*/
3535
export const marketplacePlugin = createBackendPlugin({
36-
pluginId: 'marketplace',
36+
pluginId: 'extensions',
3737
register(env) {
3838
env.registerInit({
3939
deps: {

workspaces/marketplace/plugins/marketplace-backend/src/router.test.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ const setupTest = () => {
6868
onUnhandledRequest: (req, print) => {
6969
if (
7070
req.url.pathname === '/' ||
71-
req.url.pathname.startsWith('/api/marketplace')
71+
req.url.pathname.startsWith('/api/extensions')
7272
) {
7373
// bypass
7474
return;
@@ -142,7 +142,7 @@ describe('createRouter', () => {
142142
});
143143

144144
const response = await request(backendServer).get(
145-
'/api/marketplace/collections',
145+
'/api/extensions/collections',
146146
);
147147

148148
expect(response.status).toEqual(200);
@@ -159,7 +159,7 @@ describe('createRouter', () => {
159159
});
160160

161161
const response = await request(backendServer).get(
162-
'/api/marketplace/collection/default/featured-plugins',
162+
'/api/extensions/collection/default/featured-plugins',
163163
);
164164

165165
expect(response.status).toEqual(200);
@@ -175,7 +175,7 @@ describe('createRouter', () => {
175175
});
176176

177177
const response = await request(backendServer).get(
178-
'/api/marketplace/collection/default/not-found',
178+
'/api/extensions/collection/default/not-found',
179179
);
180180

181181
expect(response.status).toEqual(404);
@@ -214,7 +214,7 @@ describe('createRouter', () => {
214214
);
215215

216216
const response = await request(backendServer).get(
217-
'/api/marketplace/collection/default/featured-plugins/plugins',
217+
'/api/extensions/collection/default/featured-plugins/plugins',
218218
);
219219

220220
expect(response.status).toEqual(200);
@@ -237,7 +237,7 @@ describe('createRouter', () => {
237237
);
238238

239239
const response = await request(backendServer).get(
240-
'/api/marketplace/collection/default/featured-plugins/plugins',
240+
'/api/extensions/collection/default/featured-plugins/plugins',
241241
);
242242

243243
expect(response.status).toEqual(200);
@@ -252,7 +252,7 @@ describe('createRouter', () => {
252252
});
253253

254254
const response = await request(backendServer).get(
255-
'/api/marketplace/collection/default/not-found/plugins',
255+
'/api/extensions/collection/default/not-found/plugins',
256256
);
257257

258258
expect(response.status).toEqual(404);
@@ -288,7 +288,7 @@ describe('createRouter', () => {
288288
});
289289

290290
const response = await request(backendServer).get(
291-
'/api/marketplace/collections/facets?facet=spec.categories',
291+
'/api/extensions/collections/facets?facet=spec.categories',
292292
);
293293

294294
expect(response.status).toEqual(200);
@@ -315,7 +315,7 @@ describe('createRouter', () => {
315315
mockData: mockPlugins,
316316
});
317317
const response = await request(backendServer).get(
318-
'/api/marketplace/plugins',
318+
'/api/extensions/plugins',
319319
);
320320
expect(response.status).toEqual(200);
321321
expect(response.body.items).toHaveLength(2);
@@ -328,7 +328,7 @@ describe('createRouter', () => {
328328
});
329329

330330
const response = await request(backendServer).get(
331-
'/api/marketplace/plugin/default/plugin1',
331+
'/api/extensions/plugin/default/plugin1',
332332
);
333333

334334
expect(response.status).toEqual(200);
@@ -341,7 +341,7 @@ describe('createRouter', () => {
341341
name: 'invalid-plugin',
342342
});
343343
const response = await request(backendServer).get(
344-
'/api/marketplace/plugin/default/invalid-plugin',
344+
'/api/extensions/plugin/default/invalid-plugin',
345345
);
346346

347347
expect(response.status).toEqual(404);

workspaces/marketplace/plugins/marketplace-backend/src/router.ts

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import express, { Request } from 'express';
1818
import Router from 'express-promise-router';
19-
19+
import { NotAllowedError } from '@backstage/errors';
2020
import {
2121
HttpAuthService,
2222
PermissionsService,
@@ -31,12 +31,12 @@ import {
3131
import {
3232
decodeGetEntitiesRequest,
3333
decodeGetEntityFacetsRequest,
34-
extensionPluginCreatePermission,
35-
extensionPluginReadPermission,
34+
extensionsPluginWritePermission,
35+
extensionsPluginReadPermission,
3636
MarketplaceApi,
3737
MarketplacePlugin,
38-
RESOURCE_TYPE_EXTENSION_PLUGIN,
39-
extensionPermissions,
38+
RESOURCE_TYPE_EXTENSIONS_PLUGIN,
39+
extensionsPermissions,
4040
} from '@red-hat-developer-hub/backstage-plugin-marketplace-common';
4141
import { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';
4242
import { createSearchParams } from './utils/createSearchParams';
@@ -55,8 +55,8 @@ export async function createRouter({
5555
}): Promise<express.Router> {
5656
const router = Router();
5757
const permissionsIntegrationRouter = createPermissionIntegrationRouter({
58-
resourceType: RESOURCE_TYPE_EXTENSION_PLUGIN,
59-
permissions: extensionPermissions,
58+
resourceType: RESOURCE_TYPE_EXTENSIONS_PLUGIN,
59+
permissions: extensionsPermissions,
6060
rules: Object.values(extensionRules),
6161
});
6262
router.use(express.json());
@@ -65,7 +65,7 @@ export async function createRouter({
6565
const authorizeConditional = async (
6666
request: Request,
6767
permission:
68-
| ResourcePermission<'extension-plugin' | 'extension-package'>
68+
| ResourcePermission<'extensions-plugin' | 'extensions-package'>
6969
| BasicPermission,
7070
) => {
7171
const credentials = await httpAuth.credentials(request);
@@ -163,18 +163,18 @@ export async function createRouter({
163163
'/plugin/:namespace/:name/configuration/authorize',
164164
async (req, res) => {
165165
const [readDecision, installDecision] = await Promise.all([
166-
authorizeConditional(req, extensionPluginReadPermission),
167-
authorizeConditional(req, extensionPluginCreatePermission),
166+
authorizeConditional(req, extensionsPluginReadPermission),
167+
authorizeConditional(req, extensionsPluginWritePermission),
168168
]);
169169
if (
170170
readDecision.result === AuthorizeResult.DENY &&
171171
installDecision.result === AuthorizeResult.DENY
172172
) {
173-
res.status(403);
173+
res.status(200).json({ read: 'DENY', write: 'DENY' });
174174
return;
175175
}
176176

177-
const authorizedActions: string[] = [];
177+
let authorizedActions = {};
178178
let plugin: MarketplacePlugin;
179179

180180
const evaluateConditional = async (
@@ -189,34 +189,35 @@ export async function createRouter({
189189
);
190190
}
191191
if (matches(plugin, decision.conditions)) {
192-
authorizedActions.push(action);
192+
authorizedActions = { ...authorizedActions, [action]: 'ALLOW' };
193193
}
194194
} else if (decision.result === AuthorizeResult.ALLOW) {
195-
authorizedActions.push(action);
195+
authorizedActions = { ...authorizedActions, [action]: 'ALLOW' };
196196
}
197197
};
198198

199199
await Promise.all([
200200
evaluateConditional(readDecision, 'read'),
201-
evaluateConditional(installDecision, 'create'),
201+
evaluateConditional(installDecision, 'write'),
202202
]);
203203

204-
if (authorizedActions.length === 0) {
205-
res.status(403);
206-
return;
204+
if (Object.keys(authorizedActions).length === 0) {
205+
res.status(200).json({ read: 'DENY', write: 'DENY' });
206+
} else {
207+
res.status(200).json(authorizedActions);
207208
}
208-
res.status(200).json({ authorizedActions });
209209
},
210210
);
211211

212212
router.get('/plugin/:namespace/:name/configuration', async (req, res) => {
213213
const readDecision = await authorizeConditional(
214214
req,
215-
extensionPluginReadPermission,
215+
extensionsPluginReadPermission,
216216
);
217217
if (readDecision.result === AuthorizeResult.DENY) {
218-
res.status(403).json({ error: 'Forbidden' });
219-
return;
218+
throw new NotAllowedError(
219+
`Not allowed to read the configuration of ${req.params.namespace}:${req.params.name}`,
220+
);
220221
}
221222

222223
const plugin = await marketplaceApi.getPluginByName(
@@ -229,8 +230,9 @@ export async function createRouter({
229230
(readDecision.result === AuthorizeResult.CONDITIONAL &&
230231
matches(plugin, readDecision.conditions));
231232
if (!hasReadAccess) {
232-
res.status(403).json({ error: 'Forbidden' });
233-
return;
233+
throw new NotAllowedError(
234+
`Not allowed to read the configuration of ${req.params.namespace}:${req.params.name}`,
235+
);
234236
}
235237

236238
res.status(200).json({}); // This should return the configuration in YAML string
@@ -240,11 +242,12 @@ export async function createRouter({
240242
// installs the plugin
241243
const installDecision = await authorizeConditional(
242244
req,
243-
extensionPluginCreatePermission,
245+
extensionsPluginWritePermission,
244246
);
245247
if (installDecision.result === AuthorizeResult.DENY) {
246-
res.status(403).json({ error: 'Forbidden' });
247-
return;
248+
throw new NotAllowedError(
249+
`Not allowed to configure ${req.params.namespace}:${req.params.name}`,
250+
);
248251
}
249252

250253
const plugin = await marketplaceApi.getPluginByName(
@@ -258,8 +261,9 @@ export async function createRouter({
258261
matches(plugin, installDecision.conditions));
259262

260263
if (!hasInstallAccess) {
261-
res.status(403).json({ error: 'Forbidden' });
262-
return;
264+
throw new NotAllowedError(
265+
`Not allowed to configure ${req.params.namespace}:${req.params.name}`,
266+
);
263267
}
264268

265269
res.status(200).json({});

workspaces/marketplace/plugins/marketplace-common/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
},
1919
"backstage": {
2020
"role": "common-library",
21-
"pluginId": "marketplace",
21+
"pluginId": "extensions",
2222
"pluginPackages": [
2323
"@red-hat-developer-hub/backstage-plugin-marketplace",
2424
"@red-hat-developer-hub/backstage-plugin-marketplace-backend",

0 commit comments

Comments
 (0)