Merge pull request #23 from snowykami/fix/20

feat: 在 OidcLogin 方法中添加当前用户获取逻辑,优化用户绑定流程 Closes #20
This commit is contained in:
2025-09-23 17:55:50 +08:00
committed by GitHub
2 changed files with 38 additions and 33 deletions

View File

@ -1,39 +1,39 @@
package model
import (
"github.com/snowykami/neo-blog/internal/dto"
"gorm.io/gorm"
"github.com/snowykami/neo-blog/internal/dto"
"gorm.io/gorm"
)
type User struct {
gorm.Model
Username string `gorm:"uniqueIndex;not null"` // 用户名,唯一
Nickname string `gorm:"default:''"` // 昵称
AvatarUrl string
Email string `gorm:"uniqueIndex"`
Gender string `gorm:"default:''"`
Role string `gorm:"default:'user'"` // user editor admin
Language string `gorm:"default:'en'"`
Password string // 密码,存储加密后的值
gorm.Model
Username string `gorm:"uniqueIndex;not null"` // 用户名,唯一
Nickname string `gorm:"default:''"` // 昵称
AvatarUrl string
Email string `gorm:"uniqueIndex"`
Gender string `gorm:"default:''"`
Role string `gorm:"default:'user'"` // user editor admin
Language string `gorm:"default:'en'"`
Password string // 密码,存储加密后的值
}
type UserOpenID struct {
gorm.Model
UserID uint `gorm:"uniqueIndex"`
User User `gorm:"foreignKey:UserID;references:ID"`
Issuer string `gorm:"index"` // OIDC Issuer
Sub string `gorm:"index"` // OIDC Sub openid
gorm.Model
UserID uint `gorm:"index"`
User User `gorm:"foreignKey:UserID;references:ID"`
Issuer string `gorm:"index"` // OIDC Issuer
Sub string `gorm:"index"` // OIDC Sub openid
}
func (user *User) ToDto() dto.UserDto {
return dto.UserDto{
ID: user.ID,
Username: user.Username,
Nickname: user.Nickname,
AvatarUrl: user.AvatarUrl,
Email: user.Email,
Gender: user.Gender,
Role: user.Role,
Language: user.Language,
}
return dto.UserDto{
ID: user.ID,
Username: user.Username,
Nickname: user.Nickname,
AvatarUrl: user.AvatarUrl,
Email: user.Email,
Gender: user.Gender,
Role: user.Role,
Language: user.Language,
}
}

View File

@ -180,6 +180,7 @@ func (s *UserService) ListOidcConfigs() ([]dto.UserOidcConfigDto, error) {
func (s *UserService) OidcLogin(ctx context.Context, req *dto.OidcLoginReq) (*dto.OidcLoginResp, error) {
// 验证state
currentUser, userOk := ctxutils.GetCurrentUser(ctx)
kvStore := utils.KV.GetInstance()
storedName, ok := kvStore.Get(constant.KVKeyOidcState + req.State)
if !ok || storedName != req.Name {
@ -211,7 +212,7 @@ func (s *UserService) OidcLogin(ctx context.Context, req *dto.OidcLoginReq) (*dt
return nil, errs.ErrInternalServer
}
// 绑定过登录
// 1.绑定过登录
userOpenID, err := repo.User.GetUserOpenIDByIssuerAndSub(oidcConfig.Issuer, userInfo.Sub)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errs.ErrInternalServer
@ -233,12 +234,16 @@ func (s *UserService) OidcLogin(ctx context.Context, req *dto.OidcLoginReq) (*dt
}
return resp, nil
} else {
// 若没有绑定过登录,则先通过邮箱查找用户,若没有再创建新用户
user, err := repo.User.GetUserByEmail(userInfo.Email)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
logrus.Errorln("Failed to get user by email:", err)
return nil, errs.ErrInternalServer
// 2.若没有绑定过登录,则判断当前有无用户登录,有则绑定,没有登录先通过邮箱查找用户
user := currentUser
if user == nil || !userOk {
user, err = repo.User.GetUserByEmail(userInfo.Email)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
logrus.Errorln("Failed to get user by email:", err)
return nil, errs.ErrInternalServer
}
}
if user != nil {
userOpenID = &model.UserOpenID{
UserID: user.ID,
@ -262,7 +267,7 @@ func (s *UserService) OidcLogin(ctx context.Context, req *dto.OidcLoginReq) (*dt
}
return resp, nil
} else {
// 第一次登录,创建新用户时才获取头像
// 3.第一次登录,创建新用户时才获取头像
user = &model.User{
Username: userInfo.PreferredUsername,
Nickname: userInfo.Name,