@backstage-community/plugin-rbac 1.32.2
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 +761 -0
- package/README.md +106 -0
- package/app-config.yaml +19 -0
- package/dist/api/LicensedUsersClient.esm.js +45 -0
- package/dist/api/LicensedUsersClient.esm.js.map +1 -0
- package/dist/api/RBACBackendClient.esm.js +337 -0
- package/dist/api/RBACBackendClient.esm.js.map +1 -0
- package/dist/components/Administration.esm.js +23 -0
- package/dist/components/Administration.esm.js.map +1 -0
- package/dist/components/ConditionalAccess/AddNestedConditionButton.esm.js +23 -0
- package/dist/components/ConditionalAccess/AddNestedConditionButton.esm.js.map +1 -0
- package/dist/components/ConditionalAccess/ComplexConditionRow.esm.js +149 -0
- package/dist/components/ConditionalAccess/ComplexConditionRow.esm.js.map +1 -0
- package/dist/components/ConditionalAccess/ComplexConditionRowButtons.esm.js +62 -0
- package/dist/components/ConditionalAccess/ComplexConditionRowButtons.esm.js.map +1 -0
- package/dist/components/ConditionalAccess/ConditionRule.esm.js +34 -0
- package/dist/components/ConditionalAccess/ConditionRule.esm.js.map +1 -0
- package/dist/components/ConditionalAccess/ConditionalAccessSidebar.esm.js +93 -0
- package/dist/components/ConditionalAccess/ConditionalAccessSidebar.esm.js.map +1 -0
- package/dist/components/ConditionalAccess/ConditionsForm.esm.js +204 -0
- package/dist/components/ConditionalAccess/ConditionsForm.esm.js.map +1 -0
- package/dist/components/ConditionalAccess/ConditionsFormRow.esm.js +459 -0
- package/dist/components/ConditionalAccess/ConditionsFormRow.esm.js.map +1 -0
- package/dist/components/ConditionalAccess/ConditionsFormRowFields.esm.js +209 -0
- package/dist/components/ConditionalAccess/ConditionsFormRowFields.esm.js.map +1 -0
- package/dist/components/ConditionalAccess/CriteriaToggleButton.esm.js +33 -0
- package/dist/components/ConditionalAccess/CriteriaToggleButton.esm.js.map +1 -0
- package/dist/components/ConditionalAccess/CustomArrayField.esm.js +47 -0
- package/dist/components/ConditionalAccess/CustomArrayField.esm.js.map +1 -0
- package/dist/components/ConditionalAccess/RulesDropdownOption.esm.js +24 -0
- package/dist/components/ConditionalAccess/RulesDropdownOption.esm.js.map +1 -0
- package/dist/components/ConditionalAccess/const.esm.js +21 -0
- package/dist/components/ConditionalAccess/const.esm.js.map +1 -0
- package/dist/components/ConditionalAccess/types.esm.js +8 -0
- package/dist/components/ConditionalAccess/types.esm.js.map +1 -0
- package/dist/components/CreateRole/AddMembersForm.esm.js +94 -0
- package/dist/components/CreateRole/AddMembersForm.esm.js.map +1 -0
- package/dist/components/CreateRole/AddedMembersTable.esm.js +31 -0
- package/dist/components/CreateRole/AddedMembersTable.esm.js.map +1 -0
- package/dist/components/CreateRole/AddedMembersTableColumn.esm.js +77 -0
- package/dist/components/CreateRole/AddedMembersTableColumn.esm.js.map +1 -0
- package/dist/components/CreateRole/CreateRolePage.esm.js +53 -0
- package/dist/components/CreateRole/CreateRolePage.esm.js.map +1 -0
- package/dist/components/CreateRole/EditRolePage.esm.js +65 -0
- package/dist/components/CreateRole/EditRolePage.esm.js.map +1 -0
- package/dist/components/CreateRole/MembersDropdownOption.esm.js +40 -0
- package/dist/components/CreateRole/MembersDropdownOption.esm.js.map +1 -0
- package/dist/components/CreateRole/PermissionPoliciesForm.esm.js +144 -0
- package/dist/components/CreateRole/PermissionPoliciesForm.esm.js.map +1 -0
- package/dist/components/CreateRole/PermissionPoliciesFormRow.esm.js +179 -0
- package/dist/components/CreateRole/PermissionPoliciesFormRow.esm.js.map +1 -0
- package/dist/components/CreateRole/PoliciesCheckboxGroup.esm.js +76 -0
- package/dist/components/CreateRole/PoliciesCheckboxGroup.esm.js.map +1 -0
- package/dist/components/CreateRole/ReviewStep.esm.js +50 -0
- package/dist/components/CreateRole/ReviewStep.esm.js.map +1 -0
- package/dist/components/CreateRole/ReviewStepTable.esm.js +29 -0
- package/dist/components/CreateRole/ReviewStepTable.esm.js.map +1 -0
- package/dist/components/CreateRole/RoleDetailsForm.esm.js +57 -0
- package/dist/components/CreateRole/RoleDetailsForm.esm.js.map +1 -0
- package/dist/components/CreateRole/RoleForm.esm.js +271 -0
- package/dist/components/CreateRole/RoleForm.esm.js.map +1 -0
- package/dist/components/CreateRole/SelectedPermissionPoliciesColumn.esm.js +34 -0
- package/dist/components/CreateRole/SelectedPermissionPoliciesColumn.esm.js.map +1 -0
- package/dist/components/CreateRole/const.esm.js +14 -0
- package/dist/components/CreateRole/const.esm.js.map +1 -0
- package/dist/components/DownloadUserStatistics.esm.js +51 -0
- package/dist/components/DownloadUserStatistics.esm.js.map +1 -0
- package/dist/components/EditRole.esm.js +30 -0
- package/dist/components/EditRole.esm.js.map +1 -0
- package/dist/components/RbacPage.esm.js +18 -0
- package/dist/components/RbacPage.esm.js.map +1 -0
- package/dist/components/RoleOverview/AboutCard.esm.js +89 -0
- package/dist/components/RoleOverview/AboutCard.esm.js.map +1 -0
- package/dist/components/RoleOverview/MembersCard.esm.js +87 -0
- package/dist/components/RoleOverview/MembersCard.esm.js.map +1 -0
- package/dist/components/RoleOverview/MembersListColumns.esm.js +48 -0
- package/dist/components/RoleOverview/MembersListColumns.esm.js.map +1 -0
- package/dist/components/RoleOverview/PermissionsCard.esm.js +99 -0
- package/dist/components/RoleOverview/PermissionsCard.esm.js.map +1 -0
- package/dist/components/RoleOverview/PermissionsListColumns.esm.js +43 -0
- package/dist/components/RoleOverview/PermissionsListColumns.esm.js.map +1 -0
- package/dist/components/RoleOverview/RoleOverviewPage.esm.js +49 -0
- package/dist/components/RoleOverview/RoleOverviewPage.esm.js.map +1 -0
- package/dist/components/RolesList/DeleteRole.esm.js +32 -0
- package/dist/components/RolesList/DeleteRole.esm.js.map +1 -0
- package/dist/components/RolesList/DeleteRoleDialog.esm.js +142 -0
- package/dist/components/RolesList/DeleteRoleDialog.esm.js.map +1 -0
- package/dist/components/RolesList/RolesList.esm.js +102 -0
- package/dist/components/RolesList/RolesList.esm.js.map +1 -0
- package/dist/components/RolesList/RolesListColumns.esm.js +76 -0
- package/dist/components/RolesList/RolesListColumns.esm.js.map +1 -0
- package/dist/components/RolesList/RolesListToolbar.esm.js +48 -0
- package/dist/components/RolesList/RolesListToolbar.esm.js.map +1 -0
- package/dist/components/Router.esm.js +57 -0
- package/dist/components/Router.esm.js.map +1 -0
- package/dist/components/SnackbarAlert.esm.js +23 -0
- package/dist/components/SnackbarAlert.esm.js.map +1 -0
- package/dist/components/ToastContext.esm.js +19 -0
- package/dist/components/ToastContext.esm.js.map +1 -0
- package/dist/components/index.esm.js +5 -0
- package/dist/components/index.esm.js.map +1 -0
- package/dist/hooks/useCheckIfLicensePluginEnabled.esm.js +20 -0
- package/dist/hooks/useCheckIfLicensePluginEnabled.esm.js.map +1 -0
- package/dist/hooks/useConditionRules.esm.js +64 -0
- package/dist/hooks/useConditionRules.esm.js.map +1 -0
- package/dist/hooks/useLocationToast.esm.js +15 -0
- package/dist/hooks/useLocationToast.esm.js.map +1 -0
- package/dist/hooks/useMembers.esm.js +92 -0
- package/dist/hooks/useMembers.esm.js.map +1 -0
- package/dist/hooks/usePermissionPolicies.esm.js +80 -0
- package/dist/hooks/usePermissionPolicies.esm.js.map +1 -0
- package/dist/hooks/useRole.esm.js +23 -0
- package/dist/hooks/useRole.esm.js.map +1 -0
- package/dist/hooks/useRoles.esm.js +169 -0
- package/dist/hooks/useRoles.esm.js.map +1 -0
- package/dist/hooks/useSelectedMembers.esm.js +39 -0
- package/dist/hooks/useSelectedMembers.esm.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.esm.js +4 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/plugin.esm.js +49 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/routes.esm.js +23 -0
- package/dist/routes.esm.js.map +1 -0
- package/dist/utils/conditional-access-utils.esm.js +268 -0
- package/dist/utils/conditional-access-utils.esm.js.map +1 -0
- package/dist/utils/create-role-utils.esm.js +231 -0
- package/dist/utils/create-role-utils.esm.js.map +1 -0
- package/dist/utils/rbac-utils.esm.js +256 -0
- package/dist/utils/rbac-utils.esm.js.map +1 -0
- package/dist/utils/role-form-utils.esm.js +66 -0
- package/dist/utils/role-form-utils.esm.js.map +1 -0
- package/package.json +120 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectedPermissionPoliciesColumn.esm.js","sources":["../../../src/components/CreateRole/SelectedPermissionPoliciesColumn.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 { getRulesNumber } from '../../utils/create-role-utils';\nimport { ConditionsData } from '../ConditionalAccess/types';\nimport { RowPolicy } from './types';\n\nexport const selectedPermissionPoliciesColumn = () => [\n {\n title: 'Plugin',\n field: 'plugin',\n },\n {\n title: 'Permission',\n field: 'permission',\n },\n {\n title: 'Policies',\n field: 'policies',\n render: (policies: RowPolicy[]) => {\n const policyStr = policies.reduce((acc: string, p) => {\n if (p.effect === 'allow') return acc.concat(`${p.policy}, `);\n return acc;\n }, '');\n return policyStr.slice(0, policyStr.length - 2);\n },\n },\n {\n title: 'Conditional',\n field: 'conditions',\n render: (conditions: ConditionsData) => {\n const totalRules = getRulesNumber(conditions);\n return totalRules\n ? `${totalRules} ${totalRules > 1 ? 'rules' : 'rule'}`\n : '-';\n },\n },\n];\n"],"names":[],"mappings":";;AAmBO,MAAM,mCAAmC,MAAM;AAAA,EACpD;AAAA,IACE,KAAO,EAAA,QAAA;AAAA,IACP,KAAO,EAAA,QAAA;AAAA,GACT;AAAA,EACA;AAAA,IACE,KAAO,EAAA,YAAA;AAAA,IACP,KAAO,EAAA,YAAA;AAAA,GACT;AAAA,EACA;AAAA,IACE,KAAO,EAAA,UAAA;AAAA,IACP,KAAO,EAAA,UAAA;AAAA,IACP,MAAA,EAAQ,CAAC,QAA0B,KAAA;AACjC,MAAA,MAAM,SAAY,GAAA,QAAA,CAAS,MAAO,CAAA,CAAC,KAAa,CAAM,KAAA;AACpD,QAAI,IAAA,CAAA,CAAE,WAAW,OAAS,EAAA,OAAO,IAAI,MAAO,CAAA,CAAA,EAAG,CAAE,CAAA,MAAM,CAAI,EAAA,CAAA,CAAA,CAAA;AAC3D,QAAO,OAAA,GAAA,CAAA;AAAA,SACN,EAAE,CAAA,CAAA;AACL,MAAA,OAAO,SAAU,CAAA,KAAA,CAAM,CAAG,EAAA,SAAA,CAAU,SAAS,CAAC,CAAA,CAAA;AAAA,KAChD;AAAA,GACF;AAAA,EACA;AAAA,IACE,KAAO,EAAA,aAAA;AAAA,IACP,KAAO,EAAA,YAAA;AAAA,IACP,MAAA,EAAQ,CAAC,UAA+B,KAAA;AACtC,MAAM,MAAA,UAAA,GAAa,eAAe,UAAU,CAAA,CAAA;AAC5C,MAAO,OAAA,UAAA,GACH,GAAG,UAAU,CAAA,CAAA,EAAI,aAAa,CAAI,GAAA,OAAA,GAAU,MAAM,CAClD,CAAA,GAAA,GAAA,CAAA;AAAA,KACN;AAAA,GACF;AACF;;;;"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const initialPermissionPolicyRowValue = {
|
|
2
|
+
plugin: "",
|
|
3
|
+
permission: "",
|
|
4
|
+
policies: [
|
|
5
|
+
{ policy: "Create", effect: "deny" },
|
|
6
|
+
{ policy: "Read", effect: "deny" },
|
|
7
|
+
{ policy: "Update", effect: "deny" },
|
|
8
|
+
{ policy: "Delete", effect: "deny" }
|
|
9
|
+
],
|
|
10
|
+
isResourced: false
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export { initialPermissionPolicyRowValue };
|
|
14
|
+
//# sourceMappingURL=const.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"const.esm.js","sources":["../../../src/components/CreateRole/const.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 { PermissionsData } from '../../types';\n\nexport const initialPermissionPolicyRowValue: PermissionsData = {\n plugin: '',\n permission: '',\n policies: [\n { policy: 'Create', effect: 'deny' },\n { policy: 'Read', effect: 'deny' },\n { policy: 'Update', effect: 'deny' },\n { policy: 'Delete', effect: 'deny' },\n ],\n isResourced: false,\n};\n"],"names":[],"mappings":"AAiBO,MAAM,+BAAmD,GAAA;AAAA,EAC9D,MAAQ,EAAA,EAAA;AAAA,EACR,UAAY,EAAA,EAAA;AAAA,EACZ,QAAU,EAAA;AAAA,IACR,EAAE,MAAA,EAAQ,QAAU,EAAA,MAAA,EAAQ,MAAO,EAAA;AAAA,IACnC,EAAE,MAAA,EAAQ,MAAQ,EAAA,MAAA,EAAQ,MAAO,EAAA;AAAA,IACjC,EAAE,MAAA,EAAQ,QAAU,EAAA,MAAA,EAAQ,MAAO,EAAA;AAAA,IACnC,EAAE,MAAA,EAAQ,QAAU,EAAA,MAAA,EAAQ,MAAO,EAAA;AAAA,GACrC;AAAA,EACA,WAAa,EAAA,KAAA;AACf;;;;"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
3
|
+
import { makeStyles } from '@material-ui/core';
|
|
4
|
+
import { licensedUsersApiRef } from '../api/LicensedUsersClient.esm.js';
|
|
5
|
+
|
|
6
|
+
const useStyles = makeStyles((theme) => ({
|
|
7
|
+
linkStyle: {
|
|
8
|
+
color: theme.palette.link,
|
|
9
|
+
textDecoration: "underline"
|
|
10
|
+
}
|
|
11
|
+
}));
|
|
12
|
+
function DownloadCSVLink() {
|
|
13
|
+
const classes = useStyles();
|
|
14
|
+
const licensedUsersClient = useApi(licensedUsersApiRef);
|
|
15
|
+
const handleDownload = async (event) => {
|
|
16
|
+
event.preventDefault();
|
|
17
|
+
try {
|
|
18
|
+
const response = await licensedUsersClient.downloadStatistics();
|
|
19
|
+
if (response.ok) {
|
|
20
|
+
const csvData = await response.text();
|
|
21
|
+
const blob = new Blob([csvData], { type: "text/csv" });
|
|
22
|
+
const url = window.URL.createObjectURL(blob);
|
|
23
|
+
const a = document.createElement("a");
|
|
24
|
+
a.href = url;
|
|
25
|
+
a.download = "licensed-users.csv";
|
|
26
|
+
document.body.appendChild(a);
|
|
27
|
+
a.click();
|
|
28
|
+
document.body.removeChild(a);
|
|
29
|
+
window.URL.revokeObjectURL(url);
|
|
30
|
+
} else {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`Failed to download the csv file with list licensed users ${response.statusText}`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
} catch (error) {
|
|
36
|
+
throw new Error(`Error during the download: ${error}`);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
return /* @__PURE__ */ React.createElement(
|
|
40
|
+
"a",
|
|
41
|
+
{
|
|
42
|
+
href: "/download-csv",
|
|
43
|
+
onClick: handleDownload,
|
|
44
|
+
className: classes.linkStyle
|
|
45
|
+
},
|
|
46
|
+
"Download User List"
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { DownloadCSVLink as default };
|
|
51
|
+
//# sourceMappingURL=DownloadUserStatistics.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DownloadUserStatistics.esm.js","sources":["../../src/components/DownloadUserStatistics.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 { useApi } from '@backstage/core-plugin-api';\n\nimport { makeStyles } from '@material-ui/core';\n\nimport { licensedUsersApiRef } from '../api/LicensedUsersClient';\n\nconst useStyles = makeStyles(theme => ({\n linkStyle: {\n color: theme.palette.link,\n textDecoration: 'underline',\n },\n}));\n\nfunction DownloadCSVLink() {\n const classes = useStyles();\n const licensedUsersClient = useApi(licensedUsersApiRef);\n const handleDownload = async (\n event: React.MouseEvent<HTMLAnchorElement, MouseEvent>,\n ) => {\n event.preventDefault(); // Prevent the default link behavior\n\n try {\n const response = await licensedUsersClient.downloadStatistics();\n\n if (response.ok) {\n // Get the CSV data as a string\n const csvData = await response.text();\n\n // Create a Blob from the CSV data\n const blob = new Blob([csvData], { type: 'text/csv' });\n const url = window.URL.createObjectURL(blob);\n\n // Create a temporary link to trigger the download\n const a = document.createElement('a');\n a.href = url;\n a.download = 'licensed-users.csv';\n document.body.appendChild(a);\n a.click();\n\n // Clean up the temporary link and object URL\n document.body.removeChild(a);\n window.URL.revokeObjectURL(url);\n } else {\n throw new Error(\n `Failed to download the csv file with list licensed users ${response.statusText}`,\n );\n }\n } catch (error) {\n throw new Error(`Error during the download: ${error}`);\n }\n };\n\n return (\n <a\n href=\"/download-csv\"\n onClick={handleDownload}\n className={classes.linkStyle}\n >\n Download User List\n </a>\n );\n}\n\nexport default DownloadCSVLink;\n"],"names":[],"mappings":";;;;;AAuBA,MAAM,SAAA,GAAY,WAAW,CAAU,KAAA,MAAA;AAAA,EACrC,SAAW,EAAA;AAAA,IACT,KAAA,EAAO,MAAM,OAAQ,CAAA,IAAA;AAAA,IACrB,cAAgB,EAAA,WAAA;AAAA,GAClB;AACF,CAAE,CAAA,CAAA,CAAA;AAEF,SAAS,eAAkB,GAAA;AACzB,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAC1B,EAAM,MAAA,mBAAA,GAAsB,OAAO,mBAAmB,CAAA,CAAA;AACtD,EAAM,MAAA,cAAA,GAAiB,OACrB,KACG,KAAA;AACH,IAAA,KAAA,CAAM,cAAe,EAAA,CAAA;AAErB,IAAI,IAAA;AACF,MAAM,MAAA,QAAA,GAAW,MAAM,mBAAA,CAAoB,kBAAmB,EAAA,CAAA;AAE9D,MAAA,IAAI,SAAS,EAAI,EAAA;AAEf,QAAM,MAAA,OAAA,GAAU,MAAM,QAAA,CAAS,IAAK,EAAA,CAAA;AAGpC,QAAM,MAAA,IAAA,GAAO,IAAI,IAAK,CAAA,CAAC,OAAO,CAAG,EAAA,EAAE,IAAM,EAAA,UAAA,EAAY,CAAA,CAAA;AACrD,QAAA,MAAM,GAAM,GAAA,MAAA,CAAO,GAAI,CAAA,eAAA,CAAgB,IAAI,CAAA,CAAA;AAG3C,QAAM,MAAA,CAAA,GAAI,QAAS,CAAA,aAAA,CAAc,GAAG,CAAA,CAAA;AACpC,QAAA,CAAA,CAAE,IAAO,GAAA,GAAA,CAAA;AACT,QAAA,CAAA,CAAE,QAAW,GAAA,oBAAA,CAAA;AACb,QAAS,QAAA,CAAA,IAAA,CAAK,YAAY,CAAC,CAAA,CAAA;AAC3B,QAAA,CAAA,CAAE,KAAM,EAAA,CAAA;AAGR,QAAS,QAAA,CAAA,IAAA,CAAK,YAAY,CAAC,CAAA,CAAA;AAC3B,QAAO,MAAA,CAAA,GAAA,CAAI,gBAAgB,GAAG,CAAA,CAAA;AAAA,OACzB,MAAA;AACL,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,0DAAA,EAA6D,SAAS,UAAU,CAAA,CAAA;AAAA,SAClF,CAAA;AAAA,OACF;AAAA,aACO,KAAO,EAAA;AACd,MAAA,MAAM,IAAI,KAAA,CAAM,CAA8B,2BAAA,EAAA,KAAK,CAAE,CAAA,CAAA,CAAA;AAAA,KACvD;AAAA,GACF,CAAA;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,IAAK,EAAA,eAAA;AAAA,MACL,OAAS,EAAA,cAAA;AAAA,MACT,WAAW,OAAQ,CAAA,SAAA;AAAA,KAAA;AAAA,IACpB,oBAAA;AAAA,GAED,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { parseEntityRef } from '@backstage/catalog-model';
|
|
3
|
+
import { Link } from '@backstage/core-components';
|
|
4
|
+
import { Tooltip, Typography, IconButton } from '@material-ui/core';
|
|
5
|
+
import EditIcon from '@material-ui/icons/Edit';
|
|
6
|
+
|
|
7
|
+
const EditRole = ({
|
|
8
|
+
roleName,
|
|
9
|
+
tooltip,
|
|
10
|
+
disable,
|
|
11
|
+
dataTestId,
|
|
12
|
+
to
|
|
13
|
+
}) => {
|
|
14
|
+
const { name, namespace, kind } = parseEntityRef(roleName);
|
|
15
|
+
return /* @__PURE__ */ React.createElement(Tooltip, { title: tooltip || "" }, /* @__PURE__ */ React.createElement(Typography, { component: "span", "data-testid": dataTestId }, /* @__PURE__ */ React.createElement(
|
|
16
|
+
IconButton,
|
|
17
|
+
{
|
|
18
|
+
color: "inherit",
|
|
19
|
+
component: Link,
|
|
20
|
+
"aria-label": "Update",
|
|
21
|
+
disabled: disable,
|
|
22
|
+
title: tooltip || "Edit Role",
|
|
23
|
+
to: to || `../role/${kind}/${namespace}/${name}`
|
|
24
|
+
},
|
|
25
|
+
/* @__PURE__ */ React.createElement(EditIcon, null)
|
|
26
|
+
)));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { EditRole as default };
|
|
30
|
+
//# sourceMappingURL=EditRole.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditRole.esm.js","sources":["../../src/components/EditRole.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 } from '@backstage/core-components';\n\nimport { IconButton, Tooltip, Typography } from '@material-ui/core';\nimport EditIcon from '@material-ui/icons/Edit';\n\ntype EditRoleProps = {\n roleName: string;\n disable: boolean;\n tooltip?: string;\n dataTestId: string;\n to?: string;\n};\n\nconst EditRole = ({\n roleName,\n tooltip,\n disable,\n dataTestId,\n to,\n}: EditRoleProps) => {\n const { name, namespace, kind } = parseEntityRef(roleName);\n return (\n <Tooltip title={tooltip || ''}>\n <Typography component=\"span\" data-testid={dataTestId}>\n <IconButton\n color=\"inherit\"\n component={Link}\n aria-label=\"Update\"\n disabled={disable}\n title={tooltip || 'Edit Role'}\n to={to || `../role/${kind}/${namespace}/${name}`}\n >\n <EditIcon />\n </IconButton>\n </Typography>\n </Tooltip>\n );\n};\n\nexport default EditRole;\n"],"names":[],"mappings":";;;;;;AA+BA,MAAM,WAAW,CAAC;AAAA,EAChB,QAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA,EAAA;AACF,CAAqB,KAAA;AACnB,EAAA,MAAM,EAAE,IAAM,EAAA,SAAA,EAAW,IAAK,EAAA,GAAI,eAAe,QAAQ,CAAA,CAAA;AACzD,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,OAAQ,EAAA,EAAA,KAAA,EAAO,OAAW,IAAA,EAAA,EAAA,sCACxB,UAAW,EAAA,EAAA,SAAA,EAAU,MAAO,EAAA,aAAA,EAAa,UACxC,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,KAAM,EAAA,SAAA;AAAA,MACN,SAAW,EAAA,IAAA;AAAA,MACX,YAAW,EAAA,QAAA;AAAA,MACX,QAAU,EAAA,OAAA;AAAA,MACV,OAAO,OAAW,IAAA,WAAA;AAAA,MAClB,IAAI,EAAM,IAAA,CAAA,QAAA,EAAW,IAAI,CAAI,CAAA,EAAA,SAAS,IAAI,IAAI,CAAA,CAAA;AAAA,KAAA;AAAA,wCAE7C,QAAS,EAAA,IAAA,CAAA;AAAA,GAEd,CACF,CAAA,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Page, Header, Content } from '@backstage/core-components';
|
|
3
|
+
import { RequirePermission } from '@backstage/plugin-permission-react';
|
|
4
|
+
import { DeleteDialogContextProvider } from '@janus-idp/shared-react';
|
|
5
|
+
import { policyEntityReadPermission } from '@backstage-community/plugin-rbac-common';
|
|
6
|
+
import { RolesList } from './RolesList/RolesList.esm.js';
|
|
7
|
+
|
|
8
|
+
const RbacPage = ({ useHeader = true }) => /* @__PURE__ */ React.createElement(
|
|
9
|
+
RequirePermission,
|
|
10
|
+
{
|
|
11
|
+
permission: policyEntityReadPermission,
|
|
12
|
+
resourceRef: policyEntityReadPermission.resourceType
|
|
13
|
+
},
|
|
14
|
+
/* @__PURE__ */ React.createElement(Page, { themeId: "tool" }, useHeader && /* @__PURE__ */ React.createElement(Header, { title: "RBAC" }), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(DeleteDialogContextProvider, null, /* @__PURE__ */ React.createElement(RolesList, null))))
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
export { RbacPage };
|
|
18
|
+
//# sourceMappingURL=RbacPage.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RbacPage.esm.js","sources":["../../src/components/RbacPage.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 { Content, Header, Page } from '@backstage/core-components';\nimport { RequirePermission } from '@backstage/plugin-permission-react';\n\nimport { DeleteDialogContextProvider } from '@janus-idp/shared-react';\n\nimport { policyEntityReadPermission } from '@backstage-community/plugin-rbac-common';\n\nimport { RolesList } from './RolesList/RolesList';\n\nexport const RbacPage = ({ useHeader = true }: { useHeader?: boolean }) => (\n <RequirePermission\n permission={policyEntityReadPermission}\n resourceRef={policyEntityReadPermission.resourceType}\n >\n <Page themeId=\"tool\">\n {useHeader && <Header title=\"RBAC\" />}\n <Content>\n <DeleteDialogContextProvider>\n <RolesList />\n </DeleteDialogContextProvider>\n </Content>\n </Page>\n </RequirePermission>\n);\n"],"names":[],"mappings":";;;;;;;AA0BO,MAAM,QAAW,GAAA,CAAC,EAAE,SAAA,GAAY,MACrC,qBAAA,KAAA,CAAA,aAAA;AAAA,EAAC,iBAAA;AAAA,EAAA;AAAA,IACC,UAAY,EAAA,0BAAA;AAAA,IACZ,aAAa,0BAA2B,CAAA,YAAA;AAAA,GAAA;AAAA,sCAEvC,IAAK,EAAA,EAAA,OAAA,EAAQ,UACX,SAAa,oBAAA,KAAA,CAAA,aAAA,CAAC,UAAO,KAAM,EAAA,MAAA,EAAO,CACnC,kBAAA,KAAA,CAAA,aAAA,CAAC,+BACE,KAAA,CAAA,aAAA,CAAA,2BAAA,EAAA,IAAA,sCACE,SAAU,EAAA,IAAA,CACb,CACF,CACF,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Progress, WarningPanel, MarkdownContent } from '@backstage/core-components';
|
|
3
|
+
import { AboutField } from '@backstage/plugin-catalog';
|
|
4
|
+
import { makeStyles, Card, CardHeader, CardContent, Grid } from '@material-ui/core';
|
|
5
|
+
import { useRole } from '../../hooks/useRole.esm.js';
|
|
6
|
+
|
|
7
|
+
const useStyles = makeStyles({
|
|
8
|
+
gridItemCard: {
|
|
9
|
+
display: "flex",
|
|
10
|
+
flexDirection: "column",
|
|
11
|
+
height: "calc(100% - 10px)",
|
|
12
|
+
// for pages without content header
|
|
13
|
+
marginBottom: "10px"
|
|
14
|
+
},
|
|
15
|
+
fullHeightCard: {
|
|
16
|
+
display: "flex",
|
|
17
|
+
flexDirection: "column",
|
|
18
|
+
height: "100%"
|
|
19
|
+
},
|
|
20
|
+
gridItemCardContent: {
|
|
21
|
+
flex: 1
|
|
22
|
+
},
|
|
23
|
+
fullHeightCardContent: {
|
|
24
|
+
flex: 1
|
|
25
|
+
},
|
|
26
|
+
text: {
|
|
27
|
+
wordBreak: "break-word"
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
const AboutCard = ({ roleName }) => {
|
|
31
|
+
const classes = useStyles();
|
|
32
|
+
const cardClass = classes.gridItemCard;
|
|
33
|
+
const cardContentClass = classes.gridItemCardContent;
|
|
34
|
+
const { role, roleError, loading } = useRole(roleName);
|
|
35
|
+
if (loading) {
|
|
36
|
+
return /* @__PURE__ */ React.createElement(Progress, null);
|
|
37
|
+
}
|
|
38
|
+
let lastModified = role?.metadata?.lastModified;
|
|
39
|
+
if (lastModified) {
|
|
40
|
+
const date = new Date(lastModified);
|
|
41
|
+
const time = date.toLocaleString("en-US", {
|
|
42
|
+
hour: "2-digit",
|
|
43
|
+
minute: "2-digit",
|
|
44
|
+
hour12: false,
|
|
45
|
+
timeZone: "UTC"
|
|
46
|
+
});
|
|
47
|
+
lastModified = `${date.getUTCDate()} ${date.toLocaleString("default", {
|
|
48
|
+
month: "short"
|
|
49
|
+
})} ${date.getUTCFullYear()}, ${time}`;
|
|
50
|
+
} else {
|
|
51
|
+
lastModified = "No information";
|
|
52
|
+
}
|
|
53
|
+
return /* @__PURE__ */ React.createElement(Card, { className: cardClass }, /* @__PURE__ */ React.createElement(CardHeader, { title: "About" }), /* @__PURE__ */ React.createElement(CardContent, { className: cardContentClass }, roleError.name ? /* @__PURE__ */ React.createElement("div", { style: { paddingBottom: "16px" } }, /* @__PURE__ */ React.createElement(
|
|
54
|
+
WarningPanel,
|
|
55
|
+
{
|
|
56
|
+
message: roleError?.message,
|
|
57
|
+
title: "Something went wrong while fetching role",
|
|
58
|
+
severity: "error"
|
|
59
|
+
}
|
|
60
|
+
)) : /* @__PURE__ */ React.createElement(Grid, { container: true }, /* @__PURE__ */ React.createElement(AboutField, { label: "Description", gridSizes: { xs: 4, sm: 8, lg: 4 } }, /* @__PURE__ */ React.createElement(
|
|
61
|
+
MarkdownContent,
|
|
62
|
+
{
|
|
63
|
+
className: classes.text,
|
|
64
|
+
content: role?.metadata?.description ?? "No description"
|
|
65
|
+
}
|
|
66
|
+
)), /* @__PURE__ */ React.createElement(AboutField, { label: "Modified By", gridSizes: { xs: 4, sm: 8, lg: 4 } }, /* @__PURE__ */ React.createElement(
|
|
67
|
+
MarkdownContent,
|
|
68
|
+
{
|
|
69
|
+
className: classes.text,
|
|
70
|
+
content: role?.metadata?.modifiedBy ?? "No information"
|
|
71
|
+
}
|
|
72
|
+
)), /* @__PURE__ */ React.createElement(
|
|
73
|
+
AboutField,
|
|
74
|
+
{
|
|
75
|
+
label: "Last Modified",
|
|
76
|
+
gridSizes: { xs: 4, sm: 8, lg: 4 }
|
|
77
|
+
},
|
|
78
|
+
/* @__PURE__ */ React.createElement(
|
|
79
|
+
MarkdownContent,
|
|
80
|
+
{
|
|
81
|
+
className: classes.text,
|
|
82
|
+
content: lastModified
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
))));
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export { AboutCard };
|
|
89
|
+
//# sourceMappingURL=AboutCard.esm.js.map
|
|
@@ -0,0 +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 {\n Card,\n CardContent,\n CardHeader,\n Grid,\n makeStyles,\n} from '@material-ui/core';\n\nimport { useRole } from '../../hooks/useRole';\n\nconst useStyles = makeStyles({\n gridItemCard: {\n display: 'flex',\n flexDirection: 'column',\n height: 'calc(100% - 10px)', // for pages without content header\n marginBottom: '10px',\n },\n fullHeightCard: {\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n },\n gridItemCardContent: {\n flex: 1,\n },\n fullHeightCardContent: {\n flex: 1,\n },\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 cardClass = classes.gridItemCard;\n const cardContentClass = classes.gridItemCardContent;\n\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 className={cardClass}>\n <CardHeader title=\"About\" />\n <CardContent className={cardContentClass}>\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>\n <AboutField label=\"Description\" gridSizes={{ xs: 4, sm: 8, lg: 4 }}>\n <MarkdownContent\n className={classes.text}\n content={role?.metadata?.description ?? 'No description'}\n />\n </AboutField>\n <AboutField label=\"Modified By\" gridSizes={{ xs: 4, sm: 8, lg: 4 }}>\n <MarkdownContent\n className={classes.text}\n content={role?.metadata?.modifiedBy ?? 'No information'}\n />\n </AboutField>\n <AboutField\n label=\"Last Modified\"\n gridSizes={{ xs: 4, sm: 8, lg: 4 }}\n >\n <MarkdownContent\n className={classes.text}\n content={lastModified}\n />\n </AboutField>\n </Grid>\n )}\n </CardContent>\n </Card>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { parseEntityRef } from '@backstage/catalog-model';
|
|
3
|
+
import { WarningPanel, Table } from '@backstage/core-components';
|
|
4
|
+
import { usePermission } from '@backstage/plugin-permission-react';
|
|
5
|
+
import { makeStyles, Card, CardContent } from '@material-ui/core';
|
|
6
|
+
import CachedIcon from '@material-ui/icons/Cached';
|
|
7
|
+
import { policyEntityUpdatePermission } from '@backstage-community/plugin-rbac-common';
|
|
8
|
+
import { getMembers } from '../../utils/rbac-utils.esm.js';
|
|
9
|
+
import EditRole from '../EditRole.esm.js';
|
|
10
|
+
import { columns } from './MembersListColumns.esm.js';
|
|
11
|
+
|
|
12
|
+
const useStyles = makeStyles((theme) => ({
|
|
13
|
+
empty: {
|
|
14
|
+
padding: theme.spacing(2),
|
|
15
|
+
display: "flex",
|
|
16
|
+
justifyContent: "center"
|
|
17
|
+
}
|
|
18
|
+
}));
|
|
19
|
+
const getRefreshIcon = () => /* @__PURE__ */ React.createElement(CachedIcon, null);
|
|
20
|
+
const getEditIcon = (isAllowed, roleName) => {
|
|
21
|
+
const { kind, name, namespace } = parseEntityRef(roleName);
|
|
22
|
+
return /* @__PURE__ */ React.createElement(
|
|
23
|
+
EditRole,
|
|
24
|
+
{
|
|
25
|
+
dataTestId: isAllowed ? "update-members" : "disable-update-members",
|
|
26
|
+
roleName,
|
|
27
|
+
disable: !isAllowed,
|
|
28
|
+
to: `../../role/${kind}/${namespace}/${name}?activeStep=${1}`
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
const MembersCard = ({ roleName, membersInfo }) => {
|
|
33
|
+
const { data, loading, retry, error, canReadUsersAndGroups } = membersInfo;
|
|
34
|
+
const [members, setMembers] = React.useState();
|
|
35
|
+
const policyEntityPermissionResult = usePermission({
|
|
36
|
+
permission: policyEntityUpdatePermission,
|
|
37
|
+
resourceRef: policyEntityUpdatePermission.resourceType
|
|
38
|
+
});
|
|
39
|
+
const classes = useStyles();
|
|
40
|
+
const actions = [
|
|
41
|
+
{
|
|
42
|
+
icon: getRefreshIcon,
|
|
43
|
+
tooltip: "Refresh",
|
|
44
|
+
isFreeAction: true,
|
|
45
|
+
onClick: () => {
|
|
46
|
+
retry.roleRetry();
|
|
47
|
+
retry.membersRetry();
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
icon: () => getEditIcon(
|
|
52
|
+
policyEntityPermissionResult.allowed && canReadUsersAndGroups,
|
|
53
|
+
roleName
|
|
54
|
+
),
|
|
55
|
+
tooltip: policyEntityPermissionResult.allowed && canReadUsersAndGroups ? "Edit" : "Unauthorized to edit",
|
|
56
|
+
isFreeAction: true,
|
|
57
|
+
onClick: () => {
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
];
|
|
61
|
+
const onSearchResultsChange = (searchResults) => {
|
|
62
|
+
setMembers(searchResults);
|
|
63
|
+
};
|
|
64
|
+
return /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(CardContent, null, !loading && error && /* @__PURE__ */ React.createElement("div", { style: { paddingBottom: "16px" } }, /* @__PURE__ */ React.createElement(
|
|
65
|
+
WarningPanel,
|
|
66
|
+
{
|
|
67
|
+
message: error?.message || error?.name,
|
|
68
|
+
title: "Something went wrong while fetching the users and groups",
|
|
69
|
+
severity: "error"
|
|
70
|
+
}
|
|
71
|
+
)), /* @__PURE__ */ React.createElement(
|
|
72
|
+
Table,
|
|
73
|
+
{
|
|
74
|
+
title: !loading && data?.length ? `Users and groups (${getMembers(members || data)})` : "Users and groups",
|
|
75
|
+
actions,
|
|
76
|
+
renderSummaryRow: (summary) => onSearchResultsChange(summary.data),
|
|
77
|
+
options: { padding: "default", search: true, paging: true },
|
|
78
|
+
data: data ?? [],
|
|
79
|
+
isLoading: loading,
|
|
80
|
+
columns,
|
|
81
|
+
emptyContent: /* @__PURE__ */ React.createElement("div", { "data-testid": "members-table-empty", className: classes.empty }, "No records found")
|
|
82
|
+
}
|
|
83
|
+
)));
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export { MembersCard };
|
|
87
|
+
//# sourceMappingURL=MembersCard.esm.js.map
|
|
@@ -0,0 +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 { Card, CardContent, makeStyles } from '@material-ui/core';\nimport CachedIcon from '@material-ui/icons/Cached';\n\nimport { policyEntityUpdatePermission } from '@backstage-community/plugin-rbac-common';\n\nimport { MembersInfo } from '../../hooks/useMembers';\nimport { MembersData } from '../../types';\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 useStyles = makeStyles(theme => ({\n empty: {\n padding: theme.spacing(2),\n display: 'flex',\n justifyContent: 'center',\n },\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 [members, setMembers] = React.useState<MembersData[]>();\n const policyEntityPermissionResult = usePermission({\n permission: policyEntityUpdatePermission,\n resourceRef: policyEntityUpdatePermission.resourceType,\n });\n\n const classes = useStyles();\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 onSearchResultsChange = (searchResults: MembersData[]) => {\n setMembers(searchResults);\n };\n\n return (\n <Card>\n <CardContent>\n {!loading && error && (\n <div 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 </div>\n )}\n <Table\n title={\n !loading && data?.length\n ? `Users and groups (${getMembers(members || data)})`\n : 'Users and groups'\n }\n actions={actions}\n renderSummaryRow={summary => onSearchResultsChange(summary.data)}\n options={{ padding: 'default', search: true, paging: true }}\n data={data ?? []}\n isLoading={loading}\n columns={columns}\n emptyContent={\n <div data-testid=\"members-table-empty\" className={classes.empty}>\n No records found\n </div>\n }\n />\n </CardContent>\n </Card>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Link } from '@backstage/core-components';
|
|
3
|
+
|
|
4
|
+
const columns = [
|
|
5
|
+
{
|
|
6
|
+
title: "Name",
|
|
7
|
+
field: "name",
|
|
8
|
+
type: "string",
|
|
9
|
+
render: (props) => {
|
|
10
|
+
return /* @__PURE__ */ React.createElement(
|
|
11
|
+
Link,
|
|
12
|
+
{
|
|
13
|
+
to: `/catalog/${props.ref.namespace}/${props.ref.kind}/${props.ref.name}`
|
|
14
|
+
},
|
|
15
|
+
props.name
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
title: "Type",
|
|
21
|
+
field: "type",
|
|
22
|
+
type: "string"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
title: "Members",
|
|
26
|
+
field: "members",
|
|
27
|
+
type: "numeric",
|
|
28
|
+
align: "left",
|
|
29
|
+
render: (props) => {
|
|
30
|
+
return props.type === "User" ? "-" : props.members;
|
|
31
|
+
},
|
|
32
|
+
customSort: (a, b) => {
|
|
33
|
+
if (a.members === 0) {
|
|
34
|
+
return -1;
|
|
35
|
+
}
|
|
36
|
+
if (b.members === 0) {
|
|
37
|
+
return 1;
|
|
38
|
+
}
|
|
39
|
+
if (a.members === b.members) {
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
return a.members < b.members ? -1 : 1;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
export { columns };
|
|
48
|
+
//# sourceMappingURL=MembersListColumns.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MembersListColumns.esm.js","sources":["../../../src/components/RoleOverview/MembersListColumns.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 { Link, TableColumn } from '@backstage/core-components';\n\nimport { MembersData } from '../../types';\n\nexport const columns: TableColumn<MembersData>[] = [\n {\n title: 'Name',\n field: 'name',\n type: 'string',\n render: props => {\n return (\n <Link\n to={`/catalog/${props.ref.namespace}/${props.ref.kind}/${props.ref.name}`}\n >\n {props.name}\n </Link>\n );\n },\n },\n {\n title: 'Type',\n field: 'type',\n type: 'string',\n },\n {\n title: 'Members',\n field: 'members',\n type: 'numeric',\n align: 'left',\n render: (props: MembersData) => {\n return props.type === 'User' ? '-' : props.members;\n },\n customSort: (a, b) => {\n if (a.members === 0) {\n return -1;\n }\n if (b.members === 0) {\n return 1;\n }\n if (a.members === b.members) {\n return 0;\n }\n return a.members < b.members ? -1 : 1;\n },\n },\n];\n"],"names":[],"mappings":";;;AAqBO,MAAM,OAAsC,GAAA;AAAA,EACjD;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,KAAO,EAAA,MAAA;AAAA,IACP,IAAM,EAAA,QAAA;AAAA,IACN,QAAQ,CAAS,KAAA,KAAA;AACf,MACE,uBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,IAAA;AAAA,QAAA;AAAA,UACC,EAAI,EAAA,CAAA,SAAA,EAAY,KAAM,CAAA,GAAA,CAAI,SAAS,CAAA,CAAA,EAAI,KAAM,CAAA,GAAA,CAAI,IAAI,CAAA,CAAA,EAAI,KAAM,CAAA,GAAA,CAAI,IAAI,CAAA,CAAA;AAAA,SAAA;AAAA,QAEtE,KAAM,CAAA,IAAA;AAAA,OACT,CAAA;AAAA,KAEJ;AAAA,GACF;AAAA,EACA;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,KAAO,EAAA,MAAA;AAAA,IACP,IAAM,EAAA,QAAA;AAAA,GACR;AAAA,EACA;AAAA,IACE,KAAO,EAAA,SAAA;AAAA,IACP,KAAO,EAAA,SAAA;AAAA,IACP,IAAM,EAAA,SAAA;AAAA,IACN,KAAO,EAAA,MAAA;AAAA,IACP,MAAA,EAAQ,CAAC,KAAuB,KAAA;AAC9B,MAAA,OAAO,KAAM,CAAA,IAAA,KAAS,MAAS,GAAA,GAAA,GAAM,KAAM,CAAA,OAAA,CAAA;AAAA,KAC7C;AAAA,IACA,UAAA,EAAY,CAAC,CAAA,EAAG,CAAM,KAAA;AACpB,MAAI,IAAA,CAAA,CAAE,YAAY,CAAG,EAAA;AACnB,QAAO,OAAA,CAAA,CAAA,CAAA;AAAA,OACT;AACA,MAAI,IAAA,CAAA,CAAE,YAAY,CAAG,EAAA;AACnB,QAAO,OAAA,CAAA,CAAA;AAAA,OACT;AACA,MAAI,IAAA,CAAA,CAAE,OAAY,KAAA,CAAA,CAAE,OAAS,EAAA;AAC3B,QAAO,OAAA,CAAA,CAAA;AAAA,OACT;AACA,MAAA,OAAO,CAAE,CAAA,OAAA,GAAU,CAAE,CAAA,OAAA,GAAU,CAAK,CAAA,GAAA,CAAA,CAAA;AAAA,KACtC;AAAA,GACF;AACF;;;;"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { parseEntityRef } from '@backstage/catalog-model';
|
|
3
|
+
import { WarningPanel, Table } from '@backstage/core-components';
|
|
4
|
+
import { usePermission } from '@backstage/plugin-permission-react';
|
|
5
|
+
import { makeStyles, Card, CardContent } from '@material-ui/core';
|
|
6
|
+
import CachedIcon from '@material-ui/icons/Cached';
|
|
7
|
+
import { policyEntityUpdatePermission } from '@backstage-community/plugin-rbac-common';
|
|
8
|
+
import { usePermissionPolicies } from '../../hooks/usePermissionPolicies.esm.js';
|
|
9
|
+
import EditRole from '../EditRole.esm.js';
|
|
10
|
+
import { columns } from './PermissionsListColumns.esm.js';
|
|
11
|
+
|
|
12
|
+
const useStyles = makeStyles((theme) => ({
|
|
13
|
+
empty: {
|
|
14
|
+
padding: theme.spacing(2),
|
|
15
|
+
display: "flex",
|
|
16
|
+
justifyContent: "center"
|
|
17
|
+
}
|
|
18
|
+
}));
|
|
19
|
+
const getRefreshIcon = () => /* @__PURE__ */ React.createElement(CachedIcon, null);
|
|
20
|
+
const getEditIcon = (isAllowed, roleName) => {
|
|
21
|
+
const { kind, name, namespace } = parseEntityRef(roleName);
|
|
22
|
+
return /* @__PURE__ */ React.createElement(
|
|
23
|
+
EditRole,
|
|
24
|
+
{
|
|
25
|
+
dataTestId: isAllowed ? "update-policies" : "disable-update-policies",
|
|
26
|
+
roleName,
|
|
27
|
+
disable: !isAllowed,
|
|
28
|
+
to: `../../role/${kind}/${namespace}/${name}?activeStep=${2}`
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
const PermissionsCard = ({
|
|
33
|
+
entityReference,
|
|
34
|
+
canReadUsersAndGroups
|
|
35
|
+
}) => {
|
|
36
|
+
const { data, loading, retry, error } = usePermissionPolicies(entityReference);
|
|
37
|
+
const [permissions, setPermissions] = React.useState();
|
|
38
|
+
const permissionResult = usePermission({
|
|
39
|
+
permission: policyEntityUpdatePermission,
|
|
40
|
+
resourceRef: policyEntityUpdatePermission.resourceType
|
|
41
|
+
});
|
|
42
|
+
const classes = useStyles();
|
|
43
|
+
const onSearchResultsChange = (searchResults) => {
|
|
44
|
+
setPermissions(searchResults);
|
|
45
|
+
};
|
|
46
|
+
let numberOfPolicies = 0;
|
|
47
|
+
(permissions || data)?.forEach((p) => {
|
|
48
|
+
if (p.conditions) {
|
|
49
|
+
numberOfPolicies++;
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
numberOfPolicies = numberOfPolicies + p.policies.filter((pol) => pol.effect === "allow").length;
|
|
53
|
+
});
|
|
54
|
+
const actions = [
|
|
55
|
+
{
|
|
56
|
+
icon: getRefreshIcon,
|
|
57
|
+
tooltip: "Refresh",
|
|
58
|
+
isFreeAction: true,
|
|
59
|
+
onClick: () => {
|
|
60
|
+
retry.permissionPoliciesRetry();
|
|
61
|
+
retry.policiesRetry();
|
|
62
|
+
retry.conditionalPoliciesRetry();
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
icon: () => getEditIcon(
|
|
67
|
+
permissionResult.allowed && canReadUsersAndGroups,
|
|
68
|
+
entityReference
|
|
69
|
+
),
|
|
70
|
+
tooltip: permissionResult.allowed && canReadUsersAndGroups ? "Edit" : "Unauthorized to edit",
|
|
71
|
+
isFreeAction: true,
|
|
72
|
+
onClick: () => {
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
];
|
|
76
|
+
return /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(CardContent, null, error?.name && error.name !== 404 && /* @__PURE__ */ React.createElement("div", { style: { paddingBottom: "16px" } }, /* @__PURE__ */ React.createElement(
|
|
77
|
+
WarningPanel,
|
|
78
|
+
{
|
|
79
|
+
message: error?.message,
|
|
80
|
+
title: "Something went wrong while fetching the permission policies",
|
|
81
|
+
severity: "error"
|
|
82
|
+
}
|
|
83
|
+
)), /* @__PURE__ */ React.createElement(
|
|
84
|
+
Table,
|
|
85
|
+
{
|
|
86
|
+
title: !loading && data.length > 0 ? `Permission Policies (${numberOfPolicies})` : "Permission Policies",
|
|
87
|
+
actions,
|
|
88
|
+
renderSummaryRow: (summary) => onSearchResultsChange(summary.data),
|
|
89
|
+
options: { padding: "default", search: true, paging: true },
|
|
90
|
+
data,
|
|
91
|
+
columns,
|
|
92
|
+
isLoading: loading,
|
|
93
|
+
emptyContent: /* @__PURE__ */ React.createElement("div", { "data-testid": "permission-table-empty", className: classes.empty }, "No records found")
|
|
94
|
+
}
|
|
95
|
+
)));
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export { PermissionsCard };
|
|
99
|
+
//# sourceMappingURL=PermissionsCard.esm.js.map
|
|
@@ -0,0 +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 { Card, CardContent, makeStyles } from '@material-ui/core';\nimport CachedIcon from '@material-ui/icons/Cached';\n\nimport { policyEntityUpdatePermission } from '@backstage-community/plugin-rbac-common';\n\nimport { usePermissionPolicies } from '../../hooks/usePermissionPolicies';\nimport { PermissionsData } from '../../types';\nimport EditRole from '../EditRole';\nimport { columns } from './PermissionsListColumns';\n\nconst useStyles = makeStyles(theme => ({\n empty: {\n padding: theme.spacing(2),\n display: 'flex',\n justifyContent: 'center',\n },\n}));\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 [permissions, setPermissions] = React.useState<PermissionsData[]>();\n const permissionResult = usePermission({\n permission: policyEntityUpdatePermission,\n resourceRef: policyEntityUpdatePermission.resourceType,\n });\n const classes = useStyles();\n\n const onSearchResultsChange = (searchResults: PermissionsData[]) => {\n setPermissions(searchResults);\n };\n\n let numberOfPolicies = 0;\n (permissions || data)?.forEach(p => {\n if (p.conditions) {\n numberOfPolicies++;\n return;\n }\n numberOfPolicies =\n numberOfPolicies +\n p.policies.filter(pol => pol.effect === 'allow').length;\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 <Card>\n <CardContent>\n {error?.name && error.name !== 404 && (\n <div style={{ paddingBottom: '16px' }}>\n <WarningPanel\n message={error?.message}\n title=\"Something went wrong while fetching the permission policies\"\n severity=\"error\"\n />\n </div>\n )}\n <Table\n title={\n !loading && data.length > 0\n ? `Permission Policies (${numberOfPolicies})`\n : 'Permission Policies'\n }\n actions={actions}\n renderSummaryRow={summary => onSearchResultsChange(summary.data)}\n options={{ padding: 'default', search: true, paging: true }}\n data={data}\n columns={columns}\n isLoading={loading}\n emptyContent={\n <div data-testid=\"permission-table-empty\" className={classes.empty}>\n No records found\n </div>\n }\n />\n </CardContent>\n </Card>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { getRulesNumber } from '../../utils/create-role-utils.esm.js';
|
|
2
|
+
|
|
3
|
+
const columns = [
|
|
4
|
+
{
|
|
5
|
+
title: "Plugin",
|
|
6
|
+
field: "plugin",
|
|
7
|
+
type: "string"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
title: "Permission",
|
|
11
|
+
field: "permission",
|
|
12
|
+
type: "string"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
title: "Policies",
|
|
16
|
+
field: "policyString",
|
|
17
|
+
type: "string",
|
|
18
|
+
customSort: (a, b) => {
|
|
19
|
+
if (a.policies.length === 0) {
|
|
20
|
+
return -1;
|
|
21
|
+
}
|
|
22
|
+
if (b.policies.length === 0) {
|
|
23
|
+
return 1;
|
|
24
|
+
}
|
|
25
|
+
if (a.policies.length === b.policies.length) {
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
return a.policies.length < b.policies.length ? -1 : 1;
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
title: "Conditional",
|
|
33
|
+
field: "conditions",
|
|
34
|
+
type: "string",
|
|
35
|
+
render: (permissionsData) => {
|
|
36
|
+
const totalRules = getRulesNumber(permissionsData.conditions);
|
|
37
|
+
return totalRules ? `${totalRules} ${totalRules > 1 ? "rules" : "rule"}` : "-";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
export { columns };
|
|
43
|
+
//# sourceMappingURL=PermissionsListColumns.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PermissionsListColumns.esm.js","sources":["../../../src/components/RoleOverview/PermissionsListColumns.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 { TableColumn } from '@backstage/core-components';\n\nimport { PermissionsData } from '../../types';\nimport { getRulesNumber } from '../../utils/create-role-utils';\n\nexport const columns: TableColumn<PermissionsData>[] = [\n {\n title: 'Plugin',\n field: 'plugin',\n type: 'string',\n },\n {\n title: 'Permission',\n field: 'permission',\n type: 'string',\n },\n {\n title: 'Policies',\n field: 'policyString',\n type: 'string',\n customSort: (a, b) => {\n if (a.policies.length === 0) {\n return -1;\n }\n if (b.policies.length === 0) {\n return 1;\n }\n if (a.policies.length === b.policies.length) {\n return 0;\n }\n return a.policies.length < b.policies.length ? -1 : 1;\n },\n },\n {\n title: 'Conditional',\n field: 'conditions',\n type: 'string',\n render: (permissionsData: PermissionsData) => {\n const totalRules = getRulesNumber(permissionsData.conditions);\n return totalRules\n ? `${totalRules} ${totalRules > 1 ? 'rules' : 'rule'}`\n : '-';\n },\n },\n];\n"],"names":[],"mappings":";;AAoBO,MAAM,OAA0C,GAAA;AAAA,EACrD;AAAA,IACE,KAAO,EAAA,QAAA;AAAA,IACP,KAAO,EAAA,QAAA;AAAA,IACP,IAAM,EAAA,QAAA;AAAA,GACR;AAAA,EACA;AAAA,IACE,KAAO,EAAA,YAAA;AAAA,IACP,KAAO,EAAA,YAAA;AAAA,IACP,IAAM,EAAA,QAAA;AAAA,GACR;AAAA,EACA;AAAA,IACE,KAAO,EAAA,UAAA;AAAA,IACP,KAAO,EAAA,cAAA;AAAA,IACP,IAAM,EAAA,QAAA;AAAA,IACN,UAAA,EAAY,CAAC,CAAA,EAAG,CAAM,KAAA;AACpB,MAAI,IAAA,CAAA,CAAE,QAAS,CAAA,MAAA,KAAW,CAAG,EAAA;AAC3B,QAAO,OAAA,CAAA,CAAA,CAAA;AAAA,OACT;AACA,MAAI,IAAA,CAAA,CAAE,QAAS,CAAA,MAAA,KAAW,CAAG,EAAA;AAC3B,QAAO,OAAA,CAAA,CAAA;AAAA,OACT;AACA,MAAA,IAAI,CAAE,CAAA,QAAA,CAAS,MAAW,KAAA,CAAA,CAAE,SAAS,MAAQ,EAAA;AAC3C,QAAO,OAAA,CAAA,CAAA;AAAA,OACT;AACA,MAAA,OAAO,EAAE,QAAS,CAAA,MAAA,GAAS,CAAE,CAAA,QAAA,CAAS,SAAS,CAAK,CAAA,GAAA,CAAA,CAAA;AAAA,KACtD;AAAA,GACF;AAAA,EACA;AAAA,IACE,KAAO,EAAA,aAAA;AAAA,IACP,KAAO,EAAA,YAAA;AAAA,IACP,IAAM,EAAA,QAAA;AAAA,IACN,MAAA,EAAQ,CAAC,eAAqC,KAAA;AAC5C,MAAM,MAAA,UAAA,GAAa,cAAe,CAAA,eAAA,CAAgB,UAAU,CAAA,CAAA;AAC5D,MAAO,OAAA,UAAA,GACH,GAAG,UAAU,CAAA,CAAA,EAAI,aAAa,CAAI,GAAA,OAAA,GAAU,MAAM,CAClD,CAAA,GAAA,GAAA,CAAA;AAAA,KACN;AAAA,GACF;AACF;;;;"}
|