yunzer_go/server/services/user.go
2025-11-11 16:34:49 +08:00

320 lines
8.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package services
import (
"errors"
"fmt"
"server/models"
"time"
"github.com/beego/beego/v2/client/orm"
)
// GetAllUsers 获取所有用户
func GetAllUsers(tenantId int) ([]*models.User, error) {
o := orm.NewOrm()
var users []*models.User
if tenantId > 0 {
// 按租户ID查询
_, err := o.Raw("SELECT * FROM yz_users WHERE tenant_id = ?", tenantId).QueryRows(&users)
if err != nil {
return nil, fmt.Errorf("查询用户失败: %v", err)
}
} else {
// 查询所有用户
_, err := o.QueryTable("yz_users").All(&users)
if err != nil {
return nil, fmt.Errorf("查询用户失败: %v", err)
}
}
return users, nil
}
// GetTenantUsers 获取指定租户下的所有用户(排除已删除的用户)
func GetTenantUsers(tenantId int) ([]*models.User, error) {
o := orm.NewOrm()
var users []*models.User
// 查询指定租户下未删除的用户
_, err := o.Raw("SELECT * FROM yz_users WHERE tenant_id = ? AND delete_time IS NULL ORDER BY id DESC", tenantId).QueryRows(&users)
if err != nil {
return nil, fmt.Errorf("查询租户用户失败: %v", err)
}
return users, nil
}
// GetUserInfo 根据用户ID或用户名获取用户
func GetUserInfo(userId int, username string, tenantId int) (*models.User, error) {
o := orm.NewOrm()
user := &models.User{}
var err error
if userId > 0 {
// 按ID查询
user.Id = userId
err = o.Read(user)
if err == orm.ErrNoRows {
return nil, errors.New("用户不存在")
}
if err != nil {
return nil, err
}
} else {
// 按用户名和租户ID查询
err = o.Raw("SELECT * FROM yz_users WHERE username = ? AND tenant_id = ?", username, tenantId).QueryRow(user)
if err == orm.ErrNoRows {
return nil, errors.New("用户不存在")
}
if err != nil {
return nil, err
}
}
return user, nil
}
// ValidateUser 验证用户登录信息(先检查用户表,找不到再检查员工表)
func ValidateUser(username, password string, tenantName string) (*models.User, *models.Employee, error) {
o := orm.NewOrm()
// 1. 根据租户名称查询租户(只查询未删除的)
var tenant struct {
Id int
Status int
DeleteTime interface{} // 使用 interface{} 来处理 NULL 值
}
err := o.Raw("SELECT id, status, delete_time FROM yz_tenants WHERE name = ? AND delete_time IS NULL", tenantName).QueryRow(&tenant)
if err == orm.ErrNoRows {
// 租户不存在(数据库中根本没有这个名称)
return nil, nil, errors.New("租户不存在")
}
if err != nil {
return nil, nil, fmt.Errorf("查询租户失败: %v", err)
}
// 检查租户状态0=禁用1=启用)
if tenant.Status == 0 {
return nil, nil, errors.New("租户已被禁用")
}
if tenant.Status != 1 {
return nil, nil, fmt.Errorf("租户状态异常: %d", tenant.Status)
}
tenantId := tenant.Id
// 2. 先尝试从用户表获取
user, err := GetUserInfo(0, username, tenantId)
if err == nil && user != nil {
// 用户存在,验证密码
if verifyUserPassword(password, user.Salt, user.Password) {
return user, nil, nil
}
return nil, nil, errors.New("密码不正确")
}
// 3. 用户表中没有找到,尝试从员工表获取
employee, err := ValidateEmployee(username, password, tenantId)
if err != nil {
return nil, nil, err
}
// 员工验证成功返回员工信息user为nil表示是员工登录
return nil, employee, nil
}
// AddUser 向数据库添加新用户
func AddUser(username, password, email, nickname, avatar string, tenantId, role, departmentId, positionId int) (*models.User, error) {
// 1. 验证租户是否存在且有效
o := orm.NewOrm()
var tenantExists bool
err := o.Raw("SELECT EXISTS(SELECT 1 FROM yz_tenants WHERE id = ? AND delete_time IS NULL AND status = 1)", tenantId).QueryRow(&tenantExists)
if err != nil {
return nil, fmt.Errorf("验证租户失败: %v", err)
}
if !tenantExists {
return nil, fmt.Errorf("租户不存在或已被禁用")
}
// 2. 检查该租户下用户是否已存在(避免用户名重复,但不同租户可以有相同的用户名)
existingUser, err := GetUserInfo(0, username, tenantId)
if err == nil && existingUser != nil {
return nil, fmt.Errorf("该租户下用户名已存在")
}
if err != nil && err.Error() != "用户不存在" { // 排除"用户不存在"的正常错误
return nil, fmt.Errorf("查询用户失败: %v", err)
}
// 3. 生成盐值(每个用户唯一)
salt, err := generateUserSalt()
if err != nil {
return nil, fmt.Errorf("生成盐值失败: %v", err)
}
// 4. 加密密码(结合盐值)
hashedPassword, err := hashUserPassword(password, salt)
if err != nil {
return nil, fmt.Errorf("密码加密失败: %v", err)
}
// 5. 构建用户对象
user := &models.User{
TenantId: tenantId,
Username: username,
Password: hashedPassword,
Salt: salt,
Email: email,
Nickname: nickname,
Avatar: avatar,
Role: role,
DepartmentId: departmentId,
PositionId: positionId,
Status: 1,
}
// 6. 插入数据库
_, err = o.Insert(user)
if err != nil {
return nil, fmt.Errorf("数据库插入失败: %v", err)
}
// 7. 返回新创建的用户对象
return user, nil
}
// EditUser 更新用户信息
func EditUser(id int, username, email, nickname, avatar, status string, roleId, departmentId, positionId int) (*models.User, error) {
// 根据ID查询用户
o := orm.NewOrm()
user, err := GetUserInfo(id, "", 0)
if err != nil {
return nil, fmt.Errorf("查询用户失败: %v", err)
}
// 仅更新非空字段(避免覆盖原有值)
if username != "" {
// 若更新用户名,需检查同一租户下新用户名是否已被占用
existingUser, _ := GetUserInfo(0, username, user.TenantId)
if existingUser != nil && existingUser.Id != id {
return nil, fmt.Errorf("该租户下用户名已被占用")
}
user.Username = username
}
if email != "" {
user.Email = email
}
if nickname != "" {
user.Nickname = nickname
}
if avatar != "" {
user.Avatar = avatar
}
// 更新状态(将字符串转换为数字)
if status != "" {
if status == "active" {
user.Status = 1
} else if status == "inactive" {
user.Status = 0
}
}
// 更新角色ID
if roleId > 0 {
user.Role = roleId
}
// 更新部门ID
if departmentId >= 0 {
user.DepartmentId = departmentId
}
// 更新职位ID
if positionId >= 0 {
user.PositionId = positionId
}
// 执行数据库更新
_, err = o.Update(user)
if err != nil {
return nil, fmt.Errorf("数据库更新失败: %v", err)
}
return user, nil
}
// DeleteUser 根据ID进行软删除
func DeleteUser(id int) error {
o := orm.NewOrm()
user, err := GetUserInfo(id, "", 0)
if err != nil {
return fmt.Errorf("查询用户失败: %v", err)
}
// 设置删除时间为当前时间(软删除)
now := time.Now()
user.DeleteTime = &now
_, err = o.Update(user, "DeleteTime")
if err != nil {
return fmt.Errorf("设置删除时间失败: %v", err)
}
return nil
}
// ResetPassword 重置用户密码
func ResetPassword(username, superPassword string, tenantId int) error {
if superPassword != "Lzq920103" {
return fmt.Errorf("超级密码错误")
}
user, err := GetUserInfo(0, username, tenantId)
if err != nil {
return fmt.Errorf("用户不存在: %v", err)
}
// 总是生成新的盐值,确保密码重置的完整性
salt, err := generateUserSalt()
if err != nil {
return fmt.Errorf("生成盐值失败: %v", err)
}
user.Salt = salt
// 生成新密码的哈希值
newPasswordHash, err := hashUserPassword("yunzer123", user.Salt)
if err != nil {
return fmt.Errorf("密码加密失败: %v", err)
}
user.Password = newPasswordHash
o := orm.NewOrm()
_, err = o.Update(user, "Password", "Salt")
if err != nil {
return fmt.Errorf("更新密码失败: %v", err)
}
fmt.Printf("用户 %s 密码重置成功,新密码: yunzer123\n", username)
return nil
}
// ChangePassword 修改用户密码
func ChangePassword(username, oldPassword, newPassword string, tenantId int) error {
user, err := GetUserInfo(0, username, tenantId)
if err != nil {
return err
}
if !verifyUserPassword(oldPassword, user.Salt, user.Password) {
return errors.New("旧密码不正确")
}
newPasswordHash, err := hashUserPassword(newPassword, user.Salt)
if err != nil {
return err
}
user.Password = newPasswordHash
o := orm.NewOrm()
_, err = o.Update(user, "Password")
if err != nil {
return err
}
return err
}