diff --git a/controllers/casbin_adapter.go b/controllers/casbin_adapter.go
index 4d394b9a..12fdc1a8 100644
--- a/controllers/casbin_adapter.go
+++ b/controllers/casbin_adapter.go
@@ -18,6 +18,7 @@ import (
"encoding/json"
"github.com/beego/beego/utils/pagination"
+ xormadapter "github.com/casbin/xorm-adapter/v3"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)
@@ -89,6 +90,69 @@ func (c *ApiController) SyncPolicies() {
id := c.Input().Get("id")
adapter := object.GetCasbinAdapter(id)
- c.Data["json"] = object.SyncPolicies(adapter)
+ policies, err := object.SyncPolicies(adapter)
+ if err != nil {
+ c.ResponseError(err.Error())
+ return
+ }
+
+ c.Data["json"] = policies
+ c.ServeJSON()
+}
+
+func (c *ApiController) UpdatePolicy() {
+ id := c.Input().Get("id")
+ adapter := object.GetCasbinAdapter(id)
+ var policies []xormadapter.CasbinRule
+ err := json.Unmarshal(c.Ctx.Input.RequestBody, &policies)
+ if err != nil {
+ c.ResponseError(err.Error())
+ return
+ }
+
+ affected, err := object.UpdatePolicy(util.CasbinToSlice(policies[0]), util.CasbinToSlice(policies[1]), adapter)
+ if err != nil {
+ c.ResponseError(err.Error())
+ return
+ }
+ c.Data["json"] = wrapActionResponse(affected)
+ c.ServeJSON()
+}
+
+func (c *ApiController) AddPolicy() {
+ id := c.Input().Get("id")
+ adapter := object.GetCasbinAdapter(id)
+ var policy xormadapter.CasbinRule
+ err := json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
+ if err != nil {
+ c.ResponseError(err.Error())
+ return
+ }
+
+ affected, err := object.AddPolicy(util.CasbinToSlice(policy), adapter)
+ if err != nil {
+ c.ResponseError(err.Error())
+ return
+ }
+ c.Data["json"] = wrapActionResponse(affected)
+ c.ServeJSON()
+}
+
+func (c *ApiController) RemovePolicy() {
+ id := c.Input().Get("id")
+ adapter := object.GetCasbinAdapter(id)
+ var policy xormadapter.CasbinRule
+ err := json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
+ if err != nil {
+ c.ResponseError(err.Error())
+ return
+ }
+
+ affected, err := object.RemovePolicy(util.CasbinToSlice(policy), adapter)
+ if err != nil {
+ c.ResponseError(err.Error())
+ return
+ }
+ c.Data["json"] = wrapActionResponse(affected)
c.ServeJSON()
}
diff --git a/object/casbin_adapter.go b/object/casbin_adapter.go
index 79f77892..c660a49f 100644
--- a/object/casbin_adapter.go
+++ b/object/casbin_adapter.go
@@ -148,34 +148,7 @@ func (casbinAdapter *CasbinAdapter) getTable() string {
}
}
-func safeReturn(policy []string, i int) string {
- if len(policy) > i {
- return policy[i]
- } else {
- return ""
- }
-}
-
-func matrixToCasbinRules(pType string, policies [][]string) []*xormadapter.CasbinRule {
- res := []*xormadapter.CasbinRule{}
-
- for _, policy := range policies {
- line := xormadapter.CasbinRule{
- Ptype: pType,
- V0: safeReturn(policy, 0),
- V1: safeReturn(policy, 1),
- V2: safeReturn(policy, 2),
- V3: safeReturn(policy, 3),
- V4: safeReturn(policy, 4),
- V5: safeReturn(policy, 5),
- }
- res = append(res, &line)
- }
-
- return res
-}
-
-func SyncPolicies(casbinAdapter *CasbinAdapter) []*xormadapter.CasbinRule {
+func initEnforcer(modelObj *Model, casbinAdapter *CasbinAdapter) (*casbin.Enforcer, error) {
// init Adapter
if casbinAdapter.Adapter == nil {
var dataSourceName string
@@ -191,20 +164,60 @@ func SyncPolicies(casbinAdapter *CasbinAdapter) []*xormadapter.CasbinRule {
dataSourceName = strings.ReplaceAll(dataSourceName, "dbi.", "db.")
}
- casbinAdapter.Adapter, _ = xormadapter.NewAdapterByEngineWithTableName(NewAdapter(casbinAdapter.DatabaseType, dataSourceName, casbinAdapter.Database).Engine, casbinAdapter.getTable(), "")
+ var err error
+ casbinAdapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(NewAdapter(casbinAdapter.DatabaseType, dataSourceName, casbinAdapter.Database).Engine, casbinAdapter.getTable(), "")
+ if err != nil {
+ return nil, err
+ }
}
// init Model
- modelObj := getModel(casbinAdapter.Owner, casbinAdapter.Model)
m, err := model.NewModelFromString(modelObj.ModelText)
if err != nil {
- panic(err)
+ return nil, err
}
// init Enforcer
enforcer, err := casbin.NewEnforcer(m, casbinAdapter.Adapter)
if err != nil {
- panic(err)
+ return nil, err
+ }
+
+ return enforcer, nil
+}
+
+func safeReturn(policy []string, i int) string {
+ if len(policy) > i {
+ return policy[i]
+ } else {
+ return ""
+ }
+}
+
+func matrixToCasbinRules(Ptype string, policies [][]string) []*xormadapter.CasbinRule {
+ res := []*xormadapter.CasbinRule{}
+
+ for _, policy := range policies {
+ line := xormadapter.CasbinRule{
+ Ptype: Ptype,
+ V0: safeReturn(policy, 0),
+ V1: safeReturn(policy, 1),
+ V2: safeReturn(policy, 2),
+ V3: safeReturn(policy, 3),
+ V4: safeReturn(policy, 4),
+ V5: safeReturn(policy, 5),
+ }
+ res = append(res, &line)
+ }
+
+ return res
+}
+
+func SyncPolicies(casbinAdapter *CasbinAdapter) ([]*xormadapter.CasbinRule, error) {
+ modelObj := getModel(casbinAdapter.Owner, casbinAdapter.Model)
+ enforcer, err := initEnforcer(modelObj, casbinAdapter)
+ if err != nil {
+ return nil, err
}
policies := matrixToCasbinRules("p", enforcer.GetPolicy())
@@ -212,5 +225,48 @@ func SyncPolicies(casbinAdapter *CasbinAdapter) []*xormadapter.CasbinRule {
policies = append(policies, matrixToCasbinRules("g", enforcer.GetGroupingPolicy())...)
}
- return policies
+ return policies, nil
+}
+
+func UpdatePolicy(oldPolicy, newPolicy []string, casbinAdapter *CasbinAdapter) (bool, error) {
+ modelObj := getModel(casbinAdapter.Owner, casbinAdapter.Model)
+ enforcer, err := initEnforcer(modelObj, casbinAdapter)
+ if err != nil {
+ return false, err
+ }
+
+ affected, err := enforcer.UpdatePolicy(oldPolicy, newPolicy)
+ if err != nil {
+ return affected, err
+ }
+ return affected, nil
+}
+
+func AddPolicy(policy []string, casbinAdapter *CasbinAdapter) (bool, error) {
+ modelObj := getModel(casbinAdapter.Owner, casbinAdapter.Model)
+ enforcer, err := initEnforcer(modelObj, casbinAdapter)
+ if err != nil {
+ return false, err
+ }
+
+ affected, err := enforcer.AddPolicy(policy)
+ if err != nil {
+ return affected, err
+ }
+ return affected, nil
+}
+
+func RemovePolicy(policy []string, casbinAdapter *CasbinAdapter) (bool, error) {
+ modelObj := getModel(casbinAdapter.Owner, casbinAdapter.Model)
+ enforcer, err := initEnforcer(modelObj, casbinAdapter)
+ if err != nil {
+ return false, err
+ }
+
+ affected, err := enforcer.RemovePolicy(policy)
+ if err != nil {
+ return affected, err
+ }
+
+ return affected, nil
}
diff --git a/routers/router.go b/routers/router.go
index 7d8e4c7c..4b03c706 100644
--- a/routers/router.go
+++ b/routers/router.go
@@ -105,6 +105,9 @@ func initAPI() {
beego.Router("/api/add-adapter", &controllers.ApiController{}, "POST:AddCasbinAdapter")
beego.Router("/api/delete-adapter", &controllers.ApiController{}, "POST:DeleteCasbinAdapter")
beego.Router("/api/sync-policies", &controllers.ApiController{}, "GET:SyncPolicies")
+ beego.Router("/api/update-policy", &controllers.ApiController{}, "POST:UpdatePolicy")
+ beego.Router("/api/add-policy", &controllers.ApiController{}, "POST:AddPolicy")
+ beego.Router("/api/remove-policy", &controllers.ApiController{}, "POST:RemovePolicy")
beego.Router("/api/set-password", &controllers.ApiController{}, "POST:SetPassword")
beego.Router("/api/check-user-password", &controllers.ApiController{}, "POST:CheckUserPassword")
diff --git a/util/struct.go b/util/struct.go
new file mode 100644
index 00000000..1dbedfc8
--- /dev/null
+++ b/util/struct.go
@@ -0,0 +1,29 @@
+// Copyright 2022 The Casdoor Authors. All Rights Reserved.
+//
+// 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.
+
+package util
+
+import xormadapter "github.com/casbin/xorm-adapter/v3"
+
+func CasbinToSlice(casbinRule xormadapter.CasbinRule) []string {
+ s := []string{
+ casbinRule.V0,
+ casbinRule.V1,
+ casbinRule.V2,
+ casbinRule.V3,
+ casbinRule.V4,
+ casbinRule.V5,
+ }
+ return s
+}
diff --git a/web/src/AdapterEditPage.js b/web/src/AdapterEditPage.js
index 4d0be6c6..825516ed 100644
--- a/web/src/AdapterEditPage.js
+++ b/web/src/AdapterEditPage.js
@@ -13,7 +13,7 @@
// limitations under the License.
import React from "react";
-import {Button, Card, Col, Input, InputNumber, Row, Select, Switch, Table, Tooltip} from "antd";
+import {Button, Card, Col, Input, InputNumber, Row, Select, Switch} from "antd";
import * as AdapterBackend from "./backend/AdapterBackend";
import * as OrganizationBackend from "./backend/OrganizationBackend";
import * as Setting from "./Setting";
@@ -21,7 +21,7 @@ import i18next from "i18next";
import "codemirror/lib/codemirror.css";
import * as ModelBackend from "./backend/ModelBackend";
-import {EditOutlined, MinusOutlined} from "@ant-design/icons";
+import PolicyTable from "./common/PoliciyTable";
require("codemirror/theme/material-darker.css");
require("codemirror/mode/javascript/javascript");
@@ -32,12 +32,11 @@ class AdapterEditPage extends React.Component {
super(props);
this.state = {
classes: props,
- organizationName: props.organizationName !== undefined ? props.organizationName : props.match.params.organizationName,
+ owner: props.organizationName !== undefined ? props.organizationName : props.match.params.organizationName,
adapterName: props.match.params.adapterName,
adapter: null,
organizations: [],
models: [],
- policyLists: [],
mode: props.location.mode !== undefined ? props.location.mode : "edit",
};
}
@@ -48,7 +47,7 @@ class AdapterEditPage extends React.Component {
}
getAdapter() {
- AdapterBackend.getAdapter(this.state.organizationName, this.state.adapterName)
+ AdapterBackend.getAdapter(this.state.owner, this.state.adapterName)
.then((adapter) => {
this.setState({
adapter: adapter,
@@ -93,93 +92,6 @@ class AdapterEditPage extends React.Component {
});
}
- synPolicies() {
- this.setState({loading: true});
- AdapterBackend.syncPolicies(this.state.adapter.owner, this.state.adapter.name)
- .then((res) => {
- this.setState({loading: false, policyLists: res});
- })
- .catch(error => {
- this.setState({loading: false});
- Setting.showMessage("error", `Adapter failed to get policies: ${error}`);
- });
- }
-
- renderTable(table) {
- const columns = [
- {
- title: "Rule Type",
- dataIndex: "PType",
- key: "PType",
- width: "100px",
- },
- {
- title: "V0",
- dataIndex: "V0",
- key: "V0",
- width: "100px",
- },
- {
- title: "V1",
- dataIndex: "V1",
- key: "V1",
- width: "100px",
- },
- {
- title: "V2",
- dataIndex: "V2",
- key: "V2",
- width: "100px",
- },
- {
- title: "V3",
- dataIndex: "V3",
- key: "V3",
- width: "100px",
- },
- {
- title: "V4",
- dataIndex: "V4",
- key: "V4",
- width: "100px",
- },
- {
- title: "V5",
- dataIndex: "V5",
- key: "V5",
- width: "100px",
- },
- {
- title: "Option",
- key: "option",
- width: "100px",
- render: (text, record, index) => {
- return (
-
-
- } size="small" />
-
-
- } size="small" />
-
-
- );
- },
- }];
-
- return (
-
- );
- }
-
renderAdapter() {
return (
{Setting.getLabel(i18next.t("adapter:Policies"), i18next.t("adapter:Policies - Tooltip"))} :
-
-
-
-
-
-
-
-
- {
- this.renderTable(this.state.policyLists)
- }
+
+
@@ -371,7 +272,7 @@ class AdapterEditPage extends React.Component {
if (willExist) {
this.props.history.push("/adapters");
} else {
- this.props.history.push(`/adapters/${this.state.adapter.name}`);
+ this.props.history.push(`/adapters/${this.state.owner}/${this.state.adapter.name}`);
}
} else {
Setting.showMessage("error", res.msg);
diff --git a/web/src/AdapterListPage.js b/web/src/AdapterListPage.js
index 09f653b7..c86a99b5 100644
--- a/web/src/AdapterListPage.js
+++ b/web/src/AdapterListPage.js
@@ -45,7 +45,7 @@ class AdapterListPage extends BaseListPage {
const newAdapter = this.newAdapter();
AdapterBackend.addAdapter(newAdapter)
.then((res) => {
- this.props.history.push({pathname: `/adapters/${newAdapter.owner}/${newAdapter.name}`, mode: "add"});
+ this.props.history.push({pathname: `/adapters/${newAdapter.organization}/${newAdapter.name}`, mode: "add"});
}
)
.catch(error => {
diff --git a/web/src/Setting.js b/web/src/Setting.js
index 016305e2..c1700b6d 100644
--- a/web/src/Setting.js
+++ b/web/src/Setting.js
@@ -416,9 +416,7 @@ export function goToLinkSoft(ths, link) {
}
export function showMessage(type, text) {
- if (type === "") {
- return;
- } else if (type === "success") {
+ if (type === "success") {
message.success(text);
} else if (type === "error") {
message.error(text);
@@ -445,8 +443,8 @@ export function deepCopy(obj) {
return Object.assign({}, obj);
}
-export function addRow(array, row) {
- return [...array, row];
+export function addRow(array, row, position = "end") {
+ return position === "end" ? [...array, row] : [row, ...array];
}
export function prependRow(array, row) {
diff --git a/web/src/backend/AdapterBackend.js b/web/src/backend/AdapterBackend.js
index ed706694..c393bb22 100644
--- a/web/src/backend/AdapterBackend.js
+++ b/web/src/backend/AdapterBackend.js
@@ -70,6 +70,41 @@ export function deleteAdapter(Adapter) {
}).then(res => res.json());
}
+export function UpdatePolicy(owner, name, policy) {
+ // eslint-disable-next-line no-console
+ console.log(policy);
+ return fetch(`${Setting.ServerUrl}/api/update-policy?id=${owner}/${encodeURIComponent(name)}`, {
+ method: "POST",
+ credentials: "include",
+ body: JSON.stringify(policy),
+ headers: {
+ "Accept-Language": Setting.getAcceptLanguage(),
+ },
+ }).then(res => res.json());
+}
+
+export function AddPolicy(owner, name, policy) {
+ return fetch(`${Setting.ServerUrl}/api/add-policy?id=${owner}/${encodeURIComponent(name)}`, {
+ method: "POST",
+ credentials: "include",
+ body: JSON.stringify(policy),
+ headers: {
+ "Accept-Language": Setting.getAcceptLanguage(),
+ },
+ }).then(res => res.json());
+}
+
+export function RemovePolicy(owner, name, policy) {
+ return fetch(`${Setting.ServerUrl}/api/remove-policy?id=${owner}/${encodeURIComponent(name)}`, {
+ method: "POST",
+ credentials: "include",
+ body: JSON.stringify(policy),
+ headers: {
+ "Accept-Language": Setting.getAcceptLanguage(),
+ },
+ }).then(res => res.json());
+}
+
export function syncPolicies(owner, name) {
return fetch(`${Setting.ServerUrl}/api/sync-policies?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET",
diff --git a/web/src/common/PoliciyTable.js b/web/src/common/PoliciyTable.js
new file mode 100644
index 00000000..7b69974c
--- /dev/null
+++ b/web/src/common/PoliciyTable.js
@@ -0,0 +1,308 @@
+// Copyright 2022 The Casdoor Authors. All Rights Reserved.
+//
+// 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 React from "react";
+import {DeleteOutlined, EditOutlined} from "@ant-design/icons";
+import {Button, Input, Popconfirm, Table, Tooltip} from "antd";
+import * as Setting from "../Setting";
+import * as AdapterBackend from "../backend/AdapterBackend";
+import i18next from "i18next";
+
+class PolicyTable extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ policyLists: [],
+ loading: false,
+ editingIndex: "",
+ oldPolicy: "",
+ add: false,
+ };
+ }
+
+ UNSAFE_componentWillMount() {
+ if (this.props.mode === "edit") {
+ this.synPolicies();
+ }
+ }
+
+ isEditing = (index) => {
+ return index === this.state.editingIndex;
+ };
+
+ edit = (record, index) => {
+ this.setState({editingIndex: index, oldPolicy: Setting.deepCopy(record)});
+ };
+
+ cancel = (table, index) => {
+ Object.keys(table[index]).forEach((key) => {
+ table[index][key] = this.state.oldPolicy[key];
+ });
+ this.updateTable(table);
+ this.setState({editingIndex: "", oldPolicy: ""});
+ if (this.state.add) {
+ this.deleteRow(this.state.policyLists, index);
+ this.setState({add: false});
+ }
+ };
+
+ updateTable(table) {
+ this.setState({policyLists: table});
+ }
+
+ updateField(table, index, key, value) {
+ table[index][key] = value;
+ this.updateTable(table);
+ }
+
+ addRow(table) {
+ const row = {Ptype: "p"};
+ if (table === undefined) {
+ table = [];
+ }
+ table = Setting.addRow(table, row, "top");
+ this.updateTable(table);
+ this.edit(row, 0);
+ this.setState({add: true});
+ }
+
+ deleteRow(table, i) {
+ table = Setting.deleteRow(table, i);
+ this.updateTable(table);
+ }
+
+ save(table, i) {
+ this.state.add ? this.addPolicy(table, i) : this.updatePolicy(table, i);
+ }
+
+ synPolicies() {
+ this.setState({loading: true});
+ AdapterBackend.syncPolicies(this.props.owner, this.props.name)
+ .then((res) => {
+ if (res.status !== "error") {
+ this.setState({loading: false, policyLists: res});
+ } else {
+ this.setState({loading: false});
+ Setting.showMessage("error", `Adapter failed to get policies, ${res.msg}`);
+ }
+ })
+ .catch(error => {
+ this.setState({loading: false});
+ Setting.showMessage("error", `Adapter failed to get policies, ${error}`);
+ });
+ }
+
+ updatePolicy(table, i) {
+ AdapterBackend.UpdatePolicy(this.props.owner, this.props.name, [this.state.oldPolicy, table[i]]).then(res => {
+ if (res.status === "ok") {
+ this.setState({editingIndex: "", oldPolicy: ""});
+ Setting.showMessage("success", i18next.t("adapter:Update policy successfully"));
+ } else {
+ Setting.showMessage("error", i18next.t(`adapter:Update policy failed, ${res.msg}`));
+ }
+ });
+ }
+
+ addPolicy(table, i) {
+ AdapterBackend.AddPolicy(this.props.owner, this.props.name, table[i]).then(res => {
+ if (res.status === "ok") {
+ this.setState({editingIndex: "", oldPolicy: "", add: false});
+ if (res.data !== "Affected") {
+ Setting.showMessage("info", i18next.t("adapter:Repeated policy"));
+ } else {
+ Setting.showMessage("success", i18next.t("adapter:Add policy successfully"));
+ }
+ } else {
+ Setting.showMessage("error", i18next.t(`adapter:Add policy failed, ${res.msg}`));
+ }
+ });
+ }
+
+ deletePolicy(table, i) {
+ AdapterBackend.RemovePolicy(this.props.owner, this.props.name, table[i]).then(res => {
+ if (res.status === "ok") {
+ table = Setting.deleteRow(table, i);
+ this.updateTable(table);
+ Setting.showMessage("success", i18next.t("adapter:Delete policy successfully"));
+ } else {
+ Setting.showMessage("error", i18next.t(`adapter:Delete policy failed, ${res.msg}`));
+ }
+ });
+ }
+
+ renderTable(table) {
+ const columns = [
+ {
+ title: "Rule Type",
+ dataIndex: "Ptype",
+ width: "100px",
+ // render: (text, record, index) => {
+ // const editing = this.isEditing(index);
+ // return (
+ // editing ?
+ // {
+ // this.updateField(table, index, "Ptype", e.target.value);
+ // }} />
+ // : text
+ // );
+ // },
+ },
+ {
+ title: "V0",
+ dataIndex: "V0",
+ width: "100px",
+ render: (text, record, index) => {
+ const editing = this.isEditing(index);
+ return (
+ editing ?
+ {
+ this.updateField(table, index, "V0", e.target.value);
+ }} />
+ : text
+ );
+ },
+ },
+ {
+ title: "V1",
+ dataIndex: "V1",
+ width: "100px",
+ render: (text, record, index) => {
+ const editing = this.isEditing(index);
+ return (
+ editing ?
+ {
+ this.updateField(table, index, "V1", e.target.value);
+ }} />
+ : text
+ );
+ },
+ },
+ {
+ title: "V2",
+ dataIndex: "V2",
+ width: "100px",
+ render: (text, record, index) => {
+ const editing = this.isEditing(index);
+ return (
+ editing ?
+ {
+ this.updateField(table, index, "V2", e.target.value);
+ }} />
+ : text
+ );
+ },
+ },
+ {
+ title: "V3",
+ dataIndex: "V3",
+ width: "100px",
+ render: (text, record, index) => {
+ const editing = this.isEditing(index);
+ return (
+ editing ?
+ {
+ this.updateField(table, index, "V3", e.target.value);
+ }} />
+ : text
+ );
+ },
+ },
+ {
+ title: "V4",
+ dataIndex: "V4",
+ width: "100px",
+ render: (text, record, index) => {
+ const editing = this.isEditing(index);
+ return (
+ editing ?
+ {
+ this.updateField(table, index, "V4", e.target.value);
+ }} />
+ : text
+ );
+ },
+ },
+ {
+ title: "V5",
+ dataIndex: "V5",
+ width: "100px",
+ render: (text, record, index) => {
+ const editing = this.isEditing(index);
+ return (
+ editing ?
+ {
+ this.updateField(table, index, "V5", e.target.value);
+ }} />
+ : text
+ );
+ },
+ },
+ {
+ title: "Option",
+ key: "option",
+ width: "100px",
+ render: (text, record, index) => {
+ const editable = this.isEditing(index);
+ return editable ? (
+
+
+ this.cancel(table, index)}>
+ Cancel
+
+
+ ) : (
+
+
+ } size="small" onClick={() => this.edit(record, index)} />
+
+
+ } size="small" onClick={() => this.deletePolicy(table, index)} />
+
+
+ );
+ },
+ }];
+
+ return (
+ (
+
+
+
+ )}
+ />
+ );
+ }
+
+ render() {
+ return (<>
+
+ {
+ this.renderTable(this.state.policyLists)
+ }
+ >
+ );
+ }
+}
+
+export default PolicyTable;
diff --git a/web/src/locales/de/data.json b/web/src/locales/de/data.json
index 07dbb2d0..b92b0437 100644
--- a/web/src/locales/de/data.json
+++ b/web/src/locales/de/data.json
@@ -6,11 +6,15 @@
"Sign Up": "Registrieren"
},
"adapter": {
+ "Add policy successfully": "Add policy successfully",
+ "Delete policy successfully": "Delete policy successfully",
"Edit Adapter": "Edit Adapter",
"New Adapter": "New Adapter",
"Policies": "Policies",
"Policies - Tooltip": "Policies - Tooltip",
- "Sync": "Sync"
+ "Repeated policy": "Repeated policy",
+ "Sync": "Sync",
+ "Update policy successfully": "Update policy successfully"
},
"application": {
"Always": "Always",
@@ -555,6 +559,7 @@
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "UserInfo URL - Tooltip",
"Visible": "Visible",
+ "admin (share)": "admin (share)",
"alertType": "alarmtyp"
},
"record": {
diff --git a/web/src/locales/en/data.json b/web/src/locales/en/data.json
index 83e0d770..b3572762 100644
--- a/web/src/locales/en/data.json
+++ b/web/src/locales/en/data.json
@@ -6,11 +6,15 @@
"Sign Up": "Sign Up"
},
"adapter": {
+ "Add policy successfully": "Add policy successfully",
+ "Delete policy successfully": "Delete policy successfully",
"Edit Adapter": "Edit Adapter",
"New Adapter": "New Adapter",
"Policies": "Policies",
"Policies - Tooltip": "Policies - Tooltip",
- "Sync": "Sync"
+ "Repeated policy": "Repeated policy",
+ "Sync": "Sync",
+ "Update policy successfully": "Update policy successfully"
},
"application": {
"Always": "Always",
@@ -555,6 +559,7 @@
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "UserInfo URL - Tooltip",
"Visible": "Visible",
+ "admin (share)": "admin (share)",
"alertType": "alertType"
},
"record": {
diff --git a/web/src/locales/fr/data.json b/web/src/locales/fr/data.json
index 43099446..b6cc6cb4 100644
--- a/web/src/locales/fr/data.json
+++ b/web/src/locales/fr/data.json
@@ -6,11 +6,15 @@
"Sign Up": "S'inscrire"
},
"adapter": {
+ "Add policy successfully": "Add policy successfully",
+ "Delete policy successfully": "Delete policy successfully",
"Edit Adapter": "Edit Adapter",
"New Adapter": "New Adapter",
"Policies": "Policies",
"Policies - Tooltip": "Policies - Tooltip",
- "Sync": "Sync"
+ "Repeated policy": "Repeated policy",
+ "Sync": "Sync",
+ "Update policy successfully": "Update policy successfully"
},
"application": {
"Always": "Always",
@@ -555,6 +559,7 @@
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "UserInfo URL - Tooltip",
"Visible": "Visible",
+ "admin (share)": "admin (share)",
"alertType": "Type d'alerte"
},
"record": {
diff --git a/web/src/locales/ja/data.json b/web/src/locales/ja/data.json
index 7147003f..4ef6eade 100644
--- a/web/src/locales/ja/data.json
+++ b/web/src/locales/ja/data.json
@@ -6,11 +6,15 @@
"Sign Up": "新規登録"
},
"adapter": {
+ "Add policy successfully": "Add policy successfully",
+ "Delete policy successfully": "Delete policy successfully",
"Edit Adapter": "Edit Adapter",
"New Adapter": "New Adapter",
"Policies": "Policies",
"Policies - Tooltip": "Policies - Tooltip",
- "Sync": "Sync"
+ "Repeated policy": "Repeated policy",
+ "Sync": "Sync",
+ "Update policy successfully": "Update policy successfully"
},
"application": {
"Always": "Always",
@@ -555,6 +559,7 @@
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "UserInfo URL - Tooltip",
"Visible": "Visible",
+ "admin (share)": "admin (share)",
"alertType": "alertType"
},
"record": {
diff --git a/web/src/locales/ko/data.json b/web/src/locales/ko/data.json
index a6804535..8f7f0752 100644
--- a/web/src/locales/ko/data.json
+++ b/web/src/locales/ko/data.json
@@ -6,11 +6,15 @@
"Sign Up": "Sign Up"
},
"adapter": {
+ "Add policy successfully": "Add policy successfully",
+ "Delete policy successfully": "Delete policy successfully",
"Edit Adapter": "Edit Adapter",
"New Adapter": "New Adapter",
"Policies": "Policies",
"Policies - Tooltip": "Policies - Tooltip",
- "Sync": "Sync"
+ "Repeated policy": "Repeated policy",
+ "Sync": "Sync",
+ "Update policy successfully": "Update policy successfully"
},
"application": {
"Always": "Always",
@@ -555,6 +559,7 @@
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "UserInfo URL - Tooltip",
"Visible": "Visible",
+ "admin (share)": "admin (share)",
"alertType": "alertType"
},
"record": {
diff --git a/web/src/locales/ru/data.json b/web/src/locales/ru/data.json
index fae7c09f..d57afed9 100644
--- a/web/src/locales/ru/data.json
+++ b/web/src/locales/ru/data.json
@@ -6,11 +6,15 @@
"Sign Up": "Регистрация"
},
"adapter": {
+ "Add policy successfully": "Add policy successfully",
+ "Delete policy successfully": "Delete policy successfully",
"Edit Adapter": "Edit Adapter",
"New Adapter": "New Adapter",
"Policies": "Policies",
"Policies - Tooltip": "Policies - Tooltip",
- "Sync": "Sync"
+ "Repeated policy": "Repeated policy",
+ "Sync": "Sync",
+ "Update policy successfully": "Update policy successfully"
},
"application": {
"Always": "Always",
@@ -555,6 +559,7 @@
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "UserInfo URL - Tooltip",
"Visible": "Visible",
+ "admin (share)": "admin (share)",
"alertType": "тип оповещения"
},
"record": {
diff --git a/web/src/locales/zh/data.json b/web/src/locales/zh/data.json
index db93a6cf..a57c6967 100644
--- a/web/src/locales/zh/data.json
+++ b/web/src/locales/zh/data.json
@@ -6,11 +6,15 @@
"Sign Up": "注册"
},
"adapter": {
+ "Add policy successfully": "添加策略成功",
+ "Delete policy successfully": "删除策略成功",
"Edit Adapter": "编辑适配器",
"New Adapter": "添加适配器",
"Policies": "策略",
"Policies - Tooltip": "策略",
- "Sync": "同步"
+ "Repeated policy": "策略重复",
+ "Sync": "同步",
+ "Update policy successfully": "更新策略成功"
},
"application": {
"Always": "始终开启",
@@ -555,6 +559,7 @@
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "UserInfo URL - 工具提示",
"Visible": "是否可见",
+ "admin (share)": "admin (share)",
"alertType": "警报类型"
},
"record": {