diff --git a/docs/en/develop/3-6-FormAction-introduction.md b/docs/en/develop/3-6-FormAction-introduction.md
index 6045b7bd..b7e8fcca 100644
--- a/docs/en/develop/3-6-FormAction-introduction.md
+++ b/docs/en/develop/3-6-FormAction-introduction.md
@@ -110,7 +110,7 @@ English | [Chinese](../../zh/develop/3-6-FormAction-introduction.md)
```
- `allowed`
- - Static functions
+ - Static functions
- Determine whether the operation needs to be disabled
- Return `Promise`
- Write directly without using disabled buttons
diff --git a/src/client/trove/index.js b/src/client/trove/index.js
index 25d573ec..f0758d52 100644
--- a/src/client/trove/index.js
+++ b/src/client/trove/index.js
@@ -48,6 +48,20 @@ export class TroveClient extends Base {
responseKey: 'log',
},
],
+ extendOperations: [
+ {
+ name: 'grantDatabase',
+ generate: (id, subId, body) => {
+ return this.request.put(
+ `${this.getDetailUrl(
+ 'instances',
+ id
+ )}/users/${subId}/databases`,
+ body
+ );
+ },
+ },
+ ],
},
{
name: 'datastores',
diff --git a/src/locales/en.json b/src/locales/en.json
index 171b4db0..3268729e 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -988,6 +988,7 @@
"Glance": "Glance",
"Global Setting": "Global Setting",
"GlusterFS": "GlusterFS",
+ "Grant Databases Access": "Grant Databases Access",
"Greece": "Greece",
"Greenland": "Greenland",
"Grenada": "Grenada",
@@ -2660,6 +2661,7 @@
"flavor": "flavor",
"floating ip": "floating ip",
"floating ips": "floating ips",
+ "gigabytes": "gigabytes",
"heat services": "heat services",
"host aggregates": "host aggregates",
"hosts": "hosts",
diff --git a/src/locales/zh.json b/src/locales/zh.json
index 68c56160..b5ce339e 100644
--- a/src/locales/zh.json
+++ b/src/locales/zh.json
@@ -988,6 +988,7 @@
"Glance": "",
"Global Setting": "平台配置",
"GlusterFS": "",
+ "Grant Databases Access": "设置数据库访问",
"Greece": "希腊",
"Greenland": "格陵兰",
"Grenada": "格林纳达",
@@ -2660,6 +2661,7 @@
"flavor": "云主机类型",
"floating ip": "浮动IP",
"floating ips": "浮动IP",
+ "gigabytes": "容量",
"heat services": "编排服务",
"host aggregates": "主机集合",
"hosts": "主机",
diff --git a/src/pages/database/containers/Instances/Detail/BaseDetail.jsx b/src/pages/database/containers/Instances/Detail/BaseDetail.jsx
index 076e30e0..ee4cde4d 100644
--- a/src/pages/database/containers/Instances/Detail/BaseDetail.jsx
+++ b/src/pages/database/containers/Instances/Detail/BaseDetail.jsx
@@ -12,6 +12,7 @@
// 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 Base from 'containers/BaseDetail';
import { InstanceStatus, policyType } from 'resources/trove/database';
@@ -104,7 +105,17 @@ export class BaseDetail extends Base {
{
label: t('Host'),
dataIndex: 'ip',
- render: (value) => (value ? value.map((it) => it) : '-'),
+ render: (value) => {
+ return value && value.length ? (
+
+ {value.map((it) => (
+ {it}
+ ))}
+
+ ) : (
+ '-'
+ );
+ },
},
{
label: t('Database Port'),
diff --git a/src/pages/database/containers/Instances/Detail/UserAction.jsx b/src/pages/database/containers/Instances/Detail/UserAction.jsx
index a81fba7c..d30c3b33 100644
--- a/src/pages/database/containers/Instances/Detail/UserAction.jsx
+++ b/src/pages/database/containers/Instances/Detail/UserAction.jsx
@@ -14,10 +14,16 @@
import DeleteUser from './UserDelete';
import CreateUser from './UserCreate';
+import UserDatabase from './UserDatabase';
const actionConfigs = {
rowActions: {
firstAction: DeleteUser,
+ moreActions: [
+ {
+ action: UserDatabase,
+ },
+ ],
},
batchActions: [DeleteUser],
primaryActions: [CreateUser],
diff --git a/src/pages/database/containers/Instances/Detail/UserDatabase.jsx b/src/pages/database/containers/Instances/Detail/UserDatabase.jsx
new file mode 100644
index 00000000..479c21cf
--- /dev/null
+++ b/src/pages/database/containers/Instances/Detail/UserDatabase.jsx
@@ -0,0 +1,94 @@
+// 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/ModalAction';
+import globalInstancesUsersStore from 'stores/trove/instances-user';
+import { InstancesDatabasesStore } from 'stores/trove/instances-database';
+
+export class UserDatabase extends ModalAction {
+ init() {
+ this.store = globalInstancesUsersStore;
+ this.databaseStore = new InstancesDatabasesStore();
+ this.fetchDatabase();
+ }
+
+ static id = 'grant-databases-access';
+
+ static title = t('Grant Databases Access');
+
+ get name() {
+ return t('Grant Databases Access');
+ }
+
+ static policy = 'instance:extension:user_access:update';
+
+ static allowed() {
+ return Promise.resolve(true);
+ }
+
+ async fetchDatabase() {
+ const { containerProps: { detail: { id } = {} } = {} } = this.props;
+ await this.databaseStore.fetchList({ id });
+ this.updateDefaultValue();
+ }
+
+ get database() {
+ return (this.databaseStore.list.data || []).map((it) => ({
+ label: it.name,
+ value: it.name,
+ key: it.name,
+ }));
+ }
+
+ get defaultValue() {
+ const { name, databases } = this.item;
+ return {
+ name,
+ database: databases,
+ };
+ }
+
+ get formItems() {
+ return [
+ {
+ name: 'name',
+ label: t('Name'),
+ type: 'input-name',
+ required: true,
+ disabled: true,
+ },
+ {
+ name: 'database',
+ label: t('Database'),
+ type: 'select',
+ options: this.database,
+ mode: 'multiple',
+ required: true,
+ loading: this.databaseStore.list.isLoading,
+ disabled: this.databaseStore.list.isLoading,
+ },
+ ];
+ }
+
+ onSubmit = (values, containerProps) => {
+ const { detail: { id } = {} } = containerProps;
+ const data = {
+ databases: values.database.map((it) => ({ name: it })),
+ };
+ return this.store.grantDatabaseAccess({ id, name: values.name, data });
+ };
+}
+
+export default inject('rootStore')(observer(UserDatabase));
diff --git a/src/pages/database/containers/Instances/Detail/Users.jsx b/src/pages/database/containers/Instances/Detail/Users.jsx
index 9ae02005..dcfeef37 100644
--- a/src/pages/database/containers/Instances/Detail/Users.jsx
+++ b/src/pages/database/containers/Instances/Detail/Users.jsx
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import React from 'react';
import Base from 'containers/List';
import { inject, observer } from 'mobx-react';
import { InstancesUsersStore } from 'stores/trove/instances-user';
@@ -58,6 +59,17 @@ export class Users extends Base {
{
title: t('Databases'),
dataIndex: 'databases',
+ render: (value) => {
+ return value.length ? (
+
+ {value.map((it) => (
+ {it}
+ ))}
+
+ ) : (
+ '-'
+ );
+ },
},
];
};
diff --git a/src/pages/database/containers/Instances/index.jsx b/src/pages/database/containers/Instances/index.jsx
index ffd616a0..98249dbe 100644
--- a/src/pages/database/containers/Instances/index.jsx
+++ b/src/pages/database/containers/Instances/index.jsx
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import React from 'react';
import { observer, inject } from 'mobx-react';
import Base from 'containers/List';
import globalInstancesStore from 'stores/trove/instances';
@@ -69,6 +70,17 @@ export class Instances extends Base {
{
title: t('Host'),
dataIndex: 'ip',
+ render: (value) => {
+ return value && value.length ? (
+ <>
+ {value.map((it) => (
+
{it}
+ ))}
+ >
+ ) : (
+ '-'
+ );
+ },
isHideable: true,
},
{
diff --git a/src/stores/trove/instances-user.js b/src/stores/trove/instances-user.js
index ea5d0129..976ac78b 100644
--- a/src/stores/trove/instances-user.js
+++ b/src/stores/trove/instances-user.js
@@ -25,6 +25,10 @@ export class InstancesUsersStore extends Base {
return client.trove.instances.databases;
}
+ get instanceClient() {
+ return client.trove.instances;
+ }
+
get isSubResource() {
return true;
}
@@ -46,11 +50,9 @@ export class InstancesUsersStore extends Base {
const { databases = [] } = await this.databaseClient.list(id);
return items.map((it) => ({
...it,
- databases:
- (it.databases || [])
- .filter((l1) => databases.find((l2) => l2.name === l1.name))
- .map((db) => db.name)
- .join(' , ') || '-',
+ databases: (it.databases || [])
+ .filter((l1) => databases.find((l2) => l2.name === l1.name))
+ .map((db) => db.name),
}));
}
@@ -63,6 +65,11 @@ export class InstancesUsersStore extends Base {
async deleteUser({ id, name }) {
return this.submitting(this.client.delete(id, name));
}
+
+ @action
+ async grantDatabaseAccess({ id, name, data }) {
+ return this.submitting(this.instanceClient.grantDatabase(id, name, data));
+ }
}
const globalInstancesUsersStore = new InstancesUsersStore();