ldap-1-backend/logic/user_logic.go

543 lines
18 KiB
Go
Raw Normal View History

2022-05-18 17:57:03 +08:00
package logic
import (
"errors"
2022-05-18 17:57:03 +08:00
"fmt"
"github.com/eryajf-world/go-ldap-admin/config"
"github.com/eryajf-world/go-ldap-admin/model"
"github.com/eryajf-world/go-ldap-admin/public/tools"
"github.com/eryajf-world/go-ldap-admin/service/ildap"
"github.com/eryajf-world/go-ldap-admin/service/isql"
"github.com/eryajf-world/go-ldap-admin/svc/request"
"github.com/eryajf-world/go-ldap-admin/svc/response"
"github.com/gin-gonic/gin"
"github.com/thoas/go-funk"
)
type UserLogic struct{}
// Add 添加数据
func (l UserLogic) Add(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
r, ok := req.(*request.UserAddReq)
if !ok {
return nil, ReqAssertErr
}
_ = c
if isql.User.Exist(tools.H{"username": r.Username}) {
return nil, tools.NewValidatorError(fmt.Errorf("用户名已存在,请勿重复添加"))
}
if isql.User.Exist(tools.H{"mobile": r.Mobile}) {
return nil, tools.NewValidatorError(fmt.Errorf("手机号已存在,请勿重复添加"))
}
if isql.User.Exist(tools.H{"job_number": r.JobNumber}) {
return nil, tools.NewValidatorError(fmt.Errorf("工号已存在,请勿重复添加"))
}
if isql.User.Exist(tools.H{"mail": r.Mail}) {
return nil, tools.NewValidatorError(fmt.Errorf("邮箱已存在,请勿重复添加"))
}
// 密码通过RSA解密
// 密码不为空就解密
if r.Password != "" {
decodeData, err := tools.RSADecrypt([]byte(r.Password), config.Conf.System.RSAPrivateBytes)
if err != nil {
return nil, tools.NewValidatorError(fmt.Errorf("密码解密失败"))
}
r.Password = string(decodeData)
if len(r.Password) < 6 {
return nil, tools.NewValidatorError(fmt.Errorf("密码长度至少为6位"))
}
} else {
r.Password = "123456"
}
// 当前登陆用户角色排序最小值(最高等级角色)以及当前登陆的用户
currentRoleSortMin, ctxUser, err := isql.User.GetCurrentUserMinRoleSort(c)
if err != nil {
return nil, tools.NewValidatorError(fmt.Errorf("获取当前登陆用户角色排序最小值失败"))
}
// 根据角色id获取角色
if r.RoleIds == nil || len(r.RoleIds) == 0 {
r.RoleIds = []uint{2} // 默认添加为普通用户角色
}
roles, err := isql.Role.GetRolesByIds(r.RoleIds)
if err != nil {
return nil, tools.NewValidatorError(fmt.Errorf("根据角色ID获取角色信息失败"))
}
var reqRoleSorts []int
for _, role := range roles {
reqRoleSorts = append(reqRoleSorts, int(role.Sort))
}
// 前端传来用户角色排序最小值(最高等级角色)
reqRoleSortMin := uint(funk.MinInt(reqRoleSorts).(int))
// 当前用户的角色排序最小值 需要小于 前端传来的角色排序最小值(用户不能创建比自己等级高的或者相同等级的用户)
if currentRoleSortMin >= reqRoleSortMin {
return nil, tools.NewValidatorError(fmt.Errorf("用户不能创建比自己等级高的或者相同等级的用户"))
}
user := model.User{
Username: r.Username,
Password: r.Password,
Nickname: r.Nickname,
GivenName: r.GivenName,
Mail: r.Mail,
JobNumber: r.JobNumber,
Mobile: r.Mobile,
Avatar: r.Avatar,
PostalAddress: r.PostalAddress,
Departments: r.Departments,
Position: r.Position,
Introduction: r.Introduction,
Status: r.Status,
Creator: ctxUser.Username,
DepartmentId: r.DepartmentId,
Source: r.Source,
2022-05-18 17:57:03 +08:00
Roles: roles,
}
if user.Source == "" {
user.Source = "platform"
}
//先识别用户选择的部门是否是OU开头
dn, err := isql.Group.GetGroupDn(r.DepartmentId, "")
if err != nil {
return nil, err.Error()
}
gdn := fmt.Sprintf("%s,%s", dn, config.Conf.Ldap.LdapBaseDN)
if gdn[:3] == "ou=" {
return nil, errors.New("不能添加用户到OU组织单元")
}
//先创建用户到默认分组
2022-05-18 17:57:03 +08:00
err = ildap.User.Add(&user)
if err != nil {
return nil, tools.NewLdapError(fmt.Errorf("向LDAP创建用户失败" + err.Error()))
}
//根据选择的部门,添加到部门内
err = ildap.Group.AddUserToGroup(gdn, fmt.Sprintf("uid=%s,%s", user.Username, config.Conf.Ldap.LdapUserDN))
if err != nil {
return nil, err.Error()
2022-05-18 17:57:03 +08:00
}
err = isql.User.Add(&user)
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("向MySQL创建用户失败" + err.Error()))
}
//根据部门分配,将用户和部门信息维护到部门关系表里面
users := []model.User{}
users = append(users, user)
depart := new(model.Group)
filter := tools.H{"id": int(r.DepartmentId)}
err = isql.Group.Find(filter, depart)
if err != nil {
return "", tools.NewMySqlError(err)
}
err = isql.Group.AddUserToGroup(depart, users)
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("向MySQL添加用户到分组关系失败" + err.Error()))
2022-05-18 17:57:03 +08:00
}
return nil, nil
}
// List 数据列表
func (l UserLogic) List(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
r, ok := req.(*request.UserListReq)
if !ok {
return nil, ReqAssertErr
}
_ = c
users, err := isql.User.List(r)
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("获取用户列表失败:" + err.Error()))
2022-05-18 17:57:03 +08:00
}
rets := make([]model.User, 0)
for _, user := range users {
rets = append(rets, *user)
}
count, err := isql.User.ListCount(r)
2022-05-18 17:57:03 +08:00
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("获取用户总数失败:" + err.Error()))
2022-05-18 17:57:03 +08:00
}
return response.UserListRsp{
Total: int(count),
Users: rets,
}, nil
}
// Update 更新数据
func (l UserLogic) Update(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
r, ok := req.(*request.UserUpdateReq)
if !ok {
return nil, ReqAssertErr
}
_ = c
if !isql.User.Exist(tools.H{"id": r.ID}) {
return nil, tools.NewMySqlError(fmt.Errorf("该记录不存在"))
}
// 获取当前登陆用户
ctxUser, err := isql.User.GetCurrentLoginUser(c)
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("获取当前登陆用户失败"))
}
// 获取当前登陆用户的所有角色
currentRoles := ctxUser.Roles
// 获取当前登陆用户角色的排序,和前端传来的角色排序做比较
var currentRoleSorts []int
// 当前登陆用户角色ID集合
var currentRoleIds []uint
for _, role := range currentRoles {
currentRoleSorts = append(currentRoleSorts, int(role.Sort))
currentRoleIds = append(currentRoleIds, role.ID)
}
// 当前登陆用户角色排序最小值(最高等级角色)
currentRoleSortMin := funk.MinInt(currentRoleSorts).(int)
// 获取前端传来的用户角色id
reqRoleIds := r.RoleIds
// 根据角色id获取角色
roles, err := isql.Role.GetRolesByIds(reqRoleIds)
if err != nil {
return nil, tools.NewValidatorError(fmt.Errorf("根据角色ID获取角色信息失败"))
}
if len(roles) == 0 {
return nil, tools.NewValidatorError(fmt.Errorf("未获取到角色信息"))
}
var reqRoleSorts []int
for _, role := range roles {
reqRoleSorts = append(reqRoleSorts, int(role.Sort))
}
// 前端传来用户角色排序最小值(最高等级角色)
reqRoleSortMin := funk.MinInt(reqRoleSorts).(int)
oldData := new(model.User)
err = isql.User.Find(tools.H{"id": r.ID}, oldData)
if err != nil {
return nil, tools.NewMySqlError(err)
}
user := model.User{
Model: oldData.Model,
Username: r.Username,
2022-05-18 17:57:03 +08:00
Nickname: r.Nickname,
GivenName: r.GivenName,
Mail: r.Mail,
JobNumber: r.JobNumber,
Mobile: r.Mobile,
Avatar: r.Avatar,
PostalAddress: r.PostalAddress,
Departments: r.Departments,
Position: r.Position,
Introduction: r.Introduction,
Creator: ctxUser.Username,
DepartmentId: r.DepartmentId,
Source: oldData.Source,
2022-05-18 17:57:03 +08:00
Roles: roles,
}
// 判断是更新自己还是更新别人,如果操作的ID与登陆用户的ID一致则说明操作的是自己
if int(r.ID) == int(ctxUser.ID) {
// 不能更改自己的角色
reqDiff, currentDiff := funk.Difference(r.RoleIds, currentRoleIds)
if len(reqDiff.([]uint)) > 0 || len(currentDiff.([]uint)) > 0 {
return nil, tools.NewValidatorError(fmt.Errorf("不能更改自己的角色"))
}
} else {
// 如果是更新别人,操作者不能更新比自己角色等级高的或者相同等级的用户
// 根据userIdID获取用户角色排序最小值
minRoleSorts, err := isql.User.GetUserMinRoleSortsByIds([]uint{uint(r.ID)})
if err != nil || len(minRoleSorts) == 0 {
return nil, tools.NewValidatorError(fmt.Errorf("根据用户ID获取用户角色排序最小值失败"))
}
if currentRoleSortMin >= minRoleSorts[0] {
return nil, tools.NewValidatorError(fmt.Errorf("用户不能更新比自己角色等级高的或者相同等级的用户"))
}
// 用户不能把别的用户角色等级更新得比自己高或相等
if currentRoleSortMin >= reqRoleSortMin {
return nil, tools.NewValidatorError(fmt.Errorf("用户不能把别的用户角色等级更新得比自己高或相等"))
}
}
err = ildap.User.Update(oldData.Username, &user)
if err != nil {
return nil, tools.NewLdapError(fmt.Errorf("在LDAP更新用户失败" + err.Error()))
2022-05-18 17:57:03 +08:00
}
// 更新用户
if !config.Conf.Ldap.LdapUserNameModify {
user.Username = oldData.Username
}
2022-05-18 17:57:03 +08:00
err = isql.User.Update(&user)
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("在MySQL更新用户失败" + err.Error()))
}
//判断部门信息是否有变化有变化则更新相应的数据库
if oldData.DepartmentId != r.DepartmentId {
//从旧组中删除
err = l.RemoveUserToGroup(oldData.DepartmentId, []uint{r.ID})
//添加到新分组中
err = l.AddUserToGroup(r.DepartmentId, []uint{r.ID})
if err != nil {
return nil, err
}
2022-05-18 17:57:03 +08:00
}
return nil, nil
}
// RemoveUser 移除用户
func (l UserLogic) RemoveUserToGroup(groupId uint, userIds []uint) error {
filter := tools.H{"id": groupId}
if !isql.Group.Exist(filter) {
return tools.NewMySqlError(fmt.Errorf("分组不存在"))
}
users, err := isql.User.GetUserByIds(userIds)
if err != nil {
return tools.NewMySqlError(fmt.Errorf("获取用户列表失败: %s", err.Error()))
}
group := new(model.Group)
err = isql.Group.Find(filter, group)
if err != nil {
return tools.NewMySqlError(fmt.Errorf("获取分组失败: %s", err.Error()))
}
gdn, err := isql.Group.GetGroupDn(groupId, "")
if err != nil {
return tools.NewMySqlError(fmt.Errorf("获取分组失败: %s", err.Error()))
}
gdn = fmt.Sprintf("%s,%s", gdn, config.Conf.Ldap.LdapBaseDN)
for _, user := range users {
err := ildap.Group.RemoveUserFromGroup(gdn, user.Username)
if err != nil {
return tools.NewLdapError(fmt.Errorf("将用户从ldap移除失败" + err.Error()))
}
}
err = isql.Group.RemoveUserFromGroup(group, users)
if err != nil {
return tools.NewMySqlError(fmt.Errorf("将用户从MySQL移除失败: %s", err.Error()))
}
return nil
}
//将用户添加到分组中
func (l UserLogic) AddUserToGroup(groupId uint, userIds []uint) error {
filter := tools.H{"id": groupId}
if !isql.Group.Exist(filter) {
return tools.NewMySqlError(fmt.Errorf("分组不存在"))
}
users, err := isql.User.GetUserByIds(userIds)
if err != nil {
return tools.NewMySqlError(fmt.Errorf("获取用户列表失败: %s", err.Error()))
}
group := new(model.Group)
err = isql.Group.Find(filter, group)
if err != nil {
return tools.NewMySqlError(fmt.Errorf("获取分组失败: %s", err.Error()))
}
for _, user := range users {
gdn, err := isql.Group.GetGroupDn(group.ID, "")
if err != nil {
return err
}
gdn = fmt.Sprintf("%s,%s", gdn, config.Conf.Ldap.LdapBaseDN)
udn := config.Conf.Ldap.LdapAdminDN
if user.Username != "admin" {
udn = fmt.Sprintf("uid=%s,%s", user.Username, config.Conf.Ldap.LdapUserDN)
}
err = ildap.Group.AddUserToGroup(gdn, udn)
if err != nil {
return tools.NewLdapError(fmt.Errorf("向LDAP添加用户到分组失败" + err.Error()))
}
}
err = isql.Group.AddUserToGroup(group, users)
if err != nil {
return tools.NewMySqlError(fmt.Errorf("添加用户到分组失败: %s", err.Error()))
}
return nil
}
2022-05-18 17:57:03 +08:00
// Delete 删除数据
func (l UserLogic) Delete(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
r, ok := req.(*request.UserDeleteReq)
if !ok {
return nil, ReqAssertErr
}
_ = c
// 根据用户ID获取用户角色排序最小值
roleMinSortList, err := isql.User.GetUserMinRoleSortsByIds(r.UserIds) // TODO: 这里应该复用下边的 GetUserByIds 方法
if err != nil || len(roleMinSortList) == 0 {
return nil, tools.NewValidatorError(fmt.Errorf("根据用户ID获取用户角色排序最小值失败"))
}
// 获取当前登陆用户角色排序最小值(最高等级角色)以及当前用户
minSort, ctxUser, err := isql.User.GetCurrentUserMinRoleSort(c)
if err != nil {
return nil, tools.NewValidatorError(fmt.Errorf("获取当前登陆用户角色排序最小值失败"))
}
currentRoleSortMin := int(minSort)
// 不能删除自己
if funk.Contains(r.UserIds, ctxUser.ID) {
return nil, tools.NewValidatorError(fmt.Errorf("用户不能删除自己"))
}
// 不能删除比自己(登陆用户)角色排序低(等级高)的用户
for _, sort := range roleMinSortList {
if currentRoleSortMin >= sort {
return nil, tools.NewValidatorError(fmt.Errorf("用户不能删除比自己角色等级高的用户"))
}
}
users, err := isql.User.GetUserByIds(r.UserIds)
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("获取用户信息失败: " + err.Error()))
}
for _, user := range users {
err := ildap.User.Delete(user.Username)
if err != nil {
return nil, tools.NewLdapError(fmt.Errorf("在LDAP删除用户失败" + err.Error()))
}
}
err = isql.User.Delete(r.UserIds)
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("在MySQL删除用户失败: " + err.Error()))
}
return nil, nil
}
// ChangePwd 修改密码
func (l UserLogic) ChangePwd(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
r, ok := req.(*request.UserChangePwdReq)
if !ok {
return nil, ReqAssertErr
}
_ = c
// 前端传来的密码是rsa加密的,先解密
// 密码通过RSA解密
decodeOldPassword, err := tools.RSADecrypt([]byte(r.OldPassword), config.Conf.System.RSAPrivateBytes)
if err != nil {
return nil, tools.NewValidatorError(fmt.Errorf("原密码解析失败"))
}
decodeNewPassword, err := tools.RSADecrypt([]byte(r.NewPassword), config.Conf.System.RSAPrivateBytes)
if err != nil {
return nil, tools.NewValidatorError(fmt.Errorf("新密码解析失败"))
}
r.OldPassword = string(decodeOldPassword)
r.NewPassword = string(decodeNewPassword)
// 获取当前用户
user, err := isql.User.GetCurrentLoginUser(c)
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("获取当前登陆用户失败"))
}
// 获取用户的真实正确密码
// correctPasswd := user.Password
// 判断前端请求的密码是否等于真实密码
// err = tools.ComparePasswd(correctPasswd, r.OldPassword)
// if err != nil {
// return nil, tools.NewValidatorError(fmt.Errorf("原密码错误"))
// }
if tools.NewParPasswd(user.Password) != r.OldPassword {
return nil, tools.NewValidatorError(fmt.Errorf("原密码错误"))
}
// ldap更新密码时可以直接指定用户DN和新密码即可更改成功
err = ildap.User.ChangePwd(user.Username, "", r.NewPassword)
if err != nil {
return nil, tools.NewLdapError(fmt.Errorf("在LDAP更新密码失败" + err.Error()))
}
// 更新密码
err = isql.User.ChangePwd(user.Username, tools.NewGenPasswd(r.NewPassword))
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("在MySQL更新密码失败: " + err.Error()))
}
return nil, nil
}
// ChangeUserStatus 修改用户状态
func (l UserLogic) ChangeUserStatus(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
r, ok := req.(*request.UserChangeUserStatusReq)
if !ok {
return nil, ReqAssertErr
}
_ = c
// 校验工作
filter := tools.H{"id": r.ID}
if !isql.User.Exist(filter) {
return nil, tools.NewValidatorError(fmt.Errorf("该用户不存在"))
}
user := new(model.User)
err := isql.User.Find(filter, user)
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("在MySQL查询用户失败: " + err.Error()))
}
if r.Status == 1 && r.Status == user.Status {
return nil, tools.NewValidatorError(fmt.Errorf("用户已经是在职状态"))
}
if r.Status == 2 && r.Status == user.Status {
return nil, tools.NewValidatorError(fmt.Errorf("用户已经是离职状态"))
}
// 获取当前登录用户,只有管理员才能够将用户状态改变
// 获取当前登陆用户角色排序最小值(最高等级角色)以及当前用户
minSort, _, err := isql.User.GetCurrentUserMinRoleSort(c)
if err != nil {
return nil, tools.NewValidatorError(fmt.Errorf("获取当前登陆用户角色排序最小值失败"))
}
if int(minSort) != 1 {
return nil, tools.NewValidatorError(fmt.Errorf("只有管理员才能更改用户状态"))
}
if r.Status == 2 {
err = ildap.User.Delete(user.Username)
if err != nil {
return nil, tools.NewLdapError(fmt.Errorf("在LDAP删除用户失败" + err.Error()))
}
} else {
err = ildap.User.Add(user)
2022-05-18 17:57:03 +08:00
if err != nil {
return nil, tools.NewLdapError(fmt.Errorf("在LDAP添加用户失败" + err.Error()))
}
}
err = isql.User.ChangeStatus(int(r.ID), int(r.Status))
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("在MySQL更新用户状态失败: " + err.Error()))
}
return nil, nil
}
// GetUserInfo 获取用户信息
func (l UserLogic) GetUserInfo(c *gin.Context, req interface{}) (data interface{}, rspError interface{}) {
r, ok := req.(*request.UserGetUserInfoReq)
if !ok {
return nil, ReqAssertErr
}
_ = c
_ = r
user, err := isql.User.GetCurrentLoginUser(c)
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("获取当前用户信息失败: " + err.Error()))
}
return user, nil
}