diff --git a/object/application.go b/object/application.go
index 768d8a62..ce217025 100644
--- a/object/application.go
+++ b/object/application.go
@@ -32,6 +32,7 @@ type Application struct {
EnablePassword bool `json:"enablePassword"`
EnableSignUp bool `json:"enableSignUp"`
Providers []*ProviderItem `xorm:"varchar(10000)" json:"providers"`
+ SignupItems []*SignupItem `xorm:"varchar(1000)" json:"signupItems"`
OrganizationObj *Organization `xorm:"-" json:"organizationObj"`
ClientId string `xorm:"varchar(100)" json:"clientId"`
diff --git a/object/init.go b/object/init.go
index ce6f5a30..799d823e 100644
--- a/object/init.go
+++ b/object/init.go
@@ -67,6 +67,7 @@ func initBuiltInApplication() {
EnablePassword: true,
EnableSignUp: true,
Providers: []*ProviderItem{},
+ SignupItems: []*SignupItem{},
RedirectUris: []string{},
ExpireInHours: 168,
}
diff --git a/object/signup_item.go b/object/signup_item.go
new file mode 100644
index 00000000..e86b6413
--- /dev/null
+++ b/object/signup_item.go
@@ -0,0 +1,22 @@
+// Copyright 2021 The casbin 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 object
+
+type SignupItem struct {
+ Name string `json:"name"`
+ Visible bool `json:"visible"`
+ Required bool `json:"required"`
+ Rule string `json:"rule"`
+}
diff --git a/web/src/ApplicationEditPage.js b/web/src/ApplicationEditPage.js
index 06fdc039..5f6dc3a2 100644
--- a/web/src/ApplicationEditPage.js
+++ b/web/src/ApplicationEditPage.js
@@ -24,6 +24,7 @@ import LoginPage from "./auth/LoginPage";
import i18next from "i18next";
import UrlTable from "./UrlTable";
import ProviderTable from "./ProviderTable";
+import SignupTable from "./SignupTable";
const { Option } = Select;
@@ -299,6 +300,18 @@ class ApplicationEditPage extends React.Component {
this.renderPreview()
}
+
+
+ {i18next.t("application:Signup items")}:
+
+
+ { this.updateApplicationField('signupItems', value)}}
+ />
+
+
)
}
diff --git a/web/src/ProviderTable.js b/web/src/ProviderTable.js
index 2d3e70b6..64ea547a 100644
--- a/web/src/ProviderTable.js
+++ b/web/src/ProviderTable.js
@@ -13,8 +13,8 @@
// limitations under the License.
import React from "react";
-import {DownOutlined, DeleteOutlined, UpOutlined, LinkOutlined} from '@ant-design/icons';
-import {Button, Col, Input, Row, Select, Switch, Table, Tooltip} from 'antd';
+import {DownOutlined, DeleteOutlined, UpOutlined} from '@ant-design/icons';
+import {Button, Col, Row, Select, Switch, Table, Tooltip} from 'antd';
import * as Setting from "./Setting";
import i18next from "i18next";
@@ -81,11 +81,6 @@ class ProviderTable extends React.Component {
}
)
- return (
- } value={text} onChange={e => {
- this.updateField(table, index, 'name', e.target.value);
- }} />
- )
}
},
{
diff --git a/web/src/SignupTable.js b/web/src/SignupTable.js
new file mode 100644
index 00000000..20efc33c
--- /dev/null
+++ b/web/src/SignupTable.js
@@ -0,0 +1,197 @@
+// Copyright 2021 The casbin 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 {DownOutlined, DeleteOutlined, UpOutlined} from '@ant-design/icons';
+import {Button, Col, Row, Select, Switch, Table, Tooltip} from 'antd';
+import * as Setting from "./Setting";
+import i18next from "i18next";
+
+const { Option } = Select;
+
+class SignupTable extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ classes: props,
+ };
+ }
+
+ updateTable(table) {
+ this.props.onUpdateTable(table);
+ }
+
+ updateField(table, index, key, value) {
+ table[index][key] = value;
+ this.updateTable(table);
+ }
+
+ addRow(table) {
+ let row = {name: "Please select a signup item", visible: true, required: true, rule: "None"};
+ if (table === undefined) {
+ table = [];
+ }
+ table = Setting.addRow(table, row);
+ this.updateTable(table);
+ }
+
+ deleteRow(table, i) {
+ table = Setting.deleteRow(table, i);
+ this.updateTable(table);
+ }
+
+ upRow(table, i) {
+ table = Setting.swapRow(table, i - 1, i);
+ this.updateTable(table);
+ }
+
+ downRow(table, i) {
+ table = Setting.swapRow(table, i, i + 1);
+ this.updateTable(table);
+ }
+
+ renderTable(table) {
+ const columns = [
+ {
+ title: i18next.t("provider:Name"),
+ dataIndex: 'name',
+ key: 'name',
+ render: (text, record, index) => {
+ return (
+
+ )
+ }
+ },
+ {
+ title: i18next.t("provider:visible"),
+ dataIndex: 'visible',
+ key: 'visible',
+ width: '120px',
+ render: (text, record, index) => {
+ return (
+ {
+ this.updateField(table, index, 'visible', checked);
+ if (!checked) {
+ this.updateField(table, index, 'required', false);
+ }
+ }} />
+ )
+ }
+ },
+ {
+ title: i18next.t("provider:required"),
+ dataIndex: 'required',
+ key: 'required',
+ width: '120px',
+ render: (text, record, index) => {
+ if (!record.visible) {
+ return null;
+ }
+
+ return (
+ {
+ this.updateField(table, index, 'required', checked);
+ }} />
+ )
+ }
+ },
+ {
+ title: i18next.t("provider:rule"),
+ dataIndex: 'rule',
+ key: 'rule',
+ width: '120px',
+ render: (text, record, index) => {
+ return (
+
+ )
+ }
+ },
+ {
+ title: i18next.t("general:Action"),
+ key: 'action',
+ width: '100px',
+ render: (text, record, index) => {
+ return (
+