github.com/SupenBysz/gf-admin-community@v0.7.4/internal/logic/sys_user/sys_user.go (about)

     1  package user
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"errors"
     7  	"github.com/SupenBysz/gf-admin-community/sys_consts"
     8  	"github.com/SupenBysz/gf-admin-community/sys_model"
     9  	"github.com/SupenBysz/gf-admin-community/sys_model/sys_dao"
    10  	"github.com/SupenBysz/gf-admin-community/sys_model/sys_do"
    11  	"github.com/SupenBysz/gf-admin-community/sys_model/sys_entity"
    12  	"github.com/SupenBysz/gf-admin-community/sys_model/sys_enum"
    13  	"github.com/SupenBysz/gf-admin-community/sys_model/sys_hook"
    14  	"github.com/SupenBysz/gf-admin-community/sys_service"
    15  	"github.com/gogf/gf/v2/container/garray"
    16  	"github.com/gogf/gf/v2/database/gdb"
    17  	"github.com/gogf/gf/v2/errors/gcode"
    18  	"github.com/gogf/gf/v2/errors/gerror"
    19  	"github.com/gogf/gf/v2/frame/g"
    20  	"github.com/gogf/gf/v2/os/gtime"
    21  	"github.com/gogf/gf/v2/util/gconv"
    22  	"github.com/kysion/base-library/base_model"
    23  	"github.com/kysion/base-library/base_model/base_enum"
    24  	"github.com/kysion/base-library/utility/base_funs"
    25  	"github.com/kysion/base-library/utility/base_verify"
    26  	"github.com/kysion/base-library/utility/daoctl"
    27  	"github.com/kysion/base-library/utility/en_crypto"
    28  	"github.com/kysion/base-library/utility/kconv"
    29  	"github.com/kysion/base-library/utility/masker"
    30  	"github.com/yitter/idgenerator-go/idgen"
    31  	"math"
    32  	"sort"
    33  	"time"
    34  )
    35  
    36  type hookInfo sys_model.KeyValueT[int64, sys_hook.UserHookInfo]
    37  
    38  type sSysUser struct {
    39  	hookArr []hookInfo
    40  	//redisCache *gcache.Cache
    41  	Duration time.Duration
    42  
    43  	//// 密码加密
    44  	//CryptoPasswordFunc func(ctx context.Context, passwordStr string, user ...sys_entity.SysUser) (pwdEncode string)
    45  }
    46  
    47  func init() {
    48  	sys_service.RegisterSysUser(New())
    49  }
    50  
    51  func New() *sSysUser {
    52  	return &sSysUser{
    53  		//redisCache: gcache.New(),
    54  		hookArr: make([]hookInfo, 0),
    55  	}
    56  }
    57  
    58  //
    59  //// 初始化缓存
    60  //func (s *sSysUser) initInnerCacheItems(ctx context.Context) {
    61  //	size, _ := s.redisCache.Size(ctx)
    62  //	if size > 0 {
    63  //		return
    64  //	}
    65  //
    66  //	items := daoctl.Scan[[]*sys_model.SysUser](
    67  //		sys_dao.SysUser.Ctx(ctx).
    68  //			OrderDesc(sys_dao.SysUser.Columns().CreatedAt),
    69  //	)
    70  //
    71  //	s.redisCache.Clear(ctx)
    72  //	for _, sysUser := range *items {
    73  //		s.redisCache.Set(ctx, sysUser.Id, sysUser, s.Duration)
    74  //	}
    75  //}
    76  
    77  // InstallHook 安装Hook
    78  func (s *sSysUser) InstallHook(event sys_enum.UserEvent, hookFunc sys_hook.UserHookFunc) int64 {
    79  	item := hookInfo{Key: idgen.NextId(), Value: sys_hook.UserHookInfo{Key: event, Value: hookFunc}}
    80  	s.hookArr = append(s.hookArr, item)
    81  	return item.Key
    82  }
    83  
    84  //// SetCryptoPasswordFunc 用于业务端自定义密码规则
    85  //func (s *sSysUser) SetCryptoPasswordFunc(f func(ctx context.Context, passwordStr string, user ...sys_entity.SysUser) (pwdEncode string)) {
    86  //	s.CryptoPasswordFunc = f
    87  //}
    88  //
    89  //// GetCryptoPasswordFunc 应用业务端自定义密码规则
    90  //func (s *sSysUser) GetCryptoPasswordFunc() func(ctx context.Context, passwordStr string, user ...sys_entity.SysUser) (pwdEncode string) {
    91  //	return s.CryptoPasswordFunc
    92  //}
    93  
    94  // UnInstallHook 卸载Hook
    95  func (s *sSysUser) UnInstallHook(savedHookId int64) {
    96  	newFuncArr := make([]hookInfo, 0)
    97  	for _, item := range s.hookArr {
    98  		if item.Key != savedHookId {
    99  			newFuncArr = append(newFuncArr, item)
   100  			continue
   101  		}
   102  	}
   103  	s.hookArr = newFuncArr
   104  }
   105  
   106  // CleanAllHook 清除所有Hook
   107  func (s *sSysUser) CleanAllHook() {
   108  	s.hookArr = make([]hookInfo, 0)
   109  }
   110  
   111  // QueryUserList 获取用户列表
   112  func (s *sSysUser) QueryUserList(ctx context.Context, info *base_model.SearchParams, unionMainId int64, isExport bool) (response *sys_model.SysUserListRes, err error) {
   113  	if info != nil {
   114  		newFields := make([]base_model.FilterInfo, 0)
   115  
   116  		// 移除类型筛选条件
   117  		for _, field := range info.Filter {
   118  			if field.Field != sys_dao.SysUser.Columns().Type {
   119  				newFields = append(newFields, field)
   120  			}
   121  		}
   122  	}
   123  
   124  	// 如果没有查询条件,则默认从缓存返回数据
   125  	if info != nil && len(info.Filter) <= 0 {
   126  		// 初始化内部缓存数据
   127  		//s.initInnerCacheItems(ctx)
   128  
   129  		response = &sys_model.SysUserListRes{}
   130  		if info.Pagination.PageSize <= 0 {
   131  			info.PageSize = 20
   132  		}
   133  		if info.Pagination.PageNum <= 0 {
   134  			info.PageSize = 1
   135  		}
   136  
   137  		// 如果缓存没有数据则直接返回
   138  		//size, _ := s.redisCache.Size(ctx)
   139  		userList, err := daoctl.Query[sys_model.SysUser](sys_dao.SysUser.Ctx(ctx), nil, true)
   140  		if err != nil {
   141  			return nil, sys_service.SysLogs().ErrorSimple(ctx, err, "用户列表查询失败", sys_dao.SysUser.Table())
   142  		}
   143  		size := len(userList.Records)
   144  
   145  		if size <= 0 {
   146  			response.PaginationRes = base_model.PaginationRes{
   147  				Pagination: info.Pagination,
   148  				PageTotal:  0,
   149  				Total:      0,
   150  			}
   151  			response.Records = []*sys_model.SysUser{}
   152  		}
   153  
   154  		// 设置分页信息
   155  		response.Pagination = info.Pagination
   156  		// 初始化分页统计信息
   157  		response.PaginationRes = base_model.PaginationRes{
   158  			Pagination: info.Pagination,
   159  			PageTotal:  gconv.Int(math.Ceil(gconv.Float64(size) / gconv.Float64(info.PageSize))),
   160  			Total:      gconv.Int64(size),
   161  		}
   162  		beginRowIndex := info.PageNum*info.PageSize - info.PageSize
   163  
   164  		// 获得所有的key,遍历
   165  		result, err := daoctl.Query[*sys_model.SysUser](sys_dao.SysUser.Ctx(ctx), info, isExport)
   166  
   167  		//keys, _ := s.redisCache.Keys(ctx)
   168  
   169  		for _, k := range result.Records {
   170  			if beginRowIndex > 0 {
   171  				beginRowIndex--
   172  			} else if len(response.Records) < info.PageSize {
   173  				// 查询用户所拥有的角色
   174  				sysUser := &sys_model.SysUser{}
   175  				sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Id: gconv.String(k.Id)}).Scan(&sysUser)
   176  
   177  				_, err = s.getUserRole(ctx, sysUser, unionMainId)
   178  				if err != nil {
   179  					return nil, err
   180  				}
   181  
   182  				sysUser = s.masker(s.makeMore(ctx, sysUser))
   183  
   184  				response.Records = append(response.Records, sysUser)
   185  			}
   186  
   187  			sort.Slice(response.Records, func(i, j int) bool {
   188  				return response.Records[i].CreatedAt.After(response.Records[j].CreatedAt)
   189  			})
   190  
   191  		}
   192  	}
   193  
   194  	result, err := daoctl.Query[*sys_model.SysUser](sys_dao.SysUser.Ctx(ctx), info, isExport)
   195  
   196  	newList := make([]*sys_model.SysUser, 0)
   197  	if result != nil && result.Records != nil && len(result.Records) > 0 {
   198  		for _, user := range result.Records {
   199  			user.RoleNames = make([]string, 0)
   200  			roleIds, err := sys_service.Casbin().Enforcer().GetRoleManager().GetRoles(gconv.String(user.Id), sys_consts.CasbinDomain)
   201  
   202  			if err != nil && err != sql.ErrNoRows {
   203  				return nil, err
   204  			}
   205  
   206  			if len(roleIds) > 0 {
   207  				roles, err := sys_service.SysRole().QueryRoleList(ctx, base_model.SearchParams{
   208  					Filter: append(make([]base_model.FilterInfo, 0), base_model.FilterInfo{
   209  						Field:     sys_dao.SysRole.Columns().Id,
   210  						Where:     "in",
   211  						IsOrWhere: false,
   212  						Value:     roleIds,
   213  					}),
   214  					Pagination: base_model.Pagination{},
   215  				}, unionMainId)
   216  				if err == nil && len(roles.Records) > 0 {
   217  					for _, role := range roles.Records {
   218  						user.RoleNames = append(user.RoleNames, role.Name)
   219  					}
   220  				}
   221  			}
   222  			user = s.masker(s.makeMore(ctx, user))
   223  			newList = append(newList, user)
   224  		}
   225  	}
   226  
   227  	if newList != nil && len(newList) > 0 {
   228  		result.Records = newList
   229  	}
   230  
   231  	return (*sys_model.SysUserListRes)(result), err
   232  }
   233  
   234  // SetUserRoleIds 设置用户角色
   235  func (s *sSysUser) SetUserRoleIds(ctx context.Context, roleIds []int64, userId int64) (bool, error) {
   236  	for _, roleId := range roleIds {
   237  		roleInfo := &sys_entity.SysRole{}
   238  		// 查找角色是否存在
   239  		roleInfo, err := sys_service.SysRole().GetRoleById(ctx, roleId)
   240  
   241  		if err != nil {
   242  			return false, sys_service.SysLogs().ErrorSimple(ctx, err, "角色ID错误", sys_dao.SysUser.Table())
   243  		}
   244  
   245  		userInfo, err := sys_service.SysUser().GetSysUserById(ctx, userId)
   246  
   247  		if err != nil {
   248  			return false, sys_service.SysLogs().ErrorSimple(ctx, err, "用户ID错误", sys_dao.SysUser.Table())
   249  		}
   250  
   251  		result, err := sys_service.Casbin().AddRoleForUserInDomain(gconv.String(userInfo.Id), gconv.String(roleInfo.Id), sys_consts.CasbinDomain)
   252  
   253  		if result == false || err != nil {
   254  			return result, sys_service.SysLogs().ErrorSimple(ctx, err, "设置用户角色失败", sys_dao.SysUser.Table())
   255  		}
   256  	}
   257  
   258  	return true, nil
   259  }
   260  
   261  // CreateUser 创建用户
   262  func (s *sSysUser) CreateUser(ctx context.Context, info sys_model.UserInnerRegister, userState sys_enum.UserState, userType sys_enum.UserType, customId ...int64) (*sys_model.SysUser, error) {
   263  	count, _ := sys_dao.SysUser.Ctx(ctx).Unscoped().Count(sys_dao.SysUser.Columns().Username, info.Username)
   264  	if count > 0 {
   265  		return nil, sys_service.SysLogs().ErrorSimple(ctx, gerror.NewCode(gcode.CodeBusinessValidationFailed, "用户名已经存在"), "", sys_dao.SysUser.Table())
   266  	}
   267  
   268  	data := sys_model.SysUser{
   269  		SysUser: &sys_entity.SysUser{
   270  			Id:        idgen.NextId(),
   271  			Username:  info.Username,
   272  			Password:  info.Password,
   273  			Mobile:    info.Mobile,
   274  			Email:     info.Email,
   275  			State:     userState.Code(),
   276  			Type:      userType.Code(),
   277  			CreatedAt: gtime.Now(),
   278  		},
   279  	}
   280  
   281  	if len(customId) > 0 && customId[0] > 0 {
   282  		data.Id = customId[0]
   283  	}
   284  	pwdHash, err := en_crypto.PwdHash(info.Password, gconv.String(data.Id))
   285  
   286  	// 业务层自定义密码加密规则
   287  	if sys_consts.Global.CryptoPasswordFunc != nil {
   288  		pwdHash = sys_consts.Global.CryptoPasswordFunc(ctx, info.Password, *data.SysUser)
   289  	}
   290  
   291  	// 密码赋值
   292  	data.Password = pwdHash
   293  
   294  	err = sys_dao.SysUser.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
   295  		// 创建前
   296  		g.Try(ctx, func(ctx context.Context) {
   297  			for _, hook := range s.hookArr {
   298  				// 枚举优化使用:直接调用Has
   299  				//enumOb := sys_enum.User.Type.New(3, "")
   300  				//if enumOb.Has(sys_enum.User.Event.BeforeCreate) { // 单个满足
   301  				//
   302  				//}
   303  				//if hook.Value.Key.Has(sys_enum.User.Event.BeforeCreate, sys_enum.User.Event.AfterCreate) { // 多个满足
   304  				//
   305  				//}
   306  
   307  				// 自增
   308  				//enumOb.Add(sys_enum.User.Event.AfterCreate, sys_enum.User.Event.BeforeCreate)
   309  
   310  				// 自减少
   311  				//enumOb.Remove(sys_enum.User.Event.AfterCreate)
   312  
   313  				if (hook.Value.Key.Code() & sys_enum.User.Event.BeforeCreate.Code()) == sys_enum.User.Event.BeforeCreate.Code() {
   314  					res, _ := hook.Value.Value(ctx, sys_enum.User.Event.BeforeCreate, data)
   315  					res.Detail = &sys_entity.SysUserDetail{}
   316  					res.Detail.Id = data.Id
   317  					data.Detail = res.Detail
   318  				}
   319  			}
   320  		})
   321  
   322  		{
   323  			_, err = sys_dao.SysUser.Ctx(ctx).OmitNilData().Data(data.SysUser).Insert()
   324  
   325  			if err != nil {
   326  				return sys_service.SysLogs().ErrorSimple(ctx, err, "账号注册失败", sys_dao.SysUser.Table())
   327  			}
   328  		}
   329  
   330  		{
   331  			if data.Detail != nil && data.Detail.Id > 0 && (data.Detail.Realname != "" || data.Detail.UnionMainName != "") {
   332  				_, err = sys_dao.SysUserDetail.Ctx(ctx).OmitNilData().Data(data.Detail).Insert()
   333  
   334  				if err != nil {
   335  					return sys_service.SysLogs().ErrorSimple(ctx, err, "账号注册失败", sys_dao.SysUser.Table())
   336  				}
   337  			}
   338  
   339  			/*
   340  				//	if data.Detail != nil && data.Detail.Id > 0 && (data.Detail.Realname != "" || data.Detail.UnionMainName != "") {
   341  
   342  						_, err = sys_dao.SysUserDetail.Ctx(ctx).OmitNilData().Data(data.Detail).Insert()
   343  
   344  						if err != nil {
   345  							return sys_service.SysLogs().ErrorSimple(ctx, err, "账号注册失败", sys_dao.SysUser.Table())
   346  						}
   347  					//}
   348  			*/
   349  
   350  		}
   351  		if len(info.RoleIds) > 0 {
   352  			ret, err := s.SetUserRoleIds(ctx, info.RoleIds, data.Id)
   353  			if ret != true || err != nil {
   354  				return sys_service.SysLogs().ErrorSimple(ctx, err, "角色设置失败!"+err.Error(), sys_dao.SysUser.Table())
   355  			}
   356  		}
   357  
   358  		return nil
   359  	})
   360  
   361  	if err != nil {
   362  		return nil, err
   363  	}
   364  
   365  	// 建后
   366  	g.Try(ctx, func(ctx context.Context) {
   367  		for _, hook := range s.hookArr {
   368  			if hook.Value.Key.Code()&sys_enum.User.Event.AfterCreate.Code() == sys_enum.User.Event.AfterCreate.Code() {
   369  				res, _ := hook.Value.Value(ctx, sys_enum.User.Event.AfterCreate, data)
   370  				res.Detail.Id = data.Id
   371  				data.Detail = res.Detail
   372  			}
   373  		}
   374  	})
   375  
   376  	// 查询用户所拥有的角色 (指针传递)
   377  	s.getUserRole(ctx, &data)
   378  
   379  	// 增删改后不需要重新设置缓存,因为增伤缓存参数Duration为-1,就是删除缓存了
   380  	// s.redisCache.Set(ctx, data.Id, data, s.Duration)
   381  
   382  	return &data, nil
   383  }
   384  
   385  // SetUserPermissions 设置用户权限
   386  func (s *sSysUser) SetUserPermissions(ctx context.Context, userId int64, permissionIds []int64) (bool, error) {
   387  	_, err := s.GetSysUserById(ctx, userId)
   388  
   389  	if err != nil {
   390  		return false, sys_service.SysLogs().ErrorSimple(ctx, err, "用户信息查询失败", sys_dao.SysRole.Table())
   391  	}
   392  
   393  	return sys_service.SysPermission().SetPermissionsByResource(ctx, gconv.String(userId), permissionIds)
   394  }
   395  
   396  // GetSysUserByUsername 根据用户名获取用户
   397  func (s *sSysUser) GetSysUserByUsername(ctx context.Context, username string) (response *sys_model.SysUser, err error) {
   398  	//s.initInnerCacheItems(ctx)
   399  
   400  	// 获取所有keys
   401  	// keys, err := s.redisCache.Keys(ctx)
   402  	userList, err := daoctl.Query[sys_model.SysUser](sys_dao.SysUser.Ctx(ctx), nil, true)
   403  
   404  	user := &sys_model.SysUser{}
   405  
   406  	for _, k := range userList.Records {
   407  		//sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Id: gconv.String(k.Id)}).Scan(&user)
   408  		if k.Username == username {
   409  			sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Id: gconv.String(k.Id)}).Scan(&user)
   410  			response = s.masker(s.makeMore(ctx, user))
   411  			// 查询用户所拥有的角色 (指针传递)
   412  			s.getUserRole(ctx, response)
   413  			return
   414  		}
   415  	}
   416  
   417  	if response == nil {
   418  		return nil, sys_service.SysLogs().ErrorSimple(ctx, sql.ErrNoRows, "用户信息不存在", sys_dao.SysUser.Table())
   419  	}
   420  
   421  	response = s.masker(s.makeMore(ctx, response))
   422  	return
   423  }
   424  
   425  // CheckPassword 检查密码是否正确
   426  func (s *sSysUser) CheckPassword(ctx context.Context, userId int64, password string) (bool, error) {
   427  	//s.initInnerCacheItems(ctx)
   428  
   429  	userInfo, err := daoctl.GetByIdWithError[sys_entity.SysUser](sys_dao.SysUser.Ctx(ctx), userId)
   430  
   431  	if err != nil {
   432  		return false, sys_service.SysLogs().ErrorSimple(ctx, sql.ErrNoRows, "用户信息不存在", sys_dao.SysUser.Table())
   433  	}
   434  	// if (){hook()}
   435  	// 取盐
   436  	salt := gconv.String(userId)
   437  
   438  	// 加密:用户输入的密码 + 他的id的后八位(盐)  --进行Hash--> 用户提供的密文
   439  	pwdHash, err := en_crypto.PwdHash(password, salt)
   440  	// 业务层自定义密码加密规则
   441  	if sys_consts.Global.CryptoPasswordFunc != nil {
   442  		pwdHash = sys_consts.Global.CryptoPasswordFunc(ctx, password, *userInfo)
   443  	}
   444  
   445  	return userInfo.Password == pwdHash, err
   446  }
   447  
   448  // HasSysUserByUsername 判断用户名是否存在
   449  func (s *sSysUser) HasSysUserByUsername(ctx context.Context, username string) bool {
   450  	data, _ := s.GetSysUserByUsername(ctx, username)
   451  	return data != nil
   452  }
   453  
   454  // GetSysUserById 根据用户ID获取用户信息
   455  func (s *sSysUser) GetSysUserById(ctx context.Context, userId int64) (*sys_model.SysUser, error) {
   456  	//s.initInnerCacheItems(ctx)
   457  
   458  	user := sys_model.SysUser{}
   459  	err := sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{
   460  		Id: userId,
   461  	}).Scan(&user)
   462  
   463  	if err != nil {
   464  		return nil, sys_service.SysLogs().ErrorSimple(ctx, sql.ErrNoRows, "用户信息不存在", sys_dao.SysUser.Table())
   465  	}
   466  
   467  	// 查询用户所拥有的角色 (指针传递)
   468  	_, err = s.getUserRole(ctx, &user)
   469  	if err != nil {
   470  		return nil, err
   471  	}
   472  
   473  	return s.masker(s.makeMore(ctx, &user)), nil
   474  }
   475  
   476  func (s *sSysUser) MakeSession(ctx context.Context, userId int64) {
   477  	user, err := s.GetSysUserById(ctx, userId)
   478  
   479  	if err != nil {
   480  		return
   481  	}
   482  
   483  	token, err := sys_service.Jwt().GenerateToken(ctx, user)
   484  	if token != nil {
   485  		sys_service.Jwt().MakeSession(ctx, token.Token)
   486  	}
   487  }
   488  
   489  // SetUserPermissionIds 设置用户权限
   490  func (s *sSysUser) SetUserPermissionIds(ctx context.Context, userId int64, permissionIds []int64) (bool, error) {
   491  	err := sys_dao.SysCasbin.Ctx(ctx).Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
   492  		{
   493  			// 先清除roleId所有权限
   494  			_, err := sys_service.Casbin().DeletePermissionsForUser(gconv.String(userId))
   495  
   496  			if len(permissionIds) <= 0 {
   497  				return err
   498  			}
   499  		}
   500  
   501  		// 重新赋予roleId新的权限清单
   502  		for _, item := range permissionIds {
   503  			ret, err := sys_service.Casbin().Enforcer().AddPermissionForUser(gconv.String(userId), sys_consts.CasbinDomain, gconv.String(item), "allow")
   504  			if err != nil || ret == false {
   505  				return err
   506  			}
   507  		}
   508  		return nil
   509  	})
   510  	if err != nil {
   511  		return false, sys_service.SysLogs().ErrorSimple(ctx, err, "设置用户权限失败", sys_dao.SysUser.Table())
   512  	}
   513  
   514  	return true, nil
   515  }
   516  
   517  // DeleteUser 删除用户信息,该方法一般由后端业务层内部调用
   518  func (s *sSysUser) DeleteUser(ctx context.Context, id int64) (bool, error) {
   519  	_, err := s.GetSysUserById(ctx, id)
   520  	if err != nil {
   521  		return false, err
   522  	}
   523  
   524  	err = sys_dao.SysUser.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
   525  		// 移除员工权限
   526  		_, err = sys_service.SysPermission().SetPermissionsByResource(ctx, gconv.String(id), []int64{0})
   527  		if err != nil && err != sql.ErrNoRows {
   528  			return err
   529  		}
   530  
   531  		// 移除员工角色
   532  		sys_service.SysUser().SetUserRoleIds(ctx, []int64{0}, id)
   533  		if err != nil {
   534  			return err
   535  		}
   536  
   537  		// 删除用户附加信息
   538  		_, err = sys_dao.SysUserDetail.Ctx(ctx).Unscoped().Delete(sys_do.SysUserDetail{Id: id})
   539  		if err != nil && err != sql.ErrNoRows {
   540  			return err
   541  		}
   542  
   543  		// 删除用户
   544  		_, err = sys_dao.SysUser.Ctx(ctx).Unscoped().Delete(sys_do.SysUser{Id: id})
   545  		if err != nil && err != sql.ErrNoRows {
   546  			return err
   547  		}
   548  
   549  		return nil
   550  	})
   551  
   552  	if err != nil {
   553  		return false, sys_service.SysLogs().ErrorSimple(ctx, err, "删除员工信息失败", sys_dao.SysUser.Table())
   554  	}
   555  
   556  	// daoctl.RemoveQueryCache(sys_dao.SysUser.DB(), sys_dao.SysUser.Table())
   557  
   558  	return true, nil
   559  }
   560  
   561  // SetUsername 修改自己的账号登陆名称
   562  func (s *sSysUser) SetUsername(ctx context.Context, newUsername string, userId int64) (bool, error) {
   563  	result, err := sys_dao.SysUser.Ctx(ctx).Data(sys_do.SysUser{Username: newUsername}).Where(sys_do.SysUser{Id: userId}).Update()
   564  
   565  	if err != nil || result == nil {
   566  		return false, err
   567  	}
   568  
   569  	return true, nil
   570  }
   571  
   572  // SetUserState 设置用户状态
   573  func (s *sSysUser) SetUserState(ctx context.Context, userId int64, state sys_enum.UserType) (bool, error) {
   574  	sys_dao.SysUser.DB().Tables(ctx)
   575  	result, err := sys_dao.SysUser.Ctx(ctx).Data(sys_do.SysUser{State: state.Code()}).Where(sys_do.SysUser{Id: userId}).Update()
   576  
   577  	sys_dao.SysUser.Table()
   578  
   579  	if err != nil || result == nil {
   580  		return false, err
   581  	}
   582  
   583  	return true, nil
   584  }
   585  
   586  // UpdateUserPassword 修改用户登录密码
   587  func (s *sSysUser) UpdateUserPassword(ctx context.Context, info sys_model.UpdateUserPassword, userId int64) (bool, error) {
   588  	// 查询到用户信息 不能使用这个操作去查询用户,因为masker操作会把用户密码变空
   589  	// sysUserInfo, err := sys_service.SysUser().GetSysUserById(ctx, userId)
   590  
   591  	sysUserInfo, err := daoctl.GetByIdWithError[sys_model.SysUser](sys_dao.SysUser.Ctx(ctx), userId)
   592  
   593  	if err != nil {
   594  		return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "用户不存在")
   595  	}
   596  
   597  	// 判断输入的两次密码是否相同
   598  	if info.Password != info.ConfirmPassword {
   599  		return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "两次输入的密码不一致,修改失败")
   600  	}
   601  
   602  	{
   603  		// 传入用户输入的原始密码,进行hash,看是否和数据库中原始密码一致
   604  		hash1, _ := en_crypto.PwdHash(info.OldPassword, gconv.String(sysUserInfo.Id))
   605  		// 业务层自定义密码加密规则
   606  		if sys_consts.Global.CryptoPasswordFunc != nil {
   607  			hash1 = sys_consts.Global.CryptoPasswordFunc(ctx, info.OldPassword, *sysUserInfo.SysUser)
   608  		}
   609  		if sysUserInfo.Password != hash1 {
   610  			return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "原密码输入错误,修改失败")
   611  		}
   612  	}
   613  
   614  	{
   615  		// 处理hook订阅
   616  		g.Try(ctx, func(ctx context.Context) {
   617  			for _, hook := range s.hookArr {
   618  				if hook.Value.Key.Code()&sys_enum.User.Event.ChangePassword.Code() == sys_enum.User.Event.ChangePassword.Code() {
   619  					// 调用hook
   620  					_, err = hook.Value.Value(ctx, sys_enum.User.Event.ChangePassword, *sysUserInfo)
   621  					if err != nil {
   622  						break
   623  					}
   624  				}
   625  			}
   626  		})
   627  		if err != nil {
   628  			return false, err
   629  		}
   630  	}
   631  
   632  	pwdHash, err := en_crypto.PwdHash(info.Password, gconv.String(sysUserInfo.Id))
   633  	// 业务层自定义密码加密规则
   634  	if sys_consts.Global.CryptoPasswordFunc != nil {
   635  		pwdHash = sys_consts.Global.CryptoPasswordFunc(ctx, info.Password, *sysUserInfo.SysUser)
   636  	}
   637  
   638  	_, err = sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Id: sysUserInfo.Id}).Update(sys_do.SysUser{Password: pwdHash})
   639  
   640  	if err != nil {
   641  		return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "密码修改失败")
   642  	}
   643  
   644  	return true, nil
   645  }
   646  
   647  // ResetUserPassword 重置用户密码 (超级管理员无需验证验证,XX商管理员重置员工密码无需验证)
   648  func (s *sSysUser) ResetUserPassword(ctx context.Context, userId int64, password string, confirmPassword string) (bool, error) {
   649  	// hook判断当前登录身份是否可以重置密码
   650  	user, err := s.GetSysUserById(ctx, userId)
   651  	{
   652  		//s.initInnerCacheItems(ctx)
   653  
   654  		if err != nil {
   655  			return false, err
   656  		}
   657  
   658  		// 发布广播
   659  		g.Try(ctx, func(ctx context.Context) {
   660  			for _, hook := range s.hookArr {
   661  				if hook.Value.Key.Code()&sys_enum.User.Event.ResetPassword.Code() == sys_enum.User.Event.ResetPassword.Code() {
   662  					_, err = hook.Value.Value(ctx, sys_enum.User.Event.ResetPassword, *kconv.Struct(user, &sys_model.SysUser{}))
   663  					if err != nil {
   664  						break
   665  					}
   666  				}
   667  			}
   668  		})
   669  
   670  		if err != nil {
   671  			return false, err
   672  		}
   673  	}
   674  
   675  	// 生成密码,重置密码
   676  	{
   677  		if password != confirmPassword {
   678  			return false, gerror.NewCode(gcode.CodeValidationFailed, "两次密码不一致,请重新输入")
   679  		}
   680  		// 取盐
   681  		salt := gconv.String(userId)
   682  
   683  		// 加密
   684  		pwdHash, _ := en_crypto.PwdHash(password, salt)
   685  		// 业务层自定义密码加密规则
   686  		if sys_consts.Global.CryptoPasswordFunc != nil {
   687  			pwdHash = sys_consts.Global.CryptoPasswordFunc(ctx, password, *user.SysUser)
   688  		}
   689  
   690  		result, err := sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Id: userId}).Update(sys_do.SysUser{Password: pwdHash})
   691  
   692  		// 受影响的行数
   693  		count, _ := result.RowsAffected()
   694  
   695  		if err != nil || count != 1 {
   696  			return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "重置密码失败")
   697  		}
   698  	}
   699  
   700  	return true, nil
   701  }
   702  
   703  // HasSysUserEmail 邮箱是否存在
   704  func (s *sSysUser) HasSysUserEmail(ctx context.Context, email string) bool {
   705  	response, _ := s.GetSysUserByEmail(ctx, email)
   706  
   707  	return response != nil
   708  }
   709  
   710  // GetSysUserByEmail 根据邮箱获取用户信息
   711  func (s *sSysUser) GetSysUserByEmail(ctx context.Context, email string) (response *sys_model.SysUser, err error) {
   712  
   713  	err = sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Email: email}).Scan(response)
   714  
   715  	return
   716  }
   717  
   718  // ResetUserEmail 重置用户邮箱
   719  func (s *sSysUser) ResetUserEmail(ctx context.Context, userId int64, email string) (bool, error) {
   720  	// hook判断当前登录身份是否可以重置密码
   721  	user, err := s.GetSysUserById(ctx, userId)
   722  	{
   723  		//s.initInnerCacheItems(ctx)
   724  
   725  		if err != nil {
   726  			return false, err
   727  		}
   728  
   729  		// 发布广播
   730  		err = g.Try(ctx, func(ctx context.Context) {
   731  			for _, hook := range s.hookArr {
   732  				if hook.Value.Key.Code()&sys_enum.User.Event.ResetEmail.Code() == sys_enum.User.Event.ResetEmail.Code() {
   733  					_, err = hook.Value.Value(ctx, sys_enum.User.Event.ResetEmail, *kconv.Struct(user, &sys_model.SysUser{}))
   734  					if err != nil {
   735  						break
   736  					}
   737  				}
   738  			}
   739  		})
   740  
   741  		if err != nil {
   742  			return false, err
   743  		}
   744  	}
   745  
   746  	affected, err := daoctl.UpdateWithError(sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Id: userId}), sys_do.SysUser{Email: email})
   747  
   748  	return affected > 0, err
   749  }
   750  
   751  // SetUserRoles 设置用户角色
   752  func (s *sSysUser) SetUserRoles(ctx context.Context, userId int64, roleIds []int64, makeUserUnionMainId int64) (bool, error) {
   753  	data, err := s.GetSysUserById(ctx, userId)
   754  	if err != nil {
   755  		return false, err
   756  	}
   757  
   758  	err = sys_dao.SysRole.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
   759  		for _, roleId := range roleIds {
   760  			roleInfo, err := sys_service.SysRole().GetRoleById(ctx, roleId)
   761  
   762  			if err != nil {
   763  				return sys_service.SysLogs().ErrorSimple(ctx, err, "角色ID错误", sys_dao.SysRole.Table())
   764  			}
   765  
   766  			if roleInfo.UnionMainId != makeUserUnionMainId {
   767  				return sys_service.SysLogs().ErrorSimple(ctx, err, roleInfo.Name+" 角色信息校验失败", sys_dao.SysRole.Table())
   768  			}
   769  
   770  			ret, _ := sys_service.Casbin().AddRoleForUserInDomain(gconv.String(userId), gconv.String(roleInfo.Id), sys_consts.CasbinDomain)
   771  			if ret == true {
   772  				// 重置用户角色名称,并自动去重
   773  				data.RoleNames = garray.NewSortedStrArrayFrom(append(data.RoleNames, roleInfo.Name)).Unique().Slice()
   774  			}
   775  		}
   776  		return nil
   777  	})
   778  	return err == nil, err
   779  }
   780  
   781  // UpdateUserExDetail 更新用户扩展信息
   782  func (s *sSysUser) UpdateUserExDetail(ctx context.Context, user *sys_model.SysUser) (*sys_model.SysUser, error) {
   783  	//s.initInnerCacheItems(ctx)
   784  
   785  	var data *sys_entity.SysUserDetail
   786  
   787  	err := sys_dao.SysUserDetail.Ctx(ctx).Where(sys_do.SysUserDetail{Id: user.Id}).Scan(&data)
   788  	if err != nil && !errors.Is(err, sql.ErrNoRows) {
   789  		return nil, err
   790  	}
   791  
   792  	if user.Detail == nil {
   793  		if data != nil {
   794  			user.Detail = data
   795  		} else {
   796  			user.Detail = &sys_entity.SysUserDetail{
   797  				Id:            user.Id,
   798  				Realname:      "",
   799  				UnionMainName: "",
   800  				LastLoginIp:   "",
   801  				LastLoginArea: "",
   802  				LastLoginAt:   nil,
   803  			}
   804  		}
   805  	}
   806  
   807  	if err == nil && data == nil || errors.Is(err, sql.ErrNoRows) {
   808  		_, err = sys_dao.SysUserDetail.Ctx(ctx).Insert(user.Detail)
   809  		if err != nil {
   810  			return nil, err
   811  		}
   812  	} else {
   813  		if data == nil {
   814  			_, err = sys_dao.SysUserDetail.Ctx(ctx).Data(sys_do.SysUserDetail{
   815  				Realname:      user.Detail.Realname,
   816  				UnionMainName: user.Detail.UnionMainName,
   817  				LastLoginIp:   user.Detail.LastLoginIp,
   818  				LastLoginArea: user.Detail.LastLoginArea,
   819  				LastLoginAt:   user.Detail.LastLoginAt,
   820  			}).Where(sys_do.SysUserDetail{Id: user.Id}).Update()
   821  			if err != nil {
   822  				return nil, err
   823  			}
   824  		}
   825  	}
   826  
   827  	//s.redisCache.Set(ctx, user.Id, user, s.Duration)
   828  	return user, nil
   829  }
   830  
   831  // GetUserDetail 查看用户详情,含完整手机号
   832  func (s *sSysUser) GetUserDetail(ctx context.Context, userId int64) (*sys_model.SysUser, error) {
   833  	//s.initInnerCacheItems(ctx)
   834  
   835  	// Ctx()里面包含对所有Cache操作的赋值,查询不需要写Cache
   836  	user := sys_model.SysUser{}
   837  	err := sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{
   838  		Id: userId,
   839  	}).Scan(&user)
   840  
   841  	if err != nil {
   842  		return nil, gerror.NewCode(gcode.CodeBusinessValidationFailed, "用户信息不存在")
   843  	}
   844  
   845  	user.Password = masker.MaskString(user.Password, masker.Password)
   846  
   847  	// 查询用户所拥有的角色 (指针传递)
   848  	_, err = s.getUserRole(ctx, &user)
   849  	if err != nil {
   850  		return nil, err
   851  	}
   852  
   853  	return s.makeMore(ctx, &user), nil
   854  }
   855  
   856  // GetUserListByMobileOrMail 根据手机号或者邮箱查询用户列表
   857  func (s *sSysUser) GetUserListByMobileOrMail(ctx context.Context, info string) (*sys_model.SysUserListRes, error) {
   858  	userModel := sys_dao.SysUser.Ctx(ctx)
   859  	if base_verify.IsPhone(info) {
   860  		userModel = userModel.Where(sys_do.SysUser{Mobile: info})
   861  	} else if base_verify.IsEmail(info) {
   862  		userModel = userModel.Where(sys_do.SysUser{Email: info})
   863  	}
   864  
   865  	userList, err := daoctl.Query[*sys_model.SysUser](userModel, nil, false)
   866  
   867  	if err != nil {
   868  		return nil, gerror.NewCode(gcode.CodeBusinessValidationFailed, "用户信息不存在")
   869  	}
   870  
   871  	newList := make([]*sys_model.SysUser, 0)
   872  	for _, user := range userList.Records {
   873  		uData := kconv.Struct(user, &sys_model.SysUser{})
   874  		uInfo := s.masker(s.makeMore(ctx, uData))
   875  		newList = append(newList, uInfo)
   876  	}
   877  
   878  	if newList != nil {
   879  		userList.Records = newList
   880  	}
   881  
   882  	return (*sys_model.SysUserListRes)(userList), nil
   883  }
   884  
   885  // SetUserMobile 设置用户手机号
   886  func (s *sSysUser) SetUserMobile(ctx context.Context, newMobile, captcha, password string, userId int64) (bool, error) {
   887  	//s.initInnerCacheItems(ctx)
   888  
   889  	_, err := sys_service.SysSms().Verify(ctx, newMobile, captcha, base_enum.Captcha.Type.SetMobile)
   890  	if err != nil {
   891  		return false, err
   892  	}
   893  
   894  	userInfo := sys_model.SysUser{}
   895  	sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{
   896  		Id: userId,
   897  	}).Scan(&userInfo)
   898  
   899  	if err != nil {
   900  		return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "用户信息不存在")
   901  	}
   902  	if newMobile == userInfo.Mobile {
   903  		return true, nil
   904  	}
   905  
   906  	// 检验密码
   907  	user, err := daoctl.GetByIdWithError[sys_entity.SysUser](sys_dao.SysUser.Ctx(ctx), userInfo.Id)
   908  
   909  	pwdHash, err := en_crypto.PwdHash(password, gconv.String(userId))
   910  
   911  	// 业务层自定义密码加密规则
   912  	if sys_consts.Global.CryptoPasswordFunc != nil {
   913  		pwdHash = sys_consts.Global.CryptoPasswordFunc(ctx, password, *userInfo.SysUser)
   914  	}
   915  
   916  	if pwdHash != user.Password {
   917  		return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "登录密码错误")
   918  	}
   919  
   920  	affected, err := daoctl.UpdateWithError(sys_dao.SysUser.Ctx(ctx).Data(sys_do.SysUser{Mobile: newMobile, UpdatedAt: gtime.Now()}).Where(sys_do.SysUser{
   921  		Id: userId,
   922  	}))
   923  
   924  	if err != nil || affected == 0 {
   925  		return false, sys_service.SysLogs().ErrorSimple(ctx, err, "设置用户手机号失败", sys_dao.SysUser.Table())
   926  	}
   927  
   928  	// 清除redis验证码缓存
   929  	//key := sys_enum.Sms.CaptchaType.SetMobile.Description() + "_" + newMobile
   930  	//g.DB().GetCache().Remove(ctx, key)
   931  
   932  	return true, nil
   933  }
   934  
   935  // SetUserMail 设置用户邮箱
   936  func (s *sSysUser) SetUserMail(ctx context.Context, oldMail, newMail, captcha, password string, userId int64) (bool, error) {
   937  	//s.initInnerCacheItems(ctx)
   938  
   939  	_, err := sys_service.SysMails().Verify(ctx, newMail, captcha, base_enum.Captcha.Type.SetMail)
   940  	if err != nil {
   941  		return false, err
   942  	}
   943  
   944  	mailUser := sys_entity.SysUser{}
   945  	err = sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{Id: userId, Email: oldMail}).Scan(&mailUser)
   946  	if err != nil {
   947  		return false, sys_service.SysLogs().ErrorSimple(ctx, err, "原邮箱错误", sys_dao.SysUser.Table())
   948  	}
   949  
   950  	userInfo := sys_model.SysUser{}
   951  	sys_dao.SysUser.Ctx(ctx).Where(sys_do.SysUser{
   952  		Id: userId,
   953  	}).Scan(&userInfo)
   954  
   955  	if err != nil {
   956  		return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "用户信息不存在")
   957  	}
   958  	if newMail == userInfo.Email {
   959  		return true, nil
   960  	}
   961  
   962  	// 检验密码
   963  	user, err := daoctl.GetByIdWithError[sys_entity.SysUser](sys_dao.SysUser.Ctx(ctx), userInfo.Id)
   964  
   965  	pwdHash, err := en_crypto.PwdHash(password, gconv.String(userId))
   966  
   967  	// 业务层自定义密码加密规则
   968  	if sys_consts.Global.CryptoPasswordFunc != nil {
   969  		pwdHash = sys_consts.Global.CryptoPasswordFunc(ctx, password, *userInfo.SysUser)
   970  	}
   971  
   972  	if pwdHash != user.Password {
   973  		return false, gerror.NewCode(gcode.CodeBusinessValidationFailed, "登录密码错误")
   974  	}
   975  
   976  	affected, err := daoctl.UpdateWithError(sys_dao.SysUser.Ctx(ctx).Data(sys_do.SysUser{Email: newMail, UpdatedAt: gtime.Now()}).Where(sys_do.SysUser{
   977  		Id: userId,
   978  	}))
   979  
   980  	if err != nil || affected == 0 {
   981  		return false, sys_service.SysLogs().ErrorSimple(ctx, err, "设置用户邮箱失败", sys_dao.SysUser.Table())
   982  	}
   983  
   984  	return true, nil
   985  }
   986  
   987  func (s *sSysUser) getUserRole(ctx context.Context, sysUser *sys_model.SysUser, unionMainId ...int64) (*sys_model.SysUser, error) {
   988  
   989  	if unionMainId == nil || len(unionMainId) <= 0 || unionMainId[0] == 0 {
   990  		getS := sys_service.SysSession().Get(ctx)
   991  		if getS != nil {
   992  			sessionUser := getS.JwtClaimsUser
   993  			if sessionUser != nil {
   994  				unionMainId = make([]int64, 1)
   995  				unionMainId[0] = sessionUser.UnionMainId
   996  			}
   997  		}
   998  
   999  	}
  1000  
  1001  	roleIds, _ := sys_service.Casbin().Enforcer().GetRoleManager().GetRoles(gconv.String(sysUser.Id), sys_consts.CasbinDomain)
  1002  
  1003  	sysUser.RoleNames = []string{}
  1004  
  1005  	// 如果有角色信息则加载角色信息
  1006  	if len(roleIds) > 0 {
  1007  		var unionMainIdInfo int64 = 0
  1008  		if len(unionMainId) > 0 {
  1009  			unionMainIdInfo = unionMainId[0]
  1010  		}
  1011  		roles, err := sys_service.SysRole().QueryRoleList(ctx, base_model.SearchParams{
  1012  			Filter: append(make([]base_model.FilterInfo, 0), base_model.FilterInfo{
  1013  				Field:     sys_dao.SysRole.Columns().Id,
  1014  				Where:     "in",
  1015  				IsOrWhere: false,
  1016  				Value:     roleIds,
  1017  			}),
  1018  			Pagination: base_model.Pagination{},
  1019  		}, unionMainIdInfo)
  1020  		if err == nil && len(roles.Records) > 0 {
  1021  			for _, role := range roles.Records {
  1022  				sysUser.RoleNames = append(sysUser.RoleNames, role.Name)
  1023  			}
  1024  		}
  1025  	}
  1026  
  1027  	return sysUser, nil
  1028  }
  1029  
  1030  func (s *sSysUser) masker(user *sys_model.SysUser) *sys_model.SysUser {
  1031  	user.Password = masker.MaskString(user.Password, masker.Password)
  1032  	user.Mobile = masker.MaskString(user.Mobile, masker.MaskPhone)
  1033  	return user
  1034  }
  1035  
  1036  // makeMore 处理订阅请求,获取订阅数据回调返回
  1037  func (s *sSysUser) makeMore(ctx context.Context, data *sys_model.SysUser) *sys_model.SysUser {
  1038  	base_funs.AttrMake[sys_model.SysUser](ctx,
  1039  		sys_dao.SysUser.Columns().Id,
  1040  		func() *sys_entity.SysUserDetail {
  1041  
  1042  			//result, _ := daoctl.GetByIdWithError[sys_entity.SysUserDetail](sys_dao.SysUserDetail.Ctx(ctx), data.Id)
  1043  			resultArr, _ := daoctl.Query[sys_entity.SysUserDetail](sys_dao.SysUserDetail.Ctx(ctx), nil, true)
  1044  			//result, _ := daoctl.ScanWithError[sys_entity.SysUserDetail](sys_dao.SysUserDetail.Ctx(ctx).Where(sys_do.SysUserDetail{Id: data.Id}))
  1045  			var result *sys_entity.SysUserDetail
  1046  			for _, record := range resultArr.Records {
  1047  				if record.Id == data.Id {
  1048  					result = &record
  1049  					break
  1050  				}
  1051  			}
  1052  			if result == nil {
  1053  				return nil
  1054  			}
  1055  			res := kconv.Struct[sys_entity.SysUserDetail](ctx, *result)
  1056  			if res.LastLoginIp == "" {
  1057  				return nil
  1058  			}
  1059  			data.Detail = &res
  1060  			return data.Detail
  1061  		},
  1062  	)
  1063  	return data
  1064  }