diff --git a/controllers/account.go b/controllers/account.go
index 98a7c343..2b06628d 100644
--- a/controllers/account.go
+++ b/controllers/account.go
@@ -41,6 +41,7 @@ type RequestForm struct {
Email string `json:"email"`
Phone string `json:"phone"`
Affiliation string `json:"affiliation"`
+ Region string `json:"region"`
Application string `json:"application"`
Provider string `json:"provider"`
@@ -149,6 +150,7 @@ func (c *ApiController) Signup() {
Phone: form.Phone,
Address: []string{},
Affiliation: form.Affiliation,
+ Region: form.Region,
IsAdmin: false,
IsGlobalAdmin: false,
IsForbidden: false,
diff --git a/object/user.go b/object/user.go
index 363e432e..2ce091e9 100644
--- a/object/user.go
+++ b/object/user.go
@@ -37,6 +37,7 @@ type User struct {
Address []string `json:"address"`
Affiliation string `xorm:"varchar(100)" json:"affiliation"`
Tag string `xorm:"varchar(100)" json:"tag"`
+ Region string `xorm:"varchar(100)" json:"region"`
Language string `xorm:"varchar(100)" json:"language"`
Score int `json:"score"`
IsAdmin bool `json:"isAdmin"`
@@ -145,7 +146,7 @@ func UpdateUser(id string, user *User) bool {
user.UpdateUserHash()
affected, err := adapter.Engine.ID(core.PK{owner, name}).Cols("owner", "display_name", "avatar",
- "address", "language", "affiliation", "score", "tag", "is_admin", "is_global_admin", "is_forbidden",
+ "address", "region", "language", "affiliation", "score", "tag", "is_admin", "is_global_admin", "is_forbidden",
"hash", "properties").Update(user)
if err != nil {
panic(err)
diff --git a/web/src/SelectRegionBox.js b/web/src/SelectRegionBox.js
new file mode 100644
index 00000000..2848e712
--- /dev/null
+++ b/web/src/SelectRegionBox.js
@@ -0,0 +1,61 @@
+// 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 * as Setting from "./Setting";
+import { Select } from "antd";
+
+const { Option } = Select;
+
+class SelectRegionBox extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ classes: props,
+ value: "",
+ };
+ }
+
+ onChange(e) {
+ this.props.onChange(e);
+ this.setState({value: e})
+ };
+
+ render() {
+ return (
+
+ )
+ };
+}
+
+export default SelectRegionBox;
diff --git a/web/src/Setting.js b/web/src/Setting.js
index 6bae541f..d1c56254 100644
--- a/web/src/Setting.js
+++ b/web/src/Setting.js
@@ -33,6 +33,9 @@ export const EmailRegEx = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(
// https://learnku.com/articles/31543, `^s*$` filter empty email individually.
export const PhoneRegEx = /^\s*$|^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/;
+// https://catamphetamine.gitlab.io/country-flag-icons/3x2/index.html
+export const CountryRegionData = [{name: "Ascension Island", code: "AC"},{name: "Andorra", code: "AD"},{name: "United Arab Emirates", code: "AE"},{name: "Afghanistan", code: "AF"},{name: "Antigua and Barbuda", code: "AG"},{name: "Anguilla", code: "AI"},{name: "Albania", code: "AL"},{name: "Armenia", code: "AM"},{name: "Angola", code: "AO"},{name: "Antarctica", code: "AQ"},{name: "Argentina", code: "AR"},{name: "American Samoa", code: "AS"},{name: "Austria", code: "AT"},{name: "Australia", code: "AU"},{name: "Aruba", code: "AW"},{name: "Åland Islands", code: "AX"},{name: "Azerbaijan", code: "AZ"},{name: "Bosnia and Herzegovina", code: "BA"},{name: "Barbados", code: "BB"},{name: "Bangladesh", code: "BD"},{name: "Belgium", code: "BE"},{name: "Burkina Faso", code: "BF"},{name: "Bulgaria", code: "BG"},{name: "Bahrain", code: "BH"},{name: "Burundi", code: "BI"},{name: "Benin", code: "BJ"},{name: "Saint Barthélemy", code: "BL"},{name: "Bermuda", code: "BM"},{name: "Brunei Darussalam", code: "BN"},{name: "Bolivia", code: "BO"},{name: "Bonaire, Sint Eustatius and Saba", code: "BQ"},{name: "Brazil", code: "BR"},{name: "Bahamas", code: "BS"},{name: "Bhutan", code: "BT"},{name: "Bouvet Island", code: "BV"},{name: "Botswana", code: "BW"},{name: "Belarus", code: "BY"},{name: "Belize", code: "BZ"},{name: "Canada", code: "CA"},{name: "Cocos (Keeling) Islands", code: "CC"},{name: "Congo, Democratic Republic of the", code: "CD"},{name: "Central African Republic", code: "CF"},{name: "Congo", code: "CG"},{name: "Switzerland", code: "CH"},{name: "Cote d'Ivoire", code: "CI"},{name: "Cook Islands", code: "CK"},{name: "Chile", code: "CL"},{name: "Cameroon", code: "CM"},{name: "China", code: "CN"},{name: "Colombia", code: "CO"},{name: "Costa Rica", code: "CR"},{name: "Cuba", code: "CU"},{name: "Cape Verde", code: "CV"},{name: "Curaçao", code: "CW"},{name: "Christmas Island", code: "CX"},{name: "Cyprus", code: "CY"},{name: "Czech Republic", code: "CZ"},{name: "Germany", code: "DE"},{name: "Djibouti", code: "DJ"},{name: "Denmark", code: "DK"},{name: "Dominica", code: "DM"},{name: "Dominican Republic", code: "DO"},{name: "Algeria", code: "DZ"},{name: "Ecuador", code: "EC"},{name: "Estonia", code: "EE"},{name: "Egypt", code: "EG"},{name: "Western Sahara", code: "EH"},{name: "Eritrea", code: "ER"},{name: "Spain", code: "ES"},{name: "Ethiopia", code: "ET"},{name: "Finland", code: "FI"},{name: "Fiji", code: "FJ"},{name: "Falkland Islands", code: "FK"},{name: "Federated States of Micronesia", code: "FM"},{name: "Faroe Islands", code: "FO"},{name: "France", code: "FR"},{name: "Gabon", code: "GA"},{name: "United Kingdom", code: "GB"},{name: "Grenada", code: "GD"},{name: "Georgia", code: "GE"},{name: "French Guiana", code: "GF"},{name: "Guernsey", code: "GG"},{name: "Ghana", code: "GH"},{name: "Gibraltar", code: "GI"},{name: "Greenland", code: "GL"},{name: "Gambia", code: "GM"},{name: "Guinea", code: "GN"},{name: "Guadeloupe", code: "GP"},{name: "Equatorial Guinea", code: "GQ"},{name: "Greece", code: "GR"},{name: "South Georgia and the South Sandwich Islands", code: "GS"},{name: "Guatemala", code: "GT"},{name: "Guam", code: "GU"},{name: "Guinea-Bissau", code: "GW"},{name: "Guyana", code: "GY"},{name: "Hong Kong", code: "HK"},{name: "Heard Island and McDonald Islands", code: "HM"},{name: "Honduras", code: "HN"},{name: "Croatia", code: "HR"},{name: "Haiti", code: "HT"},{name: "Hungary", code: "HU"},{name: "Indonesia", code: "ID"},{name: "Ireland", code: "IE"},{name: "Israel", code: "IL"},{name: "Isle of Man", code: "IM"},{name: "India", code: "IN"},{name: "British Indian Ocean Territory", code: "IO"},{name: "Iraq", code: "IQ"},{name: "Iran", code: "IR"},{name: "Iceland", code: "IS"},{name: "Italy", code: "IT"},{name: "Jersey", code: "JE"},{name: "Jamaica", code: "JM"},{name: "Jordan", code: "JO"},{name: "Japan", code: "JP"},{name: "Kenya", code: "KE"},{name: "Kyrgyzstan", code: "KG"},{name: "Cambodia", code: "KH"},{name: "Kiribati", code: "KI"},{name: "Comoros", code: "KM"},{name: "Saint Kitts and Nevis", code: "KN"},{name: "North Korea", code: "KP"},{name: "South Korea", code: "KR"},{name: "Kuwait", code: "KW"},{name: "Cayman Islands", code: "KY"},{name: "Kazakhstan", code: "KZ"},{name: "Laos", code: "LA"},{name: "Lebanon", code: "LB"},{name: "Saint Lucia", code: "LC"},{name: "Liechtenstein", code: "LI"},{name: "Sri Lanka", code: "LK"},{name: "Liberia", code: "LR"},{name: "Lesotho", code: "LS"},{name: "Lithuania", code: "LT"},{name: "Luxembourg", code: "LU"},{name: "Latvia", code: "LV"},{name: "Libya", code: "LY"},{name: "Morocco", code: "MA"},{name: "Monaco", code: "MC"},{name: "Moldova", code: "MD"},{name: "Montenegro", code: "ME"},{name: "Saint Martin (French Part)", code: "MF"},{name: "Madagascar", code: "MG"},{name: "Marshall Islands", code: "MH"},{name: "North Macedonia", code: "MK"},{name: "Mali", code: "ML"},{name: "Burma", code: "MM"},{name: "Mongolia", code: "MN"},{name: "Macao", code: "MO"},{name: "Northern Mariana Islands", code: "MP"},{name: "Martinique", code: "MQ"},{name: "Mauritania", code: "MR"},{name: "Montserrat", code: "MS"},{name: "Malta", code: "MT"},{name: "Mauritius", code: "MU"},{name: "Maldives", code: "MV"},{name: "Malawi", code: "MW"},{name: "Mexico", code: "MX"},{name: "Malaysia", code: "MY"},{name: "Mozambique", code: "MZ"},{name: "Namibia", code: "NA"},{name: "New Caledonia", code: "NC"},{name: "Niger", code: "NE"},{name: "Norfolk Island", code: "NF"},{name: "Nigeria", code: "NG"},{name: "Nicaragua", code: "NI"},{name: "Netherlands", code: "NL"},{name: "Norway", code: "NO"},{name: "Nepal", code: "NP"},{name: "Nauru", code: "NR"},{name: "Niue", code: "NU"},{name: "New Zealand", code: "NZ"},{name: "Oman", code: "OM"},{name: "Panama", code: "PA"},{name: "Peru", code: "PE"},{name: "French Polynesia", code: "PF"},{name: "Papua New Guinea", code: "PG"},{name: "Philippines", code: "PH"},{name: "Pakistan", code: "PK"},{name: "Poland", code: "PL"},{name: "Saint Pierre and Miquelon", code: "PM"},{name: "Pitcairn", code: "PN"},{name: "Puerto Rico", code: "PR"},{name: "Palestine", code: "PS"},{name: "Portugal", code: "PT"},{name: "Palau", code: "PW"},{name: "Paraguay", code: "PY"},{name: "Qatar", code: "QA"},{name: "Reunion", code: "RE"},{name: "Romania", code: "RO"},{name: "Serbia", code: "RS"},{name: "Russia", code: "RU"},{name: "Rwanda", code: "RW"},{name: "Saudi Arabia", code: "SA"},{name: "Solomon Islands", code: "SB"},{name: "Seychelles", code: "SC"},{name: "Sudan", code: "SD"},{name: "Sweden", code: "SE"},{name: "Singapore", code: "SG"},{name: "Saint Helena", code: "SH"},{name: "Slovenia", code: "SI"},{name: "Svalbard and Jan Mayen", code: "SJ"},{name: "Slovakia", code: "SK"},{name: "Sierra Leone", code: "SL"},{name: "San Marino", code: "SM"},{name: "Senegal", code: "SN"},{name: "Somalia", code: "SO"},{name: "Suriname", code: "SR"},{name: "South Sudan", code: "SS"},{name: "Sao Tome and Principe", code: "ST"},{name: "El Salvador", code: "SV"},{name: "Sint Maarten", code: "SX"},{name: "Syria", code: "SY"},{name: "Swaziland", code: "SZ"},{name: "Tristan da Cunha", code: "TA"},{name: "Turks and Caicos Islands", code: "TC"},{name: "Chad", code: "TD"},{name: "French Southern Territories", code: "TF"},{name: "Togo", code: "TG"},{name: "Thailand", code: "TH"},{name: "Tajikistan", code: "TJ"},{name: "Tokelau", code: "TK"},{name: "Timor-Leste", code: "TL"},{name: "Turkmenistan", code: "TM"},{name: "Tunisia", code: "TN"},{name: "Tonga", code: "TO"},{name: "Turkey", code: "TR"},{name: "Trinidad and Tobago", code: "TT"},{name: "Tuvalu", code: "TV"},{name: "Taiwan", code: "TW"},{name: "Tanzania", code: "TZ"},{name: "Ukraine", code: "UA"},{name: "Uganda", code: "UG"},{name: "United States", code: "US"},{name: "Uruguay", code: "UY"},{name: "Uzbekistan", code: "UZ"},{name: "Holy See (Vatican City State)", code: "VA"},{name: "Saint Vincent and the Grenadines", code: "VC"},{name: "Venezuela", code: "VE"},{name: "Virgin Islands, British", code: "VG"},{name: "Virgin Islands, U.S.", code: "VI"},{name: "Vietnam", code: "VN"},{name: "Vanuatu", code: "VU"},{name: "Wallis and Futuna", code: "WF"},{name: "Samoa", code: "WS"},{name: "Kosovo", code: "XK"},{name: "Yemen", code: "YE"},{name: "Mayotte", code: "YT"},{name: "South Africa", code: "ZA"},{name: "Zambia", code: "ZM"},{name: "Zimbabwe", code: "ZW"}];
+
export function initServerUrl() {
const hostname = window.location.hostname;
if (hostname === "localhost") {
diff --git a/web/src/SignupTable.js b/web/src/SignupTable.js
index 6d6d97fc..eb181025 100644
--- a/web/src/SignupTable.js
+++ b/web/src/SignupTable.js
@@ -73,6 +73,7 @@ class SignupTable extends React.Component {
{id: 'ID', name: 'ID'},
{id: 'Display name', name: 'Display name'},
{id: 'Affiliation', name: 'Affiliation'},
+ {id: 'Country/Region', name: 'Country/Region'},
{id: 'Email', name: 'Email'},
{id: 'Password', name: 'Password'},
{id: 'Confirm password', name: 'Confirm password'},
diff --git a/web/src/UserEditPage.js b/web/src/UserEditPage.js
index e66cc9e4..dcf78ea9 100644
--- a/web/src/UserEditPage.js
+++ b/web/src/UserEditPage.js
@@ -25,6 +25,7 @@ import PasswordModal from "./PasswordModal";
import ResetModal from "./ResetModal";
import AffiliationSelect from "./common/AffiliationSelect";
import OAuthWidget from "./common/OAuthWidget";
+import SelectRegionBox from "./SelectRegionBox";
import "codemirror/lib/codemirror.css"
require('codemirror/theme/material-darker.css');
@@ -224,6 +225,16 @@ class UserEditPage extends React.Component {
{ this.state.user.id === this.props.account?.id ? () : null}
+
+
+ {Setting.getLabel(i18next.t("user:Country/Region"), i18next.t("user:Country/Region - Tooltip"))} :
+
+
+ {
+ this.updateUserField("region", value);
+ }} />
+
+
{
(this.state.application === null || this.state.user === null) ? null : (
{ return this.updateUserField(key, value)}} />
diff --git a/web/src/UserListPage.js b/web/src/UserListPage.js
index e843e54d..dcf223ee 100644
--- a/web/src/UserListPage.js
+++ b/web/src/UserListPage.js
@@ -66,6 +66,7 @@ class UserListPage extends React.Component {
address: [],
affiliation: "Example Inc.",
tag: "staff",
+ region: "",
isAdmin: false,
isGlobalAdmin: false,
IsForbidden: false,
@@ -199,6 +200,13 @@ class UserListPage extends React.Component {
width: '120px',
sorter: (a, b) => a.affiliation.localeCompare(b.affiliation),
},
+ {
+ title: i18next.t("user:Country/Region"),
+ dataIndex: 'region',
+ key: 'region',
+ width: '120px',
+ sorter: (a, b) => a.region.localeCompare(b.region),
+ },
{
title: i18next.t("user:Tag"),
dataIndex: 'tag',
diff --git a/web/src/auth/SignupPage.js b/web/src/auth/SignupPage.js
index c802c867..bf4587f9 100644
--- a/web/src/auth/SignupPage.js
+++ b/web/src/auth/SignupPage.js
@@ -23,6 +23,7 @@ import {authConfig} from "./Auth";
import * as ApplicationBackend from "../backend/ApplicationBackend";
import * as UserBackend from "../backend/UserBackend";
import {CountDownInput} from "../component/CountDownInput";
+import SelectRegionBox from "../SelectRegionBox";
const formItemLayout = {
labelCol: {
@@ -30,7 +31,7 @@ const formItemLayout = {
span: 24,
},
sm: {
- span: 6,
+ span: 8,
},
},
wrapperCol: {
@@ -69,6 +70,7 @@ class SignupPage extends React.Component {
phoneCode: "",
validEmail: false,
validPhone: false,
+ region: "",
};
this.form = React.createRef();
@@ -208,6 +210,22 @@ class SignupPage extends React.Component {
)
+ } else if (signupItem.name === "Country/Region") {
+ return (
+
+ {this.setState({region: value})}} />
+
+ )
} else if (signupItem.name === "Email") {
return (
diff --git a/web/src/locales/en/data.json b/web/src/locales/en/data.json
index d6181473..5736e93e 100644
--- a/web/src/locales/en/data.json
+++ b/web/src/locales/en/data.json
@@ -89,6 +89,7 @@
"Please input your personal name!": "Please input your personal name!",
"Please input your address!": "Please input your address!",
"Please input your affiliation!": "Please input your affiliation!",
+ "Please select your country/region!": "Please select your country/region!",
"The input is not valid Email!": "The input is not valid Email!",
"Please input your Email!": "Please input your Email!",
"Confirm": "Confirm",
@@ -206,6 +207,8 @@
"Address - Tooltip": "Unique string-style identifier",
"Affiliation": "Affiliation",
"Affiliation - Tooltip": "Unique string-style identifier",
+ "Country/Region": "Country/Region",
+ "Country/Region - Tooltip": "Country/Region",
"Modify affiliation": "Modify affiliation",
"Tag": "Tag",
"Tag - Tooltip": "Unique string-style identifier",