mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-06 07:36:37 +08:00
refactor(repository): 收敛 model/repository 分层为唯一持久化入口
将 OpenFlare 与平台业务的数据访问从 model 与 apps 直连迁入 repository, model 仅保留实体与无 IO 规则;补充 code-check 架构守卫与开发规范。
This commit is contained in:
@@ -5,8 +5,11 @@ package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
db "github.com/Rain-kl/Wavelet/internal/infra/persistence"
|
||||
"github.com/Rain-kl/Wavelet/internal/infra/persistence/idgen"
|
||||
"github.com/Rain-kl/Wavelet/internal/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -175,7 +178,117 @@ func ListUsersByIDs(ctx context.Context, ids []uint64) ([]model.User, error) {
|
||||
return users, nil
|
||||
}
|
||||
|
||||
// ListUserIDsByUsernameContains returns user IDs whose username contains the given fragment.
|
||||
func ListUserIDsByUsernameContains(ctx context.Context, username string) ([]uint64, error) {
|
||||
if username == "" {
|
||||
return []uint64{}, nil
|
||||
}
|
||||
var userIDs []uint64
|
||||
if err := db.DB(ctx).Model(&model.User{}).
|
||||
Where("username LIKE ?", "%"+username+"%").
|
||||
Pluck("id", &userIDs).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return userIDs, nil
|
||||
}
|
||||
|
||||
// UpdateUser updates all fields of an existing user.
|
||||
func UpdateUser(ctx context.Context, user *model.User) error {
|
||||
return db.DB(ctx).Save(user).Error
|
||||
}
|
||||
|
||||
// CreateUserFromOAuth creates a user from OAuth profile data and fills userOut.
|
||||
func CreateUserFromOAuth(ctx context.Context, userOut *model.User, oauthInfo *model.OAuthUserInfo) error {
|
||||
now := time.Now()
|
||||
userID := oauthInfo.GetID()
|
||||
newUser := model.User{
|
||||
ID: userID,
|
||||
Username: oauthInfo.Username,
|
||||
Nickname: oauthInfo.Name,
|
||||
Email: oauthInfo.Email,
|
||||
AvatarURL: oauthInfo.AvatarURL,
|
||||
IsActive: oauthInfo.Active,
|
||||
LastLoginAt: now,
|
||||
IsAdmin: false,
|
||||
}
|
||||
if newUser.ID == 0 {
|
||||
newUser.ID = idgen.NextUint64ID()
|
||||
}
|
||||
if err := db.DB(ctx).Create(&newUser).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
*userOut = newUser
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListUsernamesMatchingBase returns usernames equal to base or prefixed with base+"-".
|
||||
func ListUsernamesMatchingBase(ctx context.Context, base string) ([]string, error) {
|
||||
var names []string
|
||||
if err := db.DB(ctx).Model(&model.User{}).
|
||||
Where("username = ? OR username LIKE ?", base, base+"-%").
|
||||
Pluck("username", &names).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return names, nil
|
||||
}
|
||||
|
||||
// GetActiveUserByID loads a user by ID who is active.
|
||||
func GetActiveUserByID(ctx context.Context, id uint64) (model.User, error) {
|
||||
var user model.User
|
||||
if err := db.DB(ctx).Where("id = ? AND is_active = ?", id, true).First(&user).Error; err != nil {
|
||||
return model.User{}, err
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// GetUserByUsernameOrEmail loads a user by username or email.
|
||||
func GetUserByUsernameOrEmail(ctx context.Context, input string) (model.User, error) {
|
||||
var user model.User
|
||||
if err := db.DB(ctx).Where("username = ? OR email = ?", input, input).First(&user).Error; err != nil {
|
||||
return model.User{}, err
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// CountUsersByEmailExceptID counts users with the email excluding a given user id.
|
||||
func CountUsersByEmailExceptID(ctx context.Context, email string, exceptID uint64) (int64, error) {
|
||||
var count int64
|
||||
if err := db.DB(ctx).Model(&model.User{}).Where("email = ? AND id != ?", email, exceptID).Count(&count).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateUserLastLoginAt updates only last_login_at for a user.
|
||||
func UpdateUserLastLoginAt(ctx context.Context, userID uint64, at time.Time) error {
|
||||
return db.DB(ctx).Model(&model.User{}).Where("id = ?", userID).Update("last_login_at", at).Error
|
||||
}
|
||||
|
||||
// UpdateUserPassword updates only the password hash for a user.
|
||||
func UpdateUserPassword(ctx context.Context, userID uint64, passwordHash string) error {
|
||||
return db.DB(ctx).Model(&model.User{}).Where("id = ?", userID).Update("password", passwordHash).Error
|
||||
}
|
||||
|
||||
// RegisterUserWithChecks validates username/email uniqueness then creates the user.
|
||||
func RegisterUserWithChecks(ctx context.Context, user *model.User) error {
|
||||
var count int64
|
||||
if err := db.DB(ctx).Model(&model.User{}).Where("username = ?", user.Username).Count(&count).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if count > 0 {
|
||||
return errors.New("用户名已存在")
|
||||
}
|
||||
if user.Email != "" {
|
||||
var emailCount int64
|
||||
if err := db.DB(ctx).Model(&model.User{}).Where("email = ?", user.Email).Count(&emailCount).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if emailCount > 0 {
|
||||
return errors.New("该邮箱已被其他账号绑定")
|
||||
}
|
||||
}
|
||||
if user.ID == 0 {
|
||||
user.ID = idgen.NextUint64ID()
|
||||
}
|
||||
return db.DB(ctx).Create(user).Error
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user