fix: Fix system_reader role operation permission bug

1. Fix system_reader role has operation permissions on administrator page
2. Mark TODO of supported system scope roles

Change-Id: Icd697e0b5238a25307c3d24fc6742600f892b547
This commit is contained in:
Jingwei.Zhang 2021-08-19 12:58:31 +08:00
parent ad94bb6345
commit 34c13a2dcb
11 changed files with 94 additions and 40 deletions

View File

@ -12,17 +12,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import checkItemPolicy from 'resources/policy';
import checkItemPolicy, { systemRoleIsReader } from 'resources/policy';
export async function checkAllowed(
export async function checkAllowed({
item,
policy,
allowed,
containerProps,
actionName,
extra
) {
const policyResult = checkItemPolicy(policy, item, actionName, extra);
extra,
isAdminPage,
action,
}) {
const { enableSystemReader } = action || {};
const policyResult = checkItemPolicy({
policy,
item,
actionName,
isAdminPage,
enableSystemReader,
});
if (!policyResult) {
return false;
}
@ -36,32 +45,38 @@ export async function checkAllowed(
return result;
}
export async function getAllowedResults(
export async function getAllowedResults({
actions,
data,
key,
containerProps,
extra
) {
extra,
isAdminPage,
}) {
const allowedPromises = actions.map(async (it) => {
const result = checkAllowed(
data,
key ? it[key].policy : it.policy,
key ? it[key].allowed : it.allowed,
const result = checkAllowed({
item: data,
policy: key ? it[key].policy : it.policy,
allowed: key ? it[key].allowed : it.allowed,
containerProps,
key ? it[key].title : it.title,
extra
);
actionName: key ? it[key].title : it.title,
extra,
isAdminPage,
action: it.action,
});
return result;
});
const results = await Promise.all(allowedPromises);
return results;
}
export function getPolicyResults(actions, extra) {
export function getPolicyResults({ actions, extra, isAdminPage }) {
return actions.map((it) => {
const { policy, title } = it;
const result = checkItemPolicy(policy, null, title, extra);
const { policy, title, enableSystemReader } = it;
if (isAdminPage && !enableSystemReader && systemRoleIsReader()) {
return false;
}
const result = checkItemPolicy({ policy, actionName: title, extra });
return result;
});
}
@ -76,10 +91,10 @@ export function getAction(action, item, containerProps) {
return action;
}
export function getActionsByPolicy(actions, containerProps) {
export function getActionsByPolicy({ actions, containerProps, isAdminPage }) {
const actionList = actions.map((action) =>
getAction(action, null, containerProps)
);
const policyResults = getPolicyResults(actionList);
const policyResults = getPolicyResults({ actions: actionList, isAdminPage });
return actionList.filter((it, index) => policyResults[index]);
}

View File

@ -96,12 +96,17 @@ export default function TableBatchButtons(props) {
onClickAction,
onCancelAction,
resourceName,
isAdminPage,
} = props;
let moreButton = null;
let batchButtons = null;
let showedActions = [];
let restActions = [];
const actionList = getActionsByPolicy(batchActions, containerProps);
const actionList = getActionsByPolicy({
actions: batchActions,
containerProps,
isAdminPage,
});
if (visibleButtonNumber < actionList.length) {
if (visibleButtonNumber < 0) {
restActions = actionList;

View File

@ -288,7 +288,7 @@ export default class ItemActionButtons extends Component {
}
async updateResult(item, containerProps) {
const { actions } = this.props;
const { actions, isAdminPage } = this.props;
const { actionList, firstAction, moreActions } = getActionList(
actions,
item,
@ -297,12 +297,13 @@ export default class ItemActionButtons extends Component {
this.actionList = actionList;
this.firstAction = firstAction;
this.moreActions = moreActions;
const results = await getAllowedResults(
this.actionList,
item,
'action',
containerProps
);
const results = await getAllowedResults({
actions: this.actionList,
data: item,
key: 'action',
containerProps,
isAdminPage,
});
this.setState({
results,
});

View File

@ -62,15 +62,16 @@ export default class TablePrimaryButtons extends Component {
}
async getActionsAllowed() {
const { containerProps, primaryActionsExtra } = this.props;
const { containerProps, primaryActionsExtra, isAdminPage } = this.props;
const { detail = null } = containerProps;
const results = await getAllowedResults(
this.actionList,
detail,
null,
const results = await getAllowedResults({
actions: this.actionList,
data: detail,
containerProps,
primaryActionsExtra
);
key: null,
extra: primaryActionsExtra,
isAdminPage,
});
this.setState({
primaryAllowedResults: results,
});

View File

@ -110,6 +110,7 @@ export default class BaseTable extends React.Component {
hideTotal: false,
hideDownload: false,
primaryActionsExtra: null,
isAdminPage: false,
};
constructor(props) {
@ -472,6 +473,7 @@ export default class BaseTable extends React.Component {
onClickAction,
onFinishAction,
onCancelAction,
isAdminPage,
} = this.props;
const { hideRow } = this.state;
const currentColumns = columns
@ -489,6 +491,7 @@ export default class BaseTable extends React.Component {
width: 150,
render: (text, record, index) => (
<ItemActionButtons
isAdminPage={isAdminPage}
actions={this.itemActions}
onFinishAction={onFinishAction}
onCancelAction={onCancelAction}
@ -533,6 +536,7 @@ export default class BaseTable extends React.Component {
onFinishAction,
onCancelAction,
resourceName,
isAdminPage,
} = this.props;
const selectedItems = data.filter(
(it) => selectedRowKeys.indexOf(it[rowKey]) >= 0
@ -540,6 +544,7 @@ export default class BaseTable extends React.Component {
if (batchActions) {
return (
<BatchActionButtons
isAdminPage={isAdminPage}
visibleButtonNumber={3}
selectedItemKeys={selectedRowKeys}
selectedItems={selectedItems}
@ -639,6 +644,7 @@ export default class BaseTable extends React.Component {
renderActions() {
const {
isAdminPage,
primaryActions,
containerProps,
onClickAction,
@ -649,6 +655,7 @@ export default class BaseTable extends React.Component {
if (primaryActions) {
return (
<PrimaryActionButtons
isAdminPage={isAdminPage}
primaryActions={primaryActions}
containerProps={containerProps}
onClickAction={onClickAction}

View File

@ -486,7 +486,7 @@ export default class BaseList extends React.Component {
if (this.endpointError) {
return;
}
if (!checkItemPolicy(this.policy, null, this.name)) {
if (!checkItemPolicy({ policy: this.policy, actionName: this.name })) {
const error = {
message: t("You don't have access to get {name}.", {
name: this.name.toLowerCase(),
@ -988,6 +988,7 @@ export default class BaseList extends React.Component {
hideTotal={this.hideTotal}
hideDownload={this.hideDownload}
primaryActionsExtra={this.primaryActionsExtra}
isAdminPage={this.isAdminPage}
{...this.getEnabledTableProps()}
/>
);

View File

@ -218,7 +218,7 @@ export default class DetailBase extends React.Component {
getRouteProps = () => ({});
fetchDataWithPolicy = (silent, params) => {
if (!checkItemPolicy(this.policy, null, this.name)) {
if (!checkItemPolicy({ policy: this.policy, actionName: this.name })) {
const error = {
message: t("You don't have access to get {name}.", {
name: this.name.toLowerCase(),
@ -396,6 +396,7 @@ export default class DetailBase extends React.Component {
onFinishAction={this.onFinishAction}
item={this.getActionData()}
containerProps={{ isAdminPage: this.isAdminPage }}
isAdminPage={this.isAdminPage}
// firstActionClassName={styles['attach-btn']}
/>
);

View File

@ -97,7 +97,7 @@ class BaseLayout extends Component {
if (licenseKey && !this.checkLicenseKey(licenseKey)) {
return null;
}
if (policy && !checkItemPolicy(policy)) {
if (policy && !checkItemPolicy({ policy })) {
return null;
}
if (children.length === 0) {

View File

@ -31,6 +31,8 @@ export default class View extends ModalAction {
static readOnly = true;
static enableSystemReader = true;
get name() {
return t('View');
}

View File

@ -36,11 +36,32 @@ const checkPolicyRules = (rules, every, actionName) => {
return rules.some((rule) => checkPolicyRule(rule, actionName));
};
const checkItemPolicy = (policy, item, actionName) => {
export const systemRoleIsReader = () => {
const { user: { roles = [] } = {} } = globals || {};
const readerRole = 'system_reader';
const adminRoles = ['system_admin', 'admin'];
const hasReaderRole = roles.some((it) => it.name === readerRole);
if (!hasReaderRole) {
return false;
}
const hasAdminRole = roles.some((it) => adminRoles.includes(it.name));
return hasReaderRole && !hasAdminRole;
};
const checkItemPolicy = ({
policy,
item,
actionName,
isAdminPage,
enableSystemReader,
}) => {
if (globals.policies.length === 0) {
// TODO: change to false
return true;
}
if (isAdminPage && !enableSystemReader && systemRoleIsReader()) {
return false;
}
if (!policy) {
// eslint-disable-next-line no-console
console.log('has no policy', policy, item, actionName);

View File

@ -121,7 +121,7 @@ class RootStore {
this.roles = roles;
this.baseRoles = base_roles;
this.baseDomains = base_domains;
// const adminRole = roles.find(it => it.name === 'admin');
// TODO: fix system/project admin/member/reader for W
this.hasAdminRole = checkPolicy(onlyAdminCanReadPolicy);
globals.user.hasAdminRole = this.hasAdminRole;
}