@backstage-community/plugin-rbac 1.39.2 → 1.40.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.
Files changed (33) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/api/RBACBackendClient.esm.js.map +1 -1
  3. package/dist/components/CreateRole/EditRolePage.esm.js +1 -0
  4. package/dist/components/CreateRole/EditRolePage.esm.js.map +1 -1
  5. package/dist/components/CreateRole/ReviewStep.esm.js +1 -1
  6. package/dist/components/CreateRole/ReviewStep.esm.js.map +1 -1
  7. package/dist/components/CreateRole/RoleDetailsForm.esm.js +17 -0
  8. package/dist/components/CreateRole/RoleDetailsForm.esm.js.map +1 -1
  9. package/dist/components/CreateRole/RoleForm.esm.js +1 -0
  10. package/dist/components/CreateRole/RoleForm.esm.js.map +1 -1
  11. package/dist/components/EditRole.esm.js +12 -3
  12. package/dist/components/EditRole.esm.js.map +1 -1
  13. package/dist/components/RbacPage.esm.js +15 -11
  14. package/dist/components/RbacPage.esm.js.map +1 -1
  15. package/dist/components/RoleOverview/AboutCard.esm.js +10 -7
  16. package/dist/components/RoleOverview/AboutCard.esm.js.map +1 -1
  17. package/dist/components/RoleOverview/MembersCard.esm.js +3 -12
  18. package/dist/components/RoleOverview/MembersCard.esm.js.map +1 -1
  19. package/dist/components/RoleOverview/PermissionsCard.esm.js +3 -12
  20. package/dist/components/RoleOverview/PermissionsCard.esm.js.map +1 -1
  21. package/dist/components/RoleOverview/RoleOverviewPage.esm.js +34 -24
  22. package/dist/components/RoleOverview/RoleOverviewPage.esm.js.map +1 -1
  23. package/dist/components/RolesList/DeleteRole.esm.js +13 -4
  24. package/dist/components/RolesList/DeleteRole.esm.js.map +1 -1
  25. package/dist/components/RolesList/RolesListColumns.esm.js +4 -8
  26. package/dist/components/RolesList/RolesListColumns.esm.js.map +1 -1
  27. package/dist/components/Router.esm.js +3 -23
  28. package/dist/components/Router.esm.js.map +1 -1
  29. package/dist/hooks/useRoles.esm.js +3 -17
  30. package/dist/hooks/useRoles.esm.js.map +1 -1
  31. package/dist/utils/create-role-utils.esm.js +2 -1
  32. package/dist/utils/create-role-utils.esm.js.map +1 -1
  33. package/package.json +2 -3
@@ -1 +1 @@
1
- {"version":3,"file":"AboutCard.esm.js","sources":["../../../src/components/RoleOverview/AboutCard.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 React from 'react';\n\nimport {\n MarkdownContent,\n Progress,\n WarningPanel,\n} from '@backstage/core-components';\nimport { AboutField } from '@backstage/plugin-catalog';\n\nimport Card from '@mui/material/Card';\nimport CardContent from '@mui/material/CardContent';\nimport CardHeader from '@mui/material/CardHeader';\nimport Grid from '@mui/material/Grid';\nimport { makeStyles } from '@mui/styles';\n\nimport { useRole } from '../../hooks/useRole';\n\nconst useStyles = makeStyles({\n text: {\n wordBreak: 'break-word',\n },\n});\n\ntype AboutCardProps = {\n roleName: string;\n};\n\nexport const AboutCard = ({ roleName }: AboutCardProps) => {\n const classes = useStyles();\n const { role, roleError, loading } = useRole(roleName);\n if (loading) {\n return <Progress />;\n }\n\n let lastModified = role?.metadata?.lastModified;\n if (lastModified) {\n const date = new Date(lastModified);\n const time = date.toLocaleString('en-US', {\n hour: '2-digit' as const,\n minute: '2-digit' as const,\n hour12: false,\n timeZone: 'UTC',\n });\n lastModified = `${date.getUTCDate()} ${date.toLocaleString('default', {\n month: 'short',\n })} ${date.getUTCFullYear()}, ${time}`;\n } else {\n lastModified = 'No information';\n }\n\n return (\n <Card\n sx={{\n display: 'flex',\n flexDirection: 'column',\n height: 'calc(100% - 10px)', // for pages without content header\n marginBottom: '10px',\n }}\n >\n <CardHeader title=\"About\" />\n <CardContent\n sx={{\n flex: 1,\n }}\n >\n {roleError.name ? (\n <div style={{ paddingBottom: '16px' }}>\n <WarningPanel\n message={roleError?.message}\n title=\"Something went wrong while fetching role\"\n severity=\"error\"\n />\n </div>\n ) : (\n <Grid container spacing={2}>\n <Grid item xs={4} sm={8} lg={4}>\n <AboutField label=\"Description\">\n <MarkdownContent\n className={classes.text}\n content={role?.metadata?.description ?? 'No description'}\n />\n </AboutField>\n </Grid>\n <Grid item xs={4} sm={8} lg={4}>\n <AboutField label=\"Modified By\">\n <MarkdownContent\n className={classes.text}\n content={role?.metadata?.modifiedBy ?? 'No information'}\n />\n </AboutField>\n </Grid>\n <Grid item xs={4} sm={8} lg={4}>\n <AboutField label=\"Last Modified\">\n <MarkdownContent\n className={classes.text}\n content={lastModified}\n />\n </AboutField>\n </Grid>\n </Grid>\n )}\n </CardContent>\n </Card>\n );\n};\n"],"names":["React"],"mappings":"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"}
1
+ {"version":3,"file":"AboutCard.esm.js","sources":["../../../src/components/RoleOverview/AboutCard.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 React from 'react';\n\nimport {\n MarkdownContent,\n Progress,\n WarningPanel,\n} from '@backstage/core-components';\nimport { AboutField } from '@backstage/plugin-catalog';\n\nimport Card from '@mui/material/Card';\nimport CardContent from '@mui/material/CardContent';\nimport CardHeader from '@mui/material/CardHeader';\nimport Grid from '@mui/material/Grid';\nimport { makeStyles } from '@mui/styles';\n\nimport { useRole } from '../../hooks/useRole';\n\nconst useStyles = makeStyles({\n text: {\n wordBreak: 'break-word',\n },\n});\n\ntype AboutCardProps = {\n roleName: string;\n};\n\nexport const AboutCard = ({ roleName }: AboutCardProps) => {\n const classes = useStyles();\n const { role, roleError, loading } = useRole(roleName);\n if (loading) {\n return <Progress />;\n }\n\n let lastModified = role?.metadata?.lastModified;\n if (lastModified) {\n const date = new Date(lastModified);\n const time = date.toLocaleString('en-US', {\n hour: '2-digit' as const,\n minute: '2-digit' as const,\n hour12: false,\n timeZone: 'UTC',\n });\n lastModified = `${date.getUTCDate()} ${date.toLocaleString('default', {\n month: 'short',\n })} ${date.getUTCFullYear()}, ${time}`;\n } else {\n lastModified = '--';\n }\n\n const description =\n role?.metadata?.description && role.metadata.description.length > 0\n ? role.metadata.description\n : '--';\n const modifiedBy =\n role?.metadata?.modifiedBy && role.metadata.modifiedBy.length > 0\n ? role.metadata.modifiedBy\n : '--';\n const owner =\n role?.metadata?.owner && role.metadata.owner.length > 0\n ? role.metadata.owner\n : '--';\n\n return (\n <Card\n sx={{\n display: 'flex',\n flexDirection: 'column',\n height: 'calc(100% - 10px)', // for pages without content header\n marginBottom: '10px',\n }}\n >\n <CardHeader title=\"About\" />\n <CardContent\n sx={{\n flex: 1,\n }}\n >\n {roleError.name ? (\n <div style={{ paddingBottom: '16px' }}>\n <WarningPanel\n message={roleError?.message}\n title=\"Something went wrong while fetching role\"\n severity=\"error\"\n />\n </div>\n ) : (\n <Grid container spacing={2}>\n <Grid item xs={3} sm={6} lg={3}>\n <AboutField label=\"Description\">\n <MarkdownContent\n className={classes.text}\n content={description}\n />\n </AboutField>\n </Grid>\n <Grid item xs={3} sm={6} lg={3}>\n <AboutField label=\"Modified By\">\n <MarkdownContent\n className={classes.text}\n content={modifiedBy}\n />\n </AboutField>\n </Grid>\n <Grid item xs={3} sm={6} lg={3}>\n <AboutField label=\"Last Modified\">\n <MarkdownContent\n className={classes.text}\n content={lastModified}\n />\n </AboutField>\n </Grid>\n <Grid item xs={3} sm={6} lg={3}>\n <AboutField label=\"Owner\">\n <MarkdownContent className={classes.text} content={owner} />\n </AboutField>\n </Grid>\n </Grid>\n )}\n </CardContent>\n </Card>\n );\n};\n"],"names":["React"],"mappings":"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"}
@@ -1,10 +1,8 @@
1
1
  import React__default from 'react';
2
2
  import { parseEntityRef } from '@backstage/catalog-model';
3
3
  import { WarningPanel, Table } from '@backstage/core-components';
4
- import { usePermission } from '@backstage/plugin-permission-react';
5
4
  import CachedIcon from '@mui/icons-material/Cached';
6
5
  import Box from '@mui/material/Box';
7
- import { policyEntityUpdatePermission } from '@backstage-community/plugin-rbac-common';
8
6
  import { filterTableData } from '../../utils/filter-table-data.esm.js';
9
7
  import { getMembers } from '../../utils/rbac-utils.esm.js';
10
8
  import EditRole from '../EditRole.esm.js';
