Improve syncer code.

This commit is contained in:
Yang Luo 2021-12-19 22:30:54 +08:00
parent e7f395cfd4
commit 5ee5299a68
8 changed files with 230 additions and 83 deletions

View File

@ -16,6 +16,16 @@ package object
import "fmt"
func getDbSyncerForUser(user *User) *Syncer {
syncers := GetSyncers("admin")
for _, syncer := range syncers {
if syncer.Organization == user.Owner && syncer.IsEnabled && syncer.Type == "Database" {
return syncer
}
}
return nil
}
func getEnabledSyncerForOrganization(organization string) *Syncer {
syncers := GetSyncers("admin")
for _, syncer := range syncers {

View File

@ -14,23 +14,20 @@
package object
import (
"fmt"
"strconv"
)
import "fmt"
func (syncer *Syncer) syncUsers() {
fmt.Printf("Running syncUsers()..\n")
users, userMap := syncer.getUserMap()
oUsers, oUserMap := syncer.getUserMapOriginal()
oUsers, oUserMap := syncer.getOriginalUserMap()
fmt.Printf("Users: %d, oUsers: %d\n", len(users), len(oUsers))
_, affiliationMap := syncer.getAffiliationMap()
newUsers := []*User{}
for _, oUser := range oUsers {
id := strconv.Itoa(oUser.Id)
id := oUser.Id
if _, ok := userMap[id]; !ok {
newUser := syncer.createUserFromOriginalUser(oUser, affiliationMap)
fmt.Printf("New user: %v\n", newUser)

View File

@ -16,7 +16,6 @@ package object
import (
"fmt"
"strconv"
"strings"
"time"
@ -24,38 +23,31 @@ import (
"github.com/casbin/casdoor/util"
)
type DbUser struct {
Id int `xorm:"int notnull pk autoincr" json:"id"`
Name string `xorm:"varchar(128)" json:"name"`
Password string `xorm:"varchar(128)" json:"password"`
Cellphone string `xorm:"varchar(128)" json:"cellphone"`
SchoolId int `json:"schoolId"`
Avatar string `xorm:"varchar(128)" json:"avatar"`
Deleted int `xorm:"tinyint(1)" json:"deleted"`
}
type OriginalUser = User
func (syncer *Syncer) getUsersOriginal() []*DbUser {
users := []*DbUser{}
err := syncer.Adapter.Engine.Table(syncer.Table).Asc("id").Find(&users)
func (syncer *Syncer) getOriginalUsers() []*OriginalUser {
sql := fmt.Sprintf("select * from %s", syncer.Table)
results, err := syncer.Adapter.Engine.QueryString(sql)
if err != nil {
panic(err)
}
return users
return syncer.getOriginalUsersFromMap(results)
}
func (syncer *Syncer) getUserMapOriginal() ([]*DbUser, map[string]*DbUser) {
users := syncer.getUsersOriginal()
func (syncer *Syncer) getOriginalUserMap() ([]*OriginalUser, map[string]*OriginalUser) {
users := syncer.getOriginalUsers()
m := map[string]*DbUser{}
m := map[string]*OriginalUser{}
for _, user := range users {
m[strconv.Itoa(user.Id)] = user
m[user.Id] = user
}
return users, m
}
func (syncer *Syncer) addUser(user *DbUser) bool {
affected, err := syncer.Adapter.Engine.Table(syncer.Table).Insert(user)
func (syncer *Syncer) addUser(user *OriginalUser) bool {
m := syncer.getMapFromOriginalUser(user)
affected, err := syncer.Adapter.Engine.Table(syncer.Table).Insert(m)
if err != nil {
panic(err)
}
@ -63,8 +55,20 @@ func (syncer *Syncer) addUser(user *DbUser) bool {
return affected != 0
}
func (syncer *Syncer) updateUser(user *DbUser) bool {
affected, err := syncer.Adapter.Engine.Table(syncer.Table).ID(user.Id).Cols("name", "password", "cellphone", "school_id", "avatar", "deleted").Update(user)
func (syncer *Syncer) getActiveColumns() []string {
res := []string{}
for _, tableColumn := range syncer.TableColumns {
if tableColumn.CasdoorName != "Id" {
res = append(res, tableColumn.Name)
}
}
return res
}
func (syncer *Syncer) updateUser(user *OriginalUser) bool {
m := syncer.getMapFromOriginalUser(user)
columns := syncer.getActiveColumns()
affected, err := syncer.Adapter.Engine.Table(syncer.Table).ID(user.Id).Cols(columns...).Update(m)
if err != nil {
panic(err)
}
@ -72,8 +76,14 @@ func (syncer *Syncer) updateUser(user *DbUser) bool {
return affected != 0
}
func (syncer *Syncer) calculateHash(user *DbUser) string {
s := strings.Join([]string{strconv.Itoa(user.Id), user.Password, user.Name, syncer.getFullAvatarUrl(user.Avatar), user.Cellphone, strconv.Itoa(user.SchoolId)}, "|")
func (syncer *Syncer) calculateHash(user *OriginalUser) string {
values := []string{}
m := syncer.getMapFromOriginalUser(user)
for _, tableColumn := range syncer.TableColumns {
values = append(values, m[tableColumn.Name])
}
s := strings.Join(values, "|")
return util.GetMd5Hash(s)
}

View File

@ -25,7 +25,7 @@ func TestGetUsers(t *testing.T) {
syncers := GetSyncers("admin")
syncer := syncers[0]
syncer.initAdapter()
users := syncer.getUsersOriginal()
users := syncer.getOriginalUsers()
for _, user := range users {
fmt.Printf("%v\n", user)
}

View File

@ -23,6 +23,10 @@ import (
)
func (syncer *Syncer) getFullAvatarUrl(avatar string) string {
if syncer.AvatarBaseUrl == "" {
return avatar
}
if !strings.HasPrefix(avatar, "https://") {
return fmt.Sprintf("%s%s", syncer.AvatarBaseUrl, avatar)
}
@ -36,53 +40,164 @@ func (syncer *Syncer) getPartialAvatarUrl(avatar string) string {
return avatar
}
func (syncer *Syncer) createUserFromOriginalUser(originalUser *DbUser, affiliationMap map[int]string) *User {
affiliation := ""
if originalUser.SchoolId != 0 {
var ok bool
affiliation, ok = affiliationMap[originalUser.SchoolId]
func (syncer *Syncer) createUserFromOriginalUser(originalUser *OriginalUser, affiliationMap map[int]string) *User {
user := *originalUser
user.Owner = syncer.Organization
if user.Name == "" {
user.Name = originalUser.Id
}
if user.CreatedTime == "" {
user.CreatedTime = util.GetCurrentTime()
}
if user.Type == "" {
user.Type = "normal-user"
}
if originalUser.Score != 0 {
affiliation, ok := affiliationMap[originalUser.Score]
if !ok {
panic(fmt.Sprintf("SchoolId not found: %d", originalUser.SchoolId))
panic(fmt.Sprintf("Affiliation not found: %d", originalUser.Score))
}
user.Affiliation = affiliation
}
if user.Properties == nil {
user.Properties = map[string]string{}
}
return &user
}
user := &User{
Owner: syncer.Organization,
Name: strconv.Itoa(originalUser.Id),
CreatedTime: util.GetCurrentTime(),
Id: strconv.Itoa(originalUser.Id),
Type: "normal-user",
Password: originalUser.Password,
DisplayName: originalUser.Name,
Avatar: syncer.getFullAvatarUrl(originalUser.Avatar),
Email: "",
Phone: originalUser.Cellphone,
Address: []string{},
Affiliation: affiliation,
Score: originalUser.SchoolId,
IsAdmin: false,
IsGlobalAdmin: false,
IsForbidden: originalUser.Deleted != 0,
IsDeleted: false,
Properties: map[string]string{},
}
func (syncer *Syncer) createOriginalUserFromUser(user *User) *OriginalUser {
return user
}
func (syncer *Syncer) createOriginalUserFromUser(user *User) *DbUser {
deleted := 0
if user.IsForbidden {
deleted = 1
func (syncer *Syncer) setUserByKeyValue(user *User, key string, value string) {
switch key {
case "Name":
user.Name = value
case "CreatedTime":
user.CreatedTime = value
case "UpdatedTime":
user.UpdatedTime = value
case "Id":
user.Id = value
case "Type":
user.Type = value
case "Password":
user.Password = value
case "PasswordSalt":
user.PasswordSalt = value
case "DisplayName":
user.DisplayName = value
case "Avatar":
user.Avatar = syncer.getPartialAvatarUrl(value)
case "PermanentAvatar":
user.PermanentAvatar = value
case "Email":
user.Email = value
case "Phone":
user.Phone = value
case "Location":
user.Location = value
case "Address":
user.Address = []string{value}
case "Affiliation":
user.Affiliation = value
case "Title":
user.Title = value
case "IdCardType":
user.IdCardType = value
case "IdCard":
user.IdCard = value
case "Homepage":
user.Homepage = value
case "Bio":
user.Bio = value
case "Tag":
user.Tag = value
case "Region":
user.Region = value
case "Language":
user.Language = value
case "Gender":
user.Gender = value
case "Birthday":
user.Birthday = value
case "Education":
user.Education = value
case "Score":
user.Score = util.ParseInt(value)
case "Ranking":
user.Ranking = util.ParseInt(value)
case "IsDefaultAvatar":
user.IsDefaultAvatar = util.ParseBool(value)
case "IsOnline":
user.IsOnline = util.ParseBool(value)
case "IsAdmin":
user.IsAdmin = util.ParseBool(value)
case "IsGlobalAdmin":
user.IsGlobalAdmin = util.ParseBool(value)
case "IsForbidden":
user.IsForbidden = util.ParseBool(value)
case "IsDeleted":
user.IsDeleted = util.ParseBool(value)
case "CreatedIp":
user.CreatedIp = value
}
}
func (syncer *Syncer) getOriginalUsersFromMap(results []map[string]string) []*OriginalUser {
users := []*OriginalUser{}
for _, result := range results {
originalUser := &OriginalUser{}
for _, tableColumn := range syncer.TableColumns {
syncer.setUserByKeyValue(originalUser, tableColumn.CasdoorName, result[tableColumn.Name])
}
users = append(users, originalUser)
}
return users
}
func (syncer *Syncer) getMapFromOriginalUser(user *OriginalUser) map[string]string {
m := map[string]string{}
m["Name"] = user.Name
m["CreatedTime"] = user.CreatedTime
m["UpdatedTime"] = user.UpdatedTime
m["Id"] = user.Id
m["Type"] = user.Type
m["Password"] = user.Password
m["PasswordSalt"] = user.PasswordSalt
m["DisplayName"] = user.DisplayName
m["Avatar"] = syncer.getFullAvatarUrl(user.Avatar)
m["PermanentAvatar"] = user.PermanentAvatar
m["Email"] = user.Email
m["Phone"] = user.Phone
m["Location"] = user.Location
m["Address"] = strings.Join(user.Address, "|")
m["Affiliation"] = user.Affiliation
m["Title"] = user.Title
m["IdCardType"] = user.IdCardType
m["IdCard"] = user.IdCard
m["Homepage"] = user.Homepage
m["Bio"] = user.Bio
m["Tag"] = user.Tag
m["Region"] = user.Region
m["Language"] = user.Language
m["Gender"] = user.Gender
m["Birthday"] = user.Birthday
m["Education"] = user.Education
m["Score"] = strconv.Itoa(user.Score)
m["Ranking"] = strconv.Itoa(user.Ranking)
m["IsDefaultAvatar"] = util.BoolToString(user.IsDefaultAvatar)
m["IsOnline"] = util.BoolToString(user.IsOnline)
m["IsAdmin"] = util.BoolToString(user.IsAdmin)
m["IsGlobalAdmin"] = util.BoolToString(user.IsGlobalAdmin)
m["IsForbidden"] = util.BoolToString(user.IsForbidden)
m["IsDeleted"] = util.BoolToString(user.IsDeleted)
m["CreatedIp"] = user.CreatedIp
m2 := map[string]string{}
for _, tableColumn := range syncer.TableColumns {
m2[tableColumn.CasdoorName] = m[tableColumn.CasdoorName]
}
originalUser := &DbUser{
Id: util.ParseInt(user.Id),
Name: user.DisplayName,
Password: user.Password,
Cellphone: user.Phone,
SchoolId: user.Score,
Avatar: syncer.getPartialAvatarUrl(user.Avatar),
Deleted: deleted,
}
return originalUser
return m2
}

View File

@ -14,17 +14,15 @@
package object
import (
"strconv"
"strings"
"github.com/casbin/casdoor/cred"
"github.com/casbin/casdoor/util"
)
import "github.com/casbin/casdoor/cred"
func calculateHash(user *User) string {
s := strings.Join([]string{user.Id, user.Password, user.DisplayName, user.Avatar, user.Phone, strconv.Itoa(user.Score)}, "|")
return util.GetMd5Hash(s)
syncer := getDbSyncerForUser(user)
if syncer == nil {
return ""
}
return syncer.calculateHash(user)
}
func (user *User) UpdateUserHash() {

View File

@ -27,6 +27,10 @@ import (
)
func ParseInt(s string) int {
if s == "" {
return 0
}
i, err := strconv.Atoi(s)
if err != nil {
panic(err)
@ -35,6 +39,19 @@ func ParseInt(s string) int {
return i
}
func ParseBool(s string) bool {
i := ParseInt(s)
return i != 0
}
func BoolToString(b bool) string {
if b {
return "1"
} else {
return "0"
}
}
func GetOwnerAndNameFromId(id string) (string, string) {
tokens := strings.Split(id, "/")
if len(tokens) != 2 {

View File

@ -98,9 +98,9 @@ class SyncerTableColumnTable extends React.Component {
return (
<Select virtual={false} style={{width: '100%'}} value={text} onChange={(value => {this.updateField(table, index, 'casdoorName', value);})}>
{
['name', 'createdTime', 'updatedTime', 'id', 'type', 'password', 'passwordSalt', 'displayName', 'avatar', 'permanentAvatar', 'email', 'phone',
'location', 'address', 'affiliation', 'title', 'idCardType', 'idCard', 'homepage', 'bio', 'tag', 'region', 'language', 'gender', 'birthday',
'education', 'score', 'ranking', 'isDefaultAvatar', 'isOnline', 'isAdmin', 'isGlobalAdmin', 'isForbidden', 'isDeleted', 'CreatedIp']
['Name', 'CreatedTime', 'UpdatedTime', 'Id', 'Type', 'Password', 'PasswordSalt', 'DisplayName', 'Avatar', 'PermanentAvatar', 'Email', 'Phone',
'Location', 'Address', 'Affiliation', 'Title', 'IdCardType', 'IdCard', 'Homepage', 'Bio', 'Tag', 'Region', 'Language', 'Gender', 'Birthday',
'Education', 'Score', 'Ranking', 'IsDefaultAvatar', 'IsOnline', 'IsAdmin', 'IsGlobalAdmin', 'IsForbidden', 'IsDeleted', 'CreatedIp']
.map((item, index) => <Option key={index} value={item}>{item}</Option>)
}
</Select>