@kuadrant/kuadrant-backstage-plugin-frontend 0.0.1-test.1-2bfd8489 → 0.0.1-test.1-57ace816
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/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js +52 -23
- package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js.map +1 -1
- package/dist/components/ApprovalQueueCard/ApprovalQueueCard.esm.js +148 -29
- package/dist/components/ApprovalQueueCard/ApprovalQueueCard.esm.js.map +1 -1
- package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js +43 -28
- package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js.map +1 -1
- package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js +258 -0
- package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js.map +1 -0
- package/dist/components/KuadrantPage/KuadrantPage.esm.js +85 -34
- package/dist/components/KuadrantPage/KuadrantPage.esm.js.map +1 -1
- package/dist/components/PermissionGate/PermissionGate.esm.js +7 -16
- package/dist/components/PermissionGate/PermissionGate.esm.js.map +1 -1
- package/dist/index.d.ts +81 -1
- package/dist/index.esm.js +1 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/permissions.esm.js +103 -0
- package/dist/permissions.esm.js.map +1 -0
- package/dist/utils/permissions.esm.js +19 -0
- package/dist/utils/permissions.esm.js.map +1 -0
- package/package.json +1 -1
- package/dist/hooks/useUserRole.esm.js +0 -49
- package/dist/hooks/useUserRole.esm.js.map +0 -1
|
@@ -1,30 +1,21 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Box, Typography } from '@material-ui/core';
|
|
3
3
|
import { Progress } from '@backstage/core-components';
|
|
4
|
-
import {
|
|
4
|
+
import { useKuadrantPermission } from '../../utils/permissions.esm.js';
|
|
5
5
|
|
|
6
|
-
const PermissionGate = ({ children,
|
|
7
|
-
const {
|
|
6
|
+
const PermissionGate = ({ children, permission, fallback, errorMessage }) => {
|
|
7
|
+
const { allowed, loading, error } = useKuadrantPermission(permission);
|
|
8
8
|
if (loading) {
|
|
9
9
|
return /* @__PURE__ */ React.createElement(Progress, null);
|
|
10
10
|
}
|
|
11
|
-
if (
|
|
12
|
-
return /* @__PURE__ */ React.createElement(React.
|
|
11
|
+
if (error) {
|
|
12
|
+
return /* @__PURE__ */ React.createElement(Box, { p: 4 }, /* @__PURE__ */ React.createElement(Typography, { color: "error" }, "Unable to check permissions: ", error.message), /* @__PURE__ */ React.createElement(Typography, { variant: "body2", color: "textSecondary" }, "Please try again or contact your administrator"));
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
if (requireRole) {
|
|
16
|
-
return userInfo.role === requireRole;
|
|
17
|
-
}
|
|
18
|
-
if (requireAnyRole) {
|
|
19
|
-
return requireAnyRole.includes(userInfo.role);
|
|
20
|
-
}
|
|
21
|
-
return true;
|
|
22
|
-
};
|
|
23
|
-
if (!hasPermission()) {
|
|
14
|
+
if (!allowed) {
|
|
24
15
|
if (fallback) {
|
|
25
16
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, fallback);
|
|
26
17
|
}
|
|
27
|
-
return /* @__PURE__ */ React.createElement(Box, { p: 4 }, /* @__PURE__ */ React.createElement(Typography, { color: "textSecondary" }, "
|
|
18
|
+
return /* @__PURE__ */ React.createElement(Box, { p: 4 }, /* @__PURE__ */ React.createElement(Typography, { color: "textSecondary" }, errorMessage || "You don't have permission to view this page"), /* @__PURE__ */ React.createElement(Box, { mt: 1 }, /* @__PURE__ */ React.createElement(Typography, { variant: "caption", color: "textSecondary" }, "Required permission: ", permission.name)));
|
|
28
19
|
}
|
|
29
20
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, children);
|
|
30
21
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PermissionGate.esm.js","sources":["../../../src/components/PermissionGate/PermissionGate.tsx"],"sourcesContent":["import React from 'react';\nimport { Typography, Box } from '@material-ui/core';\nimport { Progress } from '@backstage/core-components';\nimport {
|
|
1
|
+
{"version":3,"file":"PermissionGate.esm.js","sources":["../../../src/components/PermissionGate/PermissionGate.tsx"],"sourcesContent":["import React from 'react';\nimport { Typography, Box } from '@material-ui/core';\nimport { Progress } from '@backstage/core-components';\nimport { Permission } from '@backstage/plugin-permission-common';\nimport { useKuadrantPermission } from '../../utils/permissions';\n\ninterface PermissionGateProps {\n children: React.ReactNode;\n permission: Permission;\n fallback?: React.ReactNode;\n errorMessage?: string;\n}\n\nexport const PermissionGate = ({ children, permission, fallback, errorMessage }: PermissionGateProps) => {\n const { allowed, loading, error } = useKuadrantPermission(permission);\n\n if (loading) {\n return <Progress />;\n }\n\n if (error) {\n return (\n <Box p={4}>\n <Typography color=\"error\">\n Unable to check permissions: {error.message}\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Please try again or contact your administrator\n </Typography>\n </Box>\n );\n }\n\n if (!allowed) {\n if (fallback) {\n return <>{fallback}</>;\n }\n return (\n <Box p={4}>\n <Typography color=\"textSecondary\">\n {errorMessage || 'You don\\'t have permission to view this page'}\n </Typography>\n <Box mt={1}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Required permission: {permission.name}\n </Typography>\n </Box>\n </Box>\n );\n }\n\n return <>{children}</>;\n};\n"],"names":[],"mappings":";;;;;AAaO,MAAM,iBAAiB,CAAC,EAAE,UAAU,UAAY,EAAA,QAAA,EAAU,cAAwC,KAAA;AACvG,EAAA,MAAM,EAAE,OAAS,EAAA,OAAA,EAAS,KAAM,EAAA,GAAI,sBAAsB,UAAU,CAAA;AAEpE,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2CAAQ,QAAS,EAAA,IAAA,CAAA;AAAA;AAGnB,EAAA,IAAI,KAAO,EAAA;AACT,IAAA,2CACG,GAAI,EAAA,EAAA,CAAA,EAAG,qBACL,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAM,OAAQ,EAAA,EAAA,+BAAA,EACM,MAAM,OACtC,CAAA,sCACC,UAAW,EAAA,EAAA,OAAA,EAAQ,SAAQ,KAAM,EAAA,eAAA,EAAA,EAAgB,gDAElD,CACF,CAAA;AAAA;AAIJ,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAA,IAAI,QAAU,EAAA;AACZ,MAAA,iEAAU,QAAS,CAAA;AAAA;AAErB,IACE,uBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,CAAA,EAAG,CACN,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,KAAM,EAAA,eAAA,EAAA,EACf,YAAgB,IAAA,6CACnB,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,OAAI,EAAI,EAAA,CAAA,EAAA,kBACN,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,SAAA,EAAU,KAAM,EAAA,eAAA,EAAA,EAAgB,uBAC5B,EAAA,UAAA,CAAW,IACnC,CACF,CACF,CAAA;AAAA;AAIJ,EAAA,iEAAU,QAAS,CAAA;AACrB;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import react__default from 'react';
|
|
3
3
|
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
4
|
+
import * as _backstage_plugin_permission_common from '@backstage/plugin-permission-common';
|
|
4
5
|
|
|
5
6
|
interface ApiKeyManagementTabProps {
|
|
6
7
|
namespace?: string;
|
|
@@ -28,4 +29,83 @@ declare const ApiProductInfoCard: () => react__default.JSX.Element;
|
|
|
28
29
|
|
|
29
30
|
declare const ApprovalQueueCard: () => react__default.JSX.Element;
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
/**
|
|
33
|
+
* permission definitions for the kuadrant plugin
|
|
34
|
+
*
|
|
35
|
+
* these permissions control access to kuadrant resources and operations.
|
|
36
|
+
* they must match the permissions defined in the backend plugin.
|
|
37
|
+
*
|
|
38
|
+
* permission types:
|
|
39
|
+
* - BasicPermission: standard permission that applies globally
|
|
40
|
+
* - ResourcePermission: permission scoped to specific resource types (e.g., apiproduct)
|
|
41
|
+
*
|
|
42
|
+
* permission patterns:
|
|
43
|
+
* - `.create` - create new resources
|
|
44
|
+
* - `.read` - read resource details
|
|
45
|
+
* - `.read.own` - read only resources owned by the user
|
|
46
|
+
* - `.read.all` - read all resources regardless of ownership
|
|
47
|
+
* - `.update` - modify existing resources
|
|
48
|
+
* - `.delete` - delete resources
|
|
49
|
+
* - `.delete.own` - delete only resources owned by the user
|
|
50
|
+
* - `.delete.all` - delete any resource regardless of ownership
|
|
51
|
+
* - `.list` - list/view collections of resources
|
|
52
|
+
*/
|
|
53
|
+
declare const kuadrantPlanPolicyCreatePermission: _backstage_plugin_permission_common.BasicPermission;
|
|
54
|
+
declare const kuadrantPlanPolicyReadPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
55
|
+
declare const kuadrantPlanPolicyUpdatePermission: _backstage_plugin_permission_common.BasicPermission;
|
|
56
|
+
declare const kuadrantPlanPolicyDeletePermission: _backstage_plugin_permission_common.BasicPermission;
|
|
57
|
+
declare const kuadrantPlanPolicyListPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
58
|
+
declare const kuadrantApiProductCreatePermission: _backstage_plugin_permission_common.BasicPermission;
|
|
59
|
+
declare const kuadrantApiProductReadPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
60
|
+
declare const kuadrantApiProductUpdatePermission: _backstage_plugin_permission_common.BasicPermission;
|
|
61
|
+
declare const kuadrantApiProductDeletePermission: _backstage_plugin_permission_common.BasicPermission;
|
|
62
|
+
declare const kuadrantApiProductListPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
63
|
+
/**
|
|
64
|
+
* permission to create API key requests
|
|
65
|
+
*
|
|
66
|
+
* this is a ResourcePermission scoped to 'apiproduct', allowing
|
|
67
|
+
* fine-grained control over which API products users can request access to.
|
|
68
|
+
*
|
|
69
|
+
* use in frontend: useKuadrantPermission(kuadrantApiKeyRequestCreatePermission)
|
|
70
|
+
* use in backend with resource: { permission, resourceRef: 'apiproduct:namespace/name' }
|
|
71
|
+
*/
|
|
72
|
+
declare const kuadrantApiKeyRequestCreatePermission: _backstage_plugin_permission_common.ResourcePermission<"apiproduct">;
|
|
73
|
+
/**
|
|
74
|
+
* permission to read API key requests created by the current user
|
|
75
|
+
* use this for allowing users to see their own request history
|
|
76
|
+
*/
|
|
77
|
+
declare const kuadrantApiKeyRequestReadOwnPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
78
|
+
/**
|
|
79
|
+
* permission to read all API key requests regardless of who created them
|
|
80
|
+
* use this for platform engineers/admins who need to view the approval queue
|
|
81
|
+
*/
|
|
82
|
+
declare const kuadrantApiKeyRequestReadAllPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
83
|
+
/**
|
|
84
|
+
* permission to approve or reject API key requests
|
|
85
|
+
* typically granted to API owners and platform engineers
|
|
86
|
+
*/
|
|
87
|
+
declare const kuadrantApiKeyRequestUpdatePermission: _backstage_plugin_permission_common.BasicPermission;
|
|
88
|
+
declare const kuadrantApiKeyRequestListPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
89
|
+
/**
|
|
90
|
+
* permission to read API keys owned by the current user
|
|
91
|
+
* allows users to view their own active API keys
|
|
92
|
+
*/
|
|
93
|
+
declare const kuadrantApiKeyReadOwnPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
94
|
+
/**
|
|
95
|
+
* permission to read all API keys regardless of ownership
|
|
96
|
+
* for platform engineers/admins who need to audit keys
|
|
97
|
+
*/
|
|
98
|
+
declare const kuadrantApiKeyReadAllPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
99
|
+
/**
|
|
100
|
+
* permission to delete API keys owned by the current user
|
|
101
|
+
* allows users to revoke their own access
|
|
102
|
+
*/
|
|
103
|
+
declare const kuadrantApiKeyDeleteOwnPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
104
|
+
/**
|
|
105
|
+
* permission to delete any API key regardless of ownership
|
|
106
|
+
* for platform engineers/admins who need to revoke access
|
|
107
|
+
*/
|
|
108
|
+
declare const kuadrantApiKeyDeleteAllPermission: _backstage_plugin_permission_common.BasicPermission;
|
|
109
|
+
declare const kuadrantPermissions: (_backstage_plugin_permission_common.BasicPermission | _backstage_plugin_permission_common.ResourcePermission<"apiproduct">)[];
|
|
110
|
+
|
|
111
|
+
export { ApiAccessCard, ApiKeyManagementTab, ApiProductInfoCard, ApprovalQueueCard, EntityKuadrantApiAccessCard, EntityKuadrantApiKeyManagementTab, EntityKuadrantApiKeysContent, EntityKuadrantApiProductInfoContent, KuadrantApprovalQueueCard, KuadrantPage, PlanPolicyDetailPage, kuadrantApiKeyDeleteAllPermission, kuadrantApiKeyDeleteOwnPermission, kuadrantApiKeyReadAllPermission, kuadrantApiKeyReadOwnPermission, kuadrantApiKeyRequestCreatePermission, kuadrantApiKeyRequestListPermission, kuadrantApiKeyRequestReadAllPermission, kuadrantApiKeyRequestReadOwnPermission, kuadrantApiKeyRequestUpdatePermission, kuadrantApiProductCreatePermission, kuadrantApiProductDeletePermission, kuadrantApiProductListPermission, kuadrantApiProductReadPermission, kuadrantApiProductUpdatePermission, kuadrantPermissions, kuadrantPlanPolicyCreatePermission, kuadrantPlanPolicyDeletePermission, kuadrantPlanPolicyListPermission, kuadrantPlanPolicyReadPermission, kuadrantPlanPolicyUpdatePermission, kuadrantPlugin };
|
package/dist/index.esm.js
CHANGED
|
@@ -3,4 +3,5 @@ export { ApiAccessCard } from './components/ApiAccessCard/ApiAccessCard.esm.js';
|
|
|
3
3
|
export { ApiKeyManagementTab } from './components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js';
|
|
4
4
|
export { ApiProductInfoCard } from './components/ApiProductInfoCard/ApiProductInfoCard.esm.js';
|
|
5
5
|
export { ApprovalQueueCard } from './components/ApprovalQueueCard/ApprovalQueueCard.esm.js';
|
|
6
|
+
export { kuadrantApiKeyDeleteAllPermission, kuadrantApiKeyDeleteOwnPermission, kuadrantApiKeyReadAllPermission, kuadrantApiKeyReadOwnPermission, kuadrantApiKeyRequestCreatePermission, kuadrantApiKeyRequestListPermission, kuadrantApiKeyRequestReadAllPermission, kuadrantApiKeyRequestReadOwnPermission, kuadrantApiKeyRequestUpdatePermission, kuadrantApiProductCreatePermission, kuadrantApiProductDeletePermission, kuadrantApiProductListPermission, kuadrantApiProductReadPermission, kuadrantApiProductUpdatePermission, kuadrantPermissions, kuadrantPlanPolicyCreatePermission, kuadrantPlanPolicyDeletePermission, kuadrantPlanPolicyListPermission, kuadrantPlanPolicyReadPermission, kuadrantPlanPolicyUpdatePermission } from './permissions.esm.js';
|
|
6
7
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { createPermission } from '@backstage/plugin-permission-common';
|
|
2
|
+
|
|
3
|
+
const kuadrantPlanPolicyCreatePermission = createPermission({
|
|
4
|
+
name: "kuadrant.planpolicy.create",
|
|
5
|
+
attributes: { action: "create" }
|
|
6
|
+
});
|
|
7
|
+
const kuadrantPlanPolicyReadPermission = createPermission({
|
|
8
|
+
name: "kuadrant.planpolicy.read",
|
|
9
|
+
attributes: { action: "read" }
|
|
10
|
+
});
|
|
11
|
+
const kuadrantPlanPolicyUpdatePermission = createPermission({
|
|
12
|
+
name: "kuadrant.planpolicy.update",
|
|
13
|
+
attributes: { action: "update" }
|
|
14
|
+
});
|
|
15
|
+
const kuadrantPlanPolicyDeletePermission = createPermission({
|
|
16
|
+
name: "kuadrant.planpolicy.delete",
|
|
17
|
+
attributes: { action: "delete" }
|
|
18
|
+
});
|
|
19
|
+
const kuadrantPlanPolicyListPermission = createPermission({
|
|
20
|
+
name: "kuadrant.planpolicy.list",
|
|
21
|
+
attributes: { action: "read" }
|
|
22
|
+
});
|
|
23
|
+
const kuadrantApiProductCreatePermission = createPermission({
|
|
24
|
+
name: "kuadrant.apiproduct.create",
|
|
25
|
+
attributes: { action: "create" }
|
|
26
|
+
});
|
|
27
|
+
const kuadrantApiProductReadPermission = createPermission({
|
|
28
|
+
name: "kuadrant.apiproduct.read",
|
|
29
|
+
attributes: { action: "read" }
|
|
30
|
+
});
|
|
31
|
+
const kuadrantApiProductUpdatePermission = createPermission({
|
|
32
|
+
name: "kuadrant.apiproduct.update",
|
|
33
|
+
attributes: { action: "update" }
|
|
34
|
+
});
|
|
35
|
+
const kuadrantApiProductDeletePermission = createPermission({
|
|
36
|
+
name: "kuadrant.apiproduct.delete",
|
|
37
|
+
attributes: { action: "delete" }
|
|
38
|
+
});
|
|
39
|
+
const kuadrantApiProductListPermission = createPermission({
|
|
40
|
+
name: "kuadrant.apiproduct.list",
|
|
41
|
+
attributes: { action: "read" }
|
|
42
|
+
});
|
|
43
|
+
const kuadrantApiKeyRequestCreatePermission = createPermission({
|
|
44
|
+
name: "kuadrant.apikeyrequest.create",
|
|
45
|
+
attributes: { action: "create" },
|
|
46
|
+
resourceType: "apiproduct"
|
|
47
|
+
});
|
|
48
|
+
const kuadrantApiKeyRequestReadOwnPermission = createPermission({
|
|
49
|
+
name: "kuadrant.apikeyrequest.read.own",
|
|
50
|
+
attributes: { action: "read" }
|
|
51
|
+
});
|
|
52
|
+
const kuadrantApiKeyRequestReadAllPermission = createPermission({
|
|
53
|
+
name: "kuadrant.apikeyrequest.read.all",
|
|
54
|
+
attributes: { action: "read" }
|
|
55
|
+
});
|
|
56
|
+
const kuadrantApiKeyRequestUpdatePermission = createPermission({
|
|
57
|
+
name: "kuadrant.apikeyrequest.update",
|
|
58
|
+
attributes: { action: "update" }
|
|
59
|
+
});
|
|
60
|
+
const kuadrantApiKeyRequestListPermission = createPermission({
|
|
61
|
+
name: "kuadrant.apikeyrequest.list",
|
|
62
|
+
attributes: { action: "read" }
|
|
63
|
+
});
|
|
64
|
+
const kuadrantApiKeyReadOwnPermission = createPermission({
|
|
65
|
+
name: "kuadrant.apikey.read.own",
|
|
66
|
+
attributes: { action: "read" }
|
|
67
|
+
});
|
|
68
|
+
const kuadrantApiKeyReadAllPermission = createPermission({
|
|
69
|
+
name: "kuadrant.apikey.read.all",
|
|
70
|
+
attributes: { action: "read" }
|
|
71
|
+
});
|
|
72
|
+
const kuadrantApiKeyDeleteOwnPermission = createPermission({
|
|
73
|
+
name: "kuadrant.apikey.delete.own",
|
|
74
|
+
attributes: { action: "delete" }
|
|
75
|
+
});
|
|
76
|
+
const kuadrantApiKeyDeleteAllPermission = createPermission({
|
|
77
|
+
name: "kuadrant.apikey.delete.all",
|
|
78
|
+
attributes: { action: "delete" }
|
|
79
|
+
});
|
|
80
|
+
const kuadrantPermissions = [
|
|
81
|
+
kuadrantPlanPolicyCreatePermission,
|
|
82
|
+
kuadrantPlanPolicyReadPermission,
|
|
83
|
+
kuadrantPlanPolicyUpdatePermission,
|
|
84
|
+
kuadrantPlanPolicyDeletePermission,
|
|
85
|
+
kuadrantPlanPolicyListPermission,
|
|
86
|
+
kuadrantApiProductCreatePermission,
|
|
87
|
+
kuadrantApiProductReadPermission,
|
|
88
|
+
kuadrantApiProductUpdatePermission,
|
|
89
|
+
kuadrantApiProductDeletePermission,
|
|
90
|
+
kuadrantApiProductListPermission,
|
|
91
|
+
kuadrantApiKeyRequestCreatePermission,
|
|
92
|
+
kuadrantApiKeyRequestReadOwnPermission,
|
|
93
|
+
kuadrantApiKeyRequestReadAllPermission,
|
|
94
|
+
kuadrantApiKeyRequestUpdatePermission,
|
|
95
|
+
kuadrantApiKeyRequestListPermission,
|
|
96
|
+
kuadrantApiKeyReadOwnPermission,
|
|
97
|
+
kuadrantApiKeyReadAllPermission,
|
|
98
|
+
kuadrantApiKeyDeleteOwnPermission,
|
|
99
|
+
kuadrantApiKeyDeleteAllPermission
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
export { kuadrantApiKeyDeleteAllPermission, kuadrantApiKeyDeleteOwnPermission, kuadrantApiKeyReadAllPermission, kuadrantApiKeyReadOwnPermission, kuadrantApiKeyRequestCreatePermission, kuadrantApiKeyRequestListPermission, kuadrantApiKeyRequestReadAllPermission, kuadrantApiKeyRequestReadOwnPermission, kuadrantApiKeyRequestUpdatePermission, kuadrantApiProductCreatePermission, kuadrantApiProductDeletePermission, kuadrantApiProductListPermission, kuadrantApiProductReadPermission, kuadrantApiProductUpdatePermission, kuadrantPermissions, kuadrantPlanPolicyCreatePermission, kuadrantPlanPolicyDeletePermission, kuadrantPlanPolicyListPermission, kuadrantPlanPolicyReadPermission, kuadrantPlanPolicyUpdatePermission };
|
|
103
|
+
//# sourceMappingURL=permissions.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.esm.js","sources":["../src/permissions.ts"],"sourcesContent":["import { createPermission } from '@backstage/plugin-permission-common';\n\n/**\n * permission definitions for the kuadrant plugin\n *\n * these permissions control access to kuadrant resources and operations.\n * they must match the permissions defined in the backend plugin.\n *\n * permission types:\n * - BasicPermission: standard permission that applies globally\n * - ResourcePermission: permission scoped to specific resource types (e.g., apiproduct)\n *\n * permission patterns:\n * - `.create` - create new resources\n * - `.read` - read resource details\n * - `.read.own` - read only resources owned by the user\n * - `.read.all` - read all resources regardless of ownership\n * - `.update` - modify existing resources\n * - `.delete` - delete resources\n * - `.delete.own` - delete only resources owned by the user\n * - `.delete.all` - delete any resource regardless of ownership\n * - `.list` - list/view collections of resources\n */\n\n// planpolicy permissions\nexport const kuadrantPlanPolicyCreatePermission = createPermission({\n name: 'kuadrant.planpolicy.create',\n attributes: { action: 'create' },\n});\n\nexport const kuadrantPlanPolicyReadPermission = createPermission({\n name: 'kuadrant.planpolicy.read',\n attributes: { action: 'read' },\n});\n\nexport const kuadrantPlanPolicyUpdatePermission = createPermission({\n name: 'kuadrant.planpolicy.update',\n attributes: { action: 'update' },\n});\n\nexport const kuadrantPlanPolicyDeletePermission = createPermission({\n name: 'kuadrant.planpolicy.delete',\n attributes: { action: 'delete' },\n});\n\nexport const kuadrantPlanPolicyListPermission = createPermission({\n name: 'kuadrant.planpolicy.list',\n attributes: { action: 'read' },\n});\n\n// apiproduct permissions\nexport const kuadrantApiProductCreatePermission = createPermission({\n name: 'kuadrant.apiproduct.create',\n attributes: { action: 'create' },\n});\n\nexport const kuadrantApiProductReadPermission = createPermission({\n name: 'kuadrant.apiproduct.read',\n attributes: { action: 'read' },\n});\n\nexport const kuadrantApiProductUpdatePermission = createPermission({\n name: 'kuadrant.apiproduct.update',\n attributes: { action: 'update' },\n});\n\nexport const kuadrantApiProductDeletePermission = createPermission({\n name: 'kuadrant.apiproduct.delete',\n attributes: { action: 'delete' },\n});\n\nexport const kuadrantApiProductListPermission = createPermission({\n name: 'kuadrant.apiproduct.list',\n attributes: { action: 'read' },\n});\n\n// apikeyrequest permissions\n\n/**\n * permission to create API key requests\n *\n * this is a ResourcePermission scoped to 'apiproduct', allowing\n * fine-grained control over which API products users can request access to.\n *\n * use in frontend: useKuadrantPermission(kuadrantApiKeyRequestCreatePermission)\n * use in backend with resource: { permission, resourceRef: 'apiproduct:namespace/name' }\n */\nexport const kuadrantApiKeyRequestCreatePermission = createPermission({\n name: 'kuadrant.apikeyrequest.create',\n attributes: { action: 'create' },\n resourceType: 'apiproduct',\n});\n\n/**\n * permission to read API key requests created by the current user\n * use this for allowing users to see their own request history\n */\nexport const kuadrantApiKeyRequestReadOwnPermission = createPermission({\n name: 'kuadrant.apikeyrequest.read.own',\n attributes: { action: 'read' },\n});\n\n/**\n * permission to read all API key requests regardless of who created them\n * use this for platform engineers/admins who need to view the approval queue\n */\nexport const kuadrantApiKeyRequestReadAllPermission = createPermission({\n name: 'kuadrant.apikeyrequest.read.all',\n attributes: { action: 'read' },\n});\n\n/**\n * permission to approve or reject API key requests\n * typically granted to API owners and platform engineers\n */\nexport const kuadrantApiKeyRequestUpdatePermission = createPermission({\n name: 'kuadrant.apikeyrequest.update',\n attributes: { action: 'update' },\n});\n\nexport const kuadrantApiKeyRequestListPermission = createPermission({\n name: 'kuadrant.apikeyrequest.list',\n attributes: { action: 'read' },\n});\n\n// api key permissions\n\n/**\n * permission to read API keys owned by the current user\n * allows users to view their own active API keys\n */\nexport const kuadrantApiKeyReadOwnPermission = createPermission({\n name: 'kuadrant.apikey.read.own',\n attributes: { action: 'read' },\n});\n\n/**\n * permission to read all API keys regardless of ownership\n * for platform engineers/admins who need to audit keys\n */\nexport const kuadrantApiKeyReadAllPermission = createPermission({\n name: 'kuadrant.apikey.read.all',\n attributes: { action: 'read' },\n});\n\n/**\n * permission to delete API keys owned by the current user\n * allows users to revoke their own access\n */\nexport const kuadrantApiKeyDeleteOwnPermission = createPermission({\n name: 'kuadrant.apikey.delete.own',\n attributes: { action: 'delete' },\n});\n\n/**\n * permission to delete any API key regardless of ownership\n * for platform engineers/admins who need to revoke access\n */\nexport const kuadrantApiKeyDeleteAllPermission = createPermission({\n name: 'kuadrant.apikey.delete.all',\n attributes: { action: 'delete' },\n});\n\nexport const kuadrantPermissions = [\n kuadrantPlanPolicyCreatePermission,\n kuadrantPlanPolicyReadPermission,\n kuadrantPlanPolicyUpdatePermission,\n kuadrantPlanPolicyDeletePermission,\n kuadrantPlanPolicyListPermission,\n kuadrantApiProductCreatePermission,\n kuadrantApiProductReadPermission,\n kuadrantApiProductUpdatePermission,\n kuadrantApiProductDeletePermission,\n kuadrantApiProductListPermission,\n kuadrantApiKeyRequestCreatePermission,\n kuadrantApiKeyRequestReadOwnPermission,\n kuadrantApiKeyRequestReadAllPermission,\n kuadrantApiKeyRequestUpdatePermission,\n kuadrantApiKeyRequestListPermission,\n kuadrantApiKeyReadOwnPermission,\n kuadrantApiKeyReadAllPermission,\n kuadrantApiKeyDeleteOwnPermission,\n kuadrantApiKeyDeleteAllPermission,\n];\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { usePermission } from '@backstage/plugin-permission-react';
|
|
2
|
+
|
|
3
|
+
function useKuadrantPermission(permission, resourceRef) {
|
|
4
|
+
const permissionRequest = "resourceType" in permission ? { permission, resourceRef } : { permission };
|
|
5
|
+
const result = usePermission(permissionRequest);
|
|
6
|
+
return {
|
|
7
|
+
allowed: result.allowed,
|
|
8
|
+
loading: result.loading,
|
|
9
|
+
error: result.error
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function canDeleteResource(ownerId, currentUserId, canDeleteOwn, canDeleteAll) {
|
|
13
|
+
if (canDeleteAll) return true;
|
|
14
|
+
if (canDeleteOwn && ownerId === currentUserId) return true;
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { canDeleteResource, useKuadrantPermission };
|
|
19
|
+
//# sourceMappingURL=permissions.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.esm.js","sources":["../../src/utils/permissions.ts"],"sourcesContent":["import { usePermission } from '@backstage/plugin-permission-react';\nimport { Permission, ResourcePermission } from '@backstage/plugin-permission-common';\n\n/**\n * result of a permission check including error state\n */\nexport interface PermissionCheckResult {\n allowed: boolean;\n loading: boolean;\n error?: Error;\n}\n\n/**\n * custom hook for checking kuadrant permissions that handles both\n * BasicPermission and ResourcePermission types without type bypasses\n *\n * @param permission - the permission to check\n * @param resourceRef - optional resource reference for ResourcePermissions\n * @returns permission check result with error handling\n *\n * @example\n * // basic permission\n * const { allowed, loading, error } = useKuadrantPermission(\n * kuadrantApiProductListPermission\n * );\n *\n * @example\n * // resource permission\n * const { allowed, loading, error } = useKuadrantPermission(\n * kuadrantApiKeyRequestCreatePermission,\n * 'apiproduct:namespace/name'\n * );\n */\nexport function useKuadrantPermission(\n permission: Permission,\n resourceRef?: string,\n): PermissionCheckResult {\n // construct the permission request based on whether it's a ResourcePermission\n const permissionRequest = 'resourceType' in permission\n ? { permission: permission as ResourcePermission, resourceRef }\n : { permission };\n\n const result = usePermission(permissionRequest as any);\n\n return {\n allowed: result.allowed,\n loading: result.loading,\n error: result.error,\n };\n}\n\n/**\n * helper to determine if a user can delete a specific API key or request\n *\n * @param ownerId - the user id who owns the key/request\n * @param currentUserId - the current user's id\n * @param canDeleteOwn - whether user has permission to delete their own keys\n * @param canDeleteAll - whether user has permission to delete all keys\n * @returns true if user can delete this specific key/request\n */\nexport function canDeleteResource(\n ownerId: string,\n currentUserId: string,\n canDeleteOwn: boolean,\n canDeleteAll: boolean,\n): boolean {\n if (canDeleteAll) return true;\n if (canDeleteOwn && ownerId === currentUserId) return true;\n return false;\n}\n"],"names":[],"mappings":";;AAiCgB,SAAA,qBAAA,CACd,YACA,WACuB,EAAA;AAEvB,EAAM,MAAA,iBAAA,GAAoB,kBAAkB,UACxC,GAAA,EAAE,YAA8C,WAAY,EAAA,GAC5D,EAAE,UAAW,EAAA;AAEjB,EAAM,MAAA,MAAA,GAAS,cAAc,iBAAwB,CAAA;AAErD,EAAO,OAAA;AAAA,IACL,SAAS,MAAO,CAAA,OAAA;AAAA,IAChB,SAAS,MAAO,CAAA,OAAA;AAAA,IAChB,OAAO,MAAO,CAAA;AAAA,GAChB;AACF;AAWO,SAAS,iBACd,CAAA,OAAA,EACA,aACA,EAAA,YAAA,EACA,YACS,EAAA;AACT,EAAA,IAAI,cAAqB,OAAA,IAAA;AACzB,EAAI,IAAA,YAAA,IAAgB,OAAY,KAAA,aAAA,EAAsB,OAAA,IAAA;AACtD,EAAO,OAAA,KAAA;AACT;;;;"}
|
package/package.json
CHANGED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { useApi, identityApiRef } from '@backstage/core-plugin-api';
|
|
2
|
-
import useAsync from 'react-use/lib/useAsync';
|
|
3
|
-
|
|
4
|
-
function useUserRole() {
|
|
5
|
-
const identityApi = useApi(identityApiRef);
|
|
6
|
-
const { value, loading } = useAsync(async () => {
|
|
7
|
-
try {
|
|
8
|
-
const identity = await identityApi.getBackstageIdentity();
|
|
9
|
-
const userId = identity.userEntityRef.split("/")[1] || "guest";
|
|
10
|
-
const ownershipRefs = identity.ownershipEntityRefs || [];
|
|
11
|
-
console.log("useUserRole debug:", { userId, ownershipRefs });
|
|
12
|
-
const isPlatformEngineer = ownershipRefs.includes("group:default/platform-engineers") || ownershipRefs.includes("group:default/platform-admins");
|
|
13
|
-
const isApiOwner = ownershipRefs.includes("group:default/api-owners") || ownershipRefs.includes("group:default/app-developers");
|
|
14
|
-
const isApiConsumer = ownershipRefs.includes("group:default/api-consumers");
|
|
15
|
-
let role = "unknown";
|
|
16
|
-
if (isPlatformEngineer) {
|
|
17
|
-
role = "platform-engineer";
|
|
18
|
-
} else if (isApiOwner) {
|
|
19
|
-
role = "api-owner";
|
|
20
|
-
} else if (isApiConsumer) {
|
|
21
|
-
role = "api-consumer";
|
|
22
|
-
}
|
|
23
|
-
console.log("useUserRole result:", { role, isPlatformEngineer, isApiOwner, isApiConsumer });
|
|
24
|
-
return {
|
|
25
|
-
userId,
|
|
26
|
-
role,
|
|
27
|
-
isPlatformEngineer,
|
|
28
|
-
isApiOwner,
|
|
29
|
-
isApiConsumer
|
|
30
|
-
};
|
|
31
|
-
} catch (error) {
|
|
32
|
-
console.log("useUserRole error, returning guest with full access:", error);
|
|
33
|
-
return {
|
|
34
|
-
userId: "guest",
|
|
35
|
-
role: "platform-engineer",
|
|
36
|
-
isPlatformEngineer: true,
|
|
37
|
-
isApiOwner: true,
|
|
38
|
-
isApiConsumer: true
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
}, [identityApi]);
|
|
42
|
-
return {
|
|
43
|
-
userInfo: value || null,
|
|
44
|
-
loading
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export { useUserRole };
|
|
49
|
-
//# sourceMappingURL=useUserRole.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useUserRole.esm.js","sources":["../../src/hooks/useUserRole.ts"],"sourcesContent":["import { useApi, identityApiRef } from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/lib/useAsync';\n\nexport type UserRole = 'platform-engineer' | 'api-owner' | 'api-consumer' | 'unknown';\n\nexport interface UserInfo {\n userId: string;\n role: UserRole;\n isPlatformEngineer: boolean;\n isApiOwner: boolean;\n isApiConsumer: boolean;\n}\n\nexport function useUserRole(): { userInfo: UserInfo | null; loading: boolean } {\n const identityApi = useApi(identityApiRef);\n\n const { value, loading } = useAsync(async () => {\n try {\n const identity = await identityApi.getBackstageIdentity();\n const userId = identity.userEntityRef.split('/')[1] || 'guest';\n const ownershipRefs = identity.ownershipEntityRefs || [];\n\n console.log('useUserRole debug:', { userId, ownershipRefs });\n\n // determine roles based on group membership (not hierarchical)\n const isPlatformEngineer = ownershipRefs.includes('group:default/platform-engineers') ||\n ownershipRefs.includes('group:default/platform-admins');\n\n const isApiOwner = ownershipRefs.includes('group:default/api-owners') ||\n ownershipRefs.includes('group:default/app-developers');\n\n const isApiConsumer = ownershipRefs.includes('group:default/api-consumers');\n\n // primary role (for display)\n let role: UserRole = 'unknown';\n if (isPlatformEngineer) {\n role = 'platform-engineer';\n } else if (isApiOwner) {\n role = 'api-owner';\n } else if (isApiConsumer) {\n role = 'api-consumer';\n }\n\n console.log('useUserRole result:', { role, isPlatformEngineer, isApiOwner, isApiConsumer });\n\n return {\n userId,\n role,\n isPlatformEngineer,\n isApiOwner,\n isApiConsumer,\n };\n } catch (error) {\n console.log('useUserRole error, returning guest with full access:', error);\n // in dev mode without auth backend, return default guest with full access\n return {\n userId: 'guest',\n role: 'platform-engineer' as UserRole,\n isPlatformEngineer: true,\n isApiOwner: true,\n isApiConsumer: true,\n };\n }\n }, [identityApi]);\n\n return {\n userInfo: value || null,\n loading,\n };\n}\n"],"names":[],"mappings":";;;AAaO,SAAS,WAA+D,GAAA;AAC7E,EAAM,MAAA,WAAA,GAAc,OAAO,cAAc,CAAA;AAEzC,EAAA,MAAM,EAAE,KAAA,EAAO,OAAQ,EAAA,GAAI,SAAS,YAAY;AAC9C,IAAI,IAAA;AACF,MAAM,MAAA,QAAA,GAAW,MAAM,WAAA,CAAY,oBAAqB,EAAA;AACxD,MAAA,MAAM,SAAS,QAAS,CAAA,aAAA,CAAc,MAAM,GAAG,CAAA,CAAE,CAAC,CAAK,IAAA,OAAA;AACvD,MAAM,MAAA,aAAA,GAAgB,QAAS,CAAA,mBAAA,IAAuB,EAAC;AAEvD,MAAA,OAAA,CAAQ,GAAI,CAAA,oBAAA,EAAsB,EAAE,MAAA,EAAQ,eAAe,CAAA;AAG3D,MAAA,MAAM,qBAAqB,aAAc,CAAA,QAAA,CAAS,kCAAkC,CACzD,IAAA,aAAA,CAAc,SAAS,+BAA+B,CAAA;AAEjF,MAAA,MAAM,aAAa,aAAc,CAAA,QAAA,CAAS,0BAA0B,CACjD,IAAA,aAAA,CAAc,SAAS,8BAA8B,CAAA;AAExE,MAAM,MAAA,aAAA,GAAgB,aAAc,CAAA,QAAA,CAAS,6BAA6B,CAAA;AAG1E,MAAA,IAAI,IAAiB,GAAA,SAAA;AACrB,MAAA,IAAI,kBAAoB,EAAA;AACtB,QAAO,IAAA,GAAA,mBAAA;AAAA,iBACE,UAAY,EAAA;AACrB,QAAO,IAAA,GAAA,WAAA;AAAA,iBACE,aAAe,EAAA;AACxB,QAAO,IAAA,GAAA,cAAA;AAAA;AAGT,MAAA,OAAA,CAAQ,IAAI,qBAAuB,EAAA,EAAE,MAAM,kBAAoB,EAAA,UAAA,EAAY,eAAe,CAAA;AAE1F,MAAO,OAAA;AAAA,QACL,MAAA;AAAA,QACA,IAAA;AAAA,QACA,kBAAA;AAAA,QACA,UAAA;AAAA,QACA;AAAA,OACF;AAAA,aACO,KAAO,EAAA;AACd,MAAQ,OAAA,CAAA,GAAA,CAAI,wDAAwD,KAAK,CAAA;AAEzE,MAAO,OAAA;AAAA,QACL,MAAQ,EAAA,OAAA;AAAA,QACR,IAAM,EAAA,mBAAA;AAAA,QACN,kBAAoB,EAAA,IAAA;AAAA,QACpB,UAAY,EAAA,IAAA;AAAA,QACZ,aAAe,EAAA;AAAA,OACjB;AAAA;AACF,GACF,EAAG,CAAC,WAAW,CAAC,CAAA;AAEhB,EAAO,OAAA;AAAA,IACL,UAAU,KAAS,IAAA,IAAA;AAAA,IACnB;AAAA,GACF;AACF;;;;"}
|