@@ -17,8 +15,8 @@ const getEditIcon = (isAllowed, roleName) => {
17
15
  EditRole,
18
16
  {
19
17
  dataTestId: isAllowed ? "update-members" : "disable-update-members",
18
+ canEdit: isAllowed,
20
19
  roleName,
21
- disable: !isAllowed,
22
20
  to: `../../role/${kind}/${namespace}/${name}?activeStep=${1}`
23
21
  }
24
22
  );
@@ -26,10 +24,6 @@ const getEditIcon = (isAllowed, roleName) => {
26
24
  const MembersCard = ({ roleName, membersInfo }) => {
27
25
  const { data, loading, retry, error, canReadUsersAndGroups } = membersInfo;
28
26
  const [searchText, setSearchText] = React__default.useState();
29
- const policyEntityPermissionResult = usePermission({
30
- permission: policyEntityUpdatePermission,
31
- resourceRef: policyEntityUpdatePermission.resourceType
32
- });
33
27
  const actions = [
34
28
  {
35
29
  icon: getRefreshIcon,
@@ -41,11 +35,8 @@ const MembersCard = ({ roleName, membersInfo }) => {
41
35
  }
42
36
  },
43
37
  {
44
- icon: () => getEditIcon(
45
- policyEntityPermissionResult.allowed && canReadUsersAndGroups,
46
- roleName
47
- ),
48
- tooltip: policyEntityPermissionResult.allowed && canReadUsersAndGroups ? "Edit" : "Unauthorized to edit",
38
+ icon: () => getEditIcon(canReadUsersAndGroups, roleName),
39
+ tooltip: canReadUsersAndGroups ? "Edit" : "Unauthorized to edit",
49
40
  isFreeAction: true,
50
41
  onClick: () => {
51
42
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MembersCard.esm.js","sources":["../../../src/components/RoleOverview/MembersCard.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 React from 'react';\n\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport { Table, WarningPanel } from '@backstage/core-components';\nimport { usePermission } from '@backstage/plugin-permission-react';\n\nimport CachedIcon from '@mui/icons-material/Cached';\nimport Box from '@mui/material/Box';\n\nimport { policyEntityUpdatePermission } from '@backstage-community/plugin-rbac-common';\n\nimport { MembersInfo } from '../../hooks/useMembers';\nimport { filterTableData } from '../../utils/filter-table-data';\nimport { getMembers } from '../../utils/rbac-utils';\nimport EditRole from '../EditRole';\nimport { columns } from './MembersListColumns';\n\ntype MembersCardProps = {\n roleName: string;\n membersInfo: MembersInfo;\n};\n\nconst getRefreshIcon = () => <CachedIcon />;\nconst getEditIcon = (isAllowed: boolean, roleName: string) => {\n const { kind, name, namespace } = parseEntityRef(roleName);\n\n return (\n <EditRole\n dataTestId={isAllowed ? 'update-members' : 'disable-update-members'}\n roleName={roleName}\n disable={!isAllowed}\n to={`../../role/${kind}/${namespace}/${name}?activeStep=${1}`}\n />\n );\n};\n\nexport const MembersCard = ({ roleName, membersInfo }: MembersCardProps) => {\n const { data, loading, retry, error, canReadUsersAndGroups } = membersInfo;\n const [searchText, setSearchText] = React.useState<string>();\n const policyEntityPermissionResult = usePermission({\n permission: policyEntityUpdatePermission,\n resourceRef: policyEntityUpdatePermission.resourceType,\n });\n\n const actions = [\n {\n icon: getRefreshIcon,\n tooltip: 'Refresh',\n isFreeAction: true,\n onClick: () => {\n retry.roleRetry();\n retry.membersRetry();\n },\n },\n {\n icon: () =>\n getEditIcon(\n policyEntityPermissionResult.allowed && canReadUsersAndGroups,\n roleName,\n ),\n tooltip:\n policyEntityPermissionResult.allowed && canReadUsersAndGroups\n ? 'Edit'\n : 'Unauthorized to edit',\n isFreeAction: true,\n onClick: () => {},\n },\n ];\n\n const filteredData = React.useMemo(\n () => filterTableData({ data, columns, searchText }),\n [data, searchText],\n );\n\n return (\n <Box>\n {!loading && error && (\n <Box style={{ paddingBottom: '16px' }}>\n <WarningPanel\n message={(error as Error)?.message || (error as Error)?.name}\n title=\"Something went wrong while fetching the users and groups\"\n severity=\"error\"\n />\n </Box>\n )}\n <Table\n title={\n !loading && data?.length\n ? `Users and groups (${getMembers(filteredData)})`\n : 'Users and groups'\n }\n actions={actions}\n options={{ padding: 'default', search: true, paging: true }}\n data={data ?? []}\n isLoading={loading}\n columns={columns}\n emptyContent={\n <Box\n data-testid=\"members-table-empty\"\n sx={{ display: 'flex', justifyContent: 'center', p: 2 }}\n >\n No records found\n </Box>\n }\n onSearchChange={setSearchText}\n />\n </Box>\n );\n};\n"],"names":["React"],"mappings":"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"}
1
+ {"version":3,"file":"MembersCard.esm.js","sources":["../../../src/components/RoleOverview/MembersCard.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 React from 'react';\n\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport { Table, WarningPanel } from '@backstage/core-components';\n\nimport CachedIcon from '@mui/icons-material/Cached';\nimport Box from '@mui/material/Box';\n\nimport { MembersInfo } from '../../hooks/useMembers';\nimport { filterTableData } from '../../utils/filter-table-data';\nimport { getMembers } from '../../utils/rbac-utils';\nimport EditRole from '../EditRole';\nimport { columns } from './MembersListColumns';\n\ntype MembersCardProps = {\n roleName: string;\n membersInfo: MembersInfo;\n};\n\nconst getRefreshIcon = () => <CachedIcon />;\nconst getEditIcon = (isAllowed: boolean, roleName: string) => {\n const { kind, name, namespace } = parseEntityRef(roleName);\n\n return (\n <EditRole\n dataTestId={isAllowed ? 'update-members' : 'disable-update-members'}\n canEdit={isAllowed}\n roleName={roleName}\n to={`../../role/${kind}/${namespace}/${name}?activeStep=${1}`}\n />\n );\n};\n\nexport const MembersCard = ({ roleName, membersInfo }: MembersCardProps) => {\n const { data, loading, retry, error, canReadUsersAndGroups } = membersInfo;\n const [searchText, setSearchText] = React.useState<string>();\n\n const actions = [\n {\n icon: getRefreshIcon,\n tooltip: 'Refresh',\n isFreeAction: true,\n onClick: () => {\n retry.roleRetry();\n retry.membersRetry();\n },\n },\n {\n icon: () => getEditIcon(canReadUsersAndGroups, roleName),\n tooltip: canReadUsersAndGroups ? 'Edit' : 'Unauthorized to edit',\n isFreeAction: true,\n onClick: () => {},\n },\n ];\n\n const filteredData = React.useMemo(\n () => filterTableData({ data, columns, searchText }),\n [data, searchText],\n );\n\n return (\n <Box>\n {!loading && error && (\n <Box style={{ paddingBottom: '16px' }}>\n <WarningPanel\n message={(error as Error)?.message || (error as Error)?.name}\n title=\"Something went wrong while fetching the users and groups\"\n severity=\"error\"\n />\n </Box>\n )}\n <Table\n title={\n !loading && data?.length\n ? `Users and groups (${getMembers(filteredData)})`\n : 'Users and groups'\n }\n actions={actions}\n options={{ padding: 'default', search: true, paging: true }}\n data={data ?? []}\n isLoading={loading}\n columns={columns}\n emptyContent={\n <Box\n data-testid=\"members-table-empty\"\n sx={{ display: 'flex', justifyContent: 'center', p: 2 }}\n >\n No records found\n </Box>\n }\n onSearchChange={setSearchText}\n />\n </Box>\n );\n};\n"],"names":["React"],"mappings":"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"}
@@ -1,10 +1,8 @@
1
1
  import React__default from 'react';
2
2
  import { parseEntityRef } from '@backstage/catalog-model';
3
3
  import { WarningPanel, Table } from '@backstage/core-components';
4
- import { usePermission } from '@backstage/plugin-permission-react';
5
4
  import CachedIcon from '@mui/icons-material/Cached';
6
5
  import Box from '@mui/material/Box';
7
- import { policyEntityUpdatePermission } from '@backstage-community/plugin-rbac-common';
8
6
  import { usePermissionPolicies } from '../../hooks/usePermissionPolicies.esm.js';
9
7
  import { filterTableData } from '../../utils/filter-table-data.esm.js';
10
8
  import EditRole from '../EditRole.esm.js';
@@ -17,8 +15,8 @@ const getEditIcon = (isAllowed, roleName) => {
17
15
  EditRole,
18
16
  {
19
17
  dataTestId: isAllowed ? "update-policies" : "disable-update-policies",
18
+ canEdit: isAllowed,
20
19
  roleName,
21
- disable: !isAllowed,
22
20
  to: `../../role/${kind}/${namespace}/${name}?activeStep=${2}`
23
21
  }
24
22
  );
@@ -29,10 +27,6 @@ const PermissionsCard = ({
29
27
  }) => {
30
28
  const { data, loading, retry, error } = usePermissionPolicies(entityReference);
31
29
  const [searchText, setSearchText] = React__default.useState();
32
- const permissionResult = usePermission({
33
- permission: policyEntityUpdatePermission,
34
- resourceRef: policyEntityUpdatePermission.resourceType
35
- });
36
30
  const numberOfPolicies = React__default.useMemo(() => {
37
31
  const filteredPermissions = filterTableData({ data, columns, searchText });
38
32
  let policies = 0;
@@ -57,11 +51,8 @@ const PermissionsCard = ({
57
51
  }
58
52
  },
59
53
  {
60
- icon: () => getEditIcon(
61
- permissionResult.allowed && canReadUsersAndGroups,
62
- entityReference
63
- ),
64
- tooltip: permissionResult.allowed && canReadUsersAndGroups ? "Edit" : "Unauthorized to edit",
54
+ icon: () => getEditIcon(canReadUsersAndGroups, entityReference),
55
+ tooltip: canReadUsersAndGroups ? "Edit" : "Unauthorized to edit",
65
56
  isFreeAction: true,
66
57
  onClick: () => {
67
58
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PermissionsCard.esm.js","sources":["../../../src/components/RoleOverview/PermissionsCard.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 React from 'react';\n\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport { Table, WarningPanel } from '@backstage/core-components';\nimport { usePermission } from '@backstage/plugin-permission-react';\n\nimport CachedIcon from '@mui/icons-material/Cached';\nimport Box from '@mui/material/Box';\n\nimport { policyEntityUpdatePermission } from '@backstage-community/plugin-rbac-common';\n\nimport { usePermissionPolicies } from '../../hooks/usePermissionPolicies';\nimport { filterTableData } from '../../utils/filter-table-data';\nimport EditRole from '../EditRole';\nimport { columns } from './PermissionsListColumns';\n\ntype PermissionsCardProps = {\n entityReference: string;\n canReadUsersAndGroups: boolean;\n};\n\nconst getRefreshIcon = () => <CachedIcon />;\nconst getEditIcon = (isAllowed: boolean, roleName: string) => {\n const { kind, name, namespace } = parseEntityRef(roleName);\n\n return (\n <EditRole\n dataTestId={isAllowed ? 'update-policies' : 'disable-update-policies'}\n roleName={roleName}\n disable={!isAllowed}\n to={`../../role/${kind}/${namespace}/${name}?activeStep=${2}`}\n />\n );\n};\n\nexport const PermissionsCard = ({\n entityReference,\n canReadUsersAndGroups,\n}: PermissionsCardProps) => {\n const { data, loading, retry, error } =\n usePermissionPolicies(entityReference);\n const [searchText, setSearchText] = React.useState<string>();\n const permissionResult = usePermission({\n permission: policyEntityUpdatePermission,\n resourceRef: policyEntityUpdatePermission.resourceType,\n });\n\n const numberOfPolicies = React.useMemo(() => {\n const filteredPermissions = filterTableData({ data, columns, searchText });\n let policies = 0;\n filteredPermissions.forEach(p => {\n if (p.conditions) {\n policies++;\n return;\n }\n policies += p.policies.filter(pol => pol.effect === 'allow').length;\n });\n return policies;\n }, [data, searchText]);\n\n const actions = [\n {\n icon: getRefreshIcon,\n tooltip: 'Refresh',\n isFreeAction: true,\n onClick: () => {\n retry.permissionPoliciesRetry();\n retry.policiesRetry();\n retry.conditionalPoliciesRetry();\n },\n },\n {\n icon: () =>\n getEditIcon(\n permissionResult.allowed && canReadUsersAndGroups,\n entityReference,\n ),\n tooltip:\n permissionResult.allowed && canReadUsersAndGroups\n ? 'Edit'\n : 'Unauthorized to edit',\n isFreeAction: true,\n onClick: () => {},\n },\n ];\n\n return (\n <Box>\n {error?.name && error.name !== 404 && (\n <Box style={{ paddingBottom: '16px' }}>\n <WarningPanel\n message={error?.message}\n title=\"Something went wrong while fetching the permission policies\"\n severity=\"error\"\n />\n </Box>\n )}\n <Table\n title={\n !loading && data.length > 0\n ? `Permission Policies (${numberOfPolicies})`\n : 'Permission Policies'\n }\n actions={actions}\n options={{ padding: 'default', search: true, paging: true }}\n data={data}\n columns={columns}\n isLoading={loading}\n emptyContent={\n <Box\n data-testid=\"permission-table-empty\"\n sx={{ display: 'flex', justifyContent: 'center', p: 2 }}\n >\n No records found\n </Box>\n }\n onSearchChange={setSearchText}\n />\n </Box>\n );\n};\n"],"names":["React"],"mappings":"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"}
1
+ {"version":3,"file":"PermissionsCard.esm.js","sources":["../../../src/components/RoleOverview/PermissionsCard.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 React from 'react';\n\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport { Table, WarningPanel } from '@backstage/core-components';\n\nimport CachedIcon from '@mui/icons-material/Cached';\nimport Box from '@mui/material/Box';\n\nimport { usePermissionPolicies } from '../../hooks/usePermissionPolicies';\nimport { filterTableData } from '../../utils/filter-table-data';\nimport EditRole from '../EditRole';\nimport { columns } from './PermissionsListColumns';\n\ntype PermissionsCardProps = {\n entityReference: string;\n canReadUsersAndGroups: boolean;\n};\n\nconst getRefreshIcon = () => <CachedIcon />;\nconst getEditIcon = (isAllowed: boolean, roleName: string) => {\n const { kind, name, namespace } = parseEntityRef(roleName);\n\n return (\n <EditRole\n dataTestId={isAllowed ? 'update-policies' : 'disable-update-policies'}\n canEdit={isAllowed}\n roleName={roleName}\n to={`../../role/${kind}/${namespace}/${name}?activeStep=${2}`}\n />\n );\n};\n\nexport const PermissionsCard = ({\n entityReference,\n canReadUsersAndGroups,\n}: PermissionsCardProps) => {\n const { data, loading, retry, error } =\n usePermissionPolicies(entityReference);\n const [searchText, setSearchText] = React.useState<string>();\n\n const numberOfPolicies = React.useMemo(() => {\n const filteredPermissions = filterTableData({ data, columns, searchText });\n let policies = 0;\n filteredPermissions.forEach(p => {\n if (p.conditions) {\n policies++;\n return;\n }\n policies += p.policies.filter(pol => pol.effect === 'allow').length;\n });\n return policies;\n }, [data, searchText]);\n\n const actions = [\n {\n icon: getRefreshIcon,\n tooltip: 'Refresh',\n isFreeAction: true,\n onClick: () => {\n retry.permissionPoliciesRetry();\n retry.policiesRetry();\n retry.conditionalPoliciesRetry();\n },\n },\n {\n icon: () => getEditIcon(canReadUsersAndGroups, entityReference),\n tooltip: canReadUsersAndGroups ? 'Edit' : 'Unauthorized to edit',\n isFreeAction: true,\n onClick: () => {},\n },\n ];\n\n return (\n <Box>\n {error?.name && error.name !== 404 && (\n <Box style={{ paddingBottom: '16px' }}>\n <WarningPanel\n message={error?.message}\n title=\"Something went wrong while fetching the permission policies\"\n severity=\"error\"\n />\n </Box>\n )}\n <Table\n title={\n !loading && data.length > 0\n ? `Permission Policies (${numberOfPolicies})`\n : 'Permission Policies'\n }\n actions={actions}\n options={{ padding: 'default', search: true, paging: true }}\n data={data}\n columns={columns}\n isLoading={loading}\n emptyContent={\n <Box\n data-testid=\"permission-table-empty\"\n sx={{ display: 'flex', justifyContent: 'center', p: 2 }}\n >\n No records found\n </Box>\n }\n onSearchChange={setSearchText}\n />\n </Box>\n );\n};\n"],"names":["React"],"mappings":"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"}
@@ -9,6 +9,8 @@ import { useToast } from '../ToastContext.esm.js';
9
9
  import { AboutCard } from './AboutCard.esm.js';
10
10
  import { MembersCard } from './MembersCard.esm.js';
11
11
  import { PermissionsCard } from './PermissionsCard.esm.js';
12
+ import { RequirePermission } from '@backstage/plugin-permission-react';
13
+ import { policyEntityReadPermission } from '@backstage-community/plugin-rbac-common';
12
14
 
13
15
  const RoleOverviewPage = () => {
14
16
  const { roleName, roleNamespace, roleKind } = useParams();
@@ -18,31 +20,39 @@ const RoleOverviewPage = () => {
18
20
  const onAlertClose = () => {
19
21
  setToastMessage("");
20
22
  };
21
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(SnackbarAlert, { toastMessage, onAlertClose }), /* @__PURE__ */ React__default.createElement(Page, { themeId: "tool" }, /* @__PURE__ */ React__default.createElement(
22
- Header,
23
+ return /* @__PURE__ */ React__default.createElement(
24
+ RequirePermission,
23
25
  {
24
- title: `${roleKind}:${roleNamespace}/${roleName}`,
25
- type: "RBAC",
26
- typeLink: ".."
27
- }
28
- ), /* @__PURE__ */ React__default.createElement(TabbedLayout, null, /* @__PURE__ */ React__default.createElement(TabbedLayout.Route, { path: "", title: "Overview" }, /* @__PURE__ */ React__default.createElement(Grid, { container: true, direction: "row", spacing: 2 }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, lg: 12, xs: 12 }, /* @__PURE__ */ React__default.createElement(
29
- AboutCard,
30
- {
31
- roleName: `${roleKind}:${roleNamespace}/${roleName}`
32
- }
33
- )), /* @__PURE__ */ React__default.createElement(Grid, { item: true, lg: 6, xs: 12 }, /* @__PURE__ */ React__default.createElement(
34
- MembersCard,
35
- {
36
- roleName: `${roleKind}:${roleNamespace}/${roleName}`,
37
- membersInfo
38
- }
39
- )), /* @__PURE__ */ React__default.createElement(Grid, { item: true, lg: 6, xs: 12 }, /* @__PURE__ */ React__default.createElement(
40
- PermissionsCard,
41
- {
42
- entityReference: `${roleKind}:${roleNamespace}/${roleName}`,
43
- canReadUsersAndGroups: membersInfo.canReadUsersAndGroups
44
- }
45
- )))))));
26
+ permission: policyEntityReadPermission,
27
+ resourceRef: `${roleKind}:${roleNamespace}/${roleName}`
28
+ },
29
+ /* @__PURE__ */ React__default.createElement(SnackbarAlert, { toastMessage, onAlertClose }),
30
+ /* @__PURE__ */ React__default.createElement(Page, { themeId: "tool" }, /* @__PURE__ */ React__default.createElement(
31
+ Header,
32
+ {
33
+ title: `${roleKind}:${roleNamespace}/${roleName}`,
34
+ type: "RBAC",
35
+ typeLink: ".."
36
+ }
37
+ ), /* @__PURE__ */ React__default.createElement(TabbedLayout, null, /* @__PURE__ */ React__default.createElement(TabbedLayout.Route, { path: "", title: "Overview" }, /* @__PURE__ */ React__default.createElement(Grid, { container: true, direction: "row", spacing: 2 }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, lg: 12, xs: 12 }, /* @__PURE__ */ React__default.createElement(
38
+ AboutCard,
39
+ {
40
+ roleName: `${roleKind}:${roleNamespace}/${roleName}`
41
+ }
42
+ )), /* @__PURE__ */ React__default.createElement(Grid, { item: true, lg: 6, xs: 12 }, /* @__PURE__ */ React__default.createElement(
43
+ MembersCard,
44
+ {
45
+ roleName: `${roleKind}:${roleNamespace}/${roleName}`,
46
+ membersInfo
47
+ }
48
+ )), /* @__PURE__ */ React__default.createElement(Grid, { item: true, lg: 6, xs: 12 }, /* @__PURE__ */ React__default.createElement(
49
+ PermissionsCard,
50
+ {
51
+ entityReference: `${roleKind}:${roleNamespace}/${roleName}`,
52
+ canReadUsersAndGroups: membersInfo.canReadUsersAndGroups
53
+ }
54
+ ))))))
55
+ );
46
56
  };
47
57
 
48
58
  export { RoleOverviewPage };
@@ -1 +1 @@
1
- {"version":3,"file":"RoleOverviewPage.esm.js","sources":["../../../src/components/RoleOverview/RoleOverviewPage.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 React from 'react';\nimport { useParams } from 'react-router-dom';\n\nimport { Header, Page, TabbedLayout } from '@backstage/core-components';\n\nimport Grid from '@mui/material/Grid';\n\nimport { useLocationToast } from '../../hooks/useLocationToast';\nimport { useMembers } from '../../hooks/useMembers';\nimport { SnackbarAlert } from '../SnackbarAlert';\nimport { useToast } from '../ToastContext';\nimport { AboutCard } from './AboutCard';\nimport { MembersCard } from './MembersCard';\nimport { PermissionsCard } from './PermissionsCard';\n\nexport const RoleOverviewPage = () => {\n const { roleName, roleNamespace, roleKind } = useParams();\n const { toastMessage, setToastMessage } = useToast();\n const membersInfo = useMembers(`${roleKind}:${roleNamespace}/${roleName}`);\n\n useLocationToast(setToastMessage);\n\n const onAlertClose = () => {\n setToastMessage('');\n };\n\n return (\n <>\n <SnackbarAlert toastMessage={toastMessage} onAlertClose={onAlertClose} />\n <Page themeId=\"tool\">\n <Header\n title={`${roleKind}:${roleNamespace}/${roleName}`}\n type=\"RBAC\"\n typeLink=\"..\"\n />\n <TabbedLayout>\n <TabbedLayout.Route path=\"\" title=\"Overview\">\n <Grid container direction=\"row\" spacing={2}>\n <Grid item lg={12} xs={12}>\n <AboutCard\n roleName={`${roleKind}:${roleNamespace}/${roleName}`}\n />\n </Grid>\n <Grid item lg={6} xs={12}>\n <MembersCard\n roleName={`${roleKind}:${roleNamespace}/${roleName}`}\n membersInfo={membersInfo}\n />\n </Grid>\n <Grid item lg={6} xs={12}>\n <PermissionsCard\n entityReference={`${roleKind}:${roleNamespace}/${roleName}`}\n canReadUsersAndGroups={membersInfo.canReadUsersAndGroups}\n />\n </Grid>\n </Grid>\n </TabbedLayout.Route>\n </TabbedLayout>\n </Page>\n </>\n );\n};\n"],"names":["React"],"mappings":";;;;;;;;;;;;AA8BO,MAAM,mBAAmB,MAAM;AACpC,EAAA,MAAM,EAAE,QAAA,EAAU,aAAe,EAAA,QAAA,KAAa,SAAU,EAAA;AACxD,EAAA,MAAM,EAAE,YAAA,EAAc,eAAgB,EAAA,GAAI,QAAS,EAAA;AACnD,EAAM,MAAA,WAAA,GAAc,WAAW,CAAG,EAAA,QAAQ,IAAI,aAAa,CAAA,CAAA,EAAI,QAAQ,CAAE,CAAA,CAAA;AAEzE,EAAA,gBAAA,CAAiB,eAAe,CAAA;AAEhC,EAAA,MAAM,eAAe,MAAM;AACzB,IAAA,eAAA,CAAgB,EAAE,CAAA;AAAA,GACpB;AAEA,EACE,uBAAAA,cAAA,CAAA,aAAA,CAAAA,cAAA,CAAA,QAAA,EAAA,IAAA,+CACG,aAAc,EAAA,EAAA,YAAA,EAA4B,cAA4B,CACvE,kBAAAA,cAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,OAAA,EAAQ,MACZ,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,OAAO,CAAG,EAAA,QAAQ,CAAI,CAAA,EAAA,aAAa,IAAI,QAAQ,CAAA,CAAA;AAAA,MAC/C,IAAK,EAAA,MAAA;AAAA,MACL,QAAS,EAAA;AAAA;AAAA,GACX,kBACCA,cAAA,CAAA,aAAA,CAAA,YAAA,EAAA,IAAA,kBACEA,cAAA,CAAA,aAAA,CAAA,YAAA,CAAa,KAAb,EAAA,EAAmB,IAAK,EAAA,EAAA,EAAG,KAAM,EAAA,UAAA,EAAA,kBAC/BA,cAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,WAAS,IAAC,EAAA,SAAA,EAAU,KAAM,EAAA,OAAA,EAAS,CACvC,EAAA,kBAAAA,cAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,IAAA,EAAI,IAAC,EAAA,EAAA,EAAI,EAAI,EAAA,EAAA,EAAI,EACrB,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,UAAU,CAAG,EAAA,QAAQ,CAAI,CAAA,EAAA,aAAa,IAAI,QAAQ,CAAA;AAAA;AAAA,GAEtD,mBACCA,cAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,MAAI,IAAC,EAAA,EAAA,EAAI,CAAG,EAAA,EAAA,EAAI,EACpB,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,UAAU,CAAG,EAAA,QAAQ,CAAI,CAAA,EAAA,aAAa,IAAI,QAAQ,CAAA,CAAA;AAAA,MAClD;AAAA;AAAA,GAEJ,mBACCA,cAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,MAAI,IAAC,EAAA,EAAA,EAAI,CAAG,EAAA,EAAA,EAAI,EACpB,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,eAAA;AAAA,IAAA;AAAA,MACC,iBAAiB,CAAG,EAAA,QAAQ,CAAI,CAAA,EAAA,aAAa,IAAI,QAAQ,CAAA,CAAA;AAAA,MACzD,uBAAuB,WAAY,CAAA;AAAA;AAAA,GAEvC,CACF,CACF,CACF,CACF,CACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"RoleOverviewPage.esm.js","sources":["../../../src/components/RoleOverview/RoleOverviewPage.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 React from 'react';\nimport { useParams } from 'react-router-dom';\n\nimport { Header, Page, TabbedLayout } from '@backstage/core-components';\n\nimport Grid from '@mui/material/Grid';\n\nimport { useLocationToast } from '../../hooks/useLocationToast';\nimport { useMembers } from '../../hooks/useMembers';\nimport { SnackbarAlert } from '../SnackbarAlert';\nimport { useToast } from '../ToastContext';\nimport { AboutCard } from './AboutCard';\nimport { MembersCard } from './MembersCard';\nimport { PermissionsCard } from './PermissionsCard';\nimport { RequirePermission } from '@backstage/plugin-permission-react';\nimport { policyEntityReadPermission } from '@backstage-community/plugin-rbac-common';\n\nexport const RoleOverviewPage = () => {\n const { roleName, roleNamespace, roleKind } = useParams();\n const { toastMessage, setToastMessage } = useToast();\n const membersInfo = useMembers(`${roleKind}:${roleNamespace}/${roleName}`);\n\n useLocationToast(setToastMessage);\n\n const onAlertClose = () => {\n setToastMessage('');\n };\n\n return (\n <RequirePermission\n permission={policyEntityReadPermission}\n resourceRef={`${roleKind}:${roleNamespace}/${roleName}`}\n >\n <SnackbarAlert toastMessage={toastMessage} onAlertClose={onAlertClose} />\n <Page themeId=\"tool\">\n <Header\n title={`${roleKind}:${roleNamespace}/${roleName}`}\n type=\"RBAC\"\n typeLink=\"..\"\n />\n <TabbedLayout>\n <TabbedLayout.Route path=\"\" title=\"Overview\">\n <Grid container direction=\"row\" spacing={2}>\n <Grid item lg={12} xs={12}>\n <AboutCard\n roleName={`${roleKind}:${roleNamespace}/${roleName}`}\n />\n </Grid>\n <Grid item lg={6} xs={12}>\n <MembersCard\n roleName={`${roleKind}:${roleNamespace}/${roleName}`}\n membersInfo={membersInfo}\n />\n </Grid>\n <Grid item lg={6} xs={12}>\n <PermissionsCard\n entityReference={`${roleKind}:${roleNamespace}/${roleName}`}\n canReadUsersAndGroups={membersInfo.canReadUsersAndGroups}\n />\n </Grid>\n </Grid>\n </TabbedLayout.Route>\n </TabbedLayout>\n </Page>\n </RequirePermission>\n );\n};\n"],"names":["React"],"mappings":";;;;;;;;;;;;;;AAgCO,MAAM,mBAAmB,MAAM;AACpC,EAAA,MAAM,EAAE,QAAA,EAAU,aAAe,EAAA,QAAA,KAAa,SAAU,EAAA;AACxD,EAAA,MAAM,EAAE,YAAA,EAAc,eAAgB,EAAA,GAAI,QAAS,EAAA;AACnD,EAAM,MAAA,WAAA,GAAc,WAAW,CAAG,EAAA,QAAQ,IAAI,aAAa,CAAA,CAAA,EAAI,QAAQ,CAAE,CAAA,CAAA;AAEzE,EAAA,gBAAA,CAAiB,eAAe,CAAA;AAEhC,EAAA,MAAM,eAAe,MAAM;AACzB,IAAA,eAAA,CAAgB,EAAE,CAAA;AAAA,GACpB;AAEA,EACE,uBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,iBAAA;AAAA,IAAA;AAAA,MACC,UAAY,EAAA,0BAAA;AAAA,MACZ,aAAa,CAAG,EAAA,QAAQ,CAAI,CAAA,EAAA,aAAa,IAAI,QAAQ,CAAA;AAAA,KAAA;AAAA,oBAErDA,cAAA,CAAA,aAAA,CAAC,aAAc,EAAA,EAAA,YAAA,EAA4B,YAA4B,EAAA,CAAA;AAAA,oBACvEA,cAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,OAAA,EAAQ,MACZ,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAO,CAAG,EAAA,QAAQ,CAAI,CAAA,EAAA,aAAa,IAAI,QAAQ,CAAA,CAAA;AAAA,QAC/C,IAAK,EAAA,MAAA;AAAA,QACL,QAAS,EAAA;AAAA;AAAA,KACX,kBACCA,cAAA,CAAA,aAAA,CAAA,YAAA,EAAA,IAAA,kBACEA,cAAA,CAAA,aAAA,CAAA,YAAA,CAAa,KAAb,EAAA,EAAmB,IAAK,EAAA,EAAA,EAAG,KAAM,EAAA,UAAA,EAAA,kBAC/BA,cAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,WAAS,IAAC,EAAA,SAAA,EAAU,KAAM,EAAA,OAAA,EAAS,CACvC,EAAA,kBAAAA,cAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,IAAA,EAAI,IAAC,EAAA,EAAA,EAAI,EAAI,EAAA,EAAA,EAAI,EACrB,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,MAAC,SAAA;AAAA,MAAA;AAAA,QACC,UAAU,CAAG,EAAA,QAAQ,CAAI,CAAA,EAAA,aAAa,IAAI,QAAQ,CAAA;AAAA;AAAA,KAEtD,mBACCA,cAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,MAAI,IAAC,EAAA,EAAA,EAAI,CAAG,EAAA,EAAA,EAAI,EACpB,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,MAAC,WAAA;AAAA,MAAA;AAAA,QACC,UAAU,CAAG,EAAA,QAAQ,CAAI,CAAA,EAAA,aAAa,IAAI,QAAQ,CAAA,CAAA;AAAA,QAClD;AAAA;AAAA,KAEJ,mBACCA,cAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,MAAI,IAAC,EAAA,EAAA,EAAI,CAAG,EAAA,EAAA,EAAI,EACpB,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,MAAC,eAAA;AAAA,MAAA;AAAA,QACC,iBAAiB,CAAG,EAAA,QAAQ,CAAI,CAAA,EAAA,aAAa,IAAI,QAAQ,CAAA,CAAA;AAAA,QACzD,uBAAuB,WAAY,CAAA;AAAA;AAAA,KAEvC,CACF,CACF,CACF,CACF;AAAA,GACF;AAEJ;;;;"}
@@ -4,19 +4,28 @@ import Delete from '@mui/icons-material/Delete';
4
4
  import IconButton from '@mui/material/IconButton';
5
5
  import Tooltip from '@mui/material/Tooltip';
6
6
  import Typography from '@mui/material/Typography';
7
+ import { policyEntityDeletePermission } from '@backstage-community/plugin-rbac-common';
8
+ import { usePermission } from '@backstage/plugin-permission-react';
7
9
 
8
10
  const DeleteRole = ({
9
11
  roleName,
10
- tooltip,
11
- disable,
12
- dataTestId
12
+ canEdit,
13
+ dataTestId,
14
+ tooltip
13
15
  }) => {
14
16
  const { setDeleteComponent, setOpenDialog } = useDeleteDialog();
15
17
  const openDialog = (name) => {
16
18
  setDeleteComponent({ roleName: name });
17
19
  setOpenDialog(true);
18
20
  };
19
- return /* @__PURE__ */ React__default.createElement(Tooltip, { title: tooltip ?? "" }, /* @__PURE__ */ React__default.createElement(Typography, { component: "span", "data-testid": dataTestId }, /* @__PURE__ */ React__default.createElement(
21
+ const deletePermissionResult = usePermission({
22
+ permission: policyEntityDeletePermission,
23
+ resourceRef: roleName
24
+ });
25
+ const disable = !(deletePermissionResult.allowed && canEdit);
26
+ const dataTestIdText = disable ? `disable-delete-role-${roleName}` : `delete-role-${roleName}`;
27
+ const tooltipText = disable ? "Role cannot be deleted" : "";
28
+ return /* @__PURE__ */ React__default.createElement(Tooltip, { title: tooltip ?? tooltipText }, /* @__PURE__ */ React__default.createElement(Typography, { component: "span", "data-testid": dataTestId ?? dataTestIdText }, /* @__PURE__ */ React__default.createElement(
20
29
  IconButton,
21
30
  {
22
31
  onClick: () => openDialog(roleName),
@@ -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 */\nimport React from 'react';\n\nimport { useDeleteDialog } from '@janus-idp/shared-react';\nimport Delete from '@mui/icons-material/Delete';\nimport IconButton from '@mui/material/IconButton';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\n\ntype DeleteRoleProps = {\n roleName: string;\n disable: boolean;\n tooltip?: string;\n dataTestId: string;\n};\n\nconst DeleteRole = ({\n roleName,\n tooltip,\n disable,\n dataTestId,\n}: DeleteRoleProps) => {\n const { setDeleteComponent, setOpenDialog } = useDeleteDialog();\n\n const openDialog = (name: string) => {\n setDeleteComponent({ roleName: name });\n setOpenDialog(true);\n };\n\n return (\n <Tooltip title={tooltip ?? ''}>\n <Typography component=\"span\" data-testid={dataTestId}>\n <IconButton\n onClick={() => openDialog(roleName)}\n aria-label=\"Delete\"\n disabled={disable}\n title={tooltip ?? 'Delete Role'}\n style={{ padding: '0.5rem', borderRadius: '50%' }}\n sx={{ '&:hover': { borderRadius: '50%' } }}\n >\n <Delete />\n </IconButton>\n </Typography>\n </Tooltip>\n );\n};\nexport default DeleteRole;\n"],"names":["React"],"mappings":";;;;;;;AA8BA,MAAM,aAAa,CAAC;AAAA,EAClB,QAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAuB,KAAA;AACrB,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,EACE,uBAAAA,cAAA,CAAA,aAAA,CAAC,OAAQ,EAAA,EAAA,KAAA,EAAO,OAAW,IAAA,EAAA,EAAA,+CACxB,UAAW,EAAA,EAAA,SAAA,EAAU,MAAO,EAAA,aAAA,EAAa,UACxC,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAS,MAAM,UAAA,CAAW,QAAQ,CAAA;AAAA,MAClC,YAAW,EAAA,QAAA;AAAA,MACX,QAAU,EAAA,OAAA;AAAA,MACV,OAAO,OAAW,IAAA,aAAA;AAAA,MAClB,KAAO,EAAA,EAAE,OAAS,EAAA,QAAA,EAAU,cAAc,KAAM,EAAA;AAAA,MAChD,IAAI,EAAE,SAAA,EAAW,EAAE,YAAA,EAAc,OAAQ;AAAA,KAAA;AAAA,iDAExC,MAAO,EAAA,IAAA;AAAA,GAEZ,CACF,CAAA;AAEJ;;;;"}
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 */\nimport React from 'react';\n\nimport { useDeleteDialog } from '@janus-idp/shared-react';\nimport Delete from '@mui/icons-material/Delete';\nimport IconButton from '@mui/material/IconButton';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\nimport { policyEntityDeletePermission } from '@backstage-community/plugin-rbac-common';\nimport { usePermission } from '@backstage/plugin-permission-react';\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 { setDeleteComponent, setOpenDialog } = useDeleteDialog();\n\n const openDialog = (name: string) => {\n setDeleteComponent({ roleName: name });\n setOpenDialog(true);\n };\n\n const deletePermissionResult = usePermission({\n permission: policyEntityDeletePermission,\n resourceRef: roleName,\n });\n\n const disable = !(deletePermissionResult.allowed && canEdit);\n const dataTestIdText = disable\n ? `disable-delete-role-${roleName}`\n : `delete-role-${roleName}`;\n const tooltipText = disable ? 'Role cannot be deleted' : '';\n\n return (\n <Tooltip title={tooltip ?? tooltipText}>\n <Typography component=\"span\" data-testid={dataTestId ?? dataTestIdText}>\n <IconButton\n onClick={() => openDialog(roleName)}\n aria-label=\"Delete\"\n disabled={disable}\n title={tooltip ?? 'Delete Role'}\n style={{ padding: '0.5rem', borderRadius: '50%' }}\n sx={{ '&:hover': { borderRadius: '50%' } }}\n >\n <Delete />\n </IconButton>\n </Typography>\n </Tooltip>\n );\n};\nexport default DeleteRole;\n"],"names":["React"],"mappings":";;;;;;;;;AAgCA,MAAM,aAAa,CAAC;AAAA,EAClB,QAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAuB,KAAA;AACrB,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,yBAAyB,aAAc,CAAA;AAAA,IAC3C,UAAY,EAAA,4BAAA;AAAA,IACZ,WAAa,EAAA;AAAA,GACd,CAAA;AAED,EAAM,MAAA,OAAA,GAAU,EAAE,sBAAA,CAAuB,OAAW,IAAA,OAAA,CAAA;AACpD,EAAA,MAAM,iBAAiB,OACnB,GAAA,CAAA,oBAAA,EAAuB,QAAQ,CAAA,CAAA,GAC/B,eAAe,QAAQ,CAAA,CAAA;AAC3B,EAAM,MAAA,WAAA,GAAc,UAAU,wBAA2B,GAAA,EAAA;AAEzD,EACE,uBAAAA,cAAA,CAAA,aAAA,CAAC,OAAQ,EAAA,EAAA,KAAA,EAAO,OAAW,IAAA,WAAA,EAAA,kBACxBA,cAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,SAAU,EAAA,MAAA,EAAO,aAAa,EAAA,UAAA,IAAc,cACtD,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAS,MAAM,UAAA,CAAW,QAAQ,CAAA;AAAA,MAClC,YAAW,EAAA,QAAA;AAAA,MACX,QAAU,EAAA,OAAA;AAAA,MACV,OAAO,OAAW,IAAA,aAAA;AAAA,MAClB,KAAO,EAAA,EAAE,OAAS,EAAA,QAAA,EAAU,cAAc,KAAM,EAAA;AAAA,MAChD,IAAI,EAAE,SAAA,EAAW,EAAE,YAAA,EAAc,OAAQ;AAAA,KAAA;AAAA,iDAExC,MAAO,EAAA,IAAA;AAAA,GAEZ,CACF,CAAA;AAEJ;;;;"}
@@ -56,18 +56,14 @@ const columns = [
56
56
  render: (props) => /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(
57
57
  EditRole,
58
58
  {
59
- dataTestId: !props.actionsPermissionResults.edit.allowed ? `disable-update-role-${props.name}` : `update-role-${props.name}`,
60
- roleName: props.name,
61
- disable: !props.actionsPermissionResults.edit.allowed,
62
- tooltip: !props.actionsPermissionResults.edit.allowed ? "Unauthorized to edit" : ""
59
+ canEdit: props.actionsPermissionResults.edit.allowed,
60
+ roleName: props.name
63
61
  }
64
62
  ), /* @__PURE__ */ React__default.createElement(
65
63
  DeleteRole,
66
64
  {
67
- dataTestId: !props.actionsPermissionResults.delete.allowed ? `disable-delete-role-${props.name}` : `delete-role-${props.name}`,
68
- roleName: props.name,
69
- disable: !props.actionsPermissionResults.delete.allowed,
70
- tooltip: !props.actionsPermissionResults.delete.allowed ? "Role cannot be deleted" : ""
65
+ canEdit: props.actionsPermissionResults.edit.allowed,
66
+ roleName: props.name
71
67
  }
72
68
  ))
73
69
  }
@@ -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 React from 'react';\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';\n\nexport const columns: TableColumn<RolesData>[] = [\n {\n title: '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: 'Users and groups',\n field: 'members',\n type: 'string',\n align: 'left',\n render: props => getMembers(props.members),\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: 'Accessible plugins',\n field: 'accessiblePlugins',\n type: 'string',\n align: 'left',\n render: (props: RolesData) => {\n const pls = props.accessiblePlugins.map(\n p => p[0].toLocaleUpperCase('en-US') + 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: 'Actions',\n sorting: false,\n render: (props: RolesData) => (\n <>\n <EditRole\n dataTestId={\n !props.actionsPermissionResults.edit.allowed\n ? `disable-update-role-${props.name}`\n : `update-role-${props.name}`\n }\n roleName={props.name}\n disable={!props.actionsPermissionResults.edit.allowed}\n tooltip={\n !props.actionsPermissionResults.edit.allowed\n ? 'Unauthorized to edit'\n : ''\n }\n />\n <DeleteRole\n dataTestId={\n !props.actionsPermissionResults.delete.allowed\n ? `disable-delete-role-${props.name}`\n : `delete-role-${props.name}`\n }\n roleName={props.name}\n disable={!props.actionsPermissionResults.delete.allowed}\n tooltip={\n !props.actionsPermissionResults.delete.allowed\n ? 'Role cannot be deleted'\n : ''\n }\n />\n </>\n ),\n },\n];\n"],"names":["React"],"mappings":";;;;;;;;;AA4BO,MAAM,OAAoC,GAAA;AAAA,EAC/C;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,KAAO,EAAA,MAAA;AAAA,IACP,IAAM,EAAA,QAAA;AAAA,IACN,MAAA,EAAQ,CAAC,KAAqB,KAAA;AAC5B,MAAA,MAAM,EAAE,IAAM,EAAA,SAAA,EAAW,MAAS,GAAA,cAAA,CAAe,MAAM,IAAI,CAAA;AAC3D,MACE,uBAAAA,cAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,EAAA,EAAI,CAAS,MAAA,EAAA,IAAI,CAAI,CAAA,EAAA,SAAS,CAAI,CAAA,EAAA,IAAI,CAAK,CAAA,EAAA,EAAA,KAAA,CAAM,IAAK,CAAA;AAAA;AAEhE,GACF;AAAA,EACA;AAAA,IACE,KAAO,EAAA,kBAAA;AAAA,IACP,KAAO,EAAA,SAAA;AAAA,IACP,IAAM,EAAA,QAAA;AAAA,IACN,KAAO,EAAA,MAAA;AAAA,IACP,MAAQ,EAAA,CAAA,KAAA,KAAS,UAAW,CAAA,KAAA,CAAM,OAAO,CAAA;AAAA,IACzC,UAAA,EAAY,CAAC,CAAA,EAAG,CAAM,KAAA;AACpB,MAAI,IAAA,CAAA,CAAE,OAAQ,CAAA,MAAA,KAAW,CAAG,EAAA;AAC1B,QAAO,OAAA,EAAA;AAAA;AAET,MAAI,IAAA,CAAA,CAAE,OAAQ,CAAA,MAAA,KAAW,CAAG,EAAA;AAC1B,QAAO,OAAA,CAAA;AAAA;AAET,MAAA,IAAI,CAAE,CAAA,OAAA,CAAQ,MAAW,KAAA,CAAA,CAAE,QAAQ,MAAQ,EAAA;AACzC,QAAO,OAAA,CAAA;AAAA;AAET,MAAA,OAAO,EAAE,OAAQ,CAAA,MAAA,GAAS,CAAE,CAAA,OAAA,CAAQ,SAAS,EAAK,GAAA,CAAA;AAAA;AACpD,GACF;AAAA,EACA;AAAA,IACE,KAAO,EAAA,oBAAA;AAAA,IACP,KAAO,EAAA,mBAAA;AAAA,IACP,IAAM,EAAA,QAAA;AAAA,IACN,KAAO,EAAA,MAAA;AAAA,IACP,MAAA,EAAQ,CAAC,KAAqB,KAAA;AAC5B,MAAM,MAAA,GAAA,GAAM,MAAM,iBAAkB,CAAA,GAAA;AAAA,QAClC,CAAA,CAAA,KAAK,EAAE,CAAC,CAAA,CAAE,kBAAkB,OAAO,CAAA,GAAI,CAAE,CAAA,KAAA,CAAM,CAAC;AAAA,OAClD;AACA,MAAM,MAAA,UAAA,GAAa,GAAI,CAAA,IAAA,CAAK,IAAI,CAAA;AAChC,MAAM,MAAA,gBAAA,GAAmB,IAAI,MAAS,GAAA,CAAA,GAAI,KAAK,GAAI,CAAA,MAAA,GAAS,CAAC,CAAK,CAAA,GAAA,EAAA;AAElE,MAAA,OAAO,GAAI,CAAA,MAAA,GAAS,CAClB,mBAAAA,cAAA,CAAA,aAAA,CAAC,WAAQ,KAAO,EAAA,UAAA,IAAc,EAAI,EAAA,SAAA,EAAU,WAC1C,EAAA,kBAAAA,cAAA,CAAA,aAAA,CAAC,UACE,EAAA,IAAA,EAAA,GAAA,CAAI,WAAW,CACZ,GAAA,CAAA,EAAG,GAAI,CAAA,CAAC,CAAC,CAAA,CAAA,GACT,CAAG,EAAA,GAAA,CAAI,CAAC,CAAC,CAAA,EAAA,EAAK,GAAI,CAAA,CAAC,CAAC,CAAA,CAAA,EAAI,gBAAgB,CAAA,CAC9C,CACF,CAEA,GAAA,GAAA;AAAA;AAEJ,GACF;AAAA,EACA;AAAA,IACE,KAAO,EAAA,SAAA;AAAA,IACP,OAAS,EAAA,KAAA;AAAA,IACT,MAAA,EAAQ,CAAC,KAAA,qBAELA,cAAA,CAAA,aAAA,CAAAA,cAAA,CAAA,QAAA,EAAA,IAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,UACE,EAAA,CAAC,KAAM,CAAA,wBAAA,CAAyB,IAAK,CAAA,OAAA,GACjC,CAAuB,oBAAA,EAAA,KAAA,CAAM,IAAI,CAAA,CAAA,GACjC,CAAe,YAAA,EAAA,KAAA,CAAM,IAAI,CAAA,CAAA;AAAA,QAE/B,UAAU,KAAM,CAAA,IAAA;AAAA,QAChB,OAAS,EAAA,CAAC,KAAM,CAAA,wBAAA,CAAyB,IAAK,CAAA,OAAA;AAAA,QAC9C,SACE,CAAC,KAAA,CAAM,wBAAyB,CAAA,IAAA,CAAK,UACjC,sBACA,GAAA;AAAA;AAAA,KAGR,kBAAAA,cAAA,CAAA,aAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,UACE,EAAA,CAAC,KAAM,CAAA,wBAAA,CAAyB,MAAO,CAAA,OAAA,GACnC,CAAuB,oBAAA,EAAA,KAAA,CAAM,IAAI,CAAA,CAAA,GACjC,CAAe,YAAA,EAAA,KAAA,CAAM,IAAI,CAAA,CAAA;AAAA,QAE/B,UAAU,KAAM,CAAA,IAAA;AAAA,QAChB,OAAS,EAAA,CAAC,KAAM,CAAA,wBAAA,CAAyB,MAAO,CAAA,OAAA;AAAA,QAChD,SACE,CAAC,KAAA,CAAM,wBAAyB,CAAA,MAAA,CAAO,UACnC,wBACA,GAAA;AAAA;AAAA,KAGV;AAAA;AAGN;;;;"}
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 React from 'react';\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';\n\nexport const columns: TableColumn<RolesData>[] = [\n {\n title: '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: 'Users and groups',\n field: 'members',\n type: 'string',\n align: 'left',\n render: props => getMembers(props.members),\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: 'Accessible plugins',\n field: 'accessiblePlugins',\n type: 'string',\n align: 'left',\n render: (props: RolesData) => {\n const pls = props.accessiblePlugins.map(\n p => p[0].toLocaleUpperCase('en-US') + 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: 'Actions',\n sorting: false,\n render: (props: RolesData) => (\n <>\n <EditRole\n canEdit={props.actionsPermissionResults.edit.allowed}\n roleName={props.name}\n />\n <DeleteRole\n canEdit={props.actionsPermissionResults.edit.allowed}\n roleName={props.name}\n />\n </>\n ),\n },\n];\n"],"names":["React"],"mappings":"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"}
@@ -3,7 +3,7 @@ import { Routes, Route } from 'react-router-dom';
3
3
  import { ErrorPage } from '@backstage/core-components';
4
4
  import { useApi, configApiRef } from '@backstage/core-plugin-api';
5
5
  import { RequirePermission } from '@backstage/plugin-permission-react';
6
- import { policyEntityCreatePermission, policyEntityUpdatePermission } from '@backstage-community/plugin-rbac-common';
6
+ import { policyEntityCreatePermission } from '@backstage-community/plugin-rbac-common';
7
7
  import { roleRouteRef, createRoleRouteRef, editRoleRouteRef } from '../routes.esm.js';
8
8
  import { CreateRolePage } from './CreateRole/CreateRolePage.esm.js';
9
9
  import { EditRolePage } from './CreateRole/EditRolePage.esm.js';
@@ -28,29 +28,9 @@ const Router = ({ useHeader = true }) => {
28
28
  Route,
29
29
  {
30
30
  path: createRoleRouteRef.path,
31
- element: /* @__PURE__ */ React__default.createElement(
32
- RequirePermission,
33
- {
34
- permission: policyEntityCreatePermission,
35
- resourceRef: policyEntityCreatePermission.resourceType
36
- },
37
- /* @__PURE__ */ React__default.createElement(CreateRolePage, null)
38
- )
31
+ element: /* @__PURE__ */ React__default.createElement(RequirePermission, { permission: policyEntityCreatePermission }, /* @__PURE__ */ React__default.createElement(CreateRolePage, null))
39
32
  }
40
- ), /* @__PURE__ */ React__default.createElement(
41
- Route,
42
- {
43
- path: editRoleRouteRef.path,
44
- element: /* @__PURE__ */ React__default.createElement(
45
- RequirePermission,
46
- {
47
- permission: policyEntityUpdatePermission,
48
- resourceRef: policyEntityUpdatePermission.resourceType
49
- },
50
- /* @__PURE__ */ React__default.createElement(EditRolePage, null)
51
- )
52
- }
53
- )));
33
+ ), /* @__PURE__ */ React__default.createElement(Route, { path: editRoleRouteRef.path, element: /* @__PURE__ */ React__default.createElement(EditRolePage, null) })));
54
34
  };
55
35
 
56
36
  export { Router };
@@ -1 +1 @@
1
- {"version":3,"file":"Router.esm.js","sources":["../../src/components/Router.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 React from 'react';\nimport { Route, Routes } from 'react-router-dom';\n\nimport { ErrorPage } from '@backstage/core-components';\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\nimport { RequirePermission } from '@backstage/plugin-permission-react';\n\nimport {\n policyEntityCreatePermission,\n policyEntityUpdatePermission,\n} from '@backstage-community/plugin-rbac-common';\n\nimport { createRoleRouteRef, editRoleRouteRef, roleRouteRef } from '../routes';\nimport { CreateRolePage } from './CreateRole/CreateRolePage';\nimport { EditRolePage } from './CreateRole/EditRolePage';\nimport { RbacPage } from './RbacPage';\nimport { RoleOverviewPage } from './RoleOverview/RoleOverviewPage';\nimport { ToastContextProvider } from './ToastContext';\n\n/**\n *\n * @public\n */\nexport const Router = ({ useHeader = true }: { useHeader?: boolean }) => {\n const config = useApi(configApiRef);\n const isRBACPluginEnabled = config.getOptionalBoolean('permission.enabled');\n\n if (!isRBACPluginEnabled) {\n return (\n <ErrorPage\n status=\"404\"\n statusMessage=\"Enable the RBAC backend plugin to use this feature.\"\n additionalInfo=\"To enable RBAC, set `permission.enabled` to `true` in the app-config file.\"\n />\n );\n }\n\n return (\n <ToastContextProvider>\n <Routes>\n <Route path=\"/\" element={<RbacPage useHeader={useHeader} />} />\n <Route path={roleRouteRef.path} element={<RoleOverviewPage />} />\n <Route\n path={createRoleRouteRef.path}\n element={\n <RequirePermission\n permission={policyEntityCreatePermission}\n resourceRef={policyEntityCreatePermission.resourceType}\n >\n <CreateRolePage />\n </RequirePermission>\n }\n />\n <Route\n path={editRoleRouteRef.path}\n element={\n <RequirePermission\n permission={policyEntityUpdatePermission}\n resourceRef={policyEntityUpdatePermission.resourceType}\n >\n <EditRolePage />\n </RequirePermission>\n }\n />\n </Routes>\n </ToastContextProvider>\n );\n};\n"],"names":["React"],"mappings":";;;;;;;;;;;;;AAsCO,MAAM,MAAS,GAAA,CAAC,EAAE,SAAA,GAAY,MAAoC,KAAA;AACvE,EAAM,MAAA,MAAA,GAAS,OAAO,YAAY,CAAA;AAClC,EAAM,MAAA,mBAAA,GAAsB,MAAO,CAAA,kBAAA,CAAmB,oBAAoB,CAAA;AAE1E,EAAA,IAAI,CAAC,mBAAqB,EAAA;AACxB,IACE,uBAAAA,cAAA,CAAA,aAAA;AAAA,MAAC,SAAA;AAAA,MAAA;AAAA,QACC,MAAO,EAAA,KAAA;AAAA,QACP,aAAc,EAAA,qDAAA;AAAA,QACd,cAAe,EAAA;AAAA;AAAA,KACjB;AAAA;AAIJ,EACE,uBAAAA,cAAA,CAAA,aAAA,CAAC,4CACEA,cAAA,CAAA,aAAA,CAAA,MAAA,EAAA,IAAA,+CACE,KAAM,EAAA,EAAA,IAAA,EAAK,GAAI,EAAA,OAAA,kBAAUA,cAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,WAAsB,CAAI,EAAA,CAAA,kBAC5DA,cAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAM,IAAM,EAAA,YAAA,CAAa,MAAM,OAAS,kBAAAA,cAAA,CAAA,aAAA,CAAC,gBAAiB,EAAA,IAAA,CAAA,EAAI,CAC/D,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,MAAM,kBAAmB,CAAA,IAAA;AAAA,MACzB,OACE,kBAAAA,cAAA,CAAA,aAAA;AAAA,QAAC,iBAAA;AAAA,QAAA;AAAA,UACC,UAAY,EAAA,4BAAA;AAAA,UACZ,aAAa,4BAA6B,CAAA;AAAA,SAAA;AAAA,qDAEzC,cAAe,EAAA,IAAA;AAAA;AAClB;AAAA,GAGJ,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,MAAM,gBAAiB,CAAA,IAAA;AAAA,MACvB,OACE,kBAAAA,cAAA,CAAA,aAAA;AAAA,QAAC,iBAAA;AAAA,QAAA;AAAA,UACC,UAAY,EAAA,4BAAA;AAAA,UACZ,aAAa,4BAA6B,CAAA;AAAA,SAAA;AAAA,qDAEzC,YAAa,EAAA,IAAA;AAAA;AAChB;AAAA,GAGN,CACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"Router.esm.js","sources":["../../src/components/Router.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 React from 'react';\nimport { Route, Routes } from 'react-router-dom';\n\nimport { ErrorPage } from '@backstage/core-components';\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\nimport { RequirePermission } from '@backstage/plugin-permission-react';\n\nimport { policyEntityCreatePermission } from '@backstage-community/plugin-rbac-common';\n\nimport { createRoleRouteRef, editRoleRouteRef, roleRouteRef } from '../routes';\nimport { CreateRolePage } from './CreateRole/CreateRolePage';\nimport { EditRolePage } from './CreateRole/EditRolePage';\nimport { RbacPage } from './RbacPage';\nimport { RoleOverviewPage } from './RoleOverview/RoleOverviewPage';\nimport { ToastContextProvider } from './ToastContext';\n\n/**\n *\n * @public\n */\nexport const Router = ({ useHeader = true }: { useHeader?: boolean }) => {\n const config = useApi(configApiRef);\n const isRBACPluginEnabled = config.getOptionalBoolean('permission.enabled');\n\n if (!isRBACPluginEnabled) {\n return (\n <ErrorPage\n status=\"404\"\n statusMessage=\"Enable the RBAC backend plugin to use this feature.\"\n additionalInfo=\"To enable RBAC, set `permission.enabled` to `true` in the app-config file.\"\n />\n );\n }\n\n return (\n <ToastContextProvider>\n <Routes>\n <Route path=\"/\" element={<RbacPage useHeader={useHeader} />} />\n <Route path={roleRouteRef.path} element={<RoleOverviewPage />} />\n <Route\n path={createRoleRouteRef.path}\n element={\n <RequirePermission permission={policyEntityCreatePermission}>\n <CreateRolePage />\n </RequirePermission>\n }\n />\n <Route path={editRoleRouteRef.path} element={<EditRolePage />} />\n </Routes>\n </ToastContextProvider>\n );\n};\n"],"names":["React"],"mappings":";;;;;;;;;;;;;AAmCO,MAAM,MAAS,GAAA,CAAC,EAAE,SAAA,GAAY,MAAoC,KAAA;AACvE,EAAM,MAAA,MAAA,GAAS,OAAO,YAAY,CAAA;AAClC,EAAM,MAAA,mBAAA,GAAsB,MAAO,CAAA,kBAAA,CAAmB,oBAAoB,CAAA;AAE1E,EAAA,IAAI,CAAC,mBAAqB,EAAA;AACxB,IACE,uBAAAA,cAAA,CAAA,aAAA;AAAA,MAAC,SAAA;AAAA,MAAA;AAAA,QACC,MAAO,EAAA,KAAA;AAAA,QACP,aAAc,EAAA,qDAAA;AAAA,QACd,cAAe,EAAA;AAAA;AAAA,KACjB;AAAA;AAIJ,EACE,uBAAAA,cAAA,CAAA,aAAA,CAAC,4CACEA,cAAA,CAAA,aAAA,CAAA,MAAA,EAAA,IAAA,+CACE,KAAM,EAAA,EAAA,IAAA,EAAK,GAAI,EAAA,OAAA,kBAAUA,cAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,WAAsB,CAAI,EAAA,CAAA,kBAC5DA,cAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAM,IAAM,EAAA,YAAA,CAAa,MAAM,OAAS,kBAAAA,cAAA,CAAA,aAAA,CAAC,gBAAiB,EAAA,IAAA,CAAA,EAAI,CAC/D,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,MAAM,kBAAmB,CAAA,IAAA;AAAA,MACzB,yBACGA,cAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAkB,YAAY,4BAC7B,EAAA,kBAAAA,cAAA,CAAA,aAAA,CAAC,oBAAe,CAClB;AAAA;AAAA,GAEJ,kBACCA,cAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAM,IAAM,EAAA,gBAAA,CAAiB,IAAM,EAAA,OAAA,kBAAUA,cAAA,CAAA,aAAA,CAAA,YAAA,EAAA,IAAa,CAAI,EAAA,CACjE,CACF,CAAA;AAEJ;;;;"}
@@ -2,7 +2,7 @@ import React__default from 'react';
2
2
  import { useAsyncRetry, useAsync, useInterval } from 'react-use';
3
3
  import { useApi } from '@backstage/core-plugin-api';
4
4
  import { usePermission } from '@backstage/plugin-permission-react';
5
- import { policyEntityDeletePermission, policyEntityCreatePermission, policyEntityUpdatePermission } from '@backstage-community/plugin-rbac-common';
5
+ import { policyEntityCreatePermission } from '@backstage-community/plugin-rbac-common';
6
6
  import { rbacApiRef } from '../api/RBACBackendClient.esm.js';
7
7
  import { getPermissions, getPermissionsArray, getPluginInfo } from '../utils/rbac-utils.esm.js';
8
8
 
@@ -38,20 +38,11 @@ const useRoles = (pollInterval) => {
38
38
  return await rbacApi.listPermissions();
39
39
  });
40
40
  const canReadUsersAndGroups = !membersLoading && !membersError && Array.isArray(members) && members.length > 0;
41
- const deletePermissionResult = usePermission({
42
- permission: policyEntityDeletePermission,
43
- resourceRef: policyEntityDeletePermission.resourceType
44
- });
45
41
  const policyEntityCreatePermissionResult = usePermission({
46
- permission: policyEntityCreatePermission,
47
- resourceRef: policyEntityCreatePermission.resourceType
42
+ permission: policyEntityCreatePermission
48
43
  });
49
44
  const createRoleLoading = policyEntityCreatePermissionResult.loading || membersLoading;
50
45
  const createRoleAllowed = policyEntityCreatePermissionResult.allowed && canReadUsersAndGroups;
51
- const editPermissionResult = usePermission({
52
- permission: policyEntityUpdatePermission,
53
- resourceRef: policyEntityUpdatePermission.resourceType
54
- });
55
46
  const [loadingConditionalPermission, setLoadingConditionalPermission] = React__default.useState(false);
56
47
  React__default.useEffect(() => {
57
48
  const fetchAllPermissionPolicies = async () => {
@@ -124,10 +115,8 @@ const useRoles = (pollInterval) => {
124
115
  modifiedBy: "-",
125
116
  lastModified: "-",
126
117
  actionsPermissionResults: {
127
- delete: deletePermissionResult,
128
118
  edit: {
129
- allowed: editPermissionResult.allowed && canReadUsersAndGroups,
130
- loading: editPermissionResult.loading
119
+ allowed: canReadUsersAndGroups
131
120
  }
132
121
  },
133
122
  accessiblePlugins
@@ -142,9 +131,6 @@ const useRoles = (pollInterval) => {
142
131
  loadingPermissionPolicies,
143
132
  permissionPoliciesError,
144
133
  permissionPolicies,
145
- deletePermissionResult,
146
- editPermissionResult.allowed,
147
- editPermissionResult.loading,
148
134
  canReadUsersAndGroups
149
135
  ]
150
136
  );
@@ -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 React 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 policyEntityDeletePermission,\n policyEntityUpdatePermission,\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 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] = React.useState<\n RoleWithConditionalPoliciesCount[]\n >([]);\n const [firstLoad, setFirstLoad] = React.useState(true);\n const [roleConditionError, setRoleConditionError] =\n React.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();\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 deletePermissionResult = usePermission({\n permission: policyEntityDeletePermission,\n resourceRef: policyEntityDeletePermission.resourceType,\n });\n\n const policyEntityCreatePermissionResult = usePermission({\n permission: policyEntityCreatePermission,\n resourceRef: policyEntityCreatePermission.resourceType,\n });\n\n const createRoleLoading =\n policyEntityCreatePermissionResult.loading || membersLoading;\n\n const createRoleAllowed =\n policyEntityCreatePermissionResult.allowed && canReadUsersAndGroups;\n\n const editPermissionResult = usePermission({\n permission: policyEntityUpdatePermission,\n resourceRef: policyEntityUpdatePermission.resourceType,\n });\n const [loadingConditionalPermission, setLoadingConditionalPermission] =\n React.useState<boolean>(false);\n React.useEffect(() => {\n const fetchAllPermissionPolicies = async () => {\n if (!Array.isArray(roles)) return;\n setLoadingConditionalPermission(true);\n const failedFetchConditionRoles: string[] = [];\n const conditionPromises = roles.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 updatedRoles = await Promise.all(conditionPromises);\n setNewRoles(updatedRoles);\n setLoadingConditionalPermission(false);\n };\n\n fetchAllPermissionPolicies();\n }, [roles, rbacApi]);\n\n const data: RolesData[] = React.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 delete: deletePermissionResult,\n edit: {\n allowed:\n editPermissionResult.allowed && canReadUsersAndGroups,\n loading: editPermissionResult.loading,\n },\n },\n accessiblePlugins,\n },\n ];\n },\n [],\n )\n : [],\n [\n newRoles,\n policies,\n loadingPermissionPolicies,\n permissionPoliciesError,\n permissionPolicies,\n deletePermissionResult,\n editPermissionResult.allowed,\n editPermissionResult.loading,\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":["React"],"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 React 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 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] = React.useState<\n RoleWithConditionalPoliciesCount[]\n >([]);\n const [firstLoad, setFirstLoad] = React.useState(true);\n const [roleConditionError, setRoleConditionError] =\n React.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();\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 React.useState<boolean>(false);\n React.useEffect(() => {\n const fetchAllPermissionPolicies = async () => {\n if (!Array.isArray(roles)) return;\n setLoadingConditionalPermission(true);\n const failedFetchConditionRoles: string[] = [];\n const conditionPromises = roles.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 updatedRoles = await Promise.all(conditionPromises);\n setNewRoles(updatedRoles);\n setLoadingConditionalPermission(false);\n };\n\n fetchAllPermissionPolicies();\n }, [roles, rbacApi]);\n\n const data: RolesData[] = React.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":["React"],"mappings":"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"}