From e47fa9e7421125f3d723430ae2fc4eb7cb267d65 Mon Sep 17 00:00:00 2001 From: "Jingwei.Zhang" Date: Wed, 8 Jun 2022 15:22:39 +0800 Subject: [PATCH] refactor: Refactor user 1. Refactor user store 2. Refactor user list 3. Refactor edit user system role 4. Update system-admin role check in rootStore 5. Refactor user detail page 6. Update forbidden user action to danger style 7. Refactor create user: add domain select && support multi role select for projects 8. Update project manager user e2e 9. Update create user e2e 10. Update user edit system role e2e 11. Remove create user in domain detail page Closes-Bug: #1942285 Change-Id: Ieba70b002420e20ad7c3f04f5e4f6fb4b6fb1e76 --- src/locales/en.json | 10 +- src/locales/zh.json | 10 +- .../containers/Project/Detail/index.jsx | 4 + .../containers/Project/actions/ManageUser.jsx | 2 +- .../identity/containers/Project/index.jsx | 5 + .../identity/containers/User/Detail/index.jsx | 47 +- .../containers/User/actions/Create.jsx | 211 +++--- .../identity/containers/User/actions/Edit.jsx | 92 +-- .../containers/User/actions/Forbidden.jsx | 4 + .../containers/User/actions/SystemRole.jsx | 345 ++------- .../containers/User/actions/index.jsx | 14 +- .../User/actionsInDomain/Create.jsx | 256 ------- .../containers/User/actionsInDomain/index.jsx | 52 -- src/pages/identity/containers/User/index.jsx | 260 +++---- .../UserGroup/actions/ManageUser.jsx | 2 +- src/stores/keystone/user.js | 683 +++++------------- src/stores/root.js | 43 +- .../pages/identity/project.spec.js | 17 +- .../integration/pages/identity/user.spec.js | 23 +- 19 files changed, 518 insertions(+), 1562 deletions(-) delete mode 100644 src/pages/identity/containers/User/actionsInDomain/Create.jsx delete mode 100644 src/pages/identity/containers/User/actionsInDomain/index.jsx diff --git a/src/locales/en.json b/src/locales/en.json index f866d52d..81b14b6f 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -789,6 +789,7 @@ "Edit Share Metadata": "Edit Share Metadata", "Edit Subnet": "Edit Subnet", "Edit System Permission": "Edit System Permission", + "Edit User": "Edit User", "Edit User Group": "Edit User Group", "Edit VPN": "Edit VPN", "Edit VPN EndPoint Groups": "Edit VPN EndPoint Groups", @@ -1324,7 +1325,6 @@ "MacVTap": "MacVTap", "Macau": "Macau", "Madagascar": "Madagascar", - "Main Project": "Main Project", "Maintained": "Maintained", "Maintenance": "Maintenance", "Malawi": "Malawi", @@ -1349,7 +1349,6 @@ "Manageable": "Manageable", "Management": "Management", "Management Reason": "Management Reason", - "Manager user": "Manager user", "Manager user group": "Manager user group", "Manu": "Manu", "Manual backup": "Manual backup", @@ -1955,7 +1954,6 @@ "Select Project": "Select Project", "Select Project Role": "Select Project Role", "Select Snapshot": "Select Snapshot", - "Select System Role": "Select System Role", "Select User Group": "Select User Group", "Select a domain": "Select a domain", "Select a region": "Select a region", @@ -2158,6 +2156,7 @@ "System Info": "System Info", "System Load": "System Load", "System Reader": "System Reader", + "System Roles": "System Roles", "System Running Time": "System Running Time", "System is error, please try again later.": "System is error, please try again later.", "TCP": "TCP", @@ -2186,7 +2185,6 @@ "The Republic of Macedonia": "The Republic of Macedonia", "The Republic of South Sudan": "The Republic of South Sudan", "The SSH key is a way to remotely log in to the instance. The cloud platform only helps to keep the public key. Please keep your private key properly.": "The SSH key is a way to remotely log in to the instance. The cloud platform only helps to keep the public key. Please keep your private key properly.", - "The affiliated Domain cannot be modified after creation": "The affiliated Domain cannot be modified after creation", "The amphora instance is required for load balancing service setup and is not recommended": "The amphora instance is required for load balancing service setup and is not recommended", "The associated floating IP, virtual adapter, volume and other resources will be automatically disassociated.": "The associated floating IP, virtual adapter, volume and other resources will be automatically disassociated.", "The certificate contains information such as the public key and signature of the certificate. The extension of the certificate is \"pem\" or \"crt\", you can directly enter certificate content or upload certificate file.": "The certificate contains information such as the public key and signature of the certificate. The extension of the certificate is \"pem\" or \"crt\", you can directly enter certificate content or upload certificate file.", @@ -2390,6 +2388,7 @@ "User Data": "User Data", "User Detail": "User Detail", "User Edit": "User Edit", + "User Group": "User Group", "User Group Detail": "User Group Detail", "User Group ID/Name": "User Group ID/Name", "User Group Name": "User Group Name", @@ -2481,7 +2480,6 @@ "Whether the boot device should be set only for the next reboot, or persistently.": "Whether the boot device should be set only for the next reboot, or persistently.", "Which Network Interface provider to use when plumbing the network connections for this Node": "Which Network Interface provider to use when plumbing the network connections for this Node", "Windows": "Windows", - "Work Num": "Work Num", "Workdir": "Workdir", "Working Directory": "Working Directory", "X86 Architecture": "X86 Architecture", @@ -2511,6 +2509,7 @@ "application credential": "application credential", "associate floating ip": "associate floating ip", "attach interface": "attach interface", + "authorized by group ": "authorized by group ", "availability zones": "availability zones", "available": "available", "backup": "backup", @@ -2615,7 +2614,6 @@ "domain": "domain", "domains": "domains", "e.g. 2001:Db8::/48": "e.g. 2001:Db8::/48", - "edit": "edit", "edit baremetal node": "edit baremetal node", "edit default pool": "edit default pool", "edit health monitor": "edit health monitor", diff --git a/src/locales/zh.json b/src/locales/zh.json index 0dd66c9c..9d41290a 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -789,6 +789,7 @@ "Edit Share Metadata": "编辑共享元数据", "Edit Subnet": "编辑子网", "Edit System Permission": "编辑系统角色", + "Edit User": "编辑用户", "Edit User Group": "编辑用户组", "Edit VPN": "编辑VPN", "Edit VPN EndPoint Groups": "编辑VPN端点组", @@ -1324,7 +1325,6 @@ "MacVTap": "", "Macau": "澳门", "Madagascar": "马达加斯加", - "Main Project": "主项目", "Maintained": "维护", "Maintenance": "运维管理", "Malawi": "马拉维", @@ -1349,7 +1349,6 @@ "Manageable": "可管理", "Management": "维护", "Management Reason": "维护原因", - "Manager user": "管理用户", "Manager user group": "管理用户组", "Manu": "手动", "Manual backup": "手动备份", @@ -1955,7 +1954,6 @@ "Select Project": "选择项目", "Select Project Role": "选择项目角色", "Select Snapshot": "选择快照", - "Select System Role": "选择系统角色", "Select User Group": "选择用户组", "Select a domain": "请选择Domain", "Select a region": "请选择Region", @@ -2158,6 +2156,7 @@ "System Info": "系统信息", "System Load": "系统负载", "System Reader": "系统只读权限", + "System Roles": "系统角色", "System Running Time": "", "System is error, please try again later.": "系统出错,请稍后再试。", "TCP": "", @@ -2186,7 +2185,6 @@ "The Republic of Macedonia": "马其顿", "The Republic of South Sudan": "南苏丹共和国", "The SSH key is a way to remotely log in to the instance. The cloud platform only helps to keep the public key. Please keep your private key properly.": "SSH 密钥是一种远程登录云主机的方式,云平台只帮助保管公钥,请妥善保管自己的私钥。", - "The affiliated Domain cannot be modified after creation": "所属域不可修改", "The amphora instance is required for load balancing service setup and is not recommended": "amphora 相关的云主机为负载均衡服务搭建所需,不建议选择", "The associated floating IP, virtual adapter, volume and other resources will be automatically disassociated.": "绑定的浮动IP、网卡、云硬盘等资源将自动解绑。", "The certificate contains information such as the public key and signature of the certificate. The extension of the certificate is \"pem\" or \"crt\", you can directly enter certificate content or upload certificate file.": "证书包含证书的公钥和签名等信息,证书扩展名为”pem”或”crt”,您可直接输入证书内容或上传证书文件。", @@ -2390,6 +2388,7 @@ "User Data": "用户数据", "User Detail": "用户详情", "User Edit": "编辑用户", + "User Group": "用户组", "User Group Detail": "用户组详情", "User Group ID/Name": "用户组ID/名称", "User Group Name": "用户组名称", @@ -2481,7 +2480,6 @@ "Whether the boot device should be set only for the next reboot, or persistently.": "是否永久使用该引导设置。", "Which Network Interface provider to use when plumbing the network connections for this Node": "当为这个节点连接网络时,使用哪个网络接口提供者", "Windows": "", - "Work Num": "工号", "Workdir": "工作目录", "Working Directory": "工作目录", "X86 Architecture": "X86架构", @@ -2511,6 +2509,7 @@ "application credential": "应用凭证", "associate floating ip": "绑定浮动IP", "attach interface": "挂载网卡", + "authorized by group ": "由组授权", "availability zones": "可用域", "available": "可用", "backup": "备份", @@ -2615,7 +2614,6 @@ "domain": "域", "domains": "域", "e.g. 2001:Db8::/48": "", - "edit": "编辑", "edit baremetal node": "编辑裸机节点", "edit default pool": "编辑资源池", "edit health monitor": "编辑健康检查器", diff --git a/src/pages/identity/containers/Project/Detail/index.jsx b/src/pages/identity/containers/Project/Detail/index.jsx index 9b69e2f9..36bca937 100644 --- a/src/pages/identity/containers/Project/Detail/index.jsx +++ b/src/pages/identity/containers/Project/Detail/index.jsx @@ -53,6 +53,10 @@ export class Detail extends Base { dataIndex: 'name', }, enabledColumn, + { + title: t('Affiliated Domain'), + dataIndex: 'domainName', + }, { title: t('User Num'), dataIndex: 'userCount', diff --git a/src/pages/identity/containers/Project/actions/ManageUser.jsx b/src/pages/identity/containers/Project/actions/ManageUser.jsx index b8c09df9..cd06b76e 100644 --- a/src/pages/identity/containers/Project/actions/ManageUser.jsx +++ b/src/pages/identity/containers/Project/actions/ManageUser.jsx @@ -46,7 +46,7 @@ export class ManagerUser extends ModalAction { } getUser() { - this.userStore.fetchAllWithDomain(); + this.userStore.fetchList({ withProjectRole: false, withSystemRole: false }); } getInitRoleMap() { diff --git a/src/pages/identity/containers/Project/index.jsx b/src/pages/identity/containers/Project/index.jsx index f786e8fb..98a35f83 100644 --- a/src/pages/identity/containers/Project/index.jsx +++ b/src/pages/identity/containers/Project/index.jsx @@ -214,6 +214,11 @@ export class Projects extends Base { )}${groupCount}`; }, }, + { + title: t('Affiliated Domain'), + dataIndex: 'domainName', + isHideable: true, + }, enabledColumn, { title: t('Tags'), diff --git a/src/pages/identity/containers/User/Detail/index.jsx b/src/pages/identity/containers/User/Detail/index.jsx index 9e6eb425..553953d6 100644 --- a/src/pages/identity/containers/User/Detail/index.jsx +++ b/src/pages/identity/containers/User/Detail/index.jsx @@ -12,11 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. +import React from 'react'; import { inject, observer } from 'mobx-react'; import { UserStore } from 'stores/keystone/user'; -import globalDomainStore from 'stores/keystone/domain'; import Base from 'containers/TabDetail'; import Credentials from 'src/pages/user-center/containers/Credentials'; +import { emptyActionConfig } from 'utils/constants'; import { enabledColumn } from 'resources/keystone/domain'; import UserGroup from '../../UserGroup'; import Project from '../../Project'; @@ -36,33 +37,13 @@ export class UserDetail extends Base { } get actionConfigs() { - return this.isAdminPage - ? actionConfigs.adminConfigs - : actionConfigs.actionConfigs; + return this.isAdminPage ? actionConfigs : emptyActionConfig; } init() { this.store = new UserStore(); - this.domainStore = globalDomainStore; - this.getDomains(); } - getDomains() { - this.domainStore.fetchDomain(); - } - - get domainList() { - const { domains } = this.domainStore; - return domains || []; - } - - goEdit = () => { - const { - params: { id }, - } = this.props.match; - this.routing.push(`${this.listUrl}/edit/${id}`); - }; - get detailInfos() { return [ { @@ -70,25 +51,27 @@ export class UserDetail extends Base { dataIndex: 'name', }, enabledColumn, + { + title: t('System Roles'), + dataIndex: 'systemRoles', + render: (value) => { + if (!value || !value.length) { + return '-'; + } + return (value || []).map((it) =>
{it.name}
); + }, + }, { title: t('Real Name'), dataIndex: 'real_name', }, // { // title: t('User Group Num'), - // dataIndex: 'group_num', + // dataIndex: 'groupCount', // }, { title: t('Affiliated Domain'), - dataIndex: 'domain_id', - isHideable: true, - render: (domain_id) => { - const domain = this.domainList.filter((it) => it.id === domain_id); - if (domain[0]) { - return domain[0].name; - } - return domain_id; - }, + dataIndex: 'domainName', }, { title: t('Email'), diff --git a/src/pages/identity/containers/User/actions/Create.jsx b/src/pages/identity/containers/User/actions/Create.jsx index 61a7c623..05b4fe9a 100644 --- a/src/pages/identity/containers/User/actions/Create.jsx +++ b/src/pages/identity/containers/User/actions/Create.jsx @@ -13,56 +13,61 @@ // limitations under the License. import React from 'react'; -import { has } from 'lodash'; import { inject, observer } from 'mobx-react'; -import globalGroupStore from 'stores/keystone/user-group'; +import { GroupStore } from 'stores/keystone/user-group'; import globalUserStore from 'stores/keystone/user'; import { FormAction } from 'containers/Action'; import { Select } from 'antd'; -import globalProjectStore from 'stores/keystone/project'; +import { ProjectStore } from 'stores/keystone/project'; import globalRoleStore from 'stores/keystone/role'; +import globalDomainStore from 'stores/keystone/domain'; import { getPasswordOtherRule, phoneNumberValidate, emailValidate, } from 'utils/validate'; -import { statusTypes } from 'resources/keystone/domain'; +import { + statusTypes, + getDomainFormItem, + nameDomainColumns, + transferFilterOption, +} from 'resources/keystone/domain'; -export class CreateForm extends FormAction { +export class Create extends FormAction { constructor(props) { super(props); this.state = { domain: 'default', more: false, - newProjectRoles: {}, + projectRoles: {}, }; } init() { this.store = globalUserStore; - this.userGroupStore = globalGroupStore; - this.projectStore = globalProjectStore; + this.userGroupStore = new GroupStore(); + this.projectStore = new ProjectStore(); this.roleStore = globalRoleStore; - this.getUserGroup(); - this.getProject(); - this.getRole(); + this.getUserGroups(); + this.getProjects(); + this.getRoles(); this.getDomains(); } getDomains() { - this.store.fetchDomain(); + globalDomainStore.fetchDomain(); } - getUserGroup() { - this.userGroupStore.fetchList(); + getUserGroups() { + this.userGroupStore.fetchList({ withRole: false }); } - getProject() { - this.projectStore.fetchList(); + getProjects() { + this.projectStore.fetchList({ withRole: false }); } - getRole() { + getRoles() { this.roleStore.fetchList(); } @@ -97,13 +102,10 @@ export class CreateForm extends FormAction { } get defaultValue() { - const { domains } = this.store; - const { domain } = this.state; - const domainDefault = (domains || []).filter((it) => it.id === domain)[0]; const data = { more: false, enabled: statusTypes[0].value, - domain_id: domainDefault ? domainDefault.name : 'Default', + domain_id: 'default', }; return data; } @@ -129,96 +131,81 @@ export class CreateForm extends FormAction { })); } - // get roleList() { - // return (this.roleStore.list.data || []).map(it => ({ - // label: it.name, - // value: it.id, - // })); - // } - - // get adminRole() { - // return (this.roleStore.list.data || []).filter(it => - // it.name === 'admin' - // )[0]; - // } - - onValuesChange = (changedFields) => { - if (has(changedFields, 'more')) { - this.setState({ - more: changedFields.more, - }); - } - }; - static allowed = () => Promise.resolve(true); get leftProjectTable() { - return [ - { - dataIndex: 'name', - title: t('Name'), - }, - ]; + return nameDomainColumns; } get projectRoleList() { - const projectRole = this.roleStore.list.data || []; - return projectRole; + return this.roleStore.list.data || []; } - userRolesList = (role_id) => + projectRolesList = (projectId) => (this.projectRoleList || []).map((it) => ({ label: it.name, value: it.id, - role_id, + projectId, })); - defaultRoles = () => [this.projectRoleList[0].id]; + defaultRoles = () => [(this.projectRoleList[0] || {}).id]; - userRoleChange = (value, option) => { - const { newProjectRoles } = this.state; - const { role_id } = option; - newProjectRoles[role_id] = value; - this.setState({ newProjectRoles }); + onSelectChange = (value, option, projectId) => { + const { projectRoles } = this.state; + if (value.length && option.length) { + projectRoles[projectId] = value; + } else { + projectRoles[projectId] = {}; + } + this.setState({ projectRoles }); + }; + + renderSelect = (projectId) => { + return ( + - ), + render: (id) => this.renderSelect(id), }, ]; } + onChangeProject = (value) => { + const { projectRoles } = this.state; + (value || []).forEach((projectId) => { + if (!projectRoles[projectId]) { + projectRoles[projectId] = this.defaultRoles(); + } + }); + Object.keys(projectRoles).forEach((projectId) => { + if (!(value || []).includes(projectId)) { + delete projectRoles[projectId]; + } + }); + this.setState(projectRoles); + }; + get leftUserGroupTable() { - return [ - { - dataIndex: 'name', - title: t('Name'), - }, - ]; + return nameDomainColumns; } get rightUserGroupTable() { - return [ - { - dataIndex: 'name', - title: t('Name'), - }, - ]; + return nameDomainColumns; } checkName = (rule, value) => { @@ -236,17 +223,22 @@ export class CreateForm extends FormAction { }; get formItems() { - const { more, domain } = this.state; + const { more } = this.state; const labelCol = { xs: { span: 5 }, sm: { span: 6 }, }; + const domainFormItem = getDomainFormItem(this); + const currentDomainFormItem = { + ...domainFormItem, + labelCol, + colNum: 2, + }; return [ { name: 'name', label: t('User Name'), type: 'input', - placeholder: t('Please input user name'), validator: this.checkName, extra: t('User name can not be duplicated'), required: true, @@ -291,20 +283,7 @@ export class CreateForm extends FormAction { labelCol, colNum: 2, }, - { - name: 'domain_id', - label: t('Affiliated Domain'), - type: 'input', - // options: this.domainList, - // onChange: (e) => { - // this.setState({ - // domain: e, - // }); - // }, - disabled: true, - colNum: 2, - labelCol, - }, + currentDomainFormItem, { name: 'enabled', label: t('Status'), @@ -315,14 +294,6 @@ export class CreateForm extends FormAction { labelCol, colNum: 2, }, - // { - // name: 'default_project_id', - // label: t('Main Project'), - // type: 'select', - // options: this.projectList, - // labelCol, - // colNum: 2, - // }, { name: 'description', label: t('Description'), @@ -339,13 +310,6 @@ export class CreateForm extends FormAction { colNum: 2, maxLength: 30, }, - // { - // name: 'work num', - // label: t('Work Num'), - // type: 'input', - // labelCol, - // colNum: 2, - // }, { type: 'divider', }, @@ -360,12 +324,11 @@ export class CreateForm extends FormAction { type: 'transfer', leftTableColumns: this.leftProjectTable, rightTableColumns: this.rightProjectTable, - dataSource: domain - ? this.projects.filter((it) => it.domain_id === domain) - : [], - disabled: false, + dataSource: this.projects, showSearch: true, - hidden: !more || !domain, + hidden: !more, + onChange: this.onChangeProject, + filterOption: transferFilterOption, }, { name: 'select_user_group', @@ -373,12 +336,10 @@ export class CreateForm extends FormAction { type: 'transfer', leftTableColumns: this.leftUserGroupTable, rightTableColumns: this.rightUserGroupTable, - dataSource: domain - ? this.userGroupList.filter((it) => it.domain_id === domain) - : [], - disabled: false, + dataSource: this.userGroupList, showSearch: true, - hidden: !more || !domain, + hidden: !more, + filterOption: transferFilterOption, }, ]; } @@ -386,11 +347,11 @@ export class CreateForm extends FormAction { onSubmit = async (values) => { const { domain } = this.state; values.defaultRole = this.projectRoleList[0].id; - values.newProjectRoles = this.state.newProjectRoles; + values.projectRoles = this.state.projectRoles; values.domain_id = domain; const { confirmPassword, more, ...rest } = values; return this.store.create(rest); }; } -export default inject('rootStore')(observer(CreateForm)); +export default inject('rootStore')(observer(Create)); diff --git a/src/pages/identity/containers/User/actions/Edit.jsx b/src/pages/identity/containers/User/actions/Edit.jsx index a597fa01..93d4c7d1 100644 --- a/src/pages/identity/containers/User/actions/Edit.jsx +++ b/src/pages/identity/containers/User/actions/Edit.jsx @@ -15,101 +15,44 @@ import { inject, observer } from 'mobx-react'; import { ModalAction } from 'containers/Action'; import globalUserStore from 'stores/keystone/user'; -import globalDomainStore from 'stores/keystone/domain'; import { phoneNumberValidate, emailValidate } from 'utils/validate'; import parsePhoneNumberFromString from 'libphonenumber-js'; export class EditForm extends ModalAction { init() { this.store = globalUserStore; - this.domainStore = globalDomainStore; - this.getDomains(); - this.getProject(); - } - - componentDidMount() { - const { item } = this.props; - const { id } = this.item; - this.store.fetchDetail({ ...item, id }); - } - - getDomains() { - this.domainStore.fetchDomain(); - } - - getProject() { - this.store.fetchProject(); } static id = 'user-edit'; static title = t('Edit'); - // static path(item) { - // return `/identity/user-admin/edit/${item.id}`; - // } - static policy = 'identity:update_user'; static allowed() { return Promise.resolve(true); } - get domainList() { - return (this.userGroupStore.list.data || []).map((it) => ({ - label: it.name, - value: it.id, - })); - } - - get projectList() { - const { projects } = this.store; - return (projects || []).map((it) => ({ - label: it.name, - value: it.id, - })); - } - - get data() { - return this.store.detail || []; - } - - get name() { - const { name } = this.data; - return `${t('edit')} ${name}`; + get actionName() { + return t('Edit User'); } get defaultValue() { - const { + const { name, email, phone, real_name, description, domain, domain_id } = + this.item; + const formattedPhone = parsePhoneNumberFromString(phone || '', 'CN') || { + countryCallingCode: '86', + nationalNumber: '', + }; + const { countryCallingCode, nationalNumber } = formattedPhone; + return { name, + domainName: (domain || {}).name || domain_id, email, - phone, + phone: `+${countryCallingCode} ${nationalNumber}`, real_name, description, - domain_id, - default_project_id, - } = this.data; - const { domains } = this.domainStore; - const { projects } = this.store; - const domain = domains.filter((it) => it.id === domain_id)[0]; - const project = projects.filter((it) => it.id === default_project_id)[0]; - if (name && this.formRef.current) { - const formattedPhone = parsePhoneNumberFromString(phone || '', 'CN') || { - countryCallingCode: '86', - nationalNumber: '', - }; - const { countryCallingCode, nationalNumber } = formattedPhone; - this.formRef.current.setFieldsValue({ - name, - domain_id: domain ? domain.name : '', - default_project_id: project ? project.name : '', - email, - phone: `+${countryCallingCode} ${nationalNumber}`, - real_name, - description, - }); - } - return {}; + }; } checkName = (rule, value) => { @@ -119,9 +62,9 @@ export class EditForm extends ModalAction { const { list: { data }, } = this.store; - const { name } = this.item; - const nameUsed = data.filter((it) => it.name === value); - if (nameUsed[0] && nameUsed[0].name !== name) { + const { id } = this.item; + const nameUsed = data.find((it) => it.name === value && it.id !== id); + if (nameUsed) { return Promise.reject(t('Invalid: User name can not be duplicated')); } return Promise.resolve(); @@ -159,10 +102,9 @@ export class EditForm extends ModalAction { required: true, }, { - name: 'domain_id', + name: 'domainName', label: t('Affiliated Domain'), type: 'input', - required: true, disabled: true, }, { diff --git a/src/pages/identity/containers/User/actions/Forbidden.jsx b/src/pages/identity/containers/User/actions/Forbidden.jsx index e324c4f8..ed443ed0 100644 --- a/src/pages/identity/containers/User/actions/Forbidden.jsx +++ b/src/pages/identity/containers/User/actions/Forbidden.jsx @@ -29,6 +29,10 @@ export default class ForbiddenAction extends ConfirmAction { return t('Forbidden'); } + get isDanger() { + return true; + } + get actionName() { return t('Forbidden User'); } diff --git a/src/pages/identity/containers/User/actions/SystemRole.jsx b/src/pages/identity/containers/User/actions/SystemRole.jsx index 55e6a51d..461a8931 100644 --- a/src/pages/identity/containers/User/actions/SystemRole.jsx +++ b/src/pages/identity/containers/User/actions/SystemRole.jsx @@ -11,17 +11,22 @@ // 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 React from 'react'; import { inject, observer } from 'mobx-react'; -import { Select } from 'antd'; -import globalProjectStore from 'stores/keystone/project'; -import globalUserStore from 'stores/keystone/user'; -import { RoleStore } from 'stores/keystone/role'; import { ModalAction } from 'containers/Action'; -import globalDomainStore from 'stores/keystone/domain'; +import { UserStore } from 'stores/keystone/user'; +import globalRoleStore from 'stores/keystone/role'; export class SystemRole extends ModalAction { + init() { + this.store = new UserStore(); + this.roleStore = globalRoleStore; + this.getRoleList(); + } + + getRoleList() { + this.roleStore.fetchSystemRoles(); + } + static id = 'edit-system-permission'; static title = t('Edit System Permission'); @@ -30,318 +35,70 @@ export class SystemRole extends ModalAction { return t('edit system permission'); } - async init() { - const systemRole = JSON.stringify(this.item.projectMapSystemRole); - this.state.domainDefault = this.item.domain_id; - this.state.projectRoles = JSON.parse(systemRole); - this.store = new RoleStore(); - this.domainStore = globalDomainStore; - this.userStore = globalUserStore; - await this.getRoleList(); - this.getDomains(); - this.getUser(); - } - - getRoleList() { - return this.store.fetchList(); - } - - getDomains() { - this.domainStore.fetchDomain(); - } - - getUser() { - this.userStore.fetchProject(); - } - - static get modalSize() { - return 'large'; - } - - getModalSize() { - return 'large'; - } - - // get defaultSystemRoles() { - // const { projects } = this.item; - // const defaultProjects = Object.keys(projects); - // const systemRole = (this.store.list.data || []).filter(it => - // ((it.name.indexOf('system_') !== -1) && (it.name.indexOf('_system_') === -1)) || - // it.name === 'admin' - // ); - // const systemRoleId = systemRole.map(it => it.id); - // const defaultSystemRoles = {}; - // defaultProjects.forEach((project_id) => { - // const roles = projects[project_id].filter(role_id => systemRoleId.indexOf(role_id) !== -1); - // if (roles[0]) { - // defaultSystemRoles[project_id] = roles; - // } - // }); - // return defaultSystemRoles; - // } - - get domainList() { - const { - rootStore: { baseDomains }, - } = this.props; - const { domains } = this.domainStore; - const domainList = (domains || []).filter( - (it) => - baseDomains.indexOf(it.name) === -1 || it.id === this.item.domain_id - ); - return domainList.map((it) => ({ + get rolesList() { + return (this.roleStore.systemRoles.data || []).map((it) => ({ label: it.name, value: it.id, - key: it.id, - })); - } - - get item() { - const { item } = this.props; - item.roles = {}; - return item; - } - - get multipleMode() { - return 'multiple'; - } - - get projectList() { - return (this.userStore.projects || []).map((it) => ({ - ...it, - key: it.id, - })); - } - - get systemRoleList() { - const systemRole = this.store.list.data || []; - return systemRole; - } - - get adminRoleId() { - const adminRole = (this.store.list.data || []).filter( - (it) => it.name === 'admin' - ); - return adminRole[0].id; - } - - adminRoleList = (project_id) => { - const adminRole = (this.store.list.data || []).filter( - (it) => it.name === 'admin' - ); - return adminRole.map((it) => ({ - label: it.name, - value: it.id, - key: it.id, - project_id, - })); - }; - - projectRolesList = (project_id) => - this.systemRoleList.map((it) => ({ - label: it.name, - value: it.id, - key: it.id, - project_id, - })); - - defaultRoles = (projectId) => { - const { roles, projects } = this.item; - const { projectRoles } = this.state; - const filterRoles = this.multipleMode ? projects : projectRoles; - if (!filterRoles[projectId]) { - roles[projectId] = [this.systemRoleList[0].id]; - } else { - const usersSystemRole = filterRoles[projectId].filter((it) => { - const systemRole = this.systemRoleList.filter((role) => role.id === it); - if (systemRole[0]) { - return true; - } - return false; - }); - return this.multipleMode ? usersSystemRole : usersSystemRole.slice(0, 1); - } - return roles[projectId]; - }; - - static policy = 'identity:update_project'; - - static allowed = () => Promise.resolve(true); - - get leftUserTable() { - return [ - { - dataIndex: 'name', - title: t('Name'), - }, - ]; - } - - get rightUserTable() { - return [ - { - dataIndex: 'name', - title: t('Name'), - }, - { - title: t('Select System Role'), - dataIndex: 'id', - render: (id) => this.renderSelect(id), - }, - ]; - } - - renderSelect = (id) => { - let disable = false; - if (this.item.projects && this.item.projects[id]) { - // eslint-disable-next-line prefer-destructuring - disable = this.item.projects[id].filter( - (it) => it === this.adminRoleId - )[0]; - } - // for test e2e, will delete by next patch - localStorage.setItem('test-project-role', this.projectRolesList(id)); - localStorage.setItem('test-total-role', this.systemRoleList); - localStorage.setItem('test-actual', 'can get localstorage'); - return ( -