Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 0 additions & 32 deletions internal/apps/oauth/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import (
"net/http"
"time"

"github.com/google/uuid"
"github.com/hibiken/asynq"
"github.com/linux-do/cdk/internal/config"
"github.com/linux-do/cdk/internal/db"
Expand Down Expand Up @@ -163,34 +162,3 @@ func (u *User) EnqueueBadgeScoreTask(ctx context.Context) {
logger.InfoF(ctx, "下发用户[%s]徽章分数计算任务成功", u.Username)
}
}

// MarkAsDeactivatedAndCreateNew 将当前用户标记为已注销,并创建新用户
func (u *User) MarkAsDeactivatedAndCreateNew(ctx context.Context, oauthInfo *OAuthUserInfo) (*User, error) {
err := db.DB(ctx).Transaction(func(tx *gorm.DB) error {
// 将旧用户名修改为注销状态
oldUsername := fmt.Sprintf("%s已注销: %s", u.Username, uuid.NewString())
if err := tx.Model(u).Updates(map[string]interface{}{
"username": oldUsername,
"is_active": false,
}).Error; err != nil {
return err
}

// 创建新用户
newUser := User{
ID: oauthInfo.Id,
Username: oauthInfo.Username,
Nickname: oauthInfo.Name,
AvatarUrl: oauthInfo.AvatarUrl,
IsActive: oauthInfo.Active,
TrustLevel: oauthInfo.TrustLevel,
LastLoginAt: time.Now(),
}
if err := tx.Create(&newUser).Error; err != nil {
return err
}
*u = newUser
return nil
})
return u, err
}
73 changes: 35 additions & 38 deletions internal/apps/oauth/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ import (
"io"
"time"

"fmt"

"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/linux-do/cdk/internal/config"
"github.com/linux-do/cdk/internal/db"
"github.com/linux-do/cdk/internal/otel_trace"
Expand Down Expand Up @@ -106,24 +109,33 @@ func doOAuth(ctx context.Context, code string) (*User, error) {
return nil, err
}

// 处理用户信息同步逻辑
var user User
err = db.DB(ctx).Transaction(func(tx *gorm.DB) error {
var holder User
if conflictErr := tx.Where("username = ? AND id != ?", userInfo.Username, userInfo.Id).First(&holder).Error; conflictErr == nil {
// 存在冲突 -> 将占用者改名并注销
newParams := map[string]interface{}{
"username": fmt.Sprintf("%s已注销: %s", holder.Username, uuid.NewString()),
"is_active": false,
}
if updateErr := tx.Model(&holder).Updates(newParams).Error; updateErr != nil {
return updateErr
}
}

txByUsername := db.DB(ctx).Where("username = ?", userInfo.Username).First(&user)
if txByUsername.Error != nil {
txByID := db.DB(ctx).Where("id = ?", userInfo.Id).First(&user)
if txByID.Error == nil {
// ID 存在但 username 不匹配(用户改名)
if err = user.CheckActive(); err != nil {
span.SetStatus(codes.Error, err.Error())
return nil, err
// 根据 ID 处理当前用户的 更新 或 创建
queryErr := tx.Where("id = ?", userInfo.Id).First(&user).Error
if queryErr == nil {
// 用户已存在 -> 更新信息
if activeErr := user.CheckActive(); activeErr != nil {
return activeErr
}
user.UpdateFromOAuthInfo(&userInfo)
if err = db.DB(ctx).Save(&user).Error; err != nil {
span.SetStatus(codes.Error, err.Error())
return nil, err
if saveErr := tx.Save(&user).Error; saveErr != nil {
return saveErr
}
} else if errors.Is(txByUsername.Error, gorm.ErrRecordNotFound) {
} else if errors.Is(queryErr, gorm.ErrRecordNotFound) {
// 用户不存在 -> 创建新用户
user = User{
ID: userInfo.Id,
Username: userInfo.Username,
Expand All @@ -133,35 +145,20 @@ func doOAuth(ctx context.Context, code string) (*User, error) {
TrustLevel: userInfo.TrustLevel,
LastLoginAt: time.Now(),
}
if err = db.DB(ctx).Create(&user).Error; err != nil {
span.SetStatus(codes.Error, err.Error())
return nil, err
}
user.EnqueueBadgeScoreTask(ctx)
} else {
// query failed
span.SetStatus(codes.Error, txByUsername.Error.Error())
return nil, txByUsername.Error
}
} else {
if user.ID != userInfo.Id {
// username 相同但 ID 不同(账户注销后被新用户占用)
if _, err = user.MarkAsDeactivatedAndCreateNew(ctx, &userInfo); err != nil {
span.SetStatus(codes.Error, err.Error())
return nil, err
if createErr := tx.Create(&user).Error; createErr != nil {
return createErr
}
user.EnqueueBadgeScoreTask(ctx)
} else {
if err = user.CheckActive(); err != nil {
span.SetStatus(codes.Error, err.Error())
return nil, err
}
user.UpdateFromOAuthInfo(&userInfo)
if err = db.DB(ctx).Save(&user).Error; err != nil {
span.SetStatus(codes.Error, err.Error())
return nil, err
}
return queryErr
}
return nil
})

if err != nil {
span.SetStatus(codes.Error, err.Error())
return nil, err
}

return &user, nil
}
Loading