mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-23 02:35:49 +08:00
Refactor the original db code.
This commit is contained in:
parent
07f9a9ee96
commit
318cf52b33
@ -20,7 +20,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/casbin/casdoor/object"
|
"github.com/casbin/casdoor/object"
|
||||||
"github.com/casbin/casdoor/original"
|
|
||||||
"github.com/casbin/casdoor/util"
|
"github.com/casbin/casdoor/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -168,7 +167,7 @@ func (c *ApiController) Signup() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
original.AddUserToOriginalDatabase(user)
|
object.AddUserToOriginalDatabase(user)
|
||||||
|
|
||||||
if application.HasPromptPage() {
|
if application.HasPromptPage() {
|
||||||
// The prompt page needs the user to be signed in
|
// The prompt page needs the user to be signed in
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
|
|
||||||
"github.com/astaxie/beego/utils/pagination"
|
"github.com/astaxie/beego/utils/pagination"
|
||||||
"github.com/casbin/casdoor/object"
|
"github.com/casbin/casdoor/object"
|
||||||
"github.com/casbin/casdoor/original"
|
|
||||||
"github.com/casbin/casdoor/util"
|
"github.com/casbin/casdoor/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -120,7 +119,7 @@ func (c *ApiController) UpdateUser() {
|
|||||||
|
|
||||||
affected := object.UpdateUser(id, &user, columns)
|
affected := object.UpdateUser(id, &user, columns)
|
||||||
if affected {
|
if affected {
|
||||||
original.UpdateUserToOriginalDatabase(&user)
|
object.UpdateUserToOriginalDatabase(&user)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = wrapActionResponse(affected)
|
c.Data["json"] = wrapActionResponse(affected)
|
||||||
|
5
main.go
5
main.go
@ -21,7 +21,6 @@ import (
|
|||||||
_ "github.com/astaxie/beego/session/redis"
|
_ "github.com/astaxie/beego/session/redis"
|
||||||
"github.com/casbin/casdoor/authz"
|
"github.com/casbin/casdoor/authz"
|
||||||
"github.com/casbin/casdoor/object"
|
"github.com/casbin/casdoor/object"
|
||||||
"github.com/casbin/casdoor/original"
|
|
||||||
"github.com/casbin/casdoor/proxy"
|
"github.com/casbin/casdoor/proxy"
|
||||||
"github.com/casbin/casdoor/routers"
|
"github.com/casbin/casdoor/routers"
|
||||||
|
|
||||||
@ -36,9 +35,7 @@ func main() {
|
|||||||
proxy.InitHttpClient()
|
proxy.InitHttpClient()
|
||||||
authz.InitAuthz()
|
authz.InitAuthz()
|
||||||
|
|
||||||
if original.InitAdapter() {
|
go object.RunSyncUsersJob()
|
||||||
go original.RunSyncUsersJob()
|
|
||||||
}
|
|
||||||
|
|
||||||
beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
|
beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
|
||||||
AllowOrigins: []string{"*"},
|
AllowOrigins: []string{"*"},
|
||||||
|
@ -39,6 +39,8 @@ type Syncer struct {
|
|||||||
AvatarBaseUrl string `xorm:"varchar(100)" json:"avatarBaseUrl"`
|
AvatarBaseUrl string `xorm:"varchar(100)" json:"avatarBaseUrl"`
|
||||||
SyncInterval int `json:"syncInterval"`
|
SyncInterval int `json:"syncInterval"`
|
||||||
IsEnabled bool `json:"isEnabled"`
|
IsEnabled bool `json:"isEnabled"`
|
||||||
|
|
||||||
|
Adapter *Adapter `xorm:"-" json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSyncerCount(owner string) int {
|
func GetSyncerCount(owner string) int {
|
||||||
@ -143,6 +145,6 @@ func DeleteSyncer(syncer *Syncer) bool {
|
|||||||
return affected != 0
|
return affected != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Syncer) GetId() string {
|
func (syncer *Syncer) GetId() string {
|
||||||
return fmt.Sprintf("%s/%s", p.Owner, p.Name)
|
return fmt.Sprintf("%s/%s", syncer.Owner, syncer.Name)
|
||||||
}
|
}
|
||||||
|
@ -12,20 +12,16 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package original
|
package object
|
||||||
|
|
||||||
type Affiliation struct {
|
type Affiliation struct {
|
||||||
Id int `xorm:"int notnull pk autoincr" json:"id"`
|
Id int `xorm:"int notnull pk autoincr" json:"id"`
|
||||||
Name string `xorm:"varchar(128)" json:"name"`
|
Name string `xorm:"varchar(128)" json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Affiliation) TableName() string {
|
func (syncer *Syncer) getAffiliations() []*Affiliation {
|
||||||
return affiliationTableName
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAffiliations() []*Affiliation {
|
|
||||||
affiliations := []*Affiliation{}
|
affiliations := []*Affiliation{}
|
||||||
err := adapter.Engine.Asc("id").Find(&affiliations)
|
err := syncer.Adapter.Engine.Table(syncer.AffiliationTable).Asc("id").Find(&affiliations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -33,8 +29,8 @@ func getAffiliations() []*Affiliation {
|
|||||||
return affiliations
|
return affiliations
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAffiliationMap() ([]*Affiliation, map[int]string) {
|
func (syncer *Syncer) getAffiliationMap() ([]*Affiliation, map[int]string) {
|
||||||
affiliations := getAffiliations()
|
affiliations := syncer.getAffiliations()
|
||||||
|
|
||||||
m := map[int]string{}
|
m := map[int]string{}
|
||||||
for _, affiliation := range affiliations {
|
for _, affiliation := range affiliations {
|
@ -12,12 +12,29 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package original
|
package object
|
||||||
|
|
||||||
import "github.com/mileusna/crontab"
|
import "github.com/mileusna/crontab"
|
||||||
|
|
||||||
var ctab *crontab.Crontab
|
var cronMap map[string]*crontab.Crontab
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
ctab = crontab.New()
|
cronMap = map[string]*crontab.Crontab{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCrontab(name string) *crontab.Crontab {
|
||||||
|
ctab, ok := cronMap[name]
|
||||||
|
if !ok {
|
||||||
|
ctab = crontab.New()
|
||||||
|
cronMap[name] = ctab
|
||||||
|
}
|
||||||
|
return ctab
|
||||||
|
}
|
||||||
|
|
||||||
|
func clearCrontab(name string) {
|
||||||
|
ctab, ok := cronMap[name]
|
||||||
|
if ok {
|
||||||
|
ctab.Clear()
|
||||||
|
delete(cronMap, name)
|
||||||
|
}
|
||||||
}
|
}
|
@ -12,50 +12,40 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package original
|
package object
|
||||||
|
|
||||||
import (
|
import "fmt"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/casbin/casdoor/object"
|
func getEnabledSyncerForOrganization(organization string) *Syncer {
|
||||||
)
|
syncers := GetSyncers("admin")
|
||||||
|
for _, syncer := range syncers {
|
||||||
func isEnabled() bool {
|
if syncer.Organization == organization && syncer.IsEnabled {
|
||||||
if adapter == nil {
|
return syncer
|
||||||
InitAdapter()
|
|
||||||
if adapter == nil {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddUserToOriginalDatabase(user *object.User) {
|
func AddUserToOriginalDatabase(user *User) {
|
||||||
if user.Owner != orgName {
|
syncer := getEnabledSyncerForOrganization(user.Owner)
|
||||||
|
if syncer == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isEnabled() {
|
updatedOUser := syncer.createOriginalUserFromUser(user)
|
||||||
return
|
syncer.addUser(updatedOUser)
|
||||||
}
|
|
||||||
|
|
||||||
updatedOUser := createOriginalUserFromUser(user)
|
|
||||||
addUser(updatedOUser)
|
|
||||||
fmt.Printf("Add from user to oUser: %v\n", updatedOUser)
|
fmt.Printf("Add from user to oUser: %v\n", updatedOUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateUserToOriginalDatabase(user *object.User) {
|
func UpdateUserToOriginalDatabase(user *User) {
|
||||||
if user.Owner != orgName {
|
syncer := getEnabledSyncerForOrganization(user.Owner)
|
||||||
|
if syncer == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isEnabled() {
|
newUser := GetUser(user.GetId())
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
newUser := object.GetUser(user.GetId())
|
updatedOUser := syncer.createOriginalUserFromUser(newUser)
|
||||||
|
syncer.updateUser(updatedOUser)
|
||||||
updatedOUser := createOriginalUserFromUser(newUser)
|
|
||||||
updateUser(updatedOUser)
|
|
||||||
fmt.Printf("Update from user to oUser: %v\n", updatedOUser)
|
fmt.Printf("Update from user to oUser: %v\n", updatedOUser)
|
||||||
}
|
}
|
83
object/syncer_sync.go
Normal file
83
object/syncer_sync.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (syncer *Syncer) syncUsers() {
|
||||||
|
fmt.Printf("Running syncUsers()..\n")
|
||||||
|
|
||||||
|
users, userMap := syncer.getUserMap()
|
||||||
|
oUsers, oUserMap := syncer.getUserMapOriginal()
|
||||||
|
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)
|
||||||
|
if _, ok := userMap[id]; !ok {
|
||||||
|
newUser := syncer.createUserFromOriginalUser(oUser, affiliationMap)
|
||||||
|
fmt.Printf("New user: %v\n", newUser)
|
||||||
|
newUsers = append(newUsers, newUser)
|
||||||
|
} else {
|
||||||
|
user := userMap[id]
|
||||||
|
oHash := syncer.calculateHash(oUser)
|
||||||
|
|
||||||
|
if user.Hash == user.PreHash {
|
||||||
|
if user.Hash != oHash {
|
||||||
|
updatedUser := syncer.createUserFromOriginalUser(oUser, affiliationMap)
|
||||||
|
updatedUser.Hash = oHash
|
||||||
|
updatedUser.PreHash = oHash
|
||||||
|
UpdateUserForOriginalFields(updatedUser)
|
||||||
|
fmt.Printf("Update from oUser to user: %v\n", updatedUser)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if user.PreHash == oHash {
|
||||||
|
updatedOUser := syncer.createOriginalUserFromUser(user)
|
||||||
|
syncer.updateUser(updatedOUser)
|
||||||
|
fmt.Printf("Update from user to oUser: %v\n", updatedOUser)
|
||||||
|
|
||||||
|
// update preHash
|
||||||
|
user.PreHash = user.Hash
|
||||||
|
SetUserField(user, "pre_hash", user.PreHash)
|
||||||
|
} else {
|
||||||
|
if user.Hash == oHash {
|
||||||
|
// update preHash
|
||||||
|
user.PreHash = user.Hash
|
||||||
|
SetUserField(user, "pre_hash", user.PreHash)
|
||||||
|
} else {
|
||||||
|
updatedUser := syncer.createUserFromOriginalUser(oUser, affiliationMap)
|
||||||
|
updatedUser.Hash = oHash
|
||||||
|
updatedUser.PreHash = oHash
|
||||||
|
UpdateUserForOriginalFields(updatedUser)
|
||||||
|
fmt.Printf("Update from oUser to user (2nd condition): %v\n", updatedUser)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddUsersInBatch(newUsers)
|
||||||
|
|
||||||
|
for _, user := range users {
|
||||||
|
id := user.Id
|
||||||
|
if _, ok := oUserMap[id]; !ok {
|
||||||
|
panic(fmt.Sprintf("New original user: cannot create now, user = %v", user))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
109
object/syncer_user.go
Normal file
109
object/syncer_user.go
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego"
|
||||||
|
"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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (syncer *Syncer) getUsersOriginal() []*DbUser {
|
||||||
|
users := []*DbUser{}
|
||||||
|
err := syncer.Adapter.Engine.Table(syncer.Table).Asc("id").Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return users
|
||||||
|
}
|
||||||
|
|
||||||
|
func (syncer *Syncer) getUserMapOriginal() ([]*DbUser, map[string]*DbUser) {
|
||||||
|
users := syncer.getUsersOriginal()
|
||||||
|
|
||||||
|
m := map[string]*DbUser{}
|
||||||
|
for _, user := range users {
|
||||||
|
m[strconv.Itoa(user.Id)] = user
|
||||||
|
}
|
||||||
|
return users, m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (syncer *Syncer) addUser(user *DbUser) bool {
|
||||||
|
affected, err := syncer.Adapter.Engine.Table(syncer.Table).Insert(user)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)}, "|")
|
||||||
|
return util.GetMd5Hash(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (syncer *Syncer) initAdapter() {
|
||||||
|
if syncer.Adapter == nil {
|
||||||
|
dataSourceName := fmt.Sprintf("%s:%s@tcp(%s:%d)/", syncer.User, syncer.Password, syncer.Host, syncer.Port)
|
||||||
|
syncer.Adapter = NewAdapter(beego.AppConfig.String("driverName"), dataSourceName, syncer.Database)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunSyncUsersJob() {
|
||||||
|
syncers := GetSyncers("admin")
|
||||||
|
for _, syncer := range syncers {
|
||||||
|
if !syncer.IsEnabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
syncer.initAdapter()
|
||||||
|
|
||||||
|
syncer.syncUsers()
|
||||||
|
|
||||||
|
// run at every minute
|
||||||
|
//schedule := fmt.Sprintf("* * * * %d", syncer.SyncInterval)
|
||||||
|
schedule := "* * * * *"
|
||||||
|
ctab := getCrontab(syncer.Name)
|
||||||
|
err := ctab.AddJob(schedule, syncer.syncUsers)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Duration(1<<63 - 1))
|
||||||
|
}
|
@ -12,29 +12,27 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package original
|
package object
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/casbin/casdoor/object"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetUsers(t *testing.T) {
|
func TestGetUsers(t *testing.T) {
|
||||||
initConfig()
|
InitConfig()
|
||||||
InitAdapter()
|
InitAdapter()
|
||||||
|
|
||||||
users := getUsersOriginal()
|
syncer := getEnabledSyncerForOrganization("built-in")
|
||||||
|
users := syncer.getUsersOriginal()
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
fmt.Printf("%v\n", user)
|
fmt.Printf("%v\n", user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSyncUsers(t *testing.T) {
|
func TestSyncUsers(t *testing.T) {
|
||||||
initConfig()
|
InitConfig()
|
||||||
InitAdapter()
|
InitAdapter()
|
||||||
object.InitAdapter()
|
|
||||||
|
|
||||||
RunSyncUsersJob()
|
RunSyncUsersJob()
|
||||||
}
|
}
|
88
object/syncer_util.go
Normal file
88
object/syncer_util.go
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/casbin/casdoor/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (syncer *Syncer) getFullAvatarUrl(avatar string) string {
|
||||||
|
if !strings.HasPrefix(avatar, "https://") {
|
||||||
|
return fmt.Sprintf("%s%s", syncer.AvatarBaseUrl, avatar)
|
||||||
|
}
|
||||||
|
return avatar
|
||||||
|
}
|
||||||
|
|
||||||
|
func (syncer *Syncer) getPartialAvatarUrl(avatar string) string {
|
||||||
|
if strings.HasPrefix(avatar, syncer.AvatarBaseUrl) {
|
||||||
|
return avatar[len(syncer.AvatarBaseUrl):]
|
||||||
|
}
|
||||||
|
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]
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Sprintf("SchoolId not found: %d", originalUser.SchoolId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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{},
|
||||||
|
}
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
|
||||||
|
func (syncer *Syncer) createOriginalUserFromUser(user *User) *DbUser {
|
||||||
|
deleted := 0
|
||||||
|
if user.IsForbidden {
|
||||||
|
deleted = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
@ -12,19 +12,17 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package original
|
package object
|
||||||
|
|
||||||
import "github.com/casbin/casdoor/object"
|
func (syncer *Syncer) getUsers() []*User {
|
||||||
|
users := GetUsers(syncer.Organization)
|
||||||
func getUsers() []*object.User {
|
|
||||||
users := object.GetUsers(orgName)
|
|
||||||
return users
|
return users
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUserMap() ([]*object.User, map[string]*object.User) {
|
func (syncer *Syncer) getUserMap() ([]*User, map[string]*User) {
|
||||||
users := getUsers()
|
users := syncer.getUsers()
|
||||||
|
|
||||||
m := map[string]*object.User{}
|
m := map[string]*User{}
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
m[user.Name] = user
|
m[user.Name] = user
|
||||||
}
|
}
|
@ -1,50 +0,0 @@
|
|||||||
// 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 original
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/astaxie/beego"
|
|
||||||
"github.com/casbin/casdoor/conf"
|
|
||||||
"github.com/casbin/casdoor/object"
|
|
||||||
_ "github.com/go-sql-driver/mysql" // db = mysql
|
|
||||||
//_ "github.com/lib/pq" // db = postgres
|
|
||||||
)
|
|
||||||
|
|
||||||
var adapter *object.Adapter
|
|
||||||
|
|
||||||
func initConfig() {
|
|
||||||
err := beego.LoadAppConfig("ini", "../conf/app.conf")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func InitAdapter() bool {
|
|
||||||
if dbName == "dbName" {
|
|
||||||
adapter = nil
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter = object.NewAdapter(beego.AppConfig.String("driverName"), conf.GetBeegoConfDataSourceName(), dbName)
|
|
||||||
createTable(adapter)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTable(a *object.Adapter) {
|
|
||||||
err := a.Engine.Sync2(new(User))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
// 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 original
|
|
||||||
|
|
||||||
var dbName = "dbName"
|
|
||||||
var userTableName = "userTableName"
|
|
||||||
var affiliationTableName = "affiliationTableName"
|
|
||||||
var avatarBaseUrl = "https://cdn.example.com/"
|
|
||||||
|
|
||||||
var orgName = "orgName"
|
|
152
original/sync.go
152
original/sync.go
@ -1,152 +0,0 @@
|
|||||||
// 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 original
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/casbin/casdoor/object"
|
|
||||||
"github.com/casbin/casdoor/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getFullAvatarUrl(avatar string) string {
|
|
||||||
if !strings.HasPrefix(avatar, "https://") {
|
|
||||||
return fmt.Sprintf("%s%s", avatarBaseUrl, avatar)
|
|
||||||
}
|
|
||||||
return avatar
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPartialAvatarUrl(avatar string) string {
|
|
||||||
if strings.HasPrefix(avatar, avatarBaseUrl) {
|
|
||||||
return avatar[len(avatarBaseUrl):]
|
|
||||||
}
|
|
||||||
return avatar
|
|
||||||
}
|
|
||||||
|
|
||||||
func createUserFromOriginalUser(originalUser *User, affiliationMap map[int]string) *object.User {
|
|
||||||
affiliation := ""
|
|
||||||
if originalUser.SchoolId != 0 {
|
|
||||||
var ok bool
|
|
||||||
affiliation, ok = affiliationMap[originalUser.SchoolId]
|
|
||||||
if !ok {
|
|
||||||
panic(fmt.Sprintf("SchoolId not found: %d", originalUser.SchoolId))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
user := &object.User{
|
|
||||||
Owner: orgName,
|
|
||||||
Name: strconv.Itoa(originalUser.Id),
|
|
||||||
CreatedTime: util.GetCurrentTime(),
|
|
||||||
Id: strconv.Itoa(originalUser.Id),
|
|
||||||
Type: "normal-user",
|
|
||||||
Password: originalUser.Password,
|
|
||||||
DisplayName: originalUser.Name,
|
|
||||||
Avatar: 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{},
|
|
||||||
}
|
|
||||||
return user
|
|
||||||
}
|
|
||||||
|
|
||||||
func createOriginalUserFromUser(user *object.User) *User {
|
|
||||||
deleted := 0
|
|
||||||
if user.IsForbidden {
|
|
||||||
deleted = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
originalUser := &User{
|
|
||||||
Id: util.ParseInt(user.Id),
|
|
||||||
Name: user.DisplayName,
|
|
||||||
Password: user.Password,
|
|
||||||
Cellphone: user.Phone,
|
|
||||||
SchoolId: user.Score,
|
|
||||||
Avatar: getPartialAvatarUrl(user.Avatar),
|
|
||||||
Deleted: deleted,
|
|
||||||
}
|
|
||||||
return originalUser
|
|
||||||
}
|
|
||||||
|
|
||||||
func syncUsers() {
|
|
||||||
fmt.Printf("Running syncUsers()..\n")
|
|
||||||
|
|
||||||
users, userMap := getUserMap()
|
|
||||||
oUsers, oUserMap := getUserMapOriginal()
|
|
||||||
fmt.Printf("Users: %d, oUsers: %d\n", len(users), len(oUsers))
|
|
||||||
|
|
||||||
_, affiliationMap := getAffiliationMap()
|
|
||||||
|
|
||||||
newUsers := []*object.User{}
|
|
||||||
for _, oUser := range oUsers {
|
|
||||||
id := strconv.Itoa(oUser.Id)
|
|
||||||
if _, ok := userMap[id]; !ok {
|
|
||||||
newUser := createUserFromOriginalUser(oUser, affiliationMap)
|
|
||||||
fmt.Printf("New user: %v\n", newUser)
|
|
||||||
newUsers = append(newUsers, newUser)
|
|
||||||
} else {
|
|
||||||
user := userMap[id]
|
|
||||||
oHash := calculateHash(oUser)
|
|
||||||
|
|
||||||
if user.Hash == user.PreHash {
|
|
||||||
if user.Hash != oHash {
|
|
||||||
updatedUser := createUserFromOriginalUser(oUser, affiliationMap)
|
|
||||||
updatedUser.Hash = oHash
|
|
||||||
updatedUser.PreHash = oHash
|
|
||||||
object.UpdateUserForOriginalFields(updatedUser)
|
|
||||||
fmt.Printf("Update from oUser to user: %v\n", updatedUser)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if user.PreHash == oHash {
|
|
||||||
updatedOUser := createOriginalUserFromUser(user)
|
|
||||||
updateUser(updatedOUser)
|
|
||||||
fmt.Printf("Update from user to oUser: %v\n", updatedOUser)
|
|
||||||
|
|
||||||
// update preHash
|
|
||||||
user.PreHash = user.Hash
|
|
||||||
object.SetUserField(user, "pre_hash", user.PreHash)
|
|
||||||
} else {
|
|
||||||
if user.Hash == oHash {
|
|
||||||
// update preHash
|
|
||||||
user.PreHash = user.Hash
|
|
||||||
object.SetUserField(user, "pre_hash", user.PreHash)
|
|
||||||
} else {
|
|
||||||
updatedUser := createUserFromOriginalUser(oUser, affiliationMap)
|
|
||||||
updatedUser.Hash = oHash
|
|
||||||
updatedUser.PreHash = oHash
|
|
||||||
object.UpdateUserForOriginalFields(updatedUser)
|
|
||||||
fmt.Printf("Update from oUser to user (2nd condition): %v\n", updatedUser)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
object.AddUsersInBatch(newUsers)
|
|
||||||
|
|
||||||
for _, user := range users {
|
|
||||||
id := user.Id
|
|
||||||
if _, ok := oUserMap[id]; !ok {
|
|
||||||
panic(fmt.Sprintf("New original user: cannot create now, user = %v", user))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,92 +0,0 @@
|
|||||||
// 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 original
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/casbin/casdoor/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
type User 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"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (User) TableName() string {
|
|
||||||
return userTableName
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUsersOriginal() []*User {
|
|
||||||
users := []*User{}
|
|
||||||
err := adapter.Engine.Asc("id").Find(&users)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return users
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUserMapOriginal() ([]*User, map[string]*User) {
|
|
||||||
users := getUsersOriginal()
|
|
||||||
|
|
||||||
m := map[string]*User{}
|
|
||||||
for _, user := range users {
|
|
||||||
m[strconv.Itoa(user.Id)] = user
|
|
||||||
}
|
|
||||||
return users, m
|
|
||||||
}
|
|
||||||
|
|
||||||
func addUser(user *User) bool {
|
|
||||||
affected, err := adapter.Engine.Insert(user)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return affected != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateUser(user *User) bool {
|
|
||||||
affected, err := adapter.Engine.ID(user.Id).Cols("name", "password", "cellphone", "school_id", "avatar", "deleted").Update(user)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return affected != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func calculateHash(user *User) string {
|
|
||||||
s := strings.Join([]string{strconv.Itoa(user.Id), user.Password, user.Name, getFullAvatarUrl(user.Avatar), user.Cellphone, strconv.Itoa(user.SchoolId)}, "|")
|
|
||||||
return util.GetMd5Hash(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RunSyncUsersJob() {
|
|
||||||
syncUsers()
|
|
||||||
|
|
||||||
// run at every minute
|
|
||||||
schedule := "* * * * *"
|
|
||||||
err := ctab.AddJob(schedule, syncUsers)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
time.Sleep(time.Duration(1<<63 - 1))
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user