diff --git a/controllers/link.go b/controllers/link.go
index 814dd257..01c12108 100644
--- a/controllers/link.go
+++ b/controllers/link.go
@@ -49,6 +49,8 @@ func (c *ApiController) Unlink() {
return
}
+ object.ClearUserProperties(user, providerType)
+
object.LinkUserAccount(user, providerType, "")
resp = Response{Status: "ok", Msg: ""}
c.Data["json"] = resp
diff --git a/object/user_util.go b/object/user_util.go
index 2943cb45..46e1bc8d 100644
--- a/object/user_util.go
+++ b/object/user_util.go
@@ -107,6 +107,22 @@ func SetUserProperty(user *User, field string, value string) bool {
return affected != 0
}
+func ClearUserProperties(user *User, providerType string) bool {
+ for k := range user.Properties {
+ prefix := fmt.Sprintf("oauth_%s_", providerType)
+ if strings.HasPrefix(k, prefix) {
+ delete(user.Properties, k)
+ }
+ }
+
+ affected, err := adapter.Engine.ID(core.PK{user.Owner, user.Name}).Cols("properties").Update(user)
+ if err != nil {
+ panic(err)
+ }
+
+ return affected != 0
+}
+
func calculateHash(user *User) string {
s := strings.Join([]string{user.Id, user.Password, user.DisplayName, user.Avatar, user.Phone}, "|")
return util.GetMd5Hash(s)
diff --git a/web/package.json b/web/package.json
index c9e95253..34d0ecae 100644
--- a/web/package.json
+++ b/web/package.json
@@ -9,11 +9,13 @@
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"antd": "^4.15.5",
+ "codemirror": "^5.61.1",
"copy-to-clipboard": "^3.3.1",
"craco-less": "^1.17.1",
"i18next": "^19.8.9",
"moment": "^2.29.1",
"react": "^17.0.2",
+ "react-codemirror2": "^7.2.1",
"react-cropper": "^2.1.7",
"react-device-detect": "^1.14.0",
"react-dom": "^17.0.2",
diff --git a/web/src/UserEditPage.js b/web/src/UserEditPage.js
index 0647ea67..103d6b60 100644
--- a/web/src/UserEditPage.js
+++ b/web/src/UserEditPage.js
@@ -26,6 +26,11 @@ import * as Provider from "./auth/Provider";
import PasswordModal from "./PasswordModal";
import ResetModal from "./ResetModal";
+import {Controlled as CodeMirror} from 'react-codemirror2'
+import "codemirror/lib/codemirror.css"
+require('codemirror/theme/material-darker.css');
+require("codemirror/mode/javascript/javascript");
+
const { Option } = Select;
class UserEditPage extends React.Component {
@@ -321,6 +326,21 @@ class UserEditPage extends React.Component {
+ {
+ !Setting.isAdminUser(this.props.account) ? null : (
+
+
+ {i18next.t("user:Properties")}:
+
+
+
+
+
+ )
+ }
{
!Setting.isAdminUser(this.props.account) ? null : (
diff --git a/web/src/locales/en.json b/web/src/locales/en.json
index 7ec47f3c..9af0d28e 100644
--- a/web/src/locales/en.json
+++ b/web/src/locales/en.json
@@ -117,6 +117,7 @@
"Modify affiliation": "Modify affiliation",
"Tag": "Tag",
"Third-party logins": "Third-party logins",
+ "Properties": "Properties",
"Link": "Link",
"Unlink": "Unlink",
"Is admin": "Is admin",
diff --git a/web/src/locales/zh.json b/web/src/locales/zh.json
index 8536f2b0..b0793dd6 100644
--- a/web/src/locales/zh.json
+++ b/web/src/locales/zh.json
@@ -117,6 +117,7 @@
"Modify affiliation": "修改工作单位",
"Tag": "标签",
"Third-party logins": "第三方登录",
+ "Properties": "属性",
"Link": "绑定",
"Unlink": "解绑",
"Is admin": "是管理员",
diff --git a/web/yarn.lock b/web/yarn.lock
index edc7acbe..204f2d1b 100644
--- a/web/yarn.lock
+++ b/web/yarn.lock
@@ -3503,6 +3503,11 @@ coa@^2.0.2:
chalk "^2.4.1"
q "^1.1.2"
+codemirror@^5.61.1:
+ version "5.61.1"
+ resolved "https://registry.npmjs.org/codemirror/-/codemirror-5.61.1.tgz#ccfc8a43b8fcfb8b12e8e75b5ffde48d541406e0"
+ integrity sha512-+D1NZjAucuzE93vJGbAaXzvoBHwp9nJZWWWF9utjv25+5AZUiah6CIlfb4ikG4MoDsFsCG8niiJH5++OO2LgIQ==
+
collect-v8-coverage@^1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59"
@@ -9749,6 +9754,11 @@ react-app-polyfill@^2.0.0:
regenerator-runtime "^0.13.7"
whatwg-fetch "^3.4.1"
+react-codemirror2@^7.2.1:
+ version "7.2.1"
+ resolved "https://registry.npmjs.org/react-codemirror2/-/react-codemirror2-7.2.1.tgz#38dab492fcbe5fb8ebf5630e5bb7922db8d3a10c"
+ integrity sha512-t7YFmz1AXdlImgHXA9Ja0T6AWuopilub24jRaQdPVbzUJVNKIYuy3uCFZYa7CE5S3UW6SrSa5nAqVQvtzRF9gw==
+
react-cropper@^2.1.7:
version "2.1.7"
resolved "https://registry.npmjs.org/react-cropper/-/react-cropper-2.1.7.tgz#f9f8127b9516fecc44f918dd331107bfc32adfaf"