From 083e44a4019a943a2ff267c568fbec7ccec9857b Mon Sep 17 00:00:00 2001 From: "Jingwei.Zhang" Date: Mon, 6 Jun 2022 16:46:35 +0800 Subject: [PATCH] feat: Support role actions Support create/edit/delete role Change-Id: Ib8c71b2bb193b061ad6db397727fef0129f3bc44 --- src/locales/en.json | 4 ++ src/locales/zh.json | 4 ++ .../containers/Role/actions/Create.jsx | 60 +++++++++++++++++ .../containers/Role/actions/Delete.jsx | 48 +++++++++++++ .../identity/containers/Role/actions/Edit.jsx | 67 +++++++++++++++++++ .../containers/Role/actions/index.jsx | 32 +++++++++ src/pages/identity/containers/Role/index.jsx | 9 +-- src/resources/keystone/role.js | 8 +++ src/stores/keystone/role.js | 28 ++++++++ .../integration/pages/identity/role.spec.js | 2 +- 10 files changed, 257 insertions(+), 5 deletions(-) create mode 100644 src/pages/identity/containers/Role/actions/Create.jsx create mode 100644 src/pages/identity/containers/Role/actions/Delete.jsx create mode 100644 src/pages/identity/containers/Role/actions/Edit.jsx create mode 100644 src/pages/identity/containers/Role/actions/index.jsx diff --git a/src/locales/en.json b/src/locales/en.json index 2f45609d..dc9274d4 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -484,6 +484,7 @@ "Create Project": "Create Project", "Create QoS Policy": "Create QoS Policy", "Create QoS Spec": "Create QoS Spec", + "Create Role": "Create Role", "Create Router": "Create Router", "Create Rule": "Create Rule", "Create Security Group": "Create Security Group", @@ -638,6 +639,7 @@ "Delete Project": "Delete Project", "Delete QoS Policy": "Delete QoS Policy", "Delete QoS Spec": "Delete QoS Spec", + "Delete Role": "Delete Role", "Delete Router": "Delete Router", "Delete Rule": "Delete Rule", "Delete Security Group": "Delete Security Group", @@ -782,6 +784,7 @@ "Edit Project": "Edit Project", "Edit QoS Policy": "Edit QoS Policy", "Edit Quota": "Edit Quota", + "Edit Role": "Edit Role", "Edit Router": "Edit Router", "Edit Rule": "Edit Rule", "Edit Share Metadata": "Edit Share Metadata", @@ -2592,6 +2595,7 @@ "delete network": "delete network", "delete project": "delete project", "delete qos policy": "delete qos policy", + "delete role": "delete role", "delete router": "delete router", "delete snapshot": "delete snapshot", "delete stack": "delete stack", diff --git a/src/locales/zh.json b/src/locales/zh.json index 8a98c922..0880a8af 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -484,6 +484,7 @@ "Create Project": "创建项目", "Create QoS Policy": "创建QoS策略", "Create QoS Spec": "创建QoS规格", + "Create Role": "创建角色", "Create Router": "创建路由器", "Create Rule": "创建规则", "Create Security Group": "创建安全组", @@ -638,6 +639,7 @@ "Delete Project": "删除项目", "Delete QoS Policy": "删除QoS策略", "Delete QoS Spec": "删除QoS规格", + "Delete Role": "删除角色", "Delete Router": "删除路由器", "Delete Rule": "删除规则", "Delete Security Group": "删除安全组", @@ -782,6 +784,7 @@ "Edit Project": "编辑项目", "Edit QoS Policy": "编辑", "Edit Quota": "编辑配额", + "Edit Role": "编辑角色", "Edit Router": "编辑路由器", "Edit Rule": "编辑规则", "Edit Share Metadata": "编辑共享元数据", @@ -2592,6 +2595,7 @@ "delete network": "删除网络", "delete project": "删除项目", "delete qos policy": "删除QoS策略", + "delete role": "删除角色", "delete router": "删除路由器", "delete snapshot": "删除快照", "delete stack": "删除stack", diff --git a/src/pages/identity/containers/Role/actions/Create.jsx b/src/pages/identity/containers/Role/actions/Create.jsx new file mode 100644 index 00000000..958e1781 --- /dev/null +++ b/src/pages/identity/containers/Role/actions/Create.jsx @@ -0,0 +1,60 @@ +// Copyright 2021 99cloud +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { inject, observer } from 'mobx-react'; +import globalRoleStore from 'stores/keystone/role'; +import { ModalAction } from 'containers/Action'; + +export class Create extends ModalAction { + init() { + this.store = globalRoleStore; + } + + static id = 'role-create'; + + static title = t('Create Role'); + + static policy = 'identity:create_role'; + + static allowed() { + return Promise.resolve(true); + } + + get name() { + return t('Create Role'); + } + + get formItems() { + return [ + { + name: 'name', + label: t('Name'), + type: 'input', + placeholder: t('Please input name'), + required: true, + }, + { + name: 'description', + label: t('Description'), + type: 'textarea', + }, + ]; + } + + onSubmit = (values) => { + return this.store.create(values); + }; +} + +export default inject('rootStore')(observer(Create)); diff --git a/src/pages/identity/containers/Role/actions/Delete.jsx b/src/pages/identity/containers/Role/actions/Delete.jsx new file mode 100644 index 00000000..923997f1 --- /dev/null +++ b/src/pages/identity/containers/Role/actions/Delete.jsx @@ -0,0 +1,48 @@ +// Copyright 2021 99cloud +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { ConfirmAction } from 'containers/Action'; +import globalRoleStore from 'stores/keystone/role'; +import { editable } from 'resources/keystone/role'; + +export default class DeleteAction extends ConfirmAction { + get id() { + return 'delete'; + } + + get title() { + return t('Delete Role'); + } + + get isDanger() { + return true; + } + + get buttonText() { + return t('Delete'); + } + + get actionName() { + return t('delete role'); + } + + policy = 'identity:delete_role'; + + allowedCheckFunc = (data) => editable(data); + + onSubmit = (data) => { + const { id } = data; + return globalRoleStore.delete({ id }); + }; +} diff --git a/src/pages/identity/containers/Role/actions/Edit.jsx b/src/pages/identity/containers/Role/actions/Edit.jsx new file mode 100644 index 00000000..a57083fb --- /dev/null +++ b/src/pages/identity/containers/Role/actions/Edit.jsx @@ -0,0 +1,67 @@ +// Copyright 2021 99cloud +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { inject, observer } from 'mobx-react'; +import { ModalAction } from 'containers/Action'; +import globalRoleStore from 'stores/keystone/role'; +import { editable } from 'resources/keystone/role'; + +export class Edit extends ModalAction { + init() { + this.store = globalRoleStore; + } + + static id = 'role-edit'; + + static title = t('Edit Role'); + + static buttonText = t('Edit'); + + static policy = 'identity:update_role'; + + static allowed = (item) => { + return Promise.resolve(editable(item)); + }; + + get defaultValue() { + const { name, description } = this.item; + return { + name, + description, + }; + } + + get formItems() { + return [ + { + name: 'name', + label: t('Name'), + type: 'input', + required: true, + }, + { + name: 'description', + label: t('Description'), + type: 'textarea', + }, + ]; + } + + onSubmit = async (values) => { + const { id } = this.item; + return this.store.update({ id }, values); + }; +} + +export default inject('rootStore')(observer(Edit)); diff --git a/src/pages/identity/containers/Role/actions/index.jsx b/src/pages/identity/containers/Role/actions/index.jsx new file mode 100644 index 00000000..ddbe2a26 --- /dev/null +++ b/src/pages/identity/containers/Role/actions/index.jsx @@ -0,0 +1,32 @@ +// Copyright 2021 99cloud +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Create from './Create'; +import Delete from './Delete'; +import Edit from './Edit'; + +const actionConfigs = { + rowActions: { + firstAction: Edit, + moreActions: [ + { + action: Delete, + }, + ], + }, + batchActions: [Delete], + primaryActions: [Create], +}; + +export default actionConfigs; diff --git a/src/pages/identity/containers/Role/index.jsx b/src/pages/identity/containers/Role/index.jsx index c34ca2db..41531f12 100644 --- a/src/pages/identity/containers/Role/index.jsx +++ b/src/pages/identity/containers/Role/index.jsx @@ -15,16 +15,13 @@ import { observer, inject } from 'mobx-react'; import Base from 'containers/List'; import globalRoleStore from 'stores/keystone/role'; +import actionConfigs from './actions'; export class Role extends Base { init() { this.store = globalRoleStore; } - get tabs() { - return []; - } - get policy() { return 'identity:list_roles'; } @@ -37,6 +34,10 @@ export class Role extends Base { return false; } + get actionConfigs() { + return actionConfigs; + } + getColumns = () => [ { title: t('Role Name'), diff --git a/src/resources/keystone/role.js b/src/resources/keystone/role.js index db8c92ea..55be43d2 100644 --- a/src/resources/keystone/role.js +++ b/src/resources/keystone/role.js @@ -23,4 +23,12 @@ const rolePermission = { member: t('Member'), }; +export const editable = (item) => { + const { options: { immutable } = {} } = item || {}; + if (immutable || immutable === 'true' || immutable === 'True') { + return false; + } + return true; +}; + export default rolePermission; diff --git a/src/stores/keystone/role.js b/src/stores/keystone/role.js index 7be94149..33bb0d71 100644 --- a/src/stores/keystone/role.js +++ b/src/stores/keystone/role.js @@ -15,6 +15,7 @@ import { action, observable } from 'mobx'; import client from 'client'; import Base from 'stores/base'; +import List from 'stores/base-list'; export class RoleStore extends Base { get client() { @@ -24,6 +25,9 @@ export class RoleStore extends Base { @observable implyRoles = {}; + @observable + systemRoles = new List(); + @action async fetchImpliedRoles({ id }) { const rolesResult = await this.client.implies.list(id); @@ -53,6 +57,30 @@ export class RoleStore extends Base { this.isLoading = false; this.implyRoles = sourceRole; } + + checkSystemRole = (roleItem) => { + return roleItem.name === 'admin' || roleItem.name === 'reader'; + }; + + @action + async fetchSystemRoles() { + this.systemRoles.isLoading = true; + const result = await this.client.list(); + const { roles = [] } = result; + const systemRoles = roles.filter((it) => { + return this.checkSystemRole(it); + }); + this.systemRoles.data = systemRoles; + this.systemRoles.isLoading = false; + return systemRoles; + } + + @action + update({ id }, newObject) { + const body = {}; + body[this.responseKey] = newObject; + return this.submitting(this.client.patch(id, body)); + } } const globalRoleStore = new RoleStore(); diff --git a/test/e2e/integration/pages/identity/role.spec.js b/test/e2e/integration/pages/identity/role.spec.js index 761faea4..e98f9839 100644 --- a/test/e2e/integration/pages/identity/role.spec.js +++ b/test/e2e/integration/pages/identity/role.spec.js @@ -24,7 +24,7 @@ describe('The Role Page', () => { it('successfully detail', () => { cy.tableSearchText(name) - .goToDetail(0) + .goToDetail() .clickDetailTab('Binding User', 'user') .clickDetailTab('Binding Group', 'group'); cy.goBackToList(listUrl);