init push
This commit is contained in:
151
backend/repo/pg/user_access.go
Normal file
151
backend/repo/pg/user_access.go
Normal file
@@ -0,0 +1,151 @@
|
||||
package pg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/chaitin/panda-wiki/consts"
|
||||
"github.com/chaitin/panda-wiki/domain"
|
||||
"github.com/chaitin/panda-wiki/log"
|
||||
"github.com/chaitin/panda-wiki/store/pg"
|
||||
)
|
||||
|
||||
type UserAccessRepository struct {
|
||||
db *pg.DB
|
||||
logger *log.Logger
|
||||
accessMap sync.Map
|
||||
}
|
||||
|
||||
func NewUserAccessRepository(db *pg.DB, logger *log.Logger) *UserAccessRepository {
|
||||
repo := &UserAccessRepository{
|
||||
db: db,
|
||||
logger: logger.WithModule("repo.pg.user_access"),
|
||||
accessMap: sync.Map{},
|
||||
}
|
||||
// start sync task
|
||||
go repo.startSyncTask()
|
||||
return repo
|
||||
}
|
||||
|
||||
// UpdateAccessTime update user access time
|
||||
func (r *UserAccessRepository) UpdateAccessTime(userID string) {
|
||||
r.accessMap.Store(userID, time.Now())
|
||||
}
|
||||
|
||||
// GetAccessTime get user access time
|
||||
func (r *UserAccessRepository) GetAccessTime(userID string) (time.Time, bool) {
|
||||
if value, ok := r.accessMap.Load(userID); ok {
|
||||
return value.(time.Time), true
|
||||
}
|
||||
return time.Time{}, false
|
||||
}
|
||||
|
||||
// startSyncTask start sync task
|
||||
func (r *UserAccessRepository) startSyncTask() {
|
||||
ticker := time.NewTicker(1 * time.Minute)
|
||||
defer ticker.Stop()
|
||||
|
||||
for range ticker.C {
|
||||
r.syncToDatabase()
|
||||
}
|
||||
}
|
||||
|
||||
// syncToDatabase sync data to database
|
||||
func (r *UserAccessRepository) syncToDatabase() {
|
||||
// collect data to update
|
||||
updates := make([]domain.UserAccessTime, 0)
|
||||
r.accessMap.Range(func(key, value any) bool {
|
||||
userID := key.(string)
|
||||
timestamp := value.(time.Time)
|
||||
updates = append(updates, domain.UserAccessTime{
|
||||
UserID: userID,
|
||||
Timestamp: timestamp,
|
||||
})
|
||||
return true
|
||||
})
|
||||
|
||||
if len(updates) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// batch update database
|
||||
err := r.db.Transaction(func(tx *gorm.DB) error {
|
||||
for _, update := range updates {
|
||||
if err := tx.Model(&domain.User{}).
|
||||
Where("id = ?", update.UserID).
|
||||
Update("last_access", update.Timestamp).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
r.logger.Error("failed to sync user access time to database",
|
||||
log.Error(err),
|
||||
log.Int("update_count", len(updates)))
|
||||
return
|
||||
}
|
||||
|
||||
// clear synced data
|
||||
for _, update := range updates {
|
||||
if currentTime, ok := r.GetAccessTime(update.UserID); ok {
|
||||
// only delete old data
|
||||
if !currentTime.After(update.Timestamp) {
|
||||
r.accessMap.Delete(update.UserID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r.logger.Info("synced user access time to database",
|
||||
log.Int("update_count", len(updates)))
|
||||
}
|
||||
|
||||
func (r *UserAccessRepository) ValidateRole(userID string, role consts.UserRole) (bool, error) {
|
||||
var user domain.User
|
||||
if err := r.db.Model(&domain.User{}).Where("id = ?", userID).First(&user).Error; err != nil {
|
||||
return false, fmt.Errorf("get user failed")
|
||||
}
|
||||
|
||||
if user.Role == consts.UserRoleAdmin {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if user.Role == role {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (r *UserAccessRepository) ValidateKBPerm(kbId, userId string, perm consts.UserKBPermission) (bool, error) {
|
||||
var user domain.User
|
||||
if err := r.db.Model(&domain.User{}).Where("id = ?", userId).First(&user).Error; err != nil {
|
||||
return false, fmt.Errorf("get user failed %s", err)
|
||||
}
|
||||
|
||||
if user.Role == consts.UserRoleAdmin {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
var kbUser domain.KBUsers
|
||||
err := r.db.Model(&domain.KBUsers{}).
|
||||
Where("kb_id = ? AND user_id = ?", kbId, userId).
|
||||
First(&kbUser).Error
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("get kb user failed %s", err)
|
||||
|
||||
}
|
||||
|
||||
if perm == consts.UserKBPermissionNotNull {
|
||||
return kbUser.Perm != consts.UserKBPermissionNull, nil
|
||||
}
|
||||
|
||||
if kbUser.Perm == perm || kbUser.Perm == consts.UserKBPermissionFullControl {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
Reference in New Issue
Block a user