@platform-mesh/portal-server-lib 0.9.96 → 0.9.97
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/portal-options/index.d.ts +4 -0
- package/dist/portal-options/index.js +4 -0
- package/dist/portal-options/index.js.map +1 -1
- package/dist/portal-options/service-providers/content-configuration-service-providers.service.d.ts +4 -1
- package/dist/portal-options/service-providers/content-configuration-service-providers.service.js +14 -3
- package/dist/portal-options/service-providers/content-configuration-service-providers.service.js.map +1 -1
- package/dist/portal-options/service-providers/kubernetes-service-providers.service.d.ts +4 -2
- package/dist/portal-options/service-providers/kubernetes-service-providers.service.js +10 -4
- package/dist/portal-options/service-providers/kubernetes-service-providers.service.js.map +1 -1
- package/dist/portal-options/services/kcp-k8s.service.d.ts +0 -1
- package/dist/portal-options/services/kcp-k8s.service.js +4 -13
- package/dist/portal-options/services/kcp-k8s.service.js.map +1 -1
- package/dist/portal-options/services/permissions/adapters/authz-webhook.service.d.ts +14 -0
- package/dist/portal-options/services/permissions/adapters/authz-webhook.service.js +183 -0
- package/dist/portal-options/services/permissions/adapters/authz-webhook.service.js.map +1 -0
- package/dist/portal-options/services/permissions/models/permissions.model.d.ts +51 -0
- package/dist/portal-options/services/permissions/models/permissions.model.js +2 -0
- package/dist/portal-options/services/permissions/models/permissions.model.js.map +1 -0
- package/dist/portal-options/services/permissions/permissions-proxy.service.d.ts +9 -0
- package/dist/portal-options/services/permissions/permissions-proxy.service.js +48 -0
- package/dist/portal-options/services/permissions/permissions-proxy.service.js.map +1 -0
- package/dist/portal-options/services/permissions/permissions.controller.d.ts +9 -0
- package/dist/portal-options/services/permissions/permissions.controller.js +49 -0
- package/dist/portal-options/services/permissions/permissions.controller.js.map +1 -0
- package/dist/portal-options/utils/account-hierarchy-resolver.js +7 -3
- package/dist/portal-options/utils/account-hierarchy-resolver.js.map +1 -1
- package/dist/portal-options/utils/build-workspace-path.util.d.ts +1 -0
- package/dist/portal-options/utils/build-workspace-path.util.js +4 -0
- package/dist/portal-options/utils/build-workspace-path.util.js.map +1 -0
- package/dist/portal-options/utils/extract-resource-definitions.util.d.ts +7 -0
- package/dist/portal-options/utils/extract-resource-definitions.util.js +33 -0
- package/dist/portal-options/utils/extract-resource-definitions.util.js.map +1 -0
- package/package.json +1 -1
- package/src/portal-options/index.ts +4 -0
- package/src/portal-options/service-providers/content-configuration-service-providers.service.spec.ts +8 -1
- package/src/portal-options/service-providers/content-configuration-service-providers.service.ts +17 -6
- package/src/portal-options/service-providers/kubernetes-service-providers.service.spec.ts +13 -4
- package/src/portal-options/service-providers/kubernetes-service-providers.service.ts +21 -8
- package/src/portal-options/services/kcp-k8s.service.ts +4 -15
- package/src/portal-options/services/permissions/adapters/authz-webhook.service.spec.ts +500 -0
- package/src/portal-options/services/permissions/adapters/authz-webhook.service.ts +238 -0
- package/src/portal-options/services/permissions/models/permissions.model.ts +56 -0
- package/src/portal-options/services/permissions/permissions-proxy.service.spec.ts +232 -0
- package/src/portal-options/services/permissions/permissions-proxy.service.ts +58 -0
- package/src/portal-options/services/permissions/permissions.controller.spec.ts +143 -0
- package/src/portal-options/services/permissions/permissions.controller.ts +31 -0
- package/src/portal-options/utils/account-hierarchy-resolver.ts +13 -8
- package/src/portal-options/utils/build-workspace-path.util.spec.ts +59 -0
- package/src/portal-options/utils/build-workspace-path.util.ts +21 -0
- package/src/portal-options/utils/extract-resource-definitions.util.spec.ts +303 -0
- package/src/portal-options/utils/extract-resource-definitions.util.ts +62 -0
- package/tsconfig.json +2 -1
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { Body, Controller, Post, Req, UnauthorizedException } from '@nestjs/common';
|
|
14
|
+
import { HeaderParserService } from '@openmfp/portal-server-lib';
|
|
15
|
+
import { PermissionsProxyService } from './permissions-proxy.service.js';
|
|
16
|
+
let PermissionsController = class PermissionsController {
|
|
17
|
+
permissionsProxyService;
|
|
18
|
+
headerParser;
|
|
19
|
+
constructor(permissionsProxyService, headerParser) {
|
|
20
|
+
this.permissionsProxyService = permissionsProxyService;
|
|
21
|
+
this.headerParser = headerParser;
|
|
22
|
+
}
|
|
23
|
+
async checkResource(request, body) {
|
|
24
|
+
const token = this.headerParser.extractBearerToken(request);
|
|
25
|
+
if (!token) {
|
|
26
|
+
throw new UnauthorizedException();
|
|
27
|
+
}
|
|
28
|
+
const result = await this.permissionsProxyService.checkResourceInstance({
|
|
29
|
+
...body,
|
|
30
|
+
token,
|
|
31
|
+
});
|
|
32
|
+
return result ?? [];
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
__decorate([
|
|
36
|
+
Post('resource-check'),
|
|
37
|
+
__param(0, Req()),
|
|
38
|
+
__param(1, Body()),
|
|
39
|
+
__metadata("design:type", Function),
|
|
40
|
+
__metadata("design:paramtypes", [Request, Object]),
|
|
41
|
+
__metadata("design:returntype", Promise)
|
|
42
|
+
], PermissionsController.prototype, "checkResource", null);
|
|
43
|
+
PermissionsController = __decorate([
|
|
44
|
+
Controller('rest/permissions'),
|
|
45
|
+
__metadata("design:paramtypes", [PermissionsProxyService,
|
|
46
|
+
HeaderParserService])
|
|
47
|
+
], PermissionsController);
|
|
48
|
+
export { PermissionsController };
|
|
49
|
+
//# sourceMappingURL=permissions.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.controller.js","sourceRoot":"","sources":["../../../../src/portal-options/services/permissions/permissions.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAGlE,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IAEb;IACA;IAFnB,YACmB,uBAAgD,EAChD,YAAiC;QADjC,4BAAuB,GAAvB,uBAAuB,CAAyB;QAChD,iBAAY,GAAZ,YAAY,CAAqB;IACjD,CAAC;IAGE,AAAN,KAAK,CAAC,aAAa,CACV,OAAgB,EACf,IAA0B;QAElC,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAE5D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,qBAAqB,EAAE,CAAC;QACpC,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,qBAAqB,CAAC;YACtE,GAAG,IAAI;YACP,KAAK;SACN,CAAC,CAAC;QAEH,OAAO,MAAM,IAAI,EAAE,CAAC;IACtB,CAAC;CACF,CAAA;AAjBO;IADL,IAAI,CAAC,gBAAgB,CAAC;IAEpB,WAAA,GAAG,EAAE,CAAA;IACL,WAAA,IAAI,EAAE,CAAA;;qCADS,OAAO;;0DAexB;AAvBU,qBAAqB;IADjC,UAAU,CAAC,kBAAkB,CAAC;qCAGe,uBAAuB;QAClC,mBAAmB;GAHzC,qBAAqB,CAwBjC"}
|
|
@@ -2,7 +2,7 @@ import { replaceStringDeep } from './replace-string-deep.js';
|
|
|
2
2
|
const ACCOUNT_ENTITY_TYPE = 'core_platform-mesh_io_account';
|
|
3
3
|
export const updateEntityTypeFromAccountPath = (contentConfiguration, accountPath) => {
|
|
4
4
|
contentConfiguration.luigiConfigFragment.data.nodes.forEach((node) => {
|
|
5
|
-
if (!node.entityType
|
|
5
|
+
if (!node.entityType?.includes(ACCOUNT_ENTITY_TYPE)) {
|
|
6
6
|
return;
|
|
7
7
|
}
|
|
8
8
|
const accountPathParts = accountPath
|
|
@@ -15,12 +15,15 @@ export const updateEntityTypeFromAccountPath = (contentConfiguration, accountPat
|
|
|
15
15
|
return contentConfiguration;
|
|
16
16
|
};
|
|
17
17
|
export const updateAccountNodeChildren = (contentConfiguration, accountPath) => {
|
|
18
|
-
const
|
|
18
|
+
const children = contentConfiguration.luigiConfigFragment.data.nodes[0]?.children;
|
|
19
|
+
const accountChildrenNode = Array.isArray(children) ? children[0] : undefined;
|
|
19
20
|
if (accountChildrenNode) {
|
|
20
21
|
const nextHierarchyLevel = accountPath.split(':').filter(Boolean).length + 1;
|
|
21
22
|
const previousPathSegment = accountChildrenNode.pathSegment;
|
|
22
23
|
const nextPathSegment = `:${nextHierarchyLevel}_${ACCOUNT_ENTITY_TYPE}Id`;
|
|
23
|
-
|
|
24
|
+
if (previousPathSegment) {
|
|
25
|
+
replaceStringDeep(accountChildrenNode, previousPathSegment, nextPathSegment);
|
|
26
|
+
}
|
|
24
27
|
}
|
|
25
28
|
return contentConfiguration;
|
|
26
29
|
};
|
|
@@ -32,5 +35,6 @@ export const processContentConfigurationForAccountHierarchy = (contentConfigurat
|
|
|
32
35
|
}
|
|
33
36
|
return updateEntityTypeFromAccountPath(contentConfiguration, accountPath);
|
|
34
37
|
}
|
|
38
|
+
return contentConfiguration;
|
|
35
39
|
};
|
|
36
40
|
//# sourceMappingURL=account-hierarchy-resolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-hierarchy-resolver.js","sourceRoot":"","sources":["../../../src/portal-options/utils/account-hierarchy-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,MAAM,mBAAmB,GAAG,+BAA+B,CAAC;AAE5D,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAC7C,oBAA0C,EAC1C,WAAmB,EACG,EAAE;IACxB,oBAAoB,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACnE,IAAI,CAAC,IAAI,CAAC,UAAU,
|
|
1
|
+
{"version":3,"file":"account-hierarchy-resolver.js","sourceRoot":"","sources":["../../../src/portal-options/utils/account-hierarchy-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,MAAM,mBAAmB,GAAG,+BAA+B,CAAC;AAE5D,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAC7C,oBAA0C,EAC1C,WAAmB,EACG,EAAE;IACxB,oBAAoB,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACnE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YACpD,OAAO;QACT,CAAC;QAED,MAAM,gBAAgB,GAAG,WAAW;aACjC,KAAK,CAAC,GAAG,CAAC;aACV,MAAM,CAAC,OAAO,CAAC;aACf,GAAG,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC;aAC9B,IAAI,CAAC,GAAG,CAAC,CAAC;QAEb,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CACvC,mBAAmB,EACnB,gBAAgB,CACjB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,oBAAoB,CAAC;AAC9B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,oBAA0C,EAC1C,WAAmB,EACG,EAAE;IACxB,MAAM,QAAQ,GACZ,oBAAoB,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;IACnE,MAAM,mBAAmB,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE9E,IAAI,mBAAmB,EAAE,CAAC;QACxB,MAAM,kBAAkB,GACtB,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QACpD,MAAM,mBAAmB,GAAG,mBAAmB,CAAC,WAAW,CAAC;QAC5D,MAAM,eAAe,GAAG,IAAI,kBAAkB,IAAI,mBAAmB,IAAI,CAAC;QAE1E,IAAI,mBAAmB,EAAE,CAAC;YACxB,iBAAiB,CACf,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,CAChB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,oBAAoB,CAAC;AAC9B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,8CAA8C,GAAG,CAC5D,oBAA0C,EAC1C,OAA4B,EACN,EAAE;IACxB,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACxE,IAAI,WAAW,EAAE,CAAC;QAChB,IAAI,oBAAoB,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC7C,yBAAyB,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAC;QAC/D,CAAC;QAED,OAAO,+BAA+B,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAC;IAC5E,CAAC;IAED,OAAO,oBAAoB,CAAC;AAC9B,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function buildWorkspacePath(segments?: (string | undefined | null)[]): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-workspace-path.util.js","sourceRoot":"","sources":["../../../src/portal-options/utils/build-workspace-path.util.ts"],"names":[],"mappings":"AAaA,MAAM,UAAU,kBAAkB,CAChC,WAA0C,EAAE;IAE5C,OAAO,QAAQ,CAAC,MAAM,CACpB,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAC1D,WAAW,CACZ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ContentConfiguration } from '@openmfp/portal-server-lib';
|
|
2
|
+
import { PermissionsDefinition } from '../services/permissions/models/permissions.model.js';
|
|
3
|
+
export interface ResourceDefinitionLocal {
|
|
4
|
+
entity: string;
|
|
5
|
+
permissionsDefinition?: PermissionsDefinition;
|
|
6
|
+
}
|
|
7
|
+
export declare function extractResourceDefinitions(contentConfigurations: ContentConfiguration[]): ResourceDefinitionLocal[];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
function mergeResourceActions(existing, incoming) {
|
|
2
|
+
return [...new Set([...(existing ?? []), ...(incoming ?? [])])];
|
|
3
|
+
}
|
|
4
|
+
function collectFromNodes(nodes, acc) {
|
|
5
|
+
for (const node of nodes) {
|
|
6
|
+
const rd = node.context?.['resourceDefinition'];
|
|
7
|
+
if (rd?.entity !== undefined && rd.permissionsDefinition !== undefined) {
|
|
8
|
+
const existing = acc.get(rd.entity);
|
|
9
|
+
acc.set(rd.entity, {
|
|
10
|
+
...rd,
|
|
11
|
+
permissionsDefinition: {
|
|
12
|
+
...rd.permissionsDefinition,
|
|
13
|
+
resourceActions: mergeResourceActions(existing?.permissionsDefinition?.resourceActions, rd.permissionsDefinition.resourceActions),
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
const children = node.children;
|
|
18
|
+
if (Array.isArray(children) && children.length > 0) {
|
|
19
|
+
collectFromNodes(children, acc);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function extractResourceDefinitions(contentConfigurations) {
|
|
24
|
+
const acc = new Map();
|
|
25
|
+
for (const cc of contentConfigurations) {
|
|
26
|
+
const nodes = cc.luigiConfigFragment?.data?.nodes;
|
|
27
|
+
if (Array.isArray(nodes)) {
|
|
28
|
+
collectFromNodes(nodes, acc);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return Array.from(acc.values());
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=extract-resource-definitions.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-resource-definitions.util.js","sourceRoot":"","sources":["../../../src/portal-options/utils/extract-resource-definitions.util.ts"],"names":[],"mappings":"AAQA,SAAS,oBAAoB,CAC3B,QAA8B,EAC9B,QAA8B;IAE9B,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,gBAAgB,CACvB,KAAmE,EACnE,GAAyC;IAEzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,oBAAoB,CAEjC,CAAC;QAEd,IAAI,EAAE,EAAE,MAAM,KAAK,SAAS,IAAI,EAAE,CAAC,qBAAqB,KAAK,SAAS,EAAE,CAAC;YACvE,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;YAIpC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE;gBACjB,GAAG,EAAE;gBACL,qBAAqB,EAAE;oBACrB,GAAG,EAAE,CAAC,qBAAqB;oBAC3B,eAAe,EAAE,oBAAoB,CACnC,QAAQ,EAAE,qBAAqB,EAAE,eAAe,EAChD,EAAE,CAAC,qBAAqB,CAAC,eAAe,CACzC;iBACF;aACF,CAAC,CAAC;QACL,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnD,gBAAgB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,qBAA6C;IAE7C,MAAM,GAAG,GAAG,IAAI,GAAG,EAAmC,CAAC;IAEvD,KAAK,MAAM,EAAE,IAAI,qBAAqB,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,EAAE,CAAC,mBAAmB,EAAE,IAAI,EAAE,KAAK,CAAC;QAClD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,gBAAgB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;AAClC,CAAC"}
|
package/package.json
CHANGED
|
@@ -7,3 +7,7 @@ export * from './service-providers/content-configuration-service-providers.servi
|
|
|
7
7
|
export * from './service-providers/kubernetes-service-providers.service.js';
|
|
8
8
|
|
|
9
9
|
export * from './services/kcp-k8s.service.js';
|
|
10
|
+
export * from './services/permissions/adapters/authz-webhook.service.js';
|
|
11
|
+
export * from './services/permissions/models/permissions.model.js';
|
|
12
|
+
export * from './services/permissions/permissions-proxy.service.js';
|
|
13
|
+
export * from './services/permissions/permissions.controller.js';
|
package/src/portal-options/service-providers/content-configuration-service-providers.service.spec.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RequestContext } from '../pm-request-context-provider.js';
|
|
2
|
+
import { PermissionsProxyService } from '../services/permissions/permissions-proxy.service.js';
|
|
2
3
|
import { ContentConfigurationServiceProvidersService } from './content-configuration-service-providers.service.js';
|
|
3
4
|
import { welcomeNodeConfig } from './models/welcome-node-config.js';
|
|
4
5
|
import { GraphQLClient } from 'graphql-request';
|
|
@@ -18,9 +19,15 @@ describe('ContentConfigurationServiceProvidersService', () => {
|
|
|
18
19
|
let service: ContentConfigurationServiceProvidersService;
|
|
19
20
|
let mockClient: jest.Mocked<GraphQLClient>;
|
|
20
21
|
let context: RequestContext;
|
|
22
|
+
let permissionsProxyService: jest.Mocked<PermissionsProxyService>;
|
|
21
23
|
|
|
22
24
|
beforeEach(() => {
|
|
23
|
-
|
|
25
|
+
permissionsProxyService = {
|
|
26
|
+
resolvePermissions: jest.fn().mockResolvedValue([]),
|
|
27
|
+
} as unknown as jest.Mocked<PermissionsProxyService>;
|
|
28
|
+
service = new ContentConfigurationServiceProvidersService(
|
|
29
|
+
permissionsProxyService,
|
|
30
|
+
);
|
|
24
31
|
mockClient = new GraphQLClient('') as any;
|
|
25
32
|
(GraphQLClient as jest.Mock).mockReturnValue(mockClient);
|
|
26
33
|
context = {
|
package/src/portal-options/service-providers/content-configuration-service-providers.service.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import { RequestContext } from '../pm-request-context-provider.js';
|
|
2
|
-
import { processContentConfigurationForAccountHierarchy } from '../utils/account-hierarchy-resolver.js';
|
|
3
|
-
import { contentConfigurationsQuery } from './contentconfigurations-query.js';
|
|
4
|
-
import { ContentConfigurationQueryResponse } from './models/contentconfigurations.js';
|
|
5
|
-
import { welcomeNodeConfig } from './models/welcome-node-config.js';
|
|
6
1
|
import { Injectable } from '@nestjs/common';
|
|
7
2
|
import {
|
|
8
3
|
ContentConfiguration,
|
|
@@ -10,9 +5,17 @@ import {
|
|
|
10
5
|
ServiceProviderService,
|
|
11
6
|
} from '@openmfp/portal-server-lib';
|
|
12
7
|
import { GraphQLClient } from 'graphql-request';
|
|
8
|
+
import { RequestContext } from '../pm-request-context-provider.js';
|
|
9
|
+
import { PermissionsProxyService } from '../services/permissions/permissions-proxy.service.js';
|
|
10
|
+
import { processContentConfigurationForAccountHierarchy } from '../utils/account-hierarchy-resolver.js';
|
|
11
|
+
import { contentConfigurationsQuery } from './contentconfigurations-query.js';
|
|
12
|
+
import { ContentConfigurationQueryResponse } from './models/contentconfigurations.js';
|
|
13
|
+
import { welcomeNodeConfig } from './models/welcome-node-config.js';
|
|
13
14
|
|
|
14
15
|
@Injectable()
|
|
15
16
|
export class ContentConfigurationServiceProvidersService implements ServiceProviderService {
|
|
17
|
+
constructor(private permissionsProxyService: PermissionsProxyService) {}
|
|
18
|
+
|
|
16
19
|
async getServiceProviders(
|
|
17
20
|
token: string,
|
|
18
21
|
entities: string[],
|
|
@@ -31,7 +34,7 @@ export class ContentConfigurationServiceProvidersService implements ServiceProvi
|
|
|
31
34
|
throw new Error('Context with organization is required');
|
|
32
35
|
}
|
|
33
36
|
|
|
34
|
-
let url = context.crdGatewayApiUrl
|
|
37
|
+
let url = context.crdGatewayApiUrl!.replace(
|
|
35
38
|
'kubernetes-graphql-gateway/root',
|
|
36
39
|
'kubernetes-graphql-gateway/virtual-workspace/contentconfigurations/root',
|
|
37
40
|
);
|
|
@@ -112,6 +115,13 @@ export class ContentConfigurationServiceProvidersService implements ServiceProvi
|
|
|
112
115
|
}
|
|
113
116
|
});
|
|
114
117
|
|
|
118
|
+
const nodesPermissions = await this.permissionsProxyService.resolvePermissions(
|
|
119
|
+
token,
|
|
120
|
+
context.organization,
|
|
121
|
+
accountPath ?? '',
|
|
122
|
+
contentConfigurations,
|
|
123
|
+
);
|
|
124
|
+
|
|
115
125
|
return {
|
|
116
126
|
rawServiceProviders: [
|
|
117
127
|
{
|
|
@@ -119,6 +129,7 @@ export class ContentConfigurationServiceProvidersService implements ServiceProvi
|
|
|
119
129
|
displayName: '',
|
|
120
130
|
creationTimestamp: '',
|
|
121
131
|
contentConfiguration: contentConfigurations,
|
|
132
|
+
nodeContext: { nodesPermissions },
|
|
122
133
|
},
|
|
123
134
|
],
|
|
124
135
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { K8sRequestContext, K8sResourceDescriptor } from '../models/k8s.js';
|
|
2
2
|
import { KcpKubernetesService } from '../services/kcp-k8s.service.js';
|
|
3
|
+
import { PermissionsProxyService } from '../services/permissions/permissions-proxy.service.js';
|
|
3
4
|
import { KubernetesServiceProvidersService } from './kubernetes-service-providers.service.js';
|
|
4
5
|
import { welcomeNodeConfig } from './models/welcome-node-config.js';
|
|
5
6
|
import { Test, TestingModule } from '@nestjs/testing';
|
|
@@ -34,6 +35,7 @@ jest.mock('@kubernetes/client-node/dist/gen/middleware.js', () => ({
|
|
|
34
35
|
describe('KubernetesServiceProvidersService', () => {
|
|
35
36
|
let service: KubernetesServiceProvidersService;
|
|
36
37
|
let kcpKubernetesServiceMock: jest.Mocked<KcpKubernetesService>;
|
|
38
|
+
let permissionsProxyServiceMock: jest.Mocked<PermissionsProxyService>;
|
|
37
39
|
|
|
38
40
|
const mockToken = 'test-token-123';
|
|
39
41
|
const mockEntities = ['test-entity'];
|
|
@@ -44,6 +46,9 @@ describe('KubernetesServiceProvidersService', () => {
|
|
|
44
46
|
|
|
45
47
|
beforeEach(async () => {
|
|
46
48
|
kcpKubernetesServiceMock = mock<KcpKubernetesService>();
|
|
49
|
+
permissionsProxyServiceMock = {
|
|
50
|
+
resolvePermissions: jest.fn().mockResolvedValue([]),
|
|
51
|
+
} as unknown as jest.Mocked<PermissionsProxyService>;
|
|
47
52
|
|
|
48
53
|
const module: TestingModule = await Test.createTestingModule({
|
|
49
54
|
providers: [
|
|
@@ -52,6 +57,10 @@ describe('KubernetesServiceProvidersService', () => {
|
|
|
52
57
|
provide: KcpKubernetesService,
|
|
53
58
|
useValue: kcpKubernetesServiceMock,
|
|
54
59
|
},
|
|
60
|
+
{
|
|
61
|
+
provide: PermissionsProxyService,
|
|
62
|
+
useValue: permissionsProxyServiceMock,
|
|
63
|
+
},
|
|
55
64
|
],
|
|
56
65
|
}).compile();
|
|
57
66
|
|
|
@@ -443,7 +452,7 @@ describe('KubernetesServiceProvidersService', () => {
|
|
|
443
452
|
},
|
|
444
453
|
);
|
|
445
454
|
|
|
446
|
-
const svc = new KubernetesServiceProvidersService(kcpKubernetesServiceMock);
|
|
455
|
+
const svc = new KubernetesServiceProvidersService(kcpKubernetesServiceMock, permissionsProxyServiceMock);
|
|
447
456
|
const res = await svc.getServiceProviders('token', ['main'], {
|
|
448
457
|
organization: 'org',
|
|
449
458
|
isSubDomain: true,
|
|
@@ -477,7 +486,7 @@ describe('KubernetesServiceProvidersService', () => {
|
|
|
477
486
|
},
|
|
478
487
|
);
|
|
479
488
|
|
|
480
|
-
const svc = new KubernetesServiceProvidersService(kcpKubernetesServiceMock);
|
|
489
|
+
const svc = new KubernetesServiceProvidersService(kcpKubernetesServiceMock, permissionsProxyServiceMock);
|
|
481
490
|
const res = await svc.getServiceProviders('token', ['main'], {
|
|
482
491
|
organization: 'org',
|
|
483
492
|
isSubDomain: true,
|
|
@@ -524,7 +533,7 @@ describe('KubernetesServiceProvidersService', () => {
|
|
|
524
533
|
},
|
|
525
534
|
);
|
|
526
535
|
|
|
527
|
-
const svc = new KubernetesServiceProvidersService(kcpKubernetesServiceMock);
|
|
536
|
+
const svc = new KubernetesServiceProvidersService(kcpKubernetesServiceMock, permissionsProxyServiceMock);
|
|
528
537
|
const res = await svc.getServiceProviders('token', ['main'], {
|
|
529
538
|
organization: 'org',
|
|
530
539
|
isSubDomain: true,
|
|
@@ -560,7 +569,7 @@ describe('KubernetesServiceProvidersService', () => {
|
|
|
560
569
|
},
|
|
561
570
|
);
|
|
562
571
|
|
|
563
|
-
const svc = new KubernetesServiceProvidersService(kcpKubernetesServiceMock);
|
|
572
|
+
const svc = new KubernetesServiceProvidersService(kcpKubernetesServiceMock, permissionsProxyServiceMock);
|
|
564
573
|
const res = await svc.getServiceProviders('token', ['main'], {
|
|
565
574
|
organization: 'org',
|
|
566
575
|
isSubDomain: true,
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import { K8sRequestContext, K8sResourceDescriptor } from '../models/k8s.js';
|
|
2
|
-
import { KcpKubernetesService } from '../services/kcp-k8s.service.js';
|
|
3
|
-
import { processContentConfigurationForAccountHierarchy } from '../utils/account-hierarchy-resolver.js';
|
|
4
|
-
import { welcomeNodeConfig } from './models/welcome-node-config.js';
|
|
5
1
|
import { Injectable } from '@nestjs/common';
|
|
6
2
|
import {
|
|
7
3
|
ContentConfiguration,
|
|
8
4
|
ServiceProviderResponse,
|
|
9
5
|
ServiceProviderService,
|
|
10
6
|
} from '@openmfp/portal-server-lib';
|
|
7
|
+
import { K8sRequestContext, K8sResourceDescriptor } from '../models/k8s.js';
|
|
8
|
+
import { KcpKubernetesService } from '../services/kcp-k8s.service.js';
|
|
9
|
+
import { PermissionsProxyService } from '../services/permissions/permissions-proxy.service.js';
|
|
10
|
+
import { processContentConfigurationForAccountHierarchy } from '../utils/account-hierarchy-resolver.js';
|
|
11
|
+
import { welcomeNodeConfig } from './models/welcome-node-config.js';
|
|
11
12
|
|
|
12
13
|
@Injectable()
|
|
13
14
|
export class KubernetesServiceProvidersService implements ServiceProviderService {
|
|
14
|
-
constructor(
|
|
15
|
+
constructor(
|
|
16
|
+
private kcpKubernetesService: KcpKubernetesService,
|
|
17
|
+
private permissionsProxyService: PermissionsProxyService,
|
|
18
|
+
) {}
|
|
15
19
|
|
|
16
20
|
async getServiceProviders(
|
|
17
21
|
token: string,
|
|
@@ -30,7 +34,7 @@ export class KubernetesServiceProvidersService implements ServiceProviderService
|
|
|
30
34
|
if (!context?.organization) {
|
|
31
35
|
throw new Error('Context with organization is required');
|
|
32
36
|
}
|
|
33
|
-
|
|
37
|
+
|
|
34
38
|
const response = await this.listContentConfigurationsForEntity(
|
|
35
39
|
token,
|
|
36
40
|
context as K8sRequestContext,
|
|
@@ -62,6 +66,15 @@ export class KubernetesServiceProvidersService implements ServiceProviderService
|
|
|
62
66
|
return contentConfiguration;
|
|
63
67
|
});
|
|
64
68
|
|
|
69
|
+
const accountPath =
|
|
70
|
+
context?.accountPath ?? context?.['core_platform-mesh_io_account'] ?? '';
|
|
71
|
+
const nodesPermissions = await this.permissionsProxyService.resolvePermissions(
|
|
72
|
+
token,
|
|
73
|
+
context.organization,
|
|
74
|
+
accountPath,
|
|
75
|
+
contentConfigurations,
|
|
76
|
+
);
|
|
77
|
+
|
|
65
78
|
return {
|
|
66
79
|
rawServiceProviders: [
|
|
67
80
|
{
|
|
@@ -69,6 +82,7 @@ export class KubernetesServiceProvidersService implements ServiceProviderService
|
|
|
69
82
|
displayName: '',
|
|
70
83
|
creationTimestamp: '',
|
|
71
84
|
contentConfiguration: contentConfigurations,
|
|
85
|
+
nodeContext: { nodesPermissions },
|
|
72
86
|
},
|
|
73
87
|
],
|
|
74
88
|
};
|
|
@@ -90,12 +104,11 @@ export class KubernetesServiceProvidersService implements ServiceProviderService
|
|
|
90
104
|
context,
|
|
91
105
|
token,
|
|
92
106
|
);
|
|
93
|
-
} catch (error) {
|
|
107
|
+
} catch (error: any) {
|
|
94
108
|
console.error(error);
|
|
95
109
|
|
|
96
110
|
if (error.code == 429 || error.statusCode == 429) {
|
|
97
111
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
98
|
-
console.log('Retry after 1 second reading kubernetes resources.');
|
|
99
112
|
return await this.kcpKubernetesService.listClusterCustomObjectInKcpVirtualWorkspace(
|
|
100
113
|
gvr,
|
|
101
114
|
context,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { K8sRequestContext, K8sResourceDescriptor } from '../models/k8s.js';
|
|
2
|
+
import { buildWorkspacePath } from '../utils/build-workspace-path.util.js';
|
|
2
3
|
import { getOrganization } from '../utils/domain.js';
|
|
3
4
|
import {
|
|
4
5
|
CoreV1Api,
|
|
@@ -65,20 +66,8 @@ export class KcpKubernetesService {
|
|
|
65
66
|
return this.k8sCoreV1Api;
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
private buildWorkspacePath(organization?: string, account?: string) {
|
|
69
|
-
let path = `root:orgs`;
|
|
70
|
-
if (organization) {
|
|
71
|
-
path += `:${organization}`;
|
|
72
|
-
}
|
|
73
|
-
if (account) {
|
|
74
|
-
path += `:${account}`; // FIXME: how are nested accounts and paths handled in the portal?
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return path;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
69
|
getKcpVirtualWorkspaceUrl(organization: string, account: string) {
|
|
81
|
-
const path =
|
|
70
|
+
const path = buildWorkspacePath([organization, account]);
|
|
82
71
|
return new URL(
|
|
83
72
|
`${this.baseUrl.origin}/services/contentconfigurations/clusters/${path}`,
|
|
84
73
|
);
|
|
@@ -90,14 +79,14 @@ export class KcpKubernetesService {
|
|
|
90
79
|
workspacePath?: string,
|
|
91
80
|
) {
|
|
92
81
|
const path =
|
|
93
|
-
workspacePath ||
|
|
82
|
+
workspacePath || buildWorkspacePath([organization, account]);
|
|
94
83
|
return new URL(`${this.baseUrl.origin}/clusters/${path}`);
|
|
95
84
|
}
|
|
96
85
|
|
|
97
86
|
getKcpWorkspacePublicUrl(request: Request) {
|
|
98
87
|
const organization = getOrganization(request);
|
|
99
88
|
const account = request.query?.['core_platform-mesh_io_account'];
|
|
100
|
-
const path =
|
|
89
|
+
const path = buildWorkspacePath([organization, account]);
|
|
101
90
|
|
|
102
91
|
const kcpUrl = process.env.KCP_URL || '';
|
|
103
92
|
if (kcpUrl) {
|