@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,149 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { IconButton } from '@material-ui/core';
|
|
3
|
+
import RemoveIcon from '@mui/icons-material/Remove';
|
|
4
|
+
import { isSimpleRule, getRowStyle, getRowKey, getSimpleRuleErrors, getNestedRuleErrors } from '../../utils/conditional-access-utils.esm.js';
|
|
5
|
+
import { ConditionsFormRowFields } from './ConditionsFormRowFields.esm.js';
|
|
6
|
+
import { criterias } from './const.esm.js';
|
|
7
|
+
|
|
8
|
+
const ComplexConditionRow = ({
|
|
9
|
+
conditionRow,
|
|
10
|
+
nestedConditionRow,
|
|
11
|
+
criteria,
|
|
12
|
+
onRuleChange,
|
|
13
|
+
updateRules,
|
|
14
|
+
setErrors,
|
|
15
|
+
setRemoveAllClicked,
|
|
16
|
+
conditionRulesData,
|
|
17
|
+
notConditionType,
|
|
18
|
+
classes,
|
|
19
|
+
currentCondition,
|
|
20
|
+
ruleIndex,
|
|
21
|
+
activeCriteria,
|
|
22
|
+
isNestedCondition = false,
|
|
23
|
+
nestedConditionIndex,
|
|
24
|
+
activeNestedCriteria
|
|
25
|
+
}) => {
|
|
26
|
+
const handleRemoveSimpleConditionRule = (index, ruleList2) => {
|
|
27
|
+
if (!activeCriteria) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const updatedSimpleRules = ruleList2.filter(
|
|
31
|
+
(_r, rindex) => index !== rindex
|
|
32
|
+
);
|
|
33
|
+
const nestedConditions = conditionRow[criteria]?.filter(
|
|
34
|
+
(con) => criterias.allOf in con || criterias.anyOf in con || criterias.not in con
|
|
35
|
+
) || [];
|
|
36
|
+
onRuleChange({
|
|
37
|
+
[activeCriteria]: [
|
|
38
|
+
...updatedSimpleRules,
|
|
39
|
+
...nestedConditions
|
|
40
|
+
]
|
|
41
|
+
});
|
|
42
|
+
setErrors((prevErrors) => {
|
|
43
|
+
const updatedErrors = { ...prevErrors };
|
|
44
|
+
if (updatedErrors[activeCriteria]) {
|
|
45
|
+
const criteriaErrors = updatedErrors[activeCriteria];
|
|
46
|
+
const simpleRuleErrors = getSimpleRuleErrors(criteriaErrors);
|
|
47
|
+
if (Array.isArray(simpleRuleErrors) && simpleRuleErrors.length > 0) {
|
|
48
|
+
const updatedCriteriaErrors = [
|
|
49
|
+
...simpleRuleErrors.filter((_, rindex) => rindex !== index),
|
|
50
|
+
...getNestedRuleErrors(criteriaErrors)
|
|
51
|
+
];
|
|
52
|
+
updatedErrors[activeCriteria] = updatedCriteriaErrors.length > 0 ? updatedCriteriaErrors : [];
|
|
53
|
+
} else {
|
|
54
|
+
delete updatedErrors[activeCriteria];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return updatedErrors;
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const handleRemoveNestedConditionRule = (nestedConditionCriteria) => {
|
|
61
|
+
const updatedNestedConditionRow = [];
|
|
62
|
+
nestedConditionRow.forEach((c, index) => {
|
|
63
|
+
if (index === nestedConditionIndex) {
|
|
64
|
+
const updatedRules = (c[nestedConditionCriteria] || []).filter((_r, rindex) => rindex !== ruleIndex);
|
|
65
|
+
updatedNestedConditionRow.push({
|
|
66
|
+
[nestedConditionCriteria]: updatedRules
|
|
67
|
+
});
|
|
68
|
+
} else {
|
|
69
|
+
updatedNestedConditionRow.push(c);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
updateRules(
|
|
73
|
+
criteria === criterias.not ? updatedNestedConditionRow[0] : updatedNestedConditionRow
|
|
74
|
+
);
|
|
75
|
+
setErrors((prevErrors) => {
|
|
76
|
+
const updatedErrors = { ...prevErrors };
|
|
77
|
+
if (updatedErrors[criteria] !== void 0) {
|
|
78
|
+
const criteriaErrors = updatedErrors[criteria];
|
|
79
|
+
if (criteria === criterias.not && notConditionType === "nested-condition") {
|
|
80
|
+
updatedErrors[criteria][nestedConditionCriteria].splice(ruleIndex, 1);
|
|
81
|
+
return updatedErrors;
|
|
82
|
+
}
|
|
83
|
+
const nestedConditionErrors = getNestedRuleErrors(criteriaErrors);
|
|
84
|
+
if (Array.isArray(nestedConditionErrors) && nestedConditionIndex !== void 0) {
|
|
85
|
+
const nestedErrors = nestedConditionErrors[nestedConditionIndex];
|
|
86
|
+
if (nestedErrors[nestedConditionCriteria]) {
|
|
87
|
+
const updatedNestedErrors = nestedErrors[nestedConditionCriteria].filter((_error, index) => index !== ruleIndex);
|
|
88
|
+
if (updatedNestedErrors.length > 0) {
|
|
89
|
+
nestedErrors[nestedConditionCriteria] = updatedNestedErrors;
|
|
90
|
+
} else {
|
|
91
|
+
delete nestedErrors[nestedConditionCriteria];
|
|
92
|
+
}
|
|
93
|
+
nestedConditionErrors[nestedConditionIndex] = nestedErrors;
|
|
94
|
+
}
|
|
95
|
+
updatedErrors[criteria] = [
|
|
96
|
+
...getSimpleRuleErrors(criteriaErrors),
|
|
97
|
+
...nestedConditionErrors
|
|
98
|
+
];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return updatedErrors;
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
const ruleList = isNestedCondition ? currentCondition[activeCriteria] : conditionRow[activeCriteria].filter(
|
|
105
|
+
(r) => isSimpleRule(r)
|
|
106
|
+
);
|
|
107
|
+
const disabled = !isNestedCondition && conditionRow[criteria].length === 1 && nestedConditionRow.length === 0 && ruleIndex === 0;
|
|
108
|
+
const nestedDisabled = isNestedCondition && nestedConditionRow[nestedConditionIndex ?? 0][activeNestedCriteria].length === 1 && ruleIndex === 0;
|
|
109
|
+
return currentCondition.resourceType && /* @__PURE__ */ React.createElement(
|
|
110
|
+
"div",
|
|
111
|
+
{
|
|
112
|
+
style: getRowStyle(currentCondition, isNestedCondition),
|
|
113
|
+
key: getRowKey(isNestedCondition, ruleIndex)
|
|
114
|
+
},
|
|
115
|
+
/* @__PURE__ */ React.createElement(
|
|
116
|
+
ConditionsFormRowFields,
|
|
117
|
+
{
|
|
118
|
+
oldCondition: currentCondition,
|
|
119
|
+
index: isNestedCondition ? void 0 : ruleIndex,
|
|
120
|
+
onRuleChange,
|
|
121
|
+
conditionRow,
|
|
122
|
+
criteria,
|
|
123
|
+
conditionRulesData,
|
|
124
|
+
setErrors,
|
|
125
|
+
setRemoveAllClicked,
|
|
126
|
+
nestedConditionRow: isNestedCondition ? nestedConditionRow : void 0,
|
|
127
|
+
nestedConditionCriteria: isNestedCondition ? activeNestedCriteria : void 0,
|
|
128
|
+
nestedConditionIndex: isNestedCondition ? nestedConditionIndex : void 0,
|
|
129
|
+
nestedConditionRuleIndex: isNestedCondition ? ruleIndex : void 0,
|
|
130
|
+
updateRules: isNestedCondition ? updateRules : void 0
|
|
131
|
+
}
|
|
132
|
+
),
|
|
133
|
+
/* @__PURE__ */ React.createElement(
|
|
134
|
+
IconButton,
|
|
135
|
+
{
|
|
136
|
+
title: "Remove",
|
|
137
|
+
className: classes.removeRuleButton,
|
|
138
|
+
disabled: isNestedCondition ? nestedDisabled : disabled,
|
|
139
|
+
onClick: isNestedCondition && activeNestedCriteria && nestedConditionIndex !== void 0 ? () => handleRemoveNestedConditionRule(activeNestedCriteria) : () => {
|
|
140
|
+
handleRemoveSimpleConditionRule(ruleIndex, ruleList);
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
/* @__PURE__ */ React.createElement(RemoveIcon, null)
|
|
144
|
+
)
|
|
145
|
+
);
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export { ComplexConditionRow };
|
|
149
|
+
//# sourceMappingURL=ComplexConditionRow.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComplexConditionRow.esm.js","sources":["../../../src/components/ConditionalAccess/ComplexConditionRow.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 { PermissionCondition } from '@backstage/plugin-permission-common';\n\nimport { IconButton } from '@material-ui/core';\nimport RemoveIcon from '@mui/icons-material/Remove';\n\nimport {\n getNestedRuleErrors,\n getRowKey,\n getRowStyle,\n getSimpleRuleErrors,\n isSimpleRule,\n} from '../../utils/conditional-access-utils';\nimport { ConditionsFormRowFields } from './ConditionsFormRowFields';\nimport { criterias } from './const';\nimport {\n AccessConditionsErrors,\n ComplexErrors,\n Condition,\n ConditionsData,\n NestedCriteriaErrors,\n NotConditionType,\n RulesData,\n} from './types';\n\ntype ComplexConditionRowProps = {\n conditionRow: ConditionsData;\n nestedConditionRow: Condition[];\n criteria: keyof ConditionsData;\n onRuleChange: (newCondition: ConditionsData) => void;\n updateRules: (updatedNestedConditionRow: Condition[] | Condition) => void;\n setErrors: React.Dispatch<\n React.SetStateAction<AccessConditionsErrors | undefined>\n >;\n setRemoveAllClicked: React.Dispatch<React.SetStateAction<boolean>>;\n conditionRulesData?: RulesData;\n notConditionType?: NotConditionType;\n classes: any;\n currentCondition: Condition;\n ruleIndex: number;\n activeCriteria?: 'allOf' | 'anyOf';\n isNestedCondition?: boolean;\n nestedConditionIndex?: number;\n activeNestedCriteria?: 'allOf' | 'anyOf';\n};\n\nexport const ComplexConditionRow = ({\n conditionRow,\n nestedConditionRow,\n criteria,\n onRuleChange,\n updateRules,\n setErrors,\n setRemoveAllClicked,\n conditionRulesData,\n notConditionType,\n classes,\n currentCondition,\n ruleIndex,\n activeCriteria,\n isNestedCondition = false,\n nestedConditionIndex,\n activeNestedCriteria,\n}: ComplexConditionRowProps) => {\n const handleRemoveSimpleConditionRule = (\n index: number,\n ruleList: PermissionCondition[],\n ) => {\n if (!activeCriteria) {\n return;\n }\n const updatedSimpleRules = ruleList.filter(\n (_r, rindex) => index !== rindex,\n );\n const nestedConditions =\n (conditionRow[criteria] as PermissionCondition[])?.filter(\n (con: PermissionCondition) =>\n criterias.allOf in con ||\n criterias.anyOf in con ||\n criterias.not in con,\n ) || [];\n\n onRuleChange({\n [activeCriteria as keyof ConditionsData]: [\n ...updatedSimpleRules,\n ...nestedConditions,\n ],\n });\n\n setErrors(prevErrors => {\n const updatedErrors = { ...prevErrors };\n\n if (updatedErrors[activeCriteria]) {\n const criteriaErrors = updatedErrors[activeCriteria] as ComplexErrors[];\n const simpleRuleErrors = getSimpleRuleErrors(criteriaErrors);\n\n if (Array.isArray(simpleRuleErrors) && simpleRuleErrors.length > 0) {\n const updatedCriteriaErrors = [\n ...simpleRuleErrors.filter((_, rindex) => rindex !== index),\n ...getNestedRuleErrors(criteriaErrors),\n ];\n\n updatedErrors[activeCriteria] =\n updatedCriteriaErrors.length > 0 ? updatedCriteriaErrors : [];\n } else {\n delete updatedErrors[activeCriteria];\n }\n }\n\n return updatedErrors;\n });\n };\n\n const handleRemoveNestedConditionRule = (nestedConditionCriteria: string) => {\n const updatedNestedConditionRow: Condition[] = [];\n\n nestedConditionRow.forEach((c, index) => {\n if (index === nestedConditionIndex) {\n const updatedRules = (\n (c[\n nestedConditionCriteria as keyof Condition\n ] as PermissionCondition[]) || []\n ).filter((_r, rindex) => rindex !== ruleIndex);\n updatedNestedConditionRow.push({\n [nestedConditionCriteria as keyof Condition]: updatedRules,\n });\n } else {\n updatedNestedConditionRow.push(c);\n }\n });\n\n updateRules(\n criteria === criterias.not\n ? updatedNestedConditionRow[0]\n : updatedNestedConditionRow,\n );\n\n setErrors(prevErrors => {\n const updatedErrors = { ...prevErrors };\n\n if (updatedErrors[criteria] !== undefined) {\n const criteriaErrors = updatedErrors[criteria] as ComplexErrors[];\n\n if (\n criteria === criterias.not &&\n notConditionType === 'nested-condition'\n ) {\n (\n (updatedErrors[criteria] as NestedCriteriaErrors)[\n nestedConditionCriteria\n ] as string[]\n ).splice(ruleIndex, 1);\n return updatedErrors;\n }\n\n const nestedConditionErrors = getNestedRuleErrors(criteriaErrors);\n\n if (\n Array.isArray(nestedConditionErrors) &&\n nestedConditionIndex !== undefined\n ) {\n const nestedErrors = nestedConditionErrors[nestedConditionIndex];\n if (nestedErrors[nestedConditionCriteria]) {\n const updatedNestedErrors = (\n nestedErrors[nestedConditionCriteria] as string[]\n ).filter((_error, index) => index !== ruleIndex);\n\n if (updatedNestedErrors.length > 0) {\n nestedErrors[nestedConditionCriteria] = updatedNestedErrors;\n } else {\n delete nestedErrors[nestedConditionCriteria];\n }\n\n nestedConditionErrors[nestedConditionIndex] = nestedErrors;\n }\n\n updatedErrors[criteria] = [\n ...getSimpleRuleErrors(criteriaErrors),\n ...nestedConditionErrors,\n ];\n }\n }\n\n return updatedErrors;\n });\n };\n\n const ruleList = isNestedCondition\n ? (currentCondition[\n activeCriteria as keyof Condition\n ] as PermissionCondition[])\n : ((conditionRow[activeCriteria as keyof Condition] as Condition[]).filter(\n r => isSimpleRule(r),\n ) as PermissionCondition[]);\n\n const disabled =\n !isNestedCondition &&\n (conditionRow[criteria as keyof Condition] as Condition[]).length === 1 &&\n nestedConditionRow.length === 0 &&\n ruleIndex === 0;\n const nestedDisabled =\n isNestedCondition &&\n (\n nestedConditionRow[nestedConditionIndex ?? 0][\n activeNestedCriteria as keyof Condition\n ] as Condition[]\n ).length === 1 &&\n ruleIndex === 0;\n\n return (\n (currentCondition as PermissionCondition).resourceType && (\n <div\n style={getRowStyle(currentCondition, isNestedCondition)}\n key={getRowKey(isNestedCondition, ruleIndex)}\n >\n <ConditionsFormRowFields\n oldCondition={currentCondition}\n index={isNestedCondition ? undefined : ruleIndex}\n onRuleChange={onRuleChange}\n conditionRow={conditionRow}\n criteria={criteria}\n conditionRulesData={conditionRulesData}\n setErrors={setErrors}\n setRemoveAllClicked={setRemoveAllClicked}\n nestedConditionRow={\n isNestedCondition ? nestedConditionRow : undefined\n }\n nestedConditionCriteria={\n isNestedCondition ? activeNestedCriteria : undefined\n }\n nestedConditionIndex={\n isNestedCondition ? nestedConditionIndex : undefined\n }\n nestedConditionRuleIndex={isNestedCondition ? ruleIndex : undefined}\n updateRules={isNestedCondition ? updateRules : undefined}\n />\n <IconButton\n title=\"Remove\"\n className={classes.removeRuleButton}\n disabled={isNestedCondition ? nestedDisabled : disabled}\n onClick={\n isNestedCondition &&\n activeNestedCriteria &&\n nestedConditionIndex !== undefined\n ? () => handleRemoveNestedConditionRule(activeNestedCriteria)\n : () => {\n handleRemoveSimpleConditionRule(ruleIndex, ruleList);\n }\n }\n >\n <RemoveIcon />\n </IconButton>\n </div>\n )\n );\n};\n"],"names":["ruleList"],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import AddIcon from '@mui/icons-material/Add';
|
|
3
|
+
import Box from '@mui/material/Box';
|
|
4
|
+
import Button from '@mui/material/Button';
|
|
5
|
+
import { getDefaultRule } from '../../utils/conditional-access-utils.esm.js';
|
|
6
|
+
import { AddNestedConditionButton } from './AddNestedConditionButton.esm.js';
|
|
7
|
+
import { criterias } from './const.esm.js';
|
|
8
|
+
|
|
9
|
+
const ComplexConditionRowButtons = ({
|
|
10
|
+
conditionRow,
|
|
11
|
+
onRuleChange,
|
|
12
|
+
criteria,
|
|
13
|
+
classes,
|
|
14
|
+
selPluginResourceType,
|
|
15
|
+
updateErrors,
|
|
16
|
+
isNestedConditionRule,
|
|
17
|
+
handleAddNestedCondition
|
|
18
|
+
}) => {
|
|
19
|
+
const findFirstNestedConditionIndex = (rules) => {
|
|
20
|
+
return rules.findIndex((e) => isNestedConditionRule(e)) || 0;
|
|
21
|
+
};
|
|
22
|
+
const handleAddRule = () => {
|
|
23
|
+
const updatedRules = [
|
|
24
|
+
...conditionRow.allOf ?? [],
|
|
25
|
+
...conditionRow.anyOf ?? []
|
|
26
|
+
];
|
|
27
|
+
const firstNestedConditionIndex = findFirstNestedConditionIndex(updatedRules);
|
|
28
|
+
if (firstNestedConditionIndex !== -1) {
|
|
29
|
+
updatedRules.splice(
|
|
30
|
+
firstNestedConditionIndex,
|
|
31
|
+
0,
|
|
32
|
+
getDefaultRule(selPluginResourceType)
|
|
33
|
+
);
|
|
34
|
+
} else {
|
|
35
|
+
updatedRules.push(getDefaultRule(selPluginResourceType));
|
|
36
|
+
}
|
|
37
|
+
onRuleChange({ [criteria]: [...updatedRules] });
|
|
38
|
+
updateErrors(firstNestedConditionIndex);
|
|
39
|
+
};
|
|
40
|
+
return (criteria === criterias.allOf || criteria === criterias.anyOf) && /* @__PURE__ */ React.createElement(Box, { mt: 1, mb: 1 }, /* @__PURE__ */ React.createElement(
|
|
41
|
+
Button,
|
|
42
|
+
{
|
|
43
|
+
className: classes.addRuleButton,
|
|
44
|
+
size: "small",
|
|
45
|
+
onClick: handleAddRule
|
|
46
|
+
},
|
|
47
|
+
/* @__PURE__ */ React.createElement(AddIcon, { fontSize: "small" }),
|
|
48
|
+
"Add rule"
|
|
49
|
+
), /* @__PURE__ */ React.createElement(
|
|
50
|
+
Button,
|
|
51
|
+
{
|
|
52
|
+
className: classes.addNestedConditionButton,
|
|
53
|
+
size: "small",
|
|
54
|
+
onClick: () => handleAddNestedCondition(criteria)
|
|
55
|
+
},
|
|
56
|
+
/* @__PURE__ */ React.createElement(AddIcon, { fontSize: "small" }),
|
|
57
|
+
/* @__PURE__ */ React.createElement(AddNestedConditionButton, null)
|
|
58
|
+
));
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export { ComplexConditionRowButtons };
|
|
62
|
+
//# sourceMappingURL=ComplexConditionRowButtons.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComplexConditionRowButtons.esm.js","sources":["../../../src/components/ConditionalAccess/ComplexConditionRowButtons.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 AddIcon from '@mui/icons-material/Add';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\n\nimport { getDefaultRule } from '../../utils/conditional-access-utils';\nimport { AddNestedConditionButton } from './AddNestedConditionButton';\nimport { criterias } from './const';\nimport { Condition, ConditionsData } from './types';\n\ntype ComplexConditionRowButtonsProps = {\n conditionRow: ConditionsData;\n onRuleChange: (newCondition: ConditionsData) => void;\n criteria: string;\n classes: any;\n selPluginResourceType: string;\n updateErrors: (_index: number) => void;\n isNestedConditionRule: (condition: Condition) => boolean;\n handleAddNestedCondition: (criteria: string) => void;\n};\n\nexport const ComplexConditionRowButtons = ({\n conditionRow,\n onRuleChange,\n criteria,\n classes,\n selPluginResourceType,\n updateErrors,\n isNestedConditionRule,\n handleAddNestedCondition,\n}: ComplexConditionRowButtonsProps) => {\n const findFirstNestedConditionIndex = (rules: Condition[]): number => {\n return rules.findIndex(e => isNestedConditionRule(e)) || 0;\n };\n const handleAddRule = () => {\n const updatedRules = [\n ...(conditionRow.allOf ?? []),\n ...(conditionRow.anyOf ?? []),\n ];\n\n const firstNestedConditionIndex =\n findFirstNestedConditionIndex(updatedRules);\n if (firstNestedConditionIndex !== -1) {\n updatedRules.splice(\n firstNestedConditionIndex,\n 0,\n getDefaultRule(selPluginResourceType),\n );\n } else {\n updatedRules.push(getDefaultRule(selPluginResourceType));\n }\n\n onRuleChange({ [criteria]: [...updatedRules] });\n updateErrors(firstNestedConditionIndex);\n };\n\n return (\n (criteria === criterias.allOf || criteria === criterias.anyOf) && (\n <Box mt={1} mb={1}>\n <Button\n className={classes.addRuleButton}\n size=\"small\"\n onClick={handleAddRule}\n >\n <AddIcon fontSize=\"small\" />\n Add rule\n </Button>\n <Button\n className={classes.addNestedConditionButton}\n size=\"small\"\n onClick={() => handleAddNestedCondition(criteria)}\n >\n <AddIcon fontSize=\"small\" />\n <AddNestedConditionButton />\n </Button>\n </Box>\n )\n );\n};\n"],"names":[],"mappings":";;;;;;;;AAqCO,MAAM,6BAA6B,CAAC;AAAA,EACzC,YAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,qBAAA;AAAA,EACA,YAAA;AAAA,EACA,qBAAA;AAAA,EACA,wBAAA;AACF,CAAuC,KAAA;AACrC,EAAM,MAAA,6BAAA,GAAgC,CAAC,KAA+B,KAAA;AACpE,IAAA,OAAO,MAAM,SAAU,CAAA,CAAA,CAAA,KAAK,qBAAsB,CAAA,CAAC,CAAC,CAAK,IAAA,CAAA,CAAA;AAAA,GAC3D,CAAA;AACA,EAAA,MAAM,gBAAgB,MAAM;AAC1B,IAAA,MAAM,YAAe,GAAA;AAAA,MACnB,GAAI,YAAa,CAAA,KAAA,IAAS,EAAC;AAAA,MAC3B,GAAI,YAAa,CAAA,KAAA,IAAS,EAAC;AAAA,KAC7B,CAAA;AAEA,IAAM,MAAA,yBAAA,GACJ,8BAA8B,YAAY,CAAA,CAAA;AAC5C,IAAA,IAAI,8BAA8B,CAAI,CAAA,EAAA;AACpC,MAAa,YAAA,CAAA,MAAA;AAAA,QACX,yBAAA;AAAA,QACA,CAAA;AAAA,QACA,eAAe,qBAAqB,CAAA;AAAA,OACtC,CAAA;AAAA,KACK,MAAA;AACL,MAAa,YAAA,CAAA,IAAA,CAAK,cAAe,CAAA,qBAAqB,CAAC,CAAA,CAAA;AAAA,KACzD;AAEA,IAAa,YAAA,CAAA,EAAE,CAAC,QAAQ,GAAG,CAAC,GAAG,YAAY,GAAG,CAAA,CAAA;AAC9C,IAAA,YAAA,CAAa,yBAAyB,CAAA,CAAA;AAAA,GACxC,CAAA;AAEA,EACG,OAAA,CAAA,QAAA,KAAa,SAAU,CAAA,KAAA,IAAS,QAAa,KAAA,SAAA,CAAU,KACtD,qBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,EAAA,EAAI,CAAG,EAAA,EAAA,EAAI,CACd,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,WAAW,OAAQ,CAAA,aAAA;AAAA,MACnB,IAAK,EAAA,OAAA;AAAA,MACL,OAAS,EAAA,aAAA;AAAA,KAAA;AAAA,oBAET,KAAA,CAAA,aAAA,CAAC,OAAQ,EAAA,EAAA,QAAA,EAAS,OAAQ,EAAA,CAAA;AAAA,IAAE,UAAA;AAAA,GAG9B,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,WAAW,OAAQ,CAAA,wBAAA;AAAA,MACnB,IAAK,EAAA,OAAA;AAAA,MACL,OAAA,EAAS,MAAM,wBAAA,CAAyB,QAAQ,CAAA;AAAA,KAAA;AAAA,oBAEhD,KAAA,CAAA,aAAA,CAAC,OAAQ,EAAA,EAAA,QAAA,EAAS,OAAQ,EAAA,CAAA;AAAA,wCACzB,wBAAyB,EAAA,IAAA,CAAA;AAAA,GAE9B,CAAA,CAAA;AAGN;;;;"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { getDefaultRule, ruleOptionDisabled } from '../../utils/conditional-access-utils.esm.js';
|
|
3
|
+
import { ConditionsFormRowFields } from './ConditionsFormRowFields.esm.js';
|
|
4
|
+
import { criterias } from './const.esm.js';
|
|
5
|
+
|
|
6
|
+
const ConditionRule = ({
|
|
7
|
+
conditionRow,
|
|
8
|
+
selPluginResourceType,
|
|
9
|
+
onRuleChange,
|
|
10
|
+
criteria,
|
|
11
|
+
conditionRulesData,
|
|
12
|
+
setErrors,
|
|
13
|
+
setRemoveAllClicked
|
|
14
|
+
}) => {
|
|
15
|
+
return criteria === criterias.condition && /* @__PURE__ */ React.createElement(
|
|
16
|
+
ConditionsFormRowFields,
|
|
17
|
+
{
|
|
18
|
+
oldCondition: conditionRow.condition ?? getDefaultRule(selPluginResourceType),
|
|
19
|
+
onRuleChange,
|
|
20
|
+
conditionRow,
|
|
21
|
+
criteria,
|
|
22
|
+
conditionRulesData,
|
|
23
|
+
setErrors,
|
|
24
|
+
optionDisabled: (ruleOption) => ruleOptionDisabled(
|
|
25
|
+
ruleOption,
|
|
26
|
+
conditionRow.condition ? [conditionRow.condition] : void 0
|
|
27
|
+
),
|
|
28
|
+
setRemoveAllClicked
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export { ConditionRule };
|
|
34
|
+
//# sourceMappingURL=ConditionRule.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConditionRule.esm.js","sources":["../../../src/components/ConditionalAccess/ConditionRule.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 getDefaultRule,\n ruleOptionDisabled,\n} from '../../utils/conditional-access-utils';\nimport { ConditionsFormRowFields } from './ConditionsFormRowFields';\nimport { criterias } from './const';\nimport { AccessConditionsErrors, ConditionsData, RulesData } from './types';\n\ntype ConditionRuleProps = {\n conditionRow: ConditionsData;\n selPluginResourceType: string;\n onRuleChange: (newCondition: ConditionsData) => void;\n criteria: string;\n conditionRulesData?: RulesData;\n setErrors: React.Dispatch<\n React.SetStateAction<AccessConditionsErrors | undefined>\n >;\n setRemoveAllClicked: React.Dispatch<React.SetStateAction<boolean>>;\n};\n\nexport const ConditionRule = ({\n conditionRow,\n selPluginResourceType,\n onRuleChange,\n criteria,\n conditionRulesData,\n setErrors,\n setRemoveAllClicked,\n}: ConditionRuleProps) => {\n return (\n criteria === criterias.condition && (\n <ConditionsFormRowFields\n oldCondition={\n conditionRow.condition ?? getDefaultRule(selPluginResourceType)\n }\n onRuleChange={onRuleChange}\n conditionRow={conditionRow}\n criteria={criteria}\n conditionRulesData={conditionRulesData}\n setErrors={setErrors}\n optionDisabled={ruleOption =>\n ruleOptionDisabled(\n ruleOption,\n conditionRow.condition ? [conditionRow.condition] : undefined,\n )\n }\n setRemoveAllClicked={setRemoveAllClicked}\n />\n )\n );\n};\n"],"names":[],"mappings":";;;;;AAqCO,MAAM,gBAAgB,CAAC;AAAA,EAC5B,YAAA;AAAA,EACA,qBAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,kBAAA;AAAA,EACA,SAAA;AAAA,EACA,mBAAA;AACF,CAA0B,KAAA;AACxB,EACE,OAAA,QAAA,KAAa,UAAU,SACrB,oBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,uBAAA;AAAA,IAAA;AAAA,MACC,YACE,EAAA,YAAA,CAAa,SAAa,IAAA,cAAA,CAAe,qBAAqB,CAAA;AAAA,MAEhE,YAAA;AAAA,MACA,YAAA;AAAA,MACA,QAAA;AAAA,MACA,kBAAA;AAAA,MACA,SAAA;AAAA,MACA,gBAAgB,CACd,UAAA,KAAA,kBAAA;AAAA,QACE,UAAA;AAAA,QACA,YAAa,CAAA,SAAA,GAAY,CAAC,YAAA,CAAa,SAAS,CAAI,GAAA,KAAA,CAAA;AAAA,OACtD;AAAA,MAEF,mBAAA;AAAA,KAAA;AAAA,GACF,CAAA;AAGN;;;;"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { makeStyles } from '@material-ui/core';
|
|
3
|
+
import Drawer from '@material-ui/core/Drawer';
|
|
4
|
+
import CloseIcon from '@mui/icons-material/Close';
|
|
5
|
+
import Box from '@mui/material/Box';
|
|
6
|
+
import IconButton from '@mui/material/IconButton';
|
|
7
|
+
import Typography from '@mui/material/Typography';
|
|
8
|
+
import { ConditionsForm } from './ConditionsForm.esm.js';
|
|
9
|
+
|
|
10
|
+
const useDrawerStyles = makeStyles(() => ({
|
|
11
|
+
paper: {
|
|
12
|
+
["@media (max-width: 960px)"]: {
|
|
13
|
+
width: "-webkit-fill-available"
|
|
14
|
+
},
|
|
15
|
+
width: "50vw",
|
|
16
|
+
height: "100vh",
|
|
17
|
+
gap: "3%",
|
|
18
|
+
display: "-webkit-inline-box"
|
|
19
|
+
}
|
|
20
|
+
}));
|
|
21
|
+
const useDrawerContentStyles = makeStyles((theme) => ({
|
|
22
|
+
sidebar: {
|
|
23
|
+
display: "flex",
|
|
24
|
+
flexFlow: "column",
|
|
25
|
+
justifyContent: "space-between",
|
|
26
|
+
backgroundColor: `${theme.palette.background.default} !important`
|
|
27
|
+
},
|
|
28
|
+
header: {
|
|
29
|
+
display: "flex",
|
|
30
|
+
flexDirection: "row",
|
|
31
|
+
justifyContent: "space-between",
|
|
32
|
+
alignItems: "baseline",
|
|
33
|
+
padding: theme.spacing(2.5),
|
|
34
|
+
fontFamily: theme.typography.fontFamily
|
|
35
|
+
},
|
|
36
|
+
headerSubtitle: {
|
|
37
|
+
fontWeight: 400,
|
|
38
|
+
fontFamily: theme.typography.fontFamily,
|
|
39
|
+
paddingTop: theme.spacing(1)
|
|
40
|
+
}
|
|
41
|
+
}));
|
|
42
|
+
const ConditionalAccessSidebar = ({
|
|
43
|
+
open,
|
|
44
|
+
onClose,
|
|
45
|
+
onSave,
|
|
46
|
+
selPluginResourceType,
|
|
47
|
+
conditionRulesData,
|
|
48
|
+
conditionsFormVal
|
|
49
|
+
}) => {
|
|
50
|
+
const classes = useDrawerStyles();
|
|
51
|
+
const contentClasses = useDrawerContentStyles();
|
|
52
|
+
return /* @__PURE__ */ React.createElement(
|
|
53
|
+
Drawer,
|
|
54
|
+
{
|
|
55
|
+
anchor: "right",
|
|
56
|
+
open,
|
|
57
|
+
"data-testid": "rules-sidebar",
|
|
58
|
+
classes: {
|
|
59
|
+
paper: classes.paper
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
/* @__PURE__ */ React.createElement(Box, { className: contentClasses.sidebar }, /* @__PURE__ */ React.createElement(Box, { className: contentClasses.header }, /* @__PURE__ */ React.createElement(Typography, { variant: "h5" }, /* @__PURE__ */ React.createElement(Typography, { component: "span", sx: { fontWeight: 500 } }, "Configure access for the"), " ", selPluginResourceType, /* @__PURE__ */ React.createElement(
|
|
63
|
+
Typography,
|
|
64
|
+
{
|
|
65
|
+
variant: "body2",
|
|
66
|
+
className: contentClasses.headerSubtitle,
|
|
67
|
+
align: "left"
|
|
68
|
+
},
|
|
69
|
+
"By default, the selected resource type will be visible to the chosen users in step two. If you want to restrict or grant permission to specific plugin resource type rule, select it and add the required parameters."
|
|
70
|
+
)), /* @__PURE__ */ React.createElement(
|
|
71
|
+
IconButton,
|
|
72
|
+
{
|
|
73
|
+
key: "dismiss",
|
|
74
|
+
title: "Close the drawer",
|
|
75
|
+
onClick: onClose,
|
|
76
|
+
color: "inherit"
|
|
77
|
+
},
|
|
78
|
+
/* @__PURE__ */ React.createElement(CloseIcon, { fontSize: "small" })
|
|
79
|
+
)), /* @__PURE__ */ React.createElement(
|
|
80
|
+
ConditionsForm,
|
|
81
|
+
{
|
|
82
|
+
conditionRulesData,
|
|
83
|
+
selPluginResourceType,
|
|
84
|
+
conditionsFormVal,
|
|
85
|
+
onClose,
|
|
86
|
+
onSave
|
|
87
|
+
}
|
|
88
|
+
))
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export { ConditionalAccessSidebar };
|
|
93
|
+
//# sourceMappingURL=ConditionalAccessSidebar.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConditionalAccessSidebar.esm.js","sources":["../../../src/components/ConditionalAccess/ConditionalAccessSidebar.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 { makeStyles } from '@material-ui/core';\nimport Drawer from '@material-ui/core/Drawer';\nimport CloseIcon from '@mui/icons-material/Close';\nimport Box from '@mui/material/Box';\nimport IconButton from '@mui/material/IconButton';\nimport Typography from '@mui/material/Typography';\n\nimport { ConditionsForm } from './ConditionsForm';\nimport { ConditionsData, RulesData } from './types';\n\nconst useDrawerStyles = makeStyles(() => ({\n paper: {\n ['@media (max-width: 960px)']: {\n width: '-webkit-fill-available',\n },\n width: '50vw',\n height: '100vh',\n gap: '3%',\n display: '-webkit-inline-box',\n },\n}));\n\nconst useDrawerContentStyles = makeStyles(theme => ({\n sidebar: {\n display: 'flex',\n flexFlow: 'column',\n justifyContent: 'space-between',\n backgroundColor: `${theme.palette.background.default} !important`,\n },\n header: {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'baseline',\n padding: theme.spacing(2.5),\n fontFamily: theme.typography.fontFamily,\n },\n headerSubtitle: {\n fontWeight: 400,\n fontFamily: theme.typography.fontFamily,\n paddingTop: theme.spacing(1),\n },\n}));\n\ntype ConditionalAccessSidebarProps = {\n open: boolean;\n onClose: () => void;\n onSave: (conditions?: ConditionsData) => void;\n selPluginResourceType: string;\n conditionRulesData?: RulesData;\n conditionsFormVal?: ConditionsData;\n};\n\nexport const ConditionalAccessSidebar = ({\n open,\n onClose,\n onSave,\n selPluginResourceType,\n conditionRulesData,\n conditionsFormVal,\n}: ConditionalAccessSidebarProps) => {\n const classes = useDrawerStyles();\n const contentClasses = useDrawerContentStyles();\n return (\n <Drawer\n anchor=\"right\"\n open={open}\n data-testid=\"rules-sidebar\"\n classes={{\n paper: classes.paper,\n }}\n >\n <Box className={contentClasses.sidebar}>\n <Box className={contentClasses.header}>\n <Typography variant=\"h5\">\n <Typography component=\"span\" sx={{ fontWeight: 500 }}>\n Configure access for the\n </Typography>{' '}\n {selPluginResourceType}\n <Typography\n variant=\"body2\"\n className={contentClasses.headerSubtitle}\n align=\"left\"\n >\n By default, the selected resource type will be visible to the\n chosen users in step two. If you want to restrict or grant\n permission to specific plugin resource type rule, select it and\n add the required parameters.\n </Typography>\n </Typography>\n <IconButton\n key=\"dismiss\"\n title=\"Close the drawer\"\n onClick={onClose}\n color=\"inherit\"\n >\n <CloseIcon fontSize=\"small\" />\n </IconButton>\n </Box>\n <ConditionsForm\n conditionRulesData={conditionRulesData}\n selPluginResourceType={selPluginResourceType}\n conditionsFormVal={conditionsFormVal}\n onClose={onClose}\n onSave={onSave}\n />\n </Box>\n </Drawer>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { makeStyles, Box, Button } from '@material-ui/core';
|
|
3
|
+
import { Alert, AlertTitle } from '@material-ui/lab';
|
|
4
|
+
import WarningIcon from '@mui/icons-material/Warning';
|
|
5
|
+
import { initializeErrors, resetErrors, isSimpleRule, hasSimpleConditionOrNotErrors, hasNestedNotErrors, hasAllOfOrAnyOfErrors } from '../../utils/conditional-access-utils.esm.js';
|
|
6
|
+
import { ConditionsFormRow } from './ConditionsFormRow.esm.js';
|
|
7
|
+
import { criterias } from './const.esm.js';
|
|
8
|
+
|
|
9
|
+
const useStyles = makeStyles((theme) => ({
|
|
10
|
+
form: {
|
|
11
|
+
padding: theme.spacing(2.5),
|
|
12
|
+
paddingTop: 0,
|
|
13
|
+
flexGrow: 1,
|
|
14
|
+
overflow: "auto"
|
|
15
|
+
},
|
|
16
|
+
addConditionButton: {
|
|
17
|
+
color: theme.palette.primary.light
|
|
18
|
+
},
|
|
19
|
+
footer: {
|
|
20
|
+
display: "flex",
|
|
21
|
+
flexDirection: "row",
|
|
22
|
+
gap: "15px",
|
|
23
|
+
alignItems: "baseline",
|
|
24
|
+
borderTop: `2px solid ${theme.palette.border}`,
|
|
25
|
+
padding: theme.spacing(2.5),
|
|
26
|
+
"& button": {
|
|
27
|
+
textTransform: "none"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}));
|
|
31
|
+
const ConditionsForm = ({
|
|
32
|
+
conditionRulesData,
|
|
33
|
+
selPluginResourceType,
|
|
34
|
+
conditionsFormVal,
|
|
35
|
+
onClose,
|
|
36
|
+
onSave
|
|
37
|
+
}) => {
|
|
38
|
+
const classes = useStyles();
|
|
39
|
+
const [conditions, setConditions] = React.useState(
|
|
40
|
+
conditionsFormVal ?? {
|
|
41
|
+
condition: {
|
|
42
|
+
rule: "",
|
|
43
|
+
resourceType: selPluginResourceType,
|
|
44
|
+
params: {}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
const [criteria, setCriteria] = React.useState(
|
|
49
|
+
Object.keys(conditions)[0] ?? criterias.condition
|
|
50
|
+
);
|
|
51
|
+
const [errors, setErrors] = React.useState(initializeErrors(criteria, conditions));
|
|
52
|
+
const [removeAllClicked, setRemoveAllClicked] = React.useState(false);
|
|
53
|
+
const flattenConditions = (conditionData) => {
|
|
54
|
+
const flatConditions = [];
|
|
55
|
+
const processCondition = (condition) => {
|
|
56
|
+
if ("rule" in condition) {
|
|
57
|
+
flatConditions.push(condition);
|
|
58
|
+
} else {
|
|
59
|
+
if (condition.allOf) {
|
|
60
|
+
condition.allOf.forEach(processCondition);
|
|
61
|
+
}
|
|
62
|
+
if (condition.anyOf) {
|
|
63
|
+
condition.anyOf.forEach(processCondition);
|
|
64
|
+
}
|
|
65
|
+
if (condition.not) {
|
|
66
|
+
if ("rule" in condition.not) {
|
|
67
|
+
flatConditions.push(condition.not);
|
|
68
|
+
} else {
|
|
69
|
+
processCondition(condition.not);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
conditionData.forEach(processCondition);
|
|
75
|
+
return flatConditions;
|
|
76
|
+
};
|
|
77
|
+
const isNoRuleSelected = () => {
|
|
78
|
+
switch (criteria) {
|
|
79
|
+
case criterias.condition:
|
|
80
|
+
return !conditions.condition?.rule;
|
|
81
|
+
case criterias.not: {
|
|
82
|
+
const flatConditions = flattenConditions([
|
|
83
|
+
conditions.not
|
|
84
|
+
]);
|
|
85
|
+
return flatConditions.some((c) => !c.rule);
|
|
86
|
+
}
|
|
87
|
+
case criterias.allOf: {
|
|
88
|
+
const flatConditions = flattenConditions(conditions.allOf || []);
|
|
89
|
+
return flatConditions.some((c) => !c.rule);
|
|
90
|
+
}
|
|
91
|
+
case criterias.anyOf: {
|
|
92
|
+
const flatConditions = flattenConditions(conditions.anyOf || []);
|
|
93
|
+
return flatConditions.some((c) => !c.rule);
|
|
94
|
+
}
|
|
95
|
+
default:
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const hasAnyErrors = () => {
|
|
100
|
+
if (!errors) return false;
|
|
101
|
+
if (criteria === criterias.condition || criteria === criterias.not && isSimpleRule(conditions[criteria])) {
|
|
102
|
+
return hasSimpleConditionOrNotErrors(errors, criteria);
|
|
103
|
+
}
|
|
104
|
+
if (criteria === criterias.not && !isSimpleRule(conditions[criteria])) {
|
|
105
|
+
return hasNestedNotErrors(errors, conditions, criteria);
|
|
106
|
+
}
|
|
107
|
+
if (criteria === criterias.allOf || criteria === criterias.anyOf) {
|
|
108
|
+
return hasAllOfOrAnyOfErrors(errors, criteria);
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
};
|
|
112
|
+
const isSaveDisabled = () => {
|
|
113
|
+
if (removeAllClicked) return false;
|
|
114
|
+
return hasAnyErrors() || isNoRuleSelected() || Object.is(conditionsFormVal, conditions);
|
|
115
|
+
};
|
|
116
|
+
const hasMultiLevelNestedConditions = () => {
|
|
117
|
+
if (!Array.isArray(conditions[criteria])) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
return conditions[criteria].filter((condition) => !("rule" in condition)).some((firstLevelNestedCondition) => {
|
|
121
|
+
const nestedConditionCriteria = Object.keys(
|
|
122
|
+
firstLevelNestedCondition
|
|
123
|
+
)[0];
|
|
124
|
+
if (Array.isArray(
|
|
125
|
+
firstLevelNestedCondition[nestedConditionCriteria]
|
|
126
|
+
)) {
|
|
127
|
+
return firstLevelNestedCondition[nestedConditionCriteria].some((con) => !("rule" in con));
|
|
128
|
+
}
|
|
129
|
+
return !Object.keys(
|
|
130
|
+
firstLevelNestedCondition[nestedConditionCriteria]
|
|
131
|
+
).includes("rule");
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { className: classes.form }, /* @__PURE__ */ React.createElement(
|
|
135
|
+
ConditionsFormRow,
|
|
136
|
+
{
|
|
137
|
+
conditionRulesData,
|
|
138
|
+
conditionRow: conditions,
|
|
139
|
+
criteria,
|
|
140
|
+
selPluginResourceType,
|
|
141
|
+
onRuleChange: (newCondition) => setConditions(newCondition),
|
|
142
|
+
setCriteria,
|
|
143
|
+
setErrors,
|
|
144
|
+
setRemoveAllClicked
|
|
145
|
+
}
|
|
146
|
+
), hasMultiLevelNestedConditions() && /* @__PURE__ */ React.createElement(
|
|
147
|
+
Alert,
|
|
148
|
+
{
|
|
149
|
+
icon: /* @__PURE__ */ React.createElement(WarningIcon, null),
|
|
150
|
+
style: { margin: "1.5rem 0 1rem 0" },
|
|
151
|
+
severity: "warning",
|
|
152
|
+
"data-testid": "multi-level-nested-conditions-warning"
|
|
153
|
+
},
|
|
154
|
+
/* @__PURE__ */ React.createElement(AlertTitle, { "data-testid": "multi-level-nested-conditions-warning-title" }, "Multiple levels of nested conditions are not supported"),
|
|
155
|
+
"Only one level is displayed. Please use the CLI to view all nested conditions."
|
|
156
|
+
)), /* @__PURE__ */ React.createElement(Box, { className: classes.footer }, /* @__PURE__ */ React.createElement(
|
|
157
|
+
Button,
|
|
158
|
+
{
|
|
159
|
+
variant: "contained",
|
|
160
|
+
color: "primary",
|
|
161
|
+
"data-testid": "save-conditions",
|
|
162
|
+
disabled: isSaveDisabled(),
|
|
163
|
+
onClick: () => {
|
|
164
|
+
if (removeAllClicked) {
|
|
165
|
+
onSave(void 0);
|
|
166
|
+
} else onSave(conditions);
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"Save"
|
|
170
|
+
), /* @__PURE__ */ React.createElement(
|
|
171
|
+
Button,
|
|
172
|
+
{
|
|
173
|
+
variant: "outlined",
|
|
174
|
+
color: "primary",
|
|
175
|
+
onClick: onClose,
|
|
176
|
+
"data-testid": "cancel-conditions"
|
|
177
|
+
},
|
|
178
|
+
"Cancel"
|
|
179
|
+
), /* @__PURE__ */ React.createElement(
|
|
180
|
+
Button,
|
|
181
|
+
{
|
|
182
|
+
variant: "text",
|
|
183
|
+
color: "primary",
|
|
184
|
+
disabled: removeAllClicked || isNoRuleSelected(),
|
|
185
|
+
onClick: () => {
|
|
186
|
+
setRemoveAllClicked(true);
|
|
187
|
+
setCriteria(criterias.condition);
|
|
188
|
+
setConditions({
|
|
189
|
+
condition: {
|
|
190
|
+
rule: "",
|
|
191
|
+
resourceType: selPluginResourceType,
|
|
192
|
+
params: {}
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
setErrors(resetErrors(criterias.condition));
|
|
196
|
+
},
|
|
197
|
+
"data-testid": "remove-conditions"
|
|
198
|
+
},
|
|
199
|
+
"Remove all"
|
|
200
|
+
)));
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
export { ConditionsForm };
|
|
204
|
+
//# sourceMappingURL=ConditionsForm.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConditionsForm.esm.js","sources":["../../../src/components/ConditionalAccess/ConditionsForm.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 { PermissionCondition } from '@backstage/plugin-permission-common';\n\nimport { Box, Button, makeStyles } from '@material-ui/core';\nimport { Alert, AlertTitle } from '@material-ui/lab';\nimport WarningIcon from '@mui/icons-material/Warning';\n\nimport {\n hasAllOfOrAnyOfErrors,\n hasNestedNotErrors,\n hasSimpleConditionOrNotErrors,\n initializeErrors,\n isSimpleRule,\n resetErrors,\n} from '../../utils/conditional-access-utils';\nimport { ConditionsFormRow } from './ConditionsFormRow';\nimport { criterias } from './const';\nimport {\n AccessConditionsErrors,\n Condition,\n ConditionsData,\n RulesData,\n} from './types';\n\nconst useStyles = makeStyles(theme => ({\n form: {\n padding: theme.spacing(2.5),\n paddingTop: 0,\n flexGrow: 1,\n overflow: 'auto',\n },\n addConditionButton: {\n color: theme.palette.primary.light,\n },\n footer: {\n display: 'flex',\n flexDirection: 'row',\n gap: '15px',\n alignItems: 'baseline',\n borderTop: `2px solid ${theme.palette.border}`,\n padding: theme.spacing(2.5),\n '& button': {\n textTransform: 'none',\n },\n },\n}));\n\ntype ConditionFormProps = {\n conditionRulesData?: RulesData;\n conditionsFormVal?: ConditionsData;\n selPluginResourceType: string;\n onClose: () => void;\n onSave: (conditions?: ConditionsData) => void;\n};\n\nexport const ConditionsForm = ({\n conditionRulesData,\n selPluginResourceType,\n conditionsFormVal,\n onClose,\n onSave,\n}: ConditionFormProps) => {\n const classes = useStyles();\n const [conditions, setConditions] = React.useState<ConditionsData>(\n conditionsFormVal ?? {\n condition: {\n rule: '',\n resourceType: selPluginResourceType,\n params: {},\n },\n },\n );\n const [criteria, setCriteria] = React.useState<keyof ConditionsData>(\n (Object.keys(conditions)[0] as keyof ConditionsData) ?? criterias.condition,\n );\n const [errors, setErrors] = React.useState<\n AccessConditionsErrors | undefined\n >(initializeErrors(criteria, conditions));\n\n const [removeAllClicked, setRemoveAllClicked] =\n React.useState<boolean>(false);\n\n const flattenConditions = (\n conditionData: Condition[],\n ): PermissionCondition[] => {\n const flatConditions: PermissionCondition[] = [];\n\n const processCondition = (condition: Condition) => {\n if ('rule' in condition) {\n flatConditions.push(condition);\n } else {\n if (condition.allOf) {\n condition.allOf.forEach(processCondition);\n }\n if (condition.anyOf) {\n condition.anyOf.forEach(processCondition);\n }\n if (condition.not) {\n if ('rule' in condition.not) {\n flatConditions.push(condition.not);\n } else {\n processCondition(condition.not);\n }\n }\n }\n };\n conditionData.forEach(processCondition);\n return flatConditions;\n };\n\n const isNoRuleSelected = () => {\n switch (criteria) {\n case criterias.condition:\n return !conditions.condition?.rule;\n case criterias.not: {\n const flatConditions = flattenConditions([\n conditions.not as PermissionCondition,\n ]);\n return flatConditions.some(c => !c.rule);\n }\n case criterias.allOf: {\n const flatConditions = flattenConditions(conditions.allOf || []);\n return flatConditions.some(c => !c.rule);\n }\n case criterias.anyOf: {\n const flatConditions = flattenConditions(conditions.anyOf || []);\n return flatConditions.some(c => !c.rule);\n }\n default:\n return true;\n }\n };\n\n const hasAnyErrors = (): boolean => {\n if (!errors) return false;\n\n if (\n criteria === criterias.condition ||\n (criteria === criterias.not &&\n isSimpleRule(conditions[criteria] as Condition))\n ) {\n return hasSimpleConditionOrNotErrors(errors, criteria);\n }\n\n if (\n criteria === criterias.not &&\n !isSimpleRule(conditions[criteria] as Condition)\n ) {\n return hasNestedNotErrors(errors, conditions, criteria);\n }\n\n if (criteria === criterias.allOf || criteria === criterias.anyOf) {\n return hasAllOfOrAnyOfErrors(errors, criteria);\n }\n\n return false;\n };\n\n const isSaveDisabled = () => {\n if (removeAllClicked) return false;\n\n return (\n hasAnyErrors() ||\n isNoRuleSelected() ||\n Object.is(conditionsFormVal, conditions)\n );\n };\n\n const hasMultiLevelNestedConditions = (): boolean => {\n if (!Array.isArray(conditions[criteria])) {\n return false;\n }\n\n return (conditions[criteria] as Condition[])\n .filter(condition => !('rule' in condition))\n .some((firstLevelNestedCondition: Condition) => {\n const nestedConditionCriteria = Object.keys(\n firstLevelNestedCondition,\n )[0];\n if (\n Array.isArray(\n firstLevelNestedCondition[\n nestedConditionCriteria as keyof Condition\n ],\n )\n ) {\n return (\n firstLevelNestedCondition[\n nestedConditionCriteria as keyof Condition\n ] as Condition[]\n ).some((con: Condition) => !('rule' in con));\n }\n\n return !Object.keys(\n firstLevelNestedCondition[\n nestedConditionCriteria as keyof Condition\n ] as Condition[],\n ).includes('rule');\n });\n };\n\n return (\n <>\n <Box className={classes.form}>\n <ConditionsFormRow\n conditionRulesData={conditionRulesData}\n conditionRow={conditions}\n criteria={criteria}\n selPluginResourceType={selPluginResourceType}\n onRuleChange={newCondition => setConditions(newCondition)}\n setCriteria={setCriteria}\n setErrors={setErrors}\n setRemoveAllClicked={setRemoveAllClicked}\n />\n {hasMultiLevelNestedConditions() && (\n <Alert\n icon={<WarningIcon />}\n style={{ margin: '1.5rem 0 1rem 0' }}\n severity=\"warning\"\n data-testid=\"multi-level-nested-conditions-warning\"\n >\n <AlertTitle data-testid=\"multi-level-nested-conditions-warning-title\">\n Multiple levels of nested conditions are not supported\n </AlertTitle>\n Only one level is displayed. Please use the CLI to view all nested\n conditions.\n </Alert>\n )}\n </Box>\n <Box className={classes.footer}>\n <Button\n variant=\"contained\"\n color=\"primary\"\n data-testid=\"save-conditions\"\n disabled={isSaveDisabled()}\n onClick={() => {\n if (removeAllClicked) {\n onSave(undefined);\n } else onSave(conditions);\n }}\n >\n Save\n </Button>\n <Button\n variant=\"outlined\"\n color=\"primary\"\n onClick={onClose}\n data-testid=\"cancel-conditions\"\n >\n Cancel\n </Button>\n <Button\n variant=\"text\"\n color=\"primary\"\n disabled={removeAllClicked || isNoRuleSelected()}\n onClick={() => {\n setRemoveAllClicked(true);\n setCriteria(criterias.condition);\n setConditions({\n condition: {\n rule: '',\n resourceType: selPluginResourceType,\n params: {},\n },\n });\n setErrors(resetErrors(criterias.condition));\n }}\n data-testid=\"remove-conditions\"\n >\n Remove all\n </Button>\n </Box>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|