- constants: 用户状态、性别、角色代码常量定义 - model: User/Role/UserRole GORM 模型 - dao: UserDAO (CRUD + 账号查询) + RoleDAO (角色分配/查询/检查) - provider: Auth 模块 Wire Provider Set Made-with: Cursor
132 lines
3.6 KiB
Go
132 lines
3.6 KiB
Go
// Package dao 提供 auth 模块的数据库访问操作
|
||
package dao
|
||
|
||
import (
|
||
"context"
|
||
|
||
"github.com/echochat/backend/app/auth/model"
|
||
"github.com/echochat/backend/pkg/logs"
|
||
"go.uber.org/zap"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// UserDAO 用户数据访问对象
|
||
type UserDAO struct {
|
||
db *gorm.DB
|
||
}
|
||
|
||
// NewUserDAO 创建 UserDAO 实例
|
||
func NewUserDAO(db *gorm.DB) *UserDAO {
|
||
return &UserDAO{db: db}
|
||
}
|
||
|
||
// Create 创建用户
|
||
// 插入一条新用户记录,username 和 email 有唯一索引
|
||
func (d *UserDAO) Create(ctx context.Context, user *model.User) error {
|
||
funcName := "dao.user_dao.Create"
|
||
logs.Info(ctx, funcName, "创建用户",
|
||
zap.String("username", user.Username),
|
||
zap.String("email", logs.MaskEmail(user.Email)),
|
||
)
|
||
|
||
var err error
|
||
defer func() {
|
||
if err != nil {
|
||
logs.Error(ctx, funcName, "创建用户失败", zap.Error(err))
|
||
} else {
|
||
logs.Info(ctx, funcName, "创建用户成功", zap.Int64("user_id", user.ID))
|
||
}
|
||
}()
|
||
|
||
err = d.db.WithContext(ctx).Create(user).Error
|
||
return err
|
||
}
|
||
|
||
// FindByEmail 按邮箱查询用户
|
||
// 精确匹配邮箱地址,利用 email 唯一索引
|
||
func (d *UserDAO) FindByEmail(ctx context.Context, email string) (*model.User, error) {
|
||
funcName := "dao.user_dao.FindByEmail"
|
||
logs.Debug(ctx, funcName, "按邮箱查询用户", zap.String("email", logs.MaskEmail(email)))
|
||
|
||
var user model.User
|
||
err := d.db.WithContext(ctx).Where("email = ?", email).First(&user).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return &user, nil
|
||
}
|
||
|
||
// FindByUsername 按用户名查询用户
|
||
// 精确匹配用户名,利用 username 唯一索引
|
||
func (d *UserDAO) FindByUsername(ctx context.Context, username string) (*model.User, error) {
|
||
funcName := "dao.user_dao.FindByUsername"
|
||
logs.Debug(ctx, funcName, "按用户名查询用户", zap.String("username", username))
|
||
|
||
var user model.User
|
||
err := d.db.WithContext(ctx).Where("username = ?", username).First(&user).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return &user, nil
|
||
}
|
||
|
||
// FindByID 按 ID 查询用户
|
||
func (d *UserDAO) FindByID(ctx context.Context, id int64) (*model.User, error) {
|
||
funcName := "dao.user_dao.FindByID"
|
||
logs.Debug(ctx, funcName, "按ID查询用户", zap.Int64("id", id))
|
||
|
||
var user model.User
|
||
err := d.db.WithContext(ctx).First(&user, id).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return &user, nil
|
||
}
|
||
|
||
// Update 更新用户信息
|
||
// 仅更新非零值字段
|
||
func (d *UserDAO) Update(ctx context.Context, user *model.User) error {
|
||
funcName := "dao.user_dao.Update"
|
||
logs.Info(ctx, funcName, "更新用户信息", zap.Int64("user_id", user.ID))
|
||
|
||
var err error
|
||
defer func() {
|
||
if err != nil {
|
||
logs.Error(ctx, funcName, "更新用户失败", zap.Int64("user_id", user.ID), zap.Error(err))
|
||
}
|
||
}()
|
||
|
||
err = d.db.WithContext(ctx).Save(user).Error
|
||
return err
|
||
}
|
||
|
||
// UpdateLastLogin 更新最后登录信息
|
||
func (d *UserDAO) UpdateLastLogin(ctx context.Context, userID int64, ip string) error {
|
||
funcName := "dao.user_dao.UpdateLastLogin"
|
||
logs.Debug(ctx, funcName, "更新登录信息", zap.Int64("user_id", userID))
|
||
|
||
err := d.db.WithContext(ctx).
|
||
Model(&model.User{}).
|
||
Where("id = ?", userID).
|
||
Updates(map[string]interface{}{
|
||
"last_login_at": gorm.Expr("NOW()"),
|
||
"last_login_ip": ip,
|
||
}).Error
|
||
return err
|
||
}
|
||
|
||
// FindByAccount 按用户名或邮箱查找用户(登录时使用)
|
||
func (d *UserDAO) FindByAccount(ctx context.Context, account string) (*model.User, error) {
|
||
funcName := "dao.user_dao.FindByAccount"
|
||
logs.Debug(ctx, funcName, "按账号查询用户", zap.String("account", account))
|
||
|
||
var user model.User
|
||
err := d.db.WithContext(ctx).
|
||
Where("username = ? OR email = ?", account, account).
|
||
First(&user).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return &user, nil
|
||
}
|