diff --git a/controllers/syncer.go b/controllers/syncer.go index a924934a..9d396162 100644 --- a/controllers/syncer.go +++ b/controllers/syncer.go @@ -39,7 +39,7 @@ func (c *ApiController) GetSyncers() { } else { limit := util.ParseInt(limit) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetSyncerCount(owner))) - syncers := object.GetPaginationSyncers(owner, paginator.Offset(), limit) + syncers := object.GetMaskedSyncers(object.GetPaginationSyncers(owner, paginator.Offset(), limit)) c.ResponseOk(syncers, paginator.Nums()) } } @@ -53,7 +53,7 @@ func (c *ApiController) GetSyncers() { func (c *ApiController) GetSyncer() { id := c.Input().Get("id") - c.Data["json"] = object.GetSyncer(id) + c.Data["json"] = object.GetMaskedSyncer(object.GetSyncer(id)) c.ServeJSON() } diff --git a/object/syncer.go b/object/syncer.go index 4350c4ec..c7985105 100644 --- a/object/syncer.go +++ b/object/syncer.go @@ -29,14 +29,16 @@ type Syncer struct { Organization string `xorm:"varchar(100)" json:"organization"` Type string `xorm:"varchar(100)" json:"type"` - Host string `xorm:"varchar(100)" json:"host"` - Port int `json:"port"` - User string `xorm:"varchar(100)" json:"user"` - Password string `xorm:"varchar(100)" json:"password"` - Database string `xorm:"varchar(100)" json:"database"` - Table string `xorm:"varchar(100)" json:"table"` - - SyncInterval int `json:"syncInterval"` + Host string `xorm:"varchar(100)" json:"host"` + Port int `json:"port"` + User string `xorm:"varchar(100)" json:"user"` + Password string `xorm:"varchar(100)" json:"password"` + Database string `xorm:"varchar(100)" json:"database"` + Table string `xorm:"varchar(100)" json:"table"` + AffiliationTable string `xorm:"varchar(100)" json:"affiliationTable"` + AvatarBaseUrl string `xorm:"varchar(100)" json:"avatarBaseUrl"` + SyncInterval int `json:"syncInterval"` + IsEnabled bool `json:"isEnabled"` } func GetSyncerCount(owner string) int { @@ -91,6 +93,24 @@ func GetSyncer(id string) *Syncer { return getSyncer(owner, name) } +func GetMaskedSyncer(syncer *Syncer) *Syncer { + if syncer == nil { + return nil + } + + if syncer.Password != "" { + syncer.Password = "***" + } + return syncer +} + +func GetMaskedSyncers(syncers []*Syncer) []*Syncer { + for _, syncer := range syncers { + syncer = GetMaskedSyncer(syncer) + } + return syncers +} + func UpdateSyncer(id string, syncer *Syncer) bool { owner, name := util.GetOwnerAndNameFromId(id) if getSyncer(owner, name) == nil { diff --git a/web/src/SyncerEditPage.js b/web/src/SyncerEditPage.js index 0b2f95d7..fbfefffc 100644 --- a/web/src/SyncerEditPage.js +++ b/web/src/SyncerEditPage.js @@ -13,7 +13,8 @@ // limitations under the License. import React from "react"; -import {Button, Card, Col, Input, InputNumber, Row, Select} from 'antd'; +import {Button, Card, Col, Input, InputNumber, Row, Select, Switch} from 'antd'; +import {LinkOutlined} from "@ant-design/icons"; import * as SyncerBackend from "./backend/SyncerBackend"; import * as OrganizationBackend from "./backend/OrganizationBackend"; import * as Setting from "./Setting"; @@ -176,6 +177,26 @@ class SyncerEditPage extends React.Component { }} /> + + + {Setting.getLabel(i18next.t("syncer:Affiliation table"), i18next.t("syncer:Affiliation table - Tooltip"))} : + + + { + this.updateSyncerField('affiliationTable', e.target.value); + }} /> + + + + + {Setting.getLabel(i18next.t("syncer:Avatar base URL"), i18next.t("syncer:Avatar base URL - Tooltip"))} : + + + } value={this.state.syncer.avatarBaseUrl} onChange={e => { + this.updateSyncerField('avatarBaseUrl', e.target.value); + }} /> + + {Setting.getLabel(i18next.t("syncer:Sync interval"), i18next.t("syncer:Sync interval - Tooltip"))} : @@ -186,6 +207,16 @@ class SyncerEditPage extends React.Component { }} /> + + + {Setting.getLabel(i18next.t("syncer:Is enabled"), i18next.t("syncer:Is enabled - Tooltip"))} : + + + { + this.updateSyncerField('isEnabled', checked); + }} /> + + ) } diff --git a/web/src/SyncerListPage.js b/web/src/SyncerListPage.js index e57b8b54..0b9c5645 100644 --- a/web/src/SyncerListPage.js +++ b/web/src/SyncerListPage.js @@ -14,7 +14,7 @@ import React from "react"; import {Link} from "react-router-dom"; -import {Button, Popconfirm, Table} from 'antd'; +import {Button, Popconfirm, Switch, Table} from 'antd'; import moment from "moment"; import * as Setting from "./Setting"; import * as SyncerBackend from "./backend/SyncerBackend"; @@ -102,7 +102,7 @@ class SyncerListPage extends React.Component { title: i18next.t("general:Organization"), dataIndex: 'organization', key: 'organization', - width: '80px', + width: '120px', sorter: (a, b) => a.organization.localeCompare(b.organization), render: (text, record, index) => { return ( @@ -141,58 +141,70 @@ class SyncerListPage extends React.Component { title: i18next.t("provider:Type"), dataIndex: 'type', key: 'type', - width: '150px', + width: '100px', sorter: (a, b) => a.type.localeCompare(b.type), }, { title: i18next.t("provider:Host"), dataIndex: 'host', key: 'host', - width: '150px', + width: '120px', sorter: (a, b) => a.host.localeCompare(b.host), }, { title: i18next.t("provider:Port"), dataIndex: 'port', key: 'port', - width: '150px', + width: '100px', sorter: (a, b) => a.port - b.port, }, { title: i18next.t("general:User"), dataIndex: 'user', key: 'user', - width: '150px', + width: '120px', sorter: (a, b) => a.user.localeCompare(b.user), }, { title: i18next.t("general:Password"), dataIndex: 'password', key: 'password', - width: '150px', + width: '120px', sorter: (a, b) => a.password.localeCompare(b.password), }, { title: i18next.t("syncer:Database"), dataIndex: 'database', key: 'database', - width: '150px', + width: '120px', sorter: (a, b) => a.database.localeCompare(b.database), }, { title: i18next.t("syncer:Table"), dataIndex: 'table', key: 'table', - width: '150px', + width: '120px', sorter: (a, b) => a.table.localeCompare(b.table), }, { title: i18next.t("syncer:Sync interval"), dataIndex: 'syncInterval', key: 'syncInterval', - width: '150px', + width: '120px', sorter: (a, b) => a.syncInterval.localeCompare(b.syncInterval), }, + { + title: i18next.t("record:Is Enabled"), + dataIndex: 'isEnabled', + key: 'isEnabled', + width: '120px', + sorter: (a, b) => a.isEnabled - b.isEnabled, + render: (text, record, index) => { + return ( + + ) + } + }, { title: i18next.t("general:Action"), dataIndex: '',