@backstage-community/plugin-rbac 1.50.2 → 1.52.0
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/CHANGELOG.md +36 -0
- package/dist/alpha/pages.esm.js +4 -1
- package/dist/alpha/pages.esm.js.map +1 -1
- package/dist/alpha/routes.esm.js +18 -0
- package/dist/alpha/routes.esm.js.map +1 -0
- package/dist/alpha/translations/de.esm.js +2 -0
- package/dist/alpha/translations/de.esm.js.map +1 -1
- package/dist/alpha/translations/es.esm.js +2 -0
- package/dist/alpha/translations/es.esm.js.map +1 -1
- package/dist/alpha/translations/fr.esm.js +2 -0
- package/dist/alpha/translations/fr.esm.js.map +1 -1
- package/dist/alpha/translations/it.esm.js +2 -0
- package/dist/alpha/translations/it.esm.js.map +1 -1
- package/dist/alpha/translations/ref.esm.js +2 -0
- package/dist/alpha/translations/ref.esm.js.map +1 -1
- package/dist/alpha.d.ts +10 -32
- package/dist/alpha.esm.js +2 -3
- package/dist/alpha.esm.js.map +1 -1
- package/dist/components/Administration.esm.js +1 -4
- package/dist/components/Administration.esm.js.map +1 -1
- package/dist/components/CreateRole/EditRolePage.esm.js +3 -0
- package/dist/components/CreateRole/EditRolePage.esm.js.map +1 -1
- package/dist/components/EditRole.esm.js +2 -3
- package/dist/components/EditRole.esm.js.map +1 -1
- package/dist/components/RoleOverview/MembersCard.esm.js +8 -4
- package/dist/components/RoleOverview/MembersCard.esm.js.map +1 -1
- package/dist/components/RoleOverview/PermissionsCard.esm.js +18 -5
- package/dist/components/RoleOverview/PermissionsCard.esm.js.map +1 -1
- package/dist/components/RoleOverview/RoleOverviewPage.esm.js +2 -1
- package/dist/components/RoleOverview/RoleOverviewPage.esm.js.map +1 -1
- package/dist/components/RolesList/DeleteRole.esm.js +2 -3
- package/dist/components/RolesList/DeleteRole.esm.js.map +1 -1
- package/dist/components/RolesList/RolesListColumns.esm.js +23 -17
- package/dist/components/RolesList/RolesListColumns.esm.js.map +1 -1
- package/dist/hooks/useActionPermissionTooltip.esm.js +1 -1
- package/dist/hooks/useActionPermissionTooltip.esm.js.map +1 -1
- package/dist/hooks/useMembers.esm.js +3 -1
- package/dist/hooks/useMembers.esm.js.map +1 -1
- package/dist/hooks/useRoles.esm.js +2 -1
- package/dist/hooks/useRoles.esm.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/package.json.esm.js +15 -15
- package/package.json +16 -16
- package/dist/alpha/navItems.esm.js +0 -15
- package/dist/alpha/navItems.esm.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeleteRole.esm.js","sources":["../../../src/components/RolesList/DeleteRole.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport Delete from '@mui/icons-material/Delete';\nimport IconButton from '@mui/material/IconButton';\nimport Tooltip from '@mui/material/Tooltip';\nimport { policyEntityDeletePermission } from '@backstage-community/plugin-rbac-common';\nimport { useActionPermissionTooltip } from '../../hooks/useActionPermissionTooltip';\nimport { useDeleteDialog } from '../DeleteDialogContext';\nimport { useTranslation } from '../../hooks/useTranslation';\n\ntype DeleteRoleProps = {\n roleName: string;\n canEdit: boolean;\n dataTestId?: string;\n tooltip?: string;\n};\n\nconst DeleteRole = ({\n roleName,\n canEdit,\n dataTestId,\n tooltip,\n}: DeleteRoleProps) => {\n const { t } = useTranslation();\n const { setDeleteComponent, setOpenDialog } = useDeleteDialog();\n\n const openDialog = (name: string) => {\n setDeleteComponent({ roleName: name });\n setOpenDialog(true);\n };\n\n const { disable, tooltipText, testIdText } = useActionPermissionTooltip({\n permission: policyEntityDeletePermission,\n resourceRef: roleName,\n canAct: canEdit,\n action: 'delete',\n dataTestId: dataTestId,\n fallbackTooltip: tooltip,\n });\n\n return (\n <Tooltip title={tooltipText}>\n <IconButton\n
|
|
1
|
+
{"version":3,"file":"DeleteRole.esm.js","sources":["../../../src/components/RolesList/DeleteRole.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport Delete from '@mui/icons-material/Delete';\nimport IconButton from '@mui/material/IconButton';\nimport Tooltip from '@mui/material/Tooltip';\nimport { policyEntityDeletePermission } from '@backstage-community/plugin-rbac-common';\nimport { useActionPermissionTooltip } from '../../hooks/useActionPermissionTooltip';\nimport { useDeleteDialog } from '../DeleteDialogContext';\nimport { useTranslation } from '../../hooks/useTranslation';\n\ntype DeleteRoleProps = {\n roleName: string;\n canEdit: boolean;\n dataTestId?: string;\n tooltip?: string;\n};\n\nconst DeleteRole = ({\n roleName,\n canEdit,\n dataTestId,\n tooltip,\n}: DeleteRoleProps) => {\n const { t } = useTranslation();\n const { setDeleteComponent, setOpenDialog } = useDeleteDialog();\n\n const openDialog = (name: string) => {\n setDeleteComponent({ roleName: name });\n setOpenDialog(true);\n };\n\n const { disable, tooltipText, testIdText } = useActionPermissionTooltip({\n permission: policyEntityDeletePermission,\n resourceRef: roleName,\n canAct: canEdit,\n action: 'delete',\n dataTestId: dataTestId,\n fallbackTooltip: tooltip,\n });\n\n return (\n <Tooltip title={tooltipText}>\n <span style={{ display: 'inline-flex' }}>\n <IconButton\n onClick={() => openDialog(roleName)}\n data-testid={testIdText}\n aria-label={t('common.delete')}\n disabled={disable}\n sx={{\n p: 1,\n borderRadius: '50%',\n '&:hover': { borderRadius: '50%' },\n }}\n >\n <Delete />\n </IconButton>\n </span>\n </Tooltip>\n );\n};\nexport default DeleteRole;\n"],"names":[],"mappings":";;;;;;;;;AA+BA,MAAM,aAAa,CAAC;AAAA,EAClB,QAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAuB,KAAA;AACrB,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAC7B,EAAA,MAAM,EAAE,kBAAA,EAAoB,aAAc,EAAA,GAAI,eAAgB,EAAA;AAE9D,EAAM,MAAA,UAAA,GAAa,CAAC,IAAiB,KAAA;AACnC,IAAmB,kBAAA,CAAA,EAAE,QAAU,EAAA,IAAA,EAAM,CAAA;AACrC,IAAA,aAAA,CAAc,IAAI,CAAA;AAAA,GACpB;AAEA,EAAA,MAAM,EAAE,OAAA,EAAS,WAAa,EAAA,UAAA,KAAe,0BAA2B,CAAA;AAAA,IACtE,UAAY,EAAA,4BAAA;AAAA,IACZ,WAAa,EAAA,QAAA;AAAA,IACb,MAAQ,EAAA,OAAA;AAAA,IACR,MAAQ,EAAA,QAAA;AAAA,IACR,UAAA;AAAA,IACA,eAAiB,EAAA;AAAA,GAClB,CAAA;AAED,EACE,uBAAA,GAAA,CAAC,OAAQ,EAAA,EAAA,KAAA,EAAO,WACd,EAAA,QAAA,kBAAA,GAAA,CAAC,UAAK,KAAO,EAAA,EAAE,OAAS,EAAA,aAAA,EACtB,EAAA,QAAA,kBAAA,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAS,MAAM,UAAA,CAAW,QAAQ,CAAA;AAAA,MAClC,aAAa,EAAA,UAAA;AAAA,MACb,YAAA,EAAY,EAAE,eAAe,CAAA;AAAA,MAC7B,QAAU,EAAA,OAAA;AAAA,MACV,EAAI,EAAA;AAAA,QACF,CAAG,EAAA,CAAA;AAAA,QACH,YAAc,EAAA,KAAA;AAAA,QACd,SAAA,EAAW,EAAE,YAAA,EAAc,KAAM;AAAA,OACnC;AAAA,MAEA,8BAAC,MAAO,EAAA,EAAA;AAAA;AAAA,KAEZ,CACF,EAAA,CAAA;AAEJ;;;;"}
|
|
@@ -23,7 +23,7 @@ const getColumns = (t, locale) => {
|
|
|
23
23
|
field: "members",
|
|
24
24
|
type: "string",
|
|
25
25
|
align: "left",
|
|
26
|
-
render: (props) => getMembers(props.members, t),
|
|
26
|
+
render: (props) => props.isDefault ? t("table.defaultRoleUsersAndGroups") : getMembers(props.members, t),
|
|
27
27
|
customSort: (a, b) => {
|
|
28
28
|
if (a.members.length === 0) {
|
|
29
29
|
return -1;
|
|
@@ -54,22 +54,28 @@ const getColumns = (t, locale) => {
|
|
|
54
54
|
{
|
|
55
55
|
title: t("table.headers.actions"),
|
|
56
56
|
sorting: false,
|
|
57
|
-
render: (props) =>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
57
|
+
render: (props) => {
|
|
58
|
+
const canEdit = !props.isDefault && props.actionsPermissionResults.edit.allowed;
|
|
59
|
+
const defaultRoleTooltip = props.isDefault ? t("errors.defaultRoleReadOnly") : undefined;
|
|
60
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
61
|
+
/* @__PURE__ */ jsx(
|
|
62
|
+
EditRole,
|
|
63
|
+
{
|
|
64
|
+
canEdit,
|
|
65
|
+
roleName: props.name,
|
|
66
|
+
tooltip: defaultRoleTooltip
|
|
67
|
+
}
|
|
68
|
+
),
|
|
69
|
+
/* @__PURE__ */ jsx(
|
|
70
|
+
DeleteRole,
|
|
71
|
+
{
|
|
72
|
+
canEdit,
|
|
73
|
+
roleName: props.name,
|
|
74
|
+
tooltip: defaultRoleTooltip
|
|
75
|
+
}
|
|
76
|
+
)
|
|
77
|
+
] });
|
|
78
|
+
}
|
|
73
79
|
}
|
|
74
80
|
];
|
|
75
81
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RolesListColumns.esm.js","sources":["../../../src/components/RolesList/RolesListColumns.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport { Link, TableColumn } from '@backstage/core-components';\n\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\n\nimport { RolesData } from '../../types';\nimport { getMembers } from '../../utils/rbac-utils';\nimport EditRole from '../EditRole';\nimport DeleteRole from './DeleteRole';\nimport { TranslationFunction } from '@backstage/core-plugin-api/alpha';\nimport { rbacTranslationRef } from '../../alpha/translations';\n\nexport const getColumns = (\n t: TranslationFunction<typeof rbacTranslationRef.T>,\n locale: string,\n): TableColumn<RolesData>[] => {\n return [\n {\n title: t('table.headers.name'),\n field: 'name',\n type: 'string',\n render: (props: RolesData) => {\n const { kind, namespace, name } = parseEntityRef(props.name);\n return (\n <Link to={`roles/${kind}/${namespace}/${name}`}>{props.name}</Link>\n );\n },\n },\n {\n title: t('table.headers.usersAndGroups'),\n field: 'members',\n type: 'string',\n align: 'left',\n render: props
|
|
1
|
+
{"version":3,"file":"RolesListColumns.esm.js","sources":["../../../src/components/RolesList/RolesListColumns.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport { Link, TableColumn } from '@backstage/core-components';\n\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\n\nimport { RolesData } from '../../types';\nimport { getMembers } from '../../utils/rbac-utils';\nimport EditRole from '../EditRole';\nimport DeleteRole from './DeleteRole';\nimport { TranslationFunction } from '@backstage/core-plugin-api/alpha';\nimport { rbacTranslationRef } from '../../alpha/translations';\n\nexport const getColumns = (\n t: TranslationFunction<typeof rbacTranslationRef.T>,\n locale: string,\n): TableColumn<RolesData>[] => {\n return [\n {\n title: t('table.headers.name'),\n field: 'name',\n type: 'string',\n render: (props: RolesData) => {\n const { kind, namespace, name } = parseEntityRef(props.name);\n return (\n <Link to={`roles/${kind}/${namespace}/${name}`}>{props.name}</Link>\n );\n },\n },\n {\n title: t('table.headers.usersAndGroups'),\n field: 'members',\n type: 'string',\n align: 'left',\n render: props =>\n props.isDefault\n ? t('table.defaultRoleUsersAndGroups')\n : getMembers(props.members, t),\n customSort: (a, b) => {\n if (a.members.length === 0) {\n return -1;\n }\n if (b.members.length === 0) {\n return 1;\n }\n if (a.members.length === b.members.length) {\n return 0;\n }\n return a.members.length < b.members.length ? -1 : 1;\n },\n },\n {\n title: t('table.headers.accessiblePlugins'),\n field: 'accessiblePlugins',\n type: 'string',\n align: 'left',\n render: (props: RolesData) => {\n const pls = props.accessiblePlugins.map(\n p => p[0].toLocaleUpperCase(locale) + p.slice(1),\n );\n const plsTooltip = pls.join(', ');\n const plsOverflowCount = pls.length > 2 ? `+ ${pls.length - 2}` : '';\n\n return pls.length > 0 ? (\n <Tooltip title={plsTooltip || ''} placement=\"top-start\">\n <Typography>\n {pls.length === 1\n ? `${pls[0]}`\n : `${pls[0]}, ${pls[1]} ${plsOverflowCount}`}\n </Typography>\n </Tooltip>\n ) : (\n '-'\n );\n },\n },\n {\n title: t('table.headers.actions'),\n sorting: false,\n render: (props: RolesData) => {\n const canEdit =\n !props.isDefault && props.actionsPermissionResults.edit.allowed;\n const defaultRoleTooltip = props.isDefault\n ? t('errors.defaultRoleReadOnly')\n : undefined;\n return (\n <>\n <EditRole\n canEdit={canEdit}\n roleName={props.name}\n tooltip={defaultRoleTooltip}\n />\n <DeleteRole\n canEdit={canEdit}\n roleName={props.name}\n tooltip={defaultRoleTooltip}\n />\n </>\n );\n },\n },\n ];\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -20,7 +20,7 @@ function useActionPermissionTooltip({
|
|
|
20
20
|
if (isLoading) {
|
|
21
21
|
tooltipText = t("common.checkingPermissions");
|
|
22
22
|
} else if (disable) {
|
|
23
|
-
tooltipText = t("common.unauthorizedTo", { action: actionText });
|
|
23
|
+
tooltipText = fallbackTooltip ?? t("common.unauthorizedTo", { action: actionText });
|
|
24
24
|
} else {
|
|
25
25
|
tooltipText = fallbackTooltip ?? t("common.roleAction", {
|
|
26
26
|
action: capitalizeFirstLetter(actionText)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useActionPermissionTooltip.esm.js","sources":["../../src/hooks/useActionPermissionTooltip.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport { capitalizeFirstLetter } from '../utils/string-utils';\nimport { useTranslation } from './useTranslation';\n\nexport function useActionPermissionTooltip({\n permission,\n resourceRef,\n canAct,\n action,\n dataTestId,\n fallbackTooltip,\n}: {\n permission: any;\n resourceRef: string;\n canAct: boolean;\n action?: string;\n dataTestId?: string;\n fallbackTooltip?: string;\n}) {\n const { t } = useTranslation();\n const result = usePermission({ permission, resourceRef });\n\n const isLoading = result.loading;\n const isAllowed = result.allowed;\n const disable = !(isAllowed && canAct);\n\n let tooltipText: string;\n const actionText = action || t('common.performThisAction');\n\n if (isLoading) {\n tooltipText = t('common.checkingPermissions');\n } else if (disable) {\n tooltipText
|
|
1
|
+
{"version":3,"file":"useActionPermissionTooltip.esm.js","sources":["../../src/hooks/useActionPermissionTooltip.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport { capitalizeFirstLetter } from '../utils/string-utils';\nimport { useTranslation } from './useTranslation';\n\nexport function useActionPermissionTooltip({\n permission,\n resourceRef,\n canAct,\n action,\n dataTestId,\n fallbackTooltip,\n}: {\n permission: any;\n resourceRef: string;\n canAct: boolean;\n action?: string;\n dataTestId?: string;\n fallbackTooltip?: string;\n}) {\n const { t } = useTranslation();\n const result = usePermission({ permission, resourceRef });\n\n const isLoading = result.loading;\n const isAllowed = result.allowed;\n const disable = !(isAllowed && canAct);\n\n let tooltipText: string;\n const actionText = action || t('common.performThisAction');\n\n if (isLoading) {\n tooltipText = t('common.checkingPermissions');\n } else if (disable) {\n tooltipText =\n fallbackTooltip ??\n t('common.unauthorizedTo' as any, { action: actionText });\n } else {\n tooltipText =\n fallbackTooltip ??\n t('common.roleAction' as any, {\n action: capitalizeFirstLetter(actionText),\n });\n }\n const testIdText = disable\n ? `disable-${actionText}-role-${resourceRef}`\n : `${actionText}-role-${resourceRef}`;\n\n return {\n isLoading,\n isAllowed,\n disable,\n tooltipText,\n testIdText: dataTestId ?? testIdText,\n };\n}\n"],"names":[],"mappings":";;;;AAoBO,SAAS,0BAA2B,CAAA;AAAA,EACzC,UAAA;AAAA,EACA,WAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAOG,EAAA;AACD,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAC7B,EAAA,MAAM,MAAS,GAAA,aAAA,CAAc,EAAE,UAAA,EAAY,aAAa,CAAA;AAExD,EAAA,MAAM,YAAY,MAAO,CAAA,OAAA;AACzB,EAAA,MAAM,YAAY,MAAO,CAAA,OAAA;AACzB,EAAM,MAAA,OAAA,GAAU,EAAE,SAAa,IAAA,MAAA,CAAA;AAE/B,EAAI,IAAA,WAAA;AACJ,EAAM,MAAA,UAAA,GAAa,MAAU,IAAA,CAAA,CAAE,0BAA0B,CAAA;AAEzD,EAAA,IAAI,SAAW,EAAA;AACb,IAAA,WAAA,GAAc,EAAE,4BAA4B,CAAA;AAAA,aACnC,OAAS,EAAA;AAClB,IAAA,WAAA,GACE,mBACA,CAAE,CAAA,uBAAA,EAAgC,EAAE,MAAA,EAAQ,YAAY,CAAA;AAAA,GACrD,MAAA;AACL,IACE,WAAA,GAAA,eAAA,IACA,EAAE,mBAA4B,EAAA;AAAA,MAC5B,MAAA,EAAQ,sBAAsB,UAAU;AAAA,KACzC,CAAA;AAAA;AAEL,EAAM,MAAA,UAAA,GAAa,OACf,GAAA,CAAA,QAAA,EAAW,UAAU,CAAA,MAAA,EAAS,WAAW,CACzC,CAAA,GAAA,CAAA,EAAG,UAAU,CAAA,MAAA,EAAS,WAAW,CAAA,CAAA;AAErC,EAAO,OAAA;AAAA,IACL,SAAA;AAAA,IACA,SAAA;AAAA,IACA,OAAA;AAAA,IACA,WAAA;AAAA,IACA,YAAY,UAAc,IAAA;AAAA,GAC5B;AACF;;;;"}
|
|
@@ -87,12 +87,14 @@ const useMembers = (roleName, pollInterval) => {
|
|
|
87
87
|
},
|
|
88
88
|
loading ? null : 1e4
|
|
89
89
|
);
|
|
90
|
+
const isDefaultRole = Array.isArray(role) && role[0]?.metadata?.isDefault;
|
|
90
91
|
return {
|
|
91
92
|
loading,
|
|
92
93
|
data,
|
|
93
94
|
retry: { roleRetry, membersRetry },
|
|
94
95
|
error: getErrorText(role, members, t) || roleError || membersError,
|
|
95
|
-
canReadUsersAndGroups
|
|
96
|
+
canReadUsersAndGroups,
|
|
97
|
+
isDefaultRole: isDefaultRole ?? false
|
|
96
98
|
};
|
|
97
99
|
};
|
|
98
100
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMembers.esm.js","sources":["../../src/hooks/useMembers.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useMemo } from 'react';\nimport { useAsyncRetry, useInterval } from 'react-use';\n\nimport { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\n\nimport { rbacApiRef } from '../api/RBACBackendClient';\nimport { MemberEntity, MembersData } from '../types';\nimport { getMembersFromGroup } from '../utils/rbac-utils';\nimport { useLanguage } from './useLanguage';\nimport { useTranslation } from './useTranslation';\n\nexport type MembersInfo = {\n loading: boolean;\n data: MembersData[];\n retry: { roleRetry: () => void; membersRetry: () => void };\n error?: { message: string };\n canReadUsersAndGroups: boolean;\n};\n\nconst getErrorText = (\n role: any,\n members: any,\n t: (key: string, params?: any) => string,\n): { message: string } | undefined => {\n if (!Array.isArray(role) && (role as Response)?.statusText) {\n return {\n message: t('common.unableToFetchRole', {\n error: (role as Response).statusText,\n }),\n };\n } else if (!Array.isArray(members) && (members as Response)?.statusText) {\n return {\n message: t('common.unableToFetchMembers', {\n error: (members as Response).statusText,\n }),\n };\n }\n return undefined;\n};\n\nconst getMemberData = (\n memberResource: MemberEntity | undefined,\n ref: string,\n locale: string,\n) => {\n if (memberResource) {\n return {\n name:\n memberResource.spec.profile?.displayName ??\n memberResource.metadata.name,\n type: memberResource.kind,\n ref: {\n namespace: memberResource.metadata.namespace as string,\n kind: memberResource.kind.toLocaleLowerCase(locale),\n name: memberResource.metadata.name,\n },\n members:\n memberResource.kind === 'Group'\n ? getMembersFromGroup(memberResource)\n : 0,\n };\n }\n const { kind, namespace, name } = parseEntityRef(ref);\n return {\n name,\n type: kind === 'user' ? 'User' : ('Group' as 'User' | 'Group'),\n ref: {\n namespace,\n kind,\n name,\n },\n members: 0,\n };\n};\n\nexport const useMembers = (\n roleName: string,\n pollInterval?: number,\n): MembersInfo => {\n const rbacApi = useApi(rbacApiRef);\n const locale = useLanguage();\n const { t } = useTranslation();\n let data: MembersData[] = [];\n const {\n value: role,\n retry: roleRetry,\n error: roleError,\n } = useAsyncRetry(async () => {\n return await rbacApi.getRole(roleName);\n });\n\n const {\n value: members,\n retry: membersRetry,\n error: membersError,\n } = useAsyncRetry(async () => {\n return await rbacApi.getMembers();\n });\n\n const canReadUsersAndGroups =\n !membersError && Array.isArray(members) && members.length > 0;\n\n const loading = !roleError && !membersError && !role && !members;\n\n data = useMemo(\n () =>\n Array.isArray(role)\n ? role[0].memberReferences.reduce((acc: MembersData[], ref: string) => {\n const memberResource: MemberEntity | undefined = Array.isArray(\n members,\n )\n ? members.find(member => stringifyEntityRef(member) === ref)\n : undefined;\n const memberData = getMemberData(memberResource, ref, locale);\n acc.push(memberData);\n return acc;\n }, [])\n : [],\n [role, members, locale],\n );\n\n useInterval(\n () => {\n roleRetry();\n membersRetry();\n },\n loading ? null : pollInterval || 10000,\n );\n\n return {\n loading,\n data,\n retry: { roleRetry, membersRetry },\n error: getErrorText(role, members, t) || roleError || membersError,\n canReadUsersAndGroups,\n };\n};\n"],"names":[],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"useMembers.esm.js","sources":["../../src/hooks/useMembers.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useMemo } from 'react';\nimport { useAsyncRetry, useInterval } from 'react-use';\n\nimport { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\n\nimport { rbacApiRef } from '../api/RBACBackendClient';\nimport { MemberEntity, MembersData } from '../types';\nimport { getMembersFromGroup } from '../utils/rbac-utils';\nimport { useLanguage } from './useLanguage';\nimport { useTranslation } from './useTranslation';\n\nexport type MembersInfo = {\n loading: boolean;\n data: MembersData[];\n retry: { roleRetry: () => void; membersRetry: () => void };\n error?: { message: string };\n canReadUsersAndGroups: boolean;\n /** When true, this role is the default role for all users and groups. */\n isDefaultRole?: boolean;\n};\n\nconst getErrorText = (\n role: any,\n members: any,\n t: (key: string, params?: any) => string,\n): { message: string } | undefined => {\n if (!Array.isArray(role) && (role as Response)?.statusText) {\n return {\n message: t('common.unableToFetchRole', {\n error: (role as Response).statusText,\n }),\n };\n } else if (!Array.isArray(members) && (members as Response)?.statusText) {\n return {\n message: t('common.unableToFetchMembers', {\n error: (members as Response).statusText,\n }),\n };\n }\n return undefined;\n};\n\nconst getMemberData = (\n memberResource: MemberEntity | undefined,\n ref: string,\n locale: string,\n) => {\n if (memberResource) {\n return {\n name:\n memberResource.spec.profile?.displayName ??\n memberResource.metadata.name,\n type: memberResource.kind,\n ref: {\n namespace: memberResource.metadata.namespace as string,\n kind: memberResource.kind.toLocaleLowerCase(locale),\n name: memberResource.metadata.name,\n },\n members:\n memberResource.kind === 'Group'\n ? getMembersFromGroup(memberResource)\n : 0,\n };\n }\n const { kind, namespace, name } = parseEntityRef(ref);\n return {\n name,\n type: kind === 'user' ? 'User' : ('Group' as 'User' | 'Group'),\n ref: {\n namespace,\n kind,\n name,\n },\n members: 0,\n };\n};\n\nexport const useMembers = (\n roleName: string,\n pollInterval?: number,\n): MembersInfo => {\n const rbacApi = useApi(rbacApiRef);\n const locale = useLanguage();\n const { t } = useTranslation();\n let data: MembersData[] = [];\n const {\n value: role,\n retry: roleRetry,\n error: roleError,\n } = useAsyncRetry(async () => {\n return await rbacApi.getRole(roleName);\n });\n\n const {\n value: members,\n retry: membersRetry,\n error: membersError,\n } = useAsyncRetry(async () => {\n return await rbacApi.getMembers();\n });\n\n const canReadUsersAndGroups =\n !membersError && Array.isArray(members) && members.length > 0;\n\n const loading = !roleError && !membersError && !role && !members;\n\n data = useMemo(\n () =>\n Array.isArray(role)\n ? role[0].memberReferences.reduce((acc: MembersData[], ref: string) => {\n const memberResource: MemberEntity | undefined = Array.isArray(\n members,\n )\n ? members.find(member => stringifyEntityRef(member) === ref)\n : undefined;\n const memberData = getMemberData(memberResource, ref, locale);\n acc.push(memberData);\n return acc;\n }, [])\n : [],\n [role, members, locale],\n );\n\n useInterval(\n () => {\n roleRetry();\n membersRetry();\n },\n loading ? null : pollInterval || 10000,\n );\n\n const isDefaultRole = Array.isArray(role) && role[0]?.metadata?.isDefault;\n\n return {\n loading,\n data,\n retry: { roleRetry, membersRetry },\n error: getErrorText(role, members, t) || roleError || membersError,\n canReadUsersAndGroups,\n isDefaultRole: isDefaultRole ?? false,\n };\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useRoles.esm.js","sources":["../../src/hooks/useRoles.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useState, useEffect, useMemo } from 'react';\nimport { useAsync, useAsyncRetry, useInterval } from 'react-use';\n\nimport { useApi } from '@backstage/core-plugin-api';\nimport { usePermission } from '@backstage/plugin-permission-react';\n\nimport {\n PluginPermissionMetaData,\n policyEntityCreatePermission,\n Role,\n RoleBasedPolicy,\n} from '@backstage-community/plugin-rbac-common';\n\nimport { rbacApiRef } from '../api/RBACBackendClient';\nimport { RolesData } from '../types';\nimport {\n getPermissions,\n getPermissionsArray,\n getPluginInfo,\n} from '../utils/rbac-utils';\n\ntype RoleWithConditionalPoliciesCount = Role & {\n conditionalPoliciesCount: number;\n accessiblePlugins: string[];\n};\n\nexport const useRoles = (\n page = 0,\n pageSize = 5,\n pollInterval?: number,\n): {\n loading: boolean;\n data: RolesData[];\n createRoleLoading: boolean;\n createRoleAllowed: boolean;\n error: {\n rolesError: string;\n policiesError: string;\n roleConditionError: string;\n };\n retry: { roleRetry: () => void; policiesRetry: () => void };\n} => {\n const rbacApi = useApi(rbacApiRef);\n const [newRoles, setNewRoles] = useState<RoleWithConditionalPoliciesCount[]>(\n [],\n );\n const [firstLoad, setFirstLoad] = useState(true);\n const [roleConditionError, setRoleConditionError] = useState<string>('');\n const {\n loading: loadingRoles,\n value: roles,\n retry: roleRetry,\n error: rolesError,\n } = useAsyncRetry(async () => await rbacApi.getRoles());\n\n const {\n loading: loadingPolicies,\n value: policies,\n retry: policiesRetry,\n error: policiesError,\n } = useAsyncRetry(async () => await rbacApi.getPolicies(), []);\n\n const {\n loading: membersLoading,\n value: members,\n error: membersError,\n } = useAsync(async () => {\n return await rbacApi.getMembers(1, 1);\n });\n\n const {\n value: permissionPolicies,\n loading: loadingPermissionPolicies,\n error: permissionPoliciesError,\n } = useAsync(async () => {\n return await rbacApi.listPermissions();\n });\n\n const canReadUsersAndGroups =\n !membersLoading &&\n !membersError &&\n Array.isArray(members) &&\n members.length > 0;\n\n const policyEntityCreatePermissionResult = usePermission({\n permission: policyEntityCreatePermission,\n });\n\n const createRoleLoading =\n policyEntityCreatePermissionResult.loading || membersLoading;\n\n const createRoleAllowed =\n policyEntityCreatePermissionResult.allowed && canReadUsersAndGroups;\n\n const [loadingConditionalPermission, setLoadingConditionalPermission] =\n useState<boolean>(false);\n useEffect(() => {\n const fetchAllPermissionPolicies = async () => {\n if (!Array.isArray(roles)) return;\n setLoadingConditionalPermission(true);\n const failedFetchConditionRoles: string[] = [];\n\n const startIndex = page * pageSize;\n const endIndex = startIndex + pageSize;\n const paginatedRoles = roles.slice(startIndex, endIndex);\n const conditionPromises = paginatedRoles.map(async role => {\n try {\n const conditionalPolicies = await rbacApi.getRoleConditions(\n role.name,\n );\n\n if ((conditionalPolicies as any as Response)?.statusText) {\n failedFetchConditionRoles.push(role.name);\n throw new Error(\n (conditionalPolicies as any as Response).statusText,\n );\n }\n const accessiblePlugins =\n Array.isArray(conditionalPolicies) && conditionalPolicies.length > 0\n ? conditionalPolicies.map(c => c.pluginId)\n : [];\n return {\n ...role,\n conditionalPoliciesCount: Array.isArray(conditionalPolicies)\n ? conditionalPolicies.length\n : 0,\n accessiblePlugins,\n };\n } catch (error) {\n setRoleConditionError(\n `Error fetching role conditions for ${\n failedFetchConditionRoles.length > 1 ? 'roles' : 'role'\n } ${failedFetchConditionRoles.join(', ')}, please try again later.`,\n );\n return {\n ...role,\n conditionalPoliciesCount: 0,\n accessiblePlugins: [],\n };\n }\n });\n\n const settledResults = await Promise.allSettled(conditionPromises);\n const updatedPageRoles = settledResults.map((result, index) => {\n if (result.status === 'fulfilled') {\n return result.value;\n }\n const role = paginatedRoles[index];\n return {\n ...role,\n conditionalPoliciesCount: 0,\n accessiblePlugins: [],\n };\n });\n const updatedRoles = roles.map(role => {\n const updated = updatedPageRoles.find(r => r.name === role.name);\n return updated\n ? updated\n : { ...role, conditionalPoliciesCount: 0, accessiblePlugins: [] };\n });\n\n setNewRoles(updatedRoles);\n setLoadingConditionalPermission(false);\n };\n\n fetchAllPermissionPolicies();\n }, [roles, rbacApi, page, pageSize]);\n\n const data: RolesData[] = useMemo(\n () =>\n Array.isArray(newRoles) && newRoles?.length > 0\n ? newRoles.reduce(\n (acc: RolesData[], role: RoleWithConditionalPoliciesCount) => {\n const permissions = getPermissions(\n role.name,\n policies as RoleBasedPolicy[],\n );\n\n let accPls = role.accessiblePlugins;\n if (\n !loadingPermissionPolicies &&\n !permissionPoliciesError &&\n (permissionPolicies as PluginPermissionMetaData[])?.length > 0\n ) {\n const pls = getPermissionsArray(\n role.name,\n policies as RoleBasedPolicy[],\n ).map(\n po =>\n getPluginInfo(\n permissionPolicies as PluginPermissionMetaData[],\n po,\n )?.pluginId,\n );\n accPls = [...accPls, ...pls].filter(val => !!val) as string[];\n }\n const accessiblePlugins = accPls\n .filter((val, index, plugins) => plugins.indexOf(val) === index)\n .sort();\n\n return [\n ...acc,\n {\n id: role.name,\n name: role.name,\n description: role.metadata?.description ?? '-',\n members: role.memberReferences,\n permissions: role.conditionalPoliciesCount + permissions,\n modifiedBy: '-',\n lastModified: '-',\n actionsPermissionResults: {\n edit: {\n allowed: canReadUsersAndGroups,\n },\n },\n accessiblePlugins,\n },\n ];\n },\n [],\n )\n : [],\n [\n newRoles,\n policies,\n loadingPermissionPolicies,\n permissionPoliciesError,\n permissionPolicies,\n canReadUsersAndGroups,\n ],\n );\n const loading =\n firstLoad &&\n (loadingPolicies ||\n loadingRoles ||\n membersLoading ||\n loadingPermissionPolicies ||\n loadingConditionalPermission);\n\n useInterval(\n () => {\n roleRetry();\n policiesRetry();\n setFirstLoad(false);\n },\n loading ? null : pollInterval || 10000,\n );\n\n return {\n loading,\n data,\n error: {\n rolesError: (rolesError?.message ||\n (typeof roles === 'object'\n ? (roles as any as Response)?.statusText\n : '')) as string,\n policiesError: (policiesError?.message ||\n (typeof policies === 'object'\n ? (policies as any as Response)?.statusText\n : '')) as string,\n roleConditionError,\n },\n createRoleLoading,\n createRoleAllowed,\n retry: { roleRetry, policiesRetry },\n };\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useRoles.esm.js","sources":["../../src/hooks/useRoles.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useState, useEffect, useMemo } from 'react';\nimport { useAsync, useAsyncRetry, useInterval } from 'react-use';\n\nimport { useApi } from '@backstage/core-plugin-api';\nimport { usePermission } from '@backstage/plugin-permission-react';\n\nimport {\n PluginPermissionMetaData,\n policyEntityCreatePermission,\n Role,\n RoleBasedPolicy,\n} from '@backstage-community/plugin-rbac-common';\n\nimport { rbacApiRef } from '../api/RBACBackendClient';\nimport { RolesData } from '../types';\nimport {\n getPermissions,\n getPermissionsArray,\n getPluginInfo,\n} from '../utils/rbac-utils';\n\ntype RoleWithConditionalPoliciesCount = Role & {\n conditionalPoliciesCount: number;\n accessiblePlugins: string[];\n};\n\nexport const useRoles = (\n page = 0,\n pageSize = 5,\n pollInterval?: number,\n): {\n loading: boolean;\n data: RolesData[];\n createRoleLoading: boolean;\n createRoleAllowed: boolean;\n error: {\n rolesError: string;\n policiesError: string;\n roleConditionError: string;\n };\n retry: { roleRetry: () => void; policiesRetry: () => void };\n} => {\n const rbacApi = useApi(rbacApiRef);\n const [newRoles, setNewRoles] = useState<RoleWithConditionalPoliciesCount[]>(\n [],\n );\n const [firstLoad, setFirstLoad] = useState(true);\n const [roleConditionError, setRoleConditionError] = useState<string>('');\n const {\n loading: loadingRoles,\n value: roles,\n retry: roleRetry,\n error: rolesError,\n } = useAsyncRetry(async () => await rbacApi.getRoles());\n\n const {\n loading: loadingPolicies,\n value: policies,\n retry: policiesRetry,\n error: policiesError,\n } = useAsyncRetry(async () => await rbacApi.getPolicies(), []);\n\n const {\n loading: membersLoading,\n value: members,\n error: membersError,\n } = useAsync(async () => {\n return await rbacApi.getMembers(1, 1);\n });\n\n const {\n value: permissionPolicies,\n loading: loadingPermissionPolicies,\n error: permissionPoliciesError,\n } = useAsync(async () => {\n return await rbacApi.listPermissions();\n });\n\n const canReadUsersAndGroups =\n !membersLoading &&\n !membersError &&\n Array.isArray(members) &&\n members.length > 0;\n\n const policyEntityCreatePermissionResult = usePermission({\n permission: policyEntityCreatePermission,\n });\n\n const createRoleLoading =\n policyEntityCreatePermissionResult.loading || membersLoading;\n\n const createRoleAllowed =\n policyEntityCreatePermissionResult.allowed && canReadUsersAndGroups;\n\n const [loadingConditionalPermission, setLoadingConditionalPermission] =\n useState<boolean>(false);\n useEffect(() => {\n const fetchAllPermissionPolicies = async () => {\n if (!Array.isArray(roles)) return;\n setLoadingConditionalPermission(true);\n const failedFetchConditionRoles: string[] = [];\n\n const startIndex = page * pageSize;\n const endIndex = startIndex + pageSize;\n const paginatedRoles = roles.slice(startIndex, endIndex);\n const conditionPromises = paginatedRoles.map(async role => {\n try {\n const conditionalPolicies = await rbacApi.getRoleConditions(\n role.name,\n );\n\n if ((conditionalPolicies as any as Response)?.statusText) {\n failedFetchConditionRoles.push(role.name);\n throw new Error(\n (conditionalPolicies as any as Response).statusText,\n );\n }\n const accessiblePlugins =\n Array.isArray(conditionalPolicies) && conditionalPolicies.length > 0\n ? conditionalPolicies.map(c => c.pluginId)\n : [];\n return {\n ...role,\n conditionalPoliciesCount: Array.isArray(conditionalPolicies)\n ? conditionalPolicies.length\n : 0,\n accessiblePlugins,\n };\n } catch (error) {\n setRoleConditionError(\n `Error fetching role conditions for ${\n failedFetchConditionRoles.length > 1 ? 'roles' : 'role'\n } ${failedFetchConditionRoles.join(', ')}, please try again later.`,\n );\n return {\n ...role,\n conditionalPoliciesCount: 0,\n accessiblePlugins: [],\n };\n }\n });\n\n const settledResults = await Promise.allSettled(conditionPromises);\n const updatedPageRoles = settledResults.map((result, index) => {\n if (result.status === 'fulfilled') {\n return result.value;\n }\n const role = paginatedRoles[index];\n return {\n ...role,\n conditionalPoliciesCount: 0,\n accessiblePlugins: [],\n };\n });\n const updatedRoles = roles.map(role => {\n const updated = updatedPageRoles.find(r => r.name === role.name);\n return updated\n ? updated\n : { ...role, conditionalPoliciesCount: 0, accessiblePlugins: [] };\n });\n\n setNewRoles(updatedRoles);\n setLoadingConditionalPermission(false);\n };\n\n fetchAllPermissionPolicies();\n }, [roles, rbacApi, page, pageSize]);\n\n const data: RolesData[] = useMemo(\n () =>\n Array.isArray(newRoles) && newRoles?.length > 0\n ? newRoles.reduce(\n (acc: RolesData[], role: RoleWithConditionalPoliciesCount) => {\n const permissions = getPermissions(\n role.name,\n policies as RoleBasedPolicy[],\n );\n\n let accPls = role.accessiblePlugins;\n if (\n !loadingPermissionPolicies &&\n !permissionPoliciesError &&\n (permissionPolicies as PluginPermissionMetaData[])?.length > 0\n ) {\n const pls = getPermissionsArray(\n role.name,\n policies as RoleBasedPolicy[],\n ).map(\n po =>\n getPluginInfo(\n permissionPolicies as PluginPermissionMetaData[],\n po,\n )?.pluginId,\n );\n accPls = [...accPls, ...pls].filter(val => !!val) as string[];\n }\n const accessiblePlugins = accPls\n .filter((val, index, plugins) => plugins.indexOf(val) === index)\n .sort();\n\n return [\n ...acc,\n {\n id: role.name,\n name: role.name,\n description: role.metadata?.description ?? '-',\n members: role.memberReferences,\n permissions: role.conditionalPoliciesCount + permissions,\n modifiedBy: '-',\n lastModified: '-',\n actionsPermissionResults: {\n edit: {\n allowed: canReadUsersAndGroups,\n },\n },\n accessiblePlugins,\n isDefault: role.metadata?.isDefault ?? false,\n },\n ];\n },\n [],\n )\n : [],\n [\n newRoles,\n policies,\n loadingPermissionPolicies,\n permissionPoliciesError,\n permissionPolicies,\n canReadUsersAndGroups,\n ],\n );\n const loading =\n firstLoad &&\n (loadingPolicies ||\n loadingRoles ||\n membersLoading ||\n loadingPermissionPolicies ||\n loadingConditionalPermission);\n\n useInterval(\n () => {\n roleRetry();\n policiesRetry();\n setFirstLoad(false);\n },\n loading ? null : pollInterval || 10000,\n );\n\n return {\n loading,\n data,\n error: {\n rolesError: (rolesError?.message ||\n (typeof roles === 'object'\n ? (roles as any as Response)?.statusText\n : '')) as string,\n policiesError: (policiesError?.message ||\n (typeof policies === 'object'\n ? (policies as any as Response)?.statusText\n : '')) as string,\n roleConditionError,\n },\n createRoleLoading,\n createRoleAllowed,\n retry: { roleRetry, policiesRetry },\n };\n};\n"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/package.json.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var name = "@backstage-community/plugin-rbac";
|
|
2
|
-
var version = "1.
|
|
2
|
+
var version = "1.52.0";
|
|
3
3
|
var main = "src/index.ts";
|
|
4
4
|
var types = "src/index.ts";
|
|
5
5
|
var license = "Apache-2.0";
|
|
@@ -50,15 +50,15 @@ var scripts = {
|
|
|
50
50
|
};
|
|
51
51
|
var dependencies = {
|
|
52
52
|
"@backstage-community/plugin-rbac-common": "workspace:^",
|
|
53
|
-
"@backstage/catalog-model": "^1.7.
|
|
54
|
-
"@backstage/core-components": "^0.18.
|
|
55
|
-
"@backstage/core-plugin-api": "^1.12.
|
|
56
|
-
"@backstage/frontend-plugin-api": "^0.
|
|
57
|
-
"@backstage/plugin-app-react": "^0.2.
|
|
58
|
-
"@backstage/plugin-catalog": "^
|
|
53
|
+
"@backstage/catalog-model": "^1.7.7",
|
|
54
|
+
"@backstage/core-components": "^0.18.8",
|
|
55
|
+
"@backstage/core-plugin-api": "^1.12.4",
|
|
56
|
+
"@backstage/frontend-plugin-api": "^0.15.1",
|
|
57
|
+
"@backstage/plugin-app-react": "^0.2.1",
|
|
58
|
+
"@backstage/plugin-catalog": "^2.0.1",
|
|
59
59
|
"@backstage/plugin-catalog-common": "^1.1.8",
|
|
60
|
-
"@backstage/plugin-permission-common": "^0.9.
|
|
61
|
-
"@backstage/plugin-permission-react": "^0.4.
|
|
60
|
+
"@backstage/plugin-permission-common": "^0.9.7",
|
|
61
|
+
"@backstage/plugin-permission-react": "^0.4.41",
|
|
62
62
|
"@backstage/theme": "^0.7.2",
|
|
63
63
|
"@mui/icons-material": "5.18.0",
|
|
64
64
|
"@mui/material": "^5.14.18",
|
|
@@ -79,12 +79,12 @@ var peerDependencies = {
|
|
|
79
79
|
};
|
|
80
80
|
var devDependencies = {
|
|
81
81
|
"@axe-core/playwright": "^4.11.0",
|
|
82
|
-
"@backstage/cli": "^0.
|
|
83
|
-
"@backstage/core-app-api": "^1.19.
|
|
84
|
-
"@backstage/dev-utils": "^1.1.
|
|
85
|
-
"@backstage/frontend-defaults": "^0.
|
|
86
|
-
"@backstage/test-utils": "^1.7.
|
|
87
|
-
"@backstage/ui": "^0.
|
|
82
|
+
"@backstage/cli": "^0.36.0",
|
|
83
|
+
"@backstage/core-app-api": "^1.19.6",
|
|
84
|
+
"@backstage/dev-utils": "^1.1.21",
|
|
85
|
+
"@backstage/frontend-defaults": "^0.5.0",
|
|
86
|
+
"@backstage/test-utils": "^1.7.16",
|
|
87
|
+
"@backstage/ui": "^0.13.1",
|
|
88
88
|
"@playwright/test": "^1.56.1",
|
|
89
89
|
"@testing-library/dom": "^10.0.0",
|
|
90
90
|
"@testing-library/jest-dom": "^6.0.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage-community/plugin-rbac",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.52.0",
|
|
4
4
|
"main": "./dist/index.esm.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -62,16 +62,16 @@
|
|
|
62
62
|
"ui-test:legacy": "start-server-and-test start:legacy localhost:3000 'playwright test'"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@backstage-community/plugin-rbac-common": "^1.
|
|
66
|
-
"@backstage/catalog-model": "^1.7.
|
|
67
|
-
"@backstage/core-components": "^0.18.
|
|
68
|
-
"@backstage/core-plugin-api": "^1.12.
|
|
69
|
-
"@backstage/frontend-plugin-api": "^0.
|
|
70
|
-
"@backstage/plugin-app-react": "^0.2.
|
|
71
|
-
"@backstage/plugin-catalog": "^
|
|
65
|
+
"@backstage-community/plugin-rbac-common": "^1.26.0",
|
|
66
|
+
"@backstage/catalog-model": "^1.7.7",
|
|
67
|
+
"@backstage/core-components": "^0.18.8",
|
|
68
|
+
"@backstage/core-plugin-api": "^1.12.4",
|
|
69
|
+
"@backstage/frontend-plugin-api": "^0.15.1",
|
|
70
|
+
"@backstage/plugin-app-react": "^0.2.1",
|
|
71
|
+
"@backstage/plugin-catalog": "^2.0.1",
|
|
72
72
|
"@backstage/plugin-catalog-common": "^1.1.8",
|
|
73
|
-
"@backstage/plugin-permission-common": "^0.9.
|
|
74
|
-
"@backstage/plugin-permission-react": "^0.4.
|
|
73
|
+
"@backstage/plugin-permission-common": "^0.9.7",
|
|
74
|
+
"@backstage/plugin-permission-react": "^0.4.41",
|
|
75
75
|
"@backstage/theme": "^0.7.2",
|
|
76
76
|
"@mui/icons-material": "5.18.0",
|
|
77
77
|
"@mui/material": "^5.14.18",
|
|
@@ -92,12 +92,12 @@
|
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
94
|
"@axe-core/playwright": "^4.11.0",
|
|
95
|
-
"@backstage/cli": "^0.
|
|
96
|
-
"@backstage/core-app-api": "^1.19.
|
|
97
|
-
"@backstage/dev-utils": "^1.1.
|
|
98
|
-
"@backstage/frontend-defaults": "^0.
|
|
99
|
-
"@backstage/test-utils": "^1.7.
|
|
100
|
-
"@backstage/ui": "^0.
|
|
95
|
+
"@backstage/cli": "^0.36.0",
|
|
96
|
+
"@backstage/core-app-api": "^1.19.6",
|
|
97
|
+
"@backstage/dev-utils": "^1.1.21",
|
|
98
|
+
"@backstage/frontend-defaults": "^0.5.0",
|
|
99
|
+
"@backstage/test-utils": "^1.7.16",
|
|
100
|
+
"@backstage/ui": "^0.13.1",
|
|
101
101
|
"@playwright/test": "^1.56.1",
|
|
102
102
|
"@testing-library/dom": "^10.0.0",
|
|
103
103
|
"@testing-library/jest-dom": "^6.0.0",
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { NavItemBlueprint } from '@backstage/frontend-plugin-api';
|
|
2
|
-
import { rootRouteRef } from '../routes.esm.js';
|
|
3
|
-
import RbacIcon from '@mui/icons-material/VpnKeyOutlined';
|
|
4
|
-
|
|
5
|
-
const rbacNavItem = NavItemBlueprint.make({
|
|
6
|
-
params: {
|
|
7
|
-
title: "RBAC",
|
|
8
|
-
routeRef: rootRouteRef,
|
|
9
|
-
// FIXME: improve icon type in Backstage 1.49, currently the icon type is deprecated but there is no change in the NavItemBlueprint!?
|
|
10
|
-
icon: RbacIcon
|
|
11
|
-
}
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
export { rbacNavItem as default, rbacNavItem };
|
|
15
|
-
//# sourceMappingURL=navItems.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"navItems.esm.js","sources":["../../src/alpha/navItems.tsx"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { NavItemBlueprint } from '@backstage/frontend-plugin-api';\nimport { rootRouteRef } from '../routes';\nimport { RbacIcon } from '..';\n\nexport const rbacNavItem = NavItemBlueprint.make({\n params: {\n title: 'RBAC',\n routeRef: rootRouteRef,\n // FIXME: improve icon type in Backstage 1.49, currently the icon type is deprecated but there is no change in the NavItemBlueprint!?\n icon: RbacIcon as any,\n },\n});\n\nexport default rbacNavItem;\n"],"names":[],"mappings":";;;;AAoBa,MAAA,WAAA,GAAc,iBAAiB,IAAK,CAAA;AAAA,EAC/C,MAAQ,EAAA;AAAA,IACN,KAAO,EAAA,MAAA;AAAA,IACP,QAAU,EAAA,YAAA;AAAA;AAAA,IAEV,IAAM,EAAA;AAAA;AAEV,CAAC;;;;"}
|