package backend import ( "context" "errors" "fmt" operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation" "gitee.com/xuyiping_admin/pkg/jwt" "gitee.com/xuyiping_admin/pkg/logger/zaplog" "gitee.com/xuyiping_admin/pkg/tool" "gitee.com/xuyiping_admin/pkg/xerr" "go.uber.org/zap" "kpt-calf-feed/model" "net/http" "sort" "strings" "time" "gorm.io/gorm" ) const CurrentUserName = "userName" // Auth 用户登录 func (s *StoreEntry) Auth(ctx context.Context, auth *operationPb.UserAuthData) (*operationPb.SystemToken, error) { systemUser := &model.SystemUser{} if err := s.DB.Where("name = ?", auth.UserName).Find(systemUser).Error; err != nil { return nil, xerr.WithStack(err) } if systemUser.Password != auth.Password { return nil, xerr.Customf("密码错误,来自用户:%s", auth.UserName) } if systemUser.IsShow == operationPb.IsShow_NO { return nil, xerr.Customf("该账号已被禁用,请联系管理员") } jwtToken := jwt.NewJWTTokenGen(s.Cfg.AppName, s.Cfg.JwtTokenKeyConfig.PrivateKey) token, err := jwtToken.GenerateToken(systemUser.Name, s.Cfg.JwtExpireTime) if err != nil { return nil, xerr.WithStack(err) } if token == "" { return nil, xerr.Custom("获取token错误") } return &operationPb.SystemToken{ Code: http.StatusOK, Msg: "ok", Data: &operationPb.TokenData{Token: token}, }, nil } func (s *StoreEntry) GetCurrentUserName(ctx context.Context) (string, error) { userNameInter := ctx.Value(CurrentUserName) if userNameInter == nil { return "", xerr.Customf("cannot userName") } if userName, ok := userNameInter.(string); ok { return userName, nil } else { return "", xerr.Customf("waring userName") } } // GetUserInfo 获取用户信息 func (s *StoreEntry) GetUserInfo(ctx context.Context, token string) (*operationPb.UserAuth, error) { systemUser := &model.SystemUser{} userName, err := s.GetCurrentUserName(ctx) if err != nil { return nil, xerr.WithStack(err) } if err = s.DB.Where("name = ?", userName).First(systemUser).Error; err != nil { return nil, xerr.WithStack(err) } systemRole := make([]*model.SystemRole, 0) return systemUser.SystemUserFormat(systemRole, nil), nil } // CreateSystemUser 创建系统用户 func (s *StoreEntry) CreateSystemUser(ctx context.Context, req *operationPb.AddSystemUser) error { systemUsers := &model.SystemUser{ Name: req.Name, EmployeeName: req.EmployeeName, Phone: req.Phone, Password: tool.Md5String(model.InitManagerPassword), CreateUser: req.CreateUser, IsShow: operationPb.IsShow_OK, IsDelete: operationPb.IsShow_OK, } systemUsers.SystemUserRoleFormat(req) if err := s.DB.Create(systemUsers).Error; err != nil { return xerr.WithStack(err) } return nil } // SearchSystemUserList 查询系统用户 func (s *StoreEntry) SearchSystemUserList(ctx context.Context, req *operationPb.SearchUserRequest) (*operationPb.SearchUserResponse, error) { systemUserList := make([]*model.SystemUser, 0) var count int64 = 0 pref := s.DB.Model(new(model.SystemUser)).Where("is_delete = ?", operationPb.IsShow_OK) if req.Name != "" { pref.Where("name like ?", fmt.Sprintf("%s%s%s", "%", req.Name, "%")) } if req.EmployeeName != "" { pref.Where("employee_name like ?", fmt.Sprintf("%s%s%s", "%", req.EmployeeName, "%")) } if req.IsShow > 0 { pref.Where("is_show = ?", req.IsShow) } if req.CreatedStartTime > 0 && req.CreatedEndTime > 0 && req.CreatedStartTime <= req.CreatedEndTime { pref.Where("created_at BETWEEN ? AND ?", req.CreatedStartTime, req.CreatedEndTime) } if err := pref.Order("id desc").Count(&count).Limit(int(req.Pagination.PageSize)).Offset(int(req.Pagination.PageOffset)). Find(&systemUserList).Debug().Error; err != nil { return nil, xerr.WithStack(err) } roleList, err := s.SearchSystemRoleListByIds(ctx, []int64{}) if err != nil { return nil, xerr.WithStack(err) } return &operationPb.SearchUserResponse{ Code: http.StatusOK, Msg: "ok", Data: &operationPb.SearchUserData{ Page: req.Pagination.Page, Total: int32(count), PageSize: req.Pagination.PageSize, List: model.SystemUserSlice(systemUserList).ToPB(roleList), }, }, nil } // EditSystemUser 编辑用户 func (s *StoreEntry) EditSystemUser(ctx context.Context, req *operationPb.AddSystemUser) error { systemUser := &model.SystemUser{Id: int64(req.Id)} if err := s.DB.First(systemUser).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return xerr.Custom("该数据不存在!") } return xerr.WithStack(err) } updateData := &model.SystemUser{ Name: req.Name, EmployeeName: req.EmployeeName, Phone: req.Phone, } updateData.SystemUserRoleFormat(req) if err := s.DB.Model(new(model.SystemUser)).Omit("is_show", "password", "is_delete", "create_user"). Where("id = ?", systemUser.Id). Updates(updateData).Error; err != nil { return xerr.WithStack(err) } return nil } // DeleteSystemUser 删除系统用户 func (s *StoreEntry) DeleteSystemUser(ctx context.Context, userId int64) error { systemUser := &model.SystemUser{ Id: userId, } if err := s.DB.First(systemUser).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return xerr.Custom("该用户不存在") } return xerr.WithStack(err) } if err := s.DB.Model(systemUser).Update("is_delete", operationPb.IsShow_NO).Error; err != nil { return xerr.WithStack(err) } return nil } // ResetPasswordSystemUser 重置系统用户密码 func (s *StoreEntry) ResetPasswordSystemUser(ctx context.Context, userId int64) error { systemUser := &model.SystemUser{ Id: userId, } if err := s.DB.First(systemUser).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return xerr.Custom("该用户不存在") } return xerr.WithStack(err) } if err := s.DB.Model(systemUser).Update("password", tool.Md5String(model.InitManagerPassword)).Error; err != nil { return xerr.WithStack(err) } return nil } // DetailsSystemUser 系统用户详情 func (s *StoreEntry) DetailsSystemUser(ctx context.Context, userId int64) (*operationPb.UserDetails, error) { systemUser := &model.SystemUser{ Id: userId, } if err := s.DB.First(systemUser).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, xerr.Custom("该用户不存在") } return nil, xerr.WithStack(err) } return &operationPb.UserDetails{ Code: http.StatusOK, Msg: "ok", Data: systemUser.ToPb(), }, nil } // IsShowSystemUser 用户是否启用 func (s *StoreEntry) IsShowSystemUser(ctx context.Context, req *operationPb.IsShowSystemUserRequest) error { systemUser := &model.SystemUser{ Id: int64(req.UserId), } if err := s.DB.First(systemUser).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return xerr.Custom("该用户不存在") } return xerr.WithStack(err) } if err := s.DB.Model(systemUser).Update("is_show", req.IsShow).Error; err != nil { return xerr.WithStack(err) } return nil } // GetSystemUserPermissions 返回系统用户相关菜单权限 func (s *StoreEntry) GetSystemUserPermissions(ctx context.Context, token string) (*operationPb.SystemUserMenuPermissions, error) { // 解析token userName, err := s.GetCurrentUserName(ctx) if err != nil { return nil, xerr.WithStack(err) } // 根据用户token获取用户数据 systemUser := &model.SystemUser{Name: userName} if err = s.DB.Where("name = ?", userName).First(systemUser).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, xerr.Custom("该用户数据不存在") } return nil, xerr.WithStack(err) } roleIds := systemUser.SystemUserRoleToSlice() // 获取用户角色数据 systemRoles := make([]*model.SystemRole, 0) if err = s.DB.Where("is_show = ?", operationPb.IsShow_OK).Find(&systemRoles, roleIds).Error; err != nil { return nil, xerr.WithStack(err) } systemAllPermissionsList := &SystemAllPermissionsList{ MenuList: make([]*model.SystemMenuPermissions, 0), } for _, role := range systemRoles { item := s.GetSystemAllPermissionsList(ctx, role.Id) systemAllPermissionsList.MenuList = append(systemAllPermissionsList.MenuList, item.MenuList...) } systemAllPermissionsList.SystemUserMenuPermissionsUnDuplicate() menuList, err := s.GetMenuList(ctx, systemAllPermissionsList.MenuList) if err != nil { return nil, xerr.WithStack(err) } return s.SystemPermissionsFormatPb(menuList), nil } func (s *StoreEntry) SystemPermissionsFormatPb(menuList []*model.SystemMenu) *operationPb.SystemUserMenuPermissions { systemUserMenuPermissions := &operationPb.SystemUserMenuPermissions{ Code: http.StatusOK, Msg: "ok", Data: &operationPb.SystemUserMenuData{ PastureList: make([]*operationPb.AddPastureRequest, 0), MenuList: make([]*operationPb.AddMenuRequest, 0), MobileList: make([]*operationPb.AddMobileRequest, 0), MenuButtonsPath: make([]*operationPb.MenuButtonsPath, 0), }, } // TODO 后面优化成递归算法 level := make(map[int32][]*operationPb.AddMenuRequest, 0) for _, menu := range menuList { if _, ok := level[menu.Level]; !ok { level[menu.Level] = make([]*operationPb.AddMenuRequest, 0) } level[menu.Level] = append(level[menu.Level], &operationPb.AddMenuRequest{ Id: int32(menu.Id), Name: menu.Name, ParentId: int32(menu.ParentId), MenuType: menu.MenuType, Title: menu.Title, Path: menu.Path, IsShow: menu.IsShow, Component: menu.Component, Icon: menu.Icon, Sort: menu.Sort, Redirect: menu.Redirect, CreatedAt: int32(menu.CreatedAt), CreatedAtFormat: time.Unix(menu.CreatedAt, 0).Format(model.LayoutTime), Level: menu.Level, Affix: true, KeepAlive: true, Children: make([]*operationPb.AddMenuRequest, 0), }) if menu.Level == model.Level3 { systemUserMenuPermissions.Data.MenuButtonsPath = append(systemUserMenuPermissions.Data.MenuButtonsPath, &operationPb.MenuButtonsPath{ Path: menu.Path, MenuId: int32(menu.Id), }) } } level2IsShow := make([]int32, 0) for _, leve2Data := range level[model.Level2] { for _, leve3Data := range level[model.Level3] { if leve3Data.ParentId == leve2Data.Id && strings.Contains(leve3Data.Path, ":page") { level2IsShow = append(level2IsShow, leve2Data.Id) } if leve3Data.ParentId == leve2Data.Id { if leve2Data.Children == nil { leve2Data.Children = make([]*operationPb.AddMenuRequest, 0) } leve2Data.Children = append(leve2Data.Children, leve3Data) } } } sort.SliceStable(level[model.Level2], func(i, j int) bool { return level[model.Level2][i].Sort > level[model.Level2][j].Sort }) for _, leve2Data := range level[model.Level2] { var info bool for _, v := range level2IsShow { if v == leve2Data.Id { info = true } } if !info { continue } for _, leve1Data := range level[model.Level1] { if leve2Data.ParentId == leve1Data.Id { if leve1Data.Children == nil { leve1Data.Children = make([]*operationPb.AddMenuRequest, 0) } leve1Data.Children = append(leve1Data.Children, leve2Data) } } } sort.SliceStable(level[model.Level1], func(i, j int) bool { return level[model.Level1][i].Sort > level[model.Level1][j].Sort }) systemUserMenuPermissions.Data.MenuList = level[model.Level1] return systemUserMenuPermissions } // CreateSystemRole 添加角色 func (s *StoreEntry) CreateSystemRole(ctx context.Context, req *operationPb.AddRoleRequest) error { if err := s.DB.Transaction(func(tx *gorm.DB) error { // 创建角色数据 role := model.NewSystemRole(req) if err := tx.Create(role).Error; err != nil { return xerr.WithStack(err) } // 创建角色菜单权限数据 if len(req.MenuId) > 0 { menuPermissions := model.NewSystemMenuPermissions(role.Id, req.MenuId) if err := tx.Create(menuPermissions).Error; err != nil { return xerr.WithStack(err) } } return nil }); err != nil { return xerr.WithStack(err) } return nil } // EditSystemRole 编辑角色 func (s *StoreEntry) EditSystemRole(ctx context.Context, req *operationPb.AddRoleRequest) error { role := &model.SystemRole{Id: int64(req.Id)} if err := s.DB.First(role).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return xerr.Custom("该数据不存在") } return xerr.WithStack(err) } if err := s.DB.Transaction(func(tx *gorm.DB) error { updateSystemRole := model.NewSystemRole(req) if err := tx.Omit("is_show"). Where("id = ?", role.Id). Updates(updateSystemRole).Error; err != nil { return xerr.WithStack(err) } // 更新菜单权限关系表 menuIds := req.MenuId if err := tx.Model(new(model.SystemMenuPermissions)). Where("role_id = ?", req.Id).Update("is_show", operationPb.IsShow_NO).Error; err != nil { return xerr.WithStack(err) } newSystemMenuPermissions := model.NewSystemMenuPermissions(int64(req.Id), menuIds) if err := tx.Create(newSystemMenuPermissions).Error; err != nil { return xerr.WithStack(err) } return nil }); err != nil { return xerr.WithStack(err) } return nil } // DeleteSystemRole 删除系统角色 func (s *StoreEntry) DeleteSystemRole(ctx context.Context, roleId int64) error { systemRole := &model.SystemRole{ Id: roleId, } if err := s.DB.First(systemRole).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return xerr.Custom("该数据不存在") } return xerr.WithStack(err) } if err := s.DB.Model(systemRole).Update("is_show", operationPb.IsShow_NO).Error; err != nil { return xerr.WithStack(err) } return nil } // SearchSystemRoleList 查询系统角色 func (s *StoreEntry) SearchSystemRoleList(ctx context.Context, req *operationPb.SearchRoleRequest) (*operationPb.SearchRoleResponse, error) { systemRoleList := make([]*model.SystemRole, 0) var count int64 = 0 pref := s.DB.Model(new(model.SystemRole)).Where("is_show = ?", operationPb.IsShow_OK) if req.Name != "" { pref.Where("name like ?", fmt.Sprintf("%s%s%s", "%", req.Name, "%")) } if err := pref.Order("id desc").Count(&count).Limit(int(req.Pagination.PageSize)). Offset(int(req.Pagination.PageOffset)).Find(&systemRoleList).Error; err != nil { return nil, xerr.WithStack(err) } permissionsMenuMap := make(map[int64][]*model.SystemMenu, 0) for _, role := range systemRoleList { systemMenuList := make([]*model.SystemMenu, 0) if err := s.DB.Table(new(model.SystemMenu).TableName()).Select(fmt.Sprintf("%s.*", new(model.SystemMenu).TableName())). Joins(fmt.Sprintf("left join %s on %s = %s and %s", new(model.SystemMenuPermissions).TableName(), fmt.Sprintf("%s.menu_id", new(model.SystemMenuPermissions).TableName()), fmt.Sprintf("%s.id", new(model.SystemMenu).TableName()), fmt.Sprintf("%s.is_show = %d", new(model.SystemMenuPermissions).TableName(), operationPb.IsShow_OK))). Where(fmt.Sprintf("%s.role_id = ?", new(model.SystemMenuPermissions).TableName()), role.Id).Where(fmt.Sprintf("%s.level = ?", new(model.SystemMenu).TableName()), model.Level2). Find(&systemMenuList).Error; err != nil { zaplog.Error("SearchSystemRoleList", zap.Any("SystemMenuPermissions", err)) } permissionsMenuMap[role.Id] = systemMenuList } return &operationPb.SearchRoleResponse{ Code: http.StatusOK, Msg: "ok", Data: &operationPb.SearchRoleData{ Page: req.Pagination.Page, Total: int32(count), PageSize: req.Pagination.PageSize, List: model.SystemRoleSlice(systemRoleList).ToPB(permissionsMenuMap), }, }, nil } // SearchSystemRoleListByIds 根据id查询角色列表 func (s *StoreEntry) SearchSystemRoleListByIds(ctx context.Context, ids []int64) ([]*model.SystemRole, error) { systemRoleList := make([]*model.SystemRole, 0) if err := s.DB.Model(new(model.SystemRole)).Where("is_show = ?", operationPb.IsShow_OK).Find(&systemRoleList, ids).Error; err != nil { return nil, xerr.WithStack(err) } return systemRoleList, nil } // GetRolePermissions 查询系统角色权限 func (s *StoreEntry) GetRolePermissions(ctx context.Context, roleId int64) (*operationPb.RolePermissionsList, error) { systemRole := &model.SystemRole{ Id: roleId, } if err := s.DB.First(systemRole).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, xerr.Custom("该数据不存在") } return nil, xerr.WithStack(err) } systemAllPermissionsList := &SystemAllPermissionsList{ MenuList: make([]*model.SystemMenuPermissions, 0), } item := s.GetSystemAllPermissionsList(ctx, systemRole.Id) systemAllPermissionsList.MenuList = append(systemAllPermissionsList.MenuList, item.MenuList...) return s.AllPermissionsListToRolePermissions(systemAllPermissionsList), nil } // CreateSystemMenu 添加系统菜单权限 func (s *StoreEntry) CreateSystemMenu(ctx context.Context, req *operationPb.AddMenuRequest) error { systemMenu := model.NewSystemMenu(req) if err := s.DB.Create(systemMenu).Error; err != nil { return xerr.WithStack(err) } return nil } // EditSystemMenu 编辑系统菜单权限 func (s *StoreEntry) EditSystemMenu(ctx context.Context, req *operationPb.AddMenuRequest) error { systemMenu := &model.SystemMenu{Id: int64(req.Id)} if err := s.DB.First(systemMenu).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return xerr.Custom("该数据不存在!") } return xerr.WithStack(err) } updateData := &model.SystemMenu{ Name: req.Name, MenuType: req.MenuType, Title: req.Title, Path: req.Path, Component: req.Component, Icon: req.Icon, Sort: req.Sort, Redirect: req.Redirect, ParentId: int64(req.ParentId), } if err := s.DB.Model(new(model.SystemMenu)).Omit("is_show"). Where("id = ?", systemMenu.Id). Updates(updateData).Error; err != nil { return xerr.WithStack(err) } return nil } // IsShowSystemMenu 菜单是否启用 func (s *StoreEntry) IsShowSystemMenu(ctx context.Context, req *operationPb.IsShowSystemMenuRequest) error { systemMenu := &model.SystemMenu{Id: int64(req.MenuId)} if err := s.DB.First(systemMenu).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return xerr.Custom("该数据不存在") } return xerr.WithStack(err) } if err := s.DB.Model(systemMenu).Update("is_show", req.IsShow).Error; err != nil { return xerr.WithStack(err) } return nil } // SearchSystemMenuList 菜单列表查询 func (s *StoreEntry) SearchSystemMenuList(ctx context.Context, req *operationPb.SearchMenuRequest) (*operationPb.SearchMenuResponse, error) { systemMenuLevel1 := make([]*model.SystemMenu, 0) var count int64 = 0 pref := s.DB.Model(new(model.SystemMenu)).Where("is_delete = ? and level = ?", operationPb.IsShow_OK, model.Level1) if req.Name != "" { pref.Where("name like ?", fmt.Sprintf("%s%s%s", "%", req.Name, "%")) } if err := pref.Order("sort desc").Count(&count).Limit(int(req.Pagination.PageSize)).Offset(int(req.Pagination.PageOffset)). Find(&systemMenuLevel1).Debug().Error; err != nil { return nil, xerr.WithStack(err) } systemMenuLevel1 = append(systemMenuLevel1, s.searchMenuLevel23ByLevel1(ctx, systemMenuLevel1)...) return &operationPb.SearchMenuResponse{ Code: http.StatusOK, Msg: "ok", Data: &operationPb.SearchMenuData{ Page: req.Pagination.Page, Total: int32(count), List: model.SystemMenuSlice(systemMenuLevel1).ToPB(), }, }, nil } // searchMenuLevel23ByLevel1 根据一级菜单返回对应二三级菜单 func (s *StoreEntry) searchMenuLevel23ByLevel1(ctx context.Context, res []*model.SystemMenu) []*model.SystemMenu { systemMenuLevel23 := make([]*model.SystemMenu, 0) if len(res) <= 0 { return systemMenuLevel23 } ids1 := make([]int64, 0) for _, v := range res { ids1 = append(ids1, v.Id) } if err := s.DB.Model(new(model.SystemMenu)).Where("is_delete = ? and level = ?", operationPb.IsShow_OK, model.Level2). Where("parent_id IN ?", ids1).Order("sort desc"). Find(&systemMenuLevel23).Error; err != nil { return systemMenuLevel23 } ids2 := make([]int64, 0) for _, v := range systemMenuLevel23 { ids2 = append(ids2, v.Id) } systemMenuLevel3 := make([]*model.SystemMenu, 0) if err := s.DB.Model(new(model.SystemMenu)).Where("is_delete = ? and level = ?", operationPb.IsShow_OK, model.Level3). Where("parent_id IN ?", ids2).Order("sort desc"). Find(&systemMenuLevel3).Error; err != nil { return systemMenuLevel23 } if len(systemMenuLevel3) > 0 { systemMenuLevel23 = append(systemMenuLevel23, systemMenuLevel3...) } return systemMenuLevel23 } // DeleteSystemMenu 删除系统菜单 func (s *StoreEntry) DeleteSystemMenu(ctx context.Context, menuId int64) error { systemMenu := &model.SystemMenu{Id: menuId} if err := s.DB.First(systemMenu).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return xerr.Custom("该数据不存在") } return xerr.WithStack(err) } if err := s.DB.Model(systemMenu).Update("is_delete", operationPb.IsShow_NO).Error; err != nil { return xerr.WithStack(err) } return nil }