Selaa lähdekoodia

优化,整合

chengqian 10 kuukautta sitten
vanhempi
commit
1b85c2e59d

+ 19 - 11
app/file/controller/file.go

@@ -24,7 +24,7 @@ func (f *file) Distribute(c *gin.Context) {
 	//获取当前用户
 	header := c.GetHeader("Authorization")
 	claims, _ := token.JwtClaims.ParseJwtToken(header)
-	nowUser, _ := cache.GetNowUser(claims.ID)
+	nowSysUser, _ := cache.GetNowSysUser(claims.ID)
 
 	//TODO:校验签名 如果成功则上传否则不上传
 	formFile, err := c.FormFile("file")
@@ -50,47 +50,55 @@ func (f *file) Distribute(c *gin.Context) {
 
 	//获取另外一个参数
 	str := c.Request.FormValue("req")
-	userFile := model.ReqUserFile{}
+	userFile := model.ReqSysUserFile{}
 	json.Unmarshal([]byte(str), &userFile)
 
 	savePath := "uploadfiles/" + newfileName
-	distribute := service.FileService.Distribute(formFile.Filename, savePath, &userFile, nowUser.User.ID)
+	distribute := service.FileService.Distribute(formFile.Filename, savePath, &userFile, nowSysUser.ID)
 
 	c.JSON(http.StatusOK, distribute)
 }
 
-func (f *file) GetUserFiles(c *gin.Context) {
+func (f *file) GetSysUserFiles(c *gin.Context) {
 	header := c.GetHeader("Authorization")
 	claims, _ := token.JwtClaims.ParseJwtToken(header)
-	files := service.FileService.GetUserFiles(claims.ID)
+
+	var search model.SearchSysUserFiles
+	err := c.ShouldBindJSON(&search)
+	if err != nil {
+		c.JSON(http.StatusOK, common.ParamsInvalidResponse(err.Error(), nil))
+		return
+	}
+
+	files := service.FileService.GetSysUserFiles(claims.ID, search)
 	c.JSON(http.StatusOK, files)
 }
 
 // 转发文件
 func (f *file) ForwardingFile(c *gin.Context) {
-	fileid := c.Query("fileid")
+	fileid := c.Query("fileId")
 	header := c.GetHeader("Authorization")
 	claims, _ := token.JwtClaims.ParseJwtToken(header)
 
-	requsers := model.ReqUsers{}
+	requsers := model.ReqSysUsers{}
 	if err := c.ShouldBindJSON(&requsers); err != nil {
 		c.JSON(http.StatusOK, common.ParamsInvalidResponse(err.Error(), nil))
 		return
 	}
 	uid, _ := strconv.Atoi(claims.ID)
 	fid, _ := strconv.Atoi(fileid)
-	forwardingFile := service.FileService.ForwardingFile(uid, fid, requsers.UsersId)
+	forwardingFile := service.FileService.ForwardingFile(uid, fid, requsers.SysUsersId)
 	c.JSON(http.StatusOK, forwardingFile)
 }
 
 // 查看文件
 func (f *file) ViewFile(c *gin.Context) {
-	fileid := c.Query("fileid")
-	service.FileService.GetFile(fileid, c)
+	fileId := c.Query("fileId")
+	service.FileService.GetFile(fileId, c)
 }
 
 // 下载文件
 func (f *file) DownloadFile(c *gin.Context) {
-	fileid := c.Query("fileid")
+	fileid := c.Query("fileId")
 	service.FileService.GetFile(fileid, c)
 }

+ 1 - 1
app/file/dao/common.go

@@ -11,7 +11,7 @@ func InitDB(db *gorm.DB) {
 	Db = db
 	err := Db.AutoMigrate(
 		&File{},
-		&UserFile{},
+		&SysUserFile{},
 	)
 	if err != nil {
 		panic(fmt.Sprintf("AutoMigrate err : %v", err))

+ 38 - 9
app/file/dao/file.go

@@ -1,6 +1,9 @@
 package dao
 
-import "time"
+import (
+	"iot_manager_service/app/file/model"
+	"time"
+)
 
 // File 文件表
 type File struct {
@@ -13,7 +16,8 @@ type File struct {
 	SuffixName    string    `gorm:"type:varchar(12)" json:"suffixName"`                 //文件后缀名
 	UploadTime    time.Time `gorm:"column:upload_time;type:datetime" json:"uploadTime"` //上传时间
 	Uploader      int       `gorm:"type:int" json:"uploader"`                           //上传者id
-	IsShowed      int       `gorm:"type:int;default:0" json:"isShowed"`                 //收否展示 0=展示,1=不展示
+	IsShowed      int       `gorm:"type:int;default:0" json:"isShowed"`                 //是否展示 0=展示,1=不展示
+	Icon          string    `gorm:"type:varchar(191)" json:"icon"`                      //文件图标
 	IsDeleted     int       `gorm:"type:int;default:0" json:"isDeleted"`                //是否删除 0=未删除,1=删除
 }
 
@@ -25,19 +29,44 @@ func (f *File) Create() error {
 	return Db.Model(&f).Save(&f).Error
 }
 
-func (f *File) GetUserFiles(uid int) ([]File, error) {
+func (f *File) GetSysUserFiles(uid int, search model.SearchSysUserFiles) ([]File, error) {
 	var files []File
-	err := Db.Table("file").
+	//var db *gorm.DB
+	db := Db.Table("file").
 		Select("file.*").
 		Joins("left join user_file uf on uf.file_id = file.id").
-		Where("uf.receiver = ? AND file.is_showed = 0 AND file.is_deleted = 0", uid).
-		Order("upload_time DESC").
-		Group("file.id"). // 根据created_at字段降序排列
-		Scan(&files).
-		Error
+		Where("uf.receiver = ? AND file.is_showed = 0 AND file.is_deleted = 0 AND uf.is_deleted = 0 AND uf.operation_status = '下发'", uid). // 根据upload_time字段降序排列
+		Group("file.id")
+
+	if search.OriginalName != "" {
+		db.Where("original_name like ?", "%"+search.OriginalName+"%")
+	}
+	if search.SuffixName != "" {
+		db.Where("suffix_name = ?", search.SuffixName)
+	}
+	if search.Sort == 0 {
+		db.Order("upload_time DESC")
+	} else {
+		db.Order("upload_time ASC")
+	}
+	limit := search.PageSize
+	offset := search.PageSize * (search.PageNO - 1)
+	// 执行查询并检查错误
+	err := db.Limit(limit).Offset(offset).Scan(&files).Error
+	if err != nil {
+		return files, err
+	}
 	return files, err
 }
 
+func (f *File) GetFileInfo(fileid, uid string) (model.RespFileInfo, error) {
+	var result map[string]interface{}
+	Db.Raw("SELECT file.auth_id, uf.effective_date FROM file LEFT JOIN user_file uf ON uf.file_id = file.id WHERE uf.file_id = ? AND uf.operation_status = '下发' AND uf.receiver = ? ORDER BY uf.effective_date DESC LIMIT 1", fileid, uid).Scan(&result)
+	authId, _ := result["auth_id"].(string)
+	effectiveDate, _ := result["effective_date"].(time.Time)
+	return model.RespFileInfo{AuthId: authId, EffectiveDate: effectiveDate}, nil
+}
+
 func (f *File) GetFile(id string) (*File, error) {
 	err := Db.Model(&f).Where("id = ?", id).First(&f).Error
 	return f, err

+ 11 - 10
app/file/dao/userfile.go

@@ -2,20 +2,21 @@ package dao
 
 import "time"
 
-// UserFile 用户文件记录表
-type UserFile struct {
-	ID              int        `gorm:"primary_key;type:int" json:"id"`                          //编号
-	Operator        int        `gorm:"type:int" json:"operator"`                                //操作者id
-	Receiver        int        `gorm:"type:int" json:"receiver"`                                //接收者id
-	FileID          int        `gorm:"type:int" json:"fileid"`                                  //文件id
-	EffectiveDate   *time.Time `gorm:"column:effectiveDate;type:datetime" json:"effectiveDate"` //阅读的有效日期
-	OperationStatus string     `gorm:"type:varchar(12)" json:"operationStatus"`                 //操作状态
+// SysUserFile 用户文件记录表
+type SysUserFile struct {
+	ID              int        `gorm:"primary_key;type:int" json:"id"`          //编号
+	Operator        int        `gorm:"type:int" json:"operator"`                //操作者id
+	Receiver        int        `gorm:"type:int" json:"receiver"`                //接收者id
+	FileID          int        `gorm:"type:int" json:"fileid"`                  //文件id
+	EffectiveDate   *time.Time `gorm:"type:datetime" json:"effectiveDate"`      //阅读的有效日期
+	OperationStatus string     `gorm:"type:varchar(12)" json:"operationStatus"` //操作状态
+	IsDeleted       int        `gorm:"type:int;default:0" json:"isDeleted"`     //是否删除 0=未删除,1=删除
 }
 
-func (*UserFile) TableName() string {
+func (*SysUserFile) TableName() string {
 	return "user_file"
 }
 
-func (uf *UserFile) BatchUFRecords(userfile []UserFile) error {
+func (uf *SysUserFile) BatchUFRecords(userfile []SysUserFile) error {
 	return Db.Model(&uf).Create(&userfile).Error
 }

+ 24 - 9
app/file/model/file.go

@@ -1,15 +1,30 @@
 package model
 
-import "time"
+import (
+	"time"
+)
 
-type ReqUserFile struct {
-	OriginalName  string    `json:"originalName"`  //文件原始名
-	AuthId        string    `json:"authId"`        //权限id
-	CategoryName  string    `json:"categoryName"`  //文件类别名
-	DeptsId       []int     `json:"deptsId"`       //下发的部门id
-	EffectiveDate time.Time `json:"effectiveDate"` //阅读的有效日期
+type ReqSysUserFile struct {
+	OriginalName  string     `json:"originalName"`  //文件原始名
+	AuthId        string     `json:"authId"`        //权限id
+	CategoryName  string     `json:"categoryName"`  //文件类别名
+	DeptsId       []int      `json:"deptsId"`       //下发的部门id
+	EffectiveDate *time.Time `json:"effectiveDate"` //阅读的有效日期
 }
 
-type ReqUsers struct {
-	UsersId []int `json:"users"` //转发的用户id
+type ReqSysUsers struct {
+	SysUsersId []int `json:"users"` //转发的用户id
+}
+
+type SearchSysUserFiles struct {
+	OriginalName string `json:"originalName"` //文件原始名
+	SuffixName   string `json:"suffixName"`   //文件后缀名
+	Sort         int    `json:"sort"`         //排序方式
+	PageNO       int    `json:"pageNO"`       //当前页
+	PageSize     int    `json:"pageSize"`     //每页大小
+}
+
+type RespFileInfo struct {
+	AuthId        string    `json:"authId"`                             //权限id
+	EffectiveDate time.Time `json:"effectiveDate" gorm:"effectiveDate"` //阅读的有效日期
 }

+ 15 - 13
app/file/service/fileService.go

@@ -11,6 +11,7 @@ import (
 	"net/http"
 	"path"
 	"strconv"
+	"strings"
 	"time"
 )
 
@@ -19,7 +20,7 @@ var FileService = new(fileService)
 
 type fileService struct{}
 
-func (f *fileService) Distribute(encryptedname, savepath string, requserfile *model.ReqUserFile, uid int) *common.Errors {
+func (f *fileService) Distribute(encryptedname, savepath string, requserfile *model.ReqSysUserFile, uid int) *common.Errors {
 	file := &dao.File{
 		OriginalName:  requserfile.OriginalName,
 		EncryptedName: encryptedname,
@@ -29,28 +30,29 @@ func (f *fileService) Distribute(encryptedname, savepath string, requserfile *mo
 		SuffixName:    path.Ext(requserfile.OriginalName),
 		UploadTime:    time.Now(),
 		Uploader:      uid,
+		Icon:          strings.TrimPrefix(path.Ext(requserfile.OriginalName), ".") + ".png",
 	}
 	err := file.Create()
 	if err != nil {
 		return common.FailResponse("保存文件失败", nil)
 	}
 	//查询部门下对应的员工
-	user := &userdao.User{}
-	users, err := user.GetDeptsUsers(requserfile.DeptsId)
+	user := &userdao.SysUser{}
+	users, err := user.GetDeptsSysUsers(requserfile.DeptsId)
 	if err != nil {
 		return common.FailResponse(err.Error(), nil)
 	}
-	var userfile []dao.UserFile
+	var userfile []dao.SysUserFile
 	for _, u := range users {
-		userfile = append(userfile, dao.UserFile{
+		userfile = append(userfile, dao.SysUserFile{
 			Operator:        uid,
 			Receiver:        u.ID,
 			FileID:          file.ID,
-			EffectiveDate:   &requserfile.EffectiveDate,
-			OperationStatus: "上传",
+			EffectiveDate:   requserfile.EffectiveDate,
+			OperationStatus: "下发",
 		})
 	}
-	userfiledao := &dao.UserFile{}
+	userfiledao := &dao.SysUserFile{}
 	err = userfiledao.BatchUFRecords(userfile)
 	if err != nil {
 		return common.FailResponse(err.Error(), nil)
@@ -64,10 +66,10 @@ func (f *fileService) Distribute(encryptedname, savepath string, requserfile *mo
 	return common.SuccessResponse("新增记录成功", nil)
 }
 
-func (f *fileService) GetUserFiles(id string) *common.Errors {
+func (f *fileService) GetSysUserFiles(id string, search model.SearchSysUserFiles) *common.Errors {
 	filedao := &dao.File{}
 	uid, _ := strconv.Atoi(id)
-	files, err := filedao.GetUserFiles(uid)
+	files, err := filedao.GetSysUserFiles(uid, search)
 	if err != nil {
 		return common.FailResponse(err.Error(), nil)
 	}
@@ -91,10 +93,10 @@ func (f *fileService) GetFile(id string, c *gin.Context) {
 
 // 转发
 func (f *fileService) ForwardingFile(uid, fileid int, users []int) *common.Errors {
-	var userfile []dao.UserFile
+	var userfile []dao.SysUserFile
 	var nilTime *time.Time
 	for _, u := range users {
-		userfile = append(userfile, dao.UserFile{
+		userfile = append(userfile, dao.SysUserFile{
 			Operator:        uid,
 			Receiver:        u,
 			FileID:          fileid,
@@ -102,7 +104,7 @@ func (f *fileService) ForwardingFile(uid, fileid int, users []int) *common.Error
 			OperationStatus: "转发",
 		})
 	}
-	userfiledao := &dao.UserFile{}
+	userfiledao := &dao.SysUserFile{}
 	err := userfiledao.BatchUFRecords(userfile)
 	if err != nil {
 		return common.FailResponse(err.Error(), nil)

+ 31 - 13
app/middleware/checkAuth.go

@@ -4,11 +4,13 @@ import (
 	"fmt"
 	"github.com/gin-gonic/gin"
 	"iot_manager_service/app/file/dao"
-	"iot_manager_service/util/cache"
+	dao2 "iot_manager_service/app/user/dao"
 	"iot_manager_service/util/common"
 	"iot_manager_service/util/token"
 	"net/http"
+	"strconv"
 	"strings"
+	"time"
 )
 
 // 校验用户对文件的权限
@@ -16,37 +18,53 @@ func CheckAuth() gin.HandlerFunc {
 	return func(c *gin.Context) {
 		header := c.GetHeader("Authorization")
 		claims, _ := token.JwtClaims.ParseJwtToken(header)
-		user, _ := cache.GetNowUser(claims.ID)
-		fileid := c.Query("fileid")
+		userdao := dao2.SysUser{}
+		id, _ := strconv.Atoi(claims.ID)
+		nowSysUser, err2 := userdao.GetNowSysUser(id)
+		if err2 != nil {
+			panic(err2)
+		}
+		fileid := c.Query("fileId")
 
 		filedao := &dao.File{}
-		file, err := filedao.GetFile(fileid)
+		fileInfo, err := filedao.GetFileInfo(fileid, claims.ID)
 		if err != nil {
 			c.JSON(http.StatusOK, err)
 			c.Abort()
 			return
 		}
-		userAuth := user.User.AuthId
-		fileAuth := file.AuthId
+
+		// 将时间字符串解析为时间对象
+		targetTime, _ := time.Parse("2006-01-02 15:04:05 -0700 MST", fileInfo.EffectiveDate.String())
+		now := time.Now()
+		// 比较两个时间
+		if !now.Before(targetTime) {
+			c.JSON(http.StatusForbidden, common.StatusForbidden("访问时间已过,无权访问", nil))
+			c.Abort()
+			return
+		}
+
+		userAuth := nowSysUser.AuthId
+		fileAuth := fileInfo.AuthId
 
 		var permissionMap = map[string]struct {
-			index   int
+			index   string
 			message string
 		}{
-			"/viewfile":       {0, "查看"},
-			"/downloadfile":   {1, "下载"},
-			"/forwardingfile": {2, "转发"},
+			"/viewFile":       {"1", "查看"},
+			"/downloadFile":   {"2", "下载"},
+			"/forwardingFile": {"3", "转发"},
 		}
 
 		for url, obj := range permissionMap {
 			if strings.Contains(c.Request.RequestURI, url) {
-				if fileAuth[obj.index] != '1' {
+				if !strings.Contains(fileAuth, obj.index) {
 					c.JSON(http.StatusForbidden, common.StatusForbidden(fmt.Sprintf("抱歉,该文件不支持【%s】操作,请联系管理员。", obj.message), nil))
 					c.Abort()
 					return
 				}
-				if userAuth[obj.index] != fileAuth[obj.index] || userAuth[obj.index] != '1' {
-					c.JSON(http.StatusForbidden, common.StatusForbidden(fmt.Sprintf("抱歉,您没有【%s】该文件权限,请联系管理员。", obj.message), nil))
+				if !strings.Contains(userAuth, obj.index) {
+					c.JSON(http.StatusForbidden, common.StatusForbidden(fmt.Sprintf("抱歉,您没有对文件的【%s】权限,请联系管理员。", obj.message), nil))
 					c.Abort()
 					return
 				}

+ 11 - 4
app/middleware/token.go

@@ -2,6 +2,7 @@ package middleware
 
 import (
 	"github.com/gin-gonic/gin"
+	"iot_manager_service/util/cache"
 	"iot_manager_service/util/common"
 	"iot_manager_service/util/token"
 	"net/http"
@@ -14,22 +15,28 @@ func AuthMiddleware() gin.HandlerFunc {
 		//如果包含路径/login则放行,其余的都要进行token认证
 		if strings.Contains(c.Request.RequestURI, "/login") ||
 			strings.Contains(c.Request.RequestURI, "/websocket") ||
-			strings.Contains(c.Request.RequestURI, "/getpublickey") {
+			strings.Contains(c.Request.RequestURI, "/getPublicKey") {
 			c.Next()
 			return
 		}
 		// 从请求头中获取token
 		tokenString := c.GetHeader("Authorization")
 		if tokenString == "" {
-			c.JSON(http.StatusOK, common.ParamsInvalidResponse("Token不能为空", nil))
+			c.JSON(http.StatusOK, common.ParamsInvalidResponse("验证不能为空", nil))
 			c.Abort()
 			return
 		}
 		//解析token
-		_, err := token.JwtClaims.ParseJwtToken(tokenString)
+		claims, err := token.JwtClaims.ParseJwtToken(tokenString)
+		user, _ := cache.GetNowSysUser(claims.ID)
+		if user.ID == 0 {
+			c.JSON(http.StatusUnauthorized, common.StatusUnauthorized("请先登录!", nil))
+			c.Abort()
+			return
+		}
 		//过期或者无效
 		if err != nil {
-			c.JSON(http.StatusUnauthorized, common.StatusUnauthorized("Token失效", nil))
+			c.JSON(http.StatusUnauthorized, common.StatusUnauthorized("登录过期,请重新登录", nil))
 			c.Abort()
 			return
 		}

+ 22 - 13
app/user/controller/user.go

@@ -1,57 +1,66 @@
 package controller
 
 import (
+	"encoding/base64"
 	"fmt"
 	"github.com/gin-gonic/gin"
-	"github.com/google/uuid"
 	"iot_manager_service/app/user/model"
 	"iot_manager_service/app/user/service"
 	"iot_manager_service/util/cache"
 	"iot_manager_service/util/common"
+	"iot_manager_service/util/rsa"
 	"iot_manager_service/util/token"
 	"iot_manager_service/util/websocket"
 	"net/http"
 	"strconv"
 )
 
-var UserController = new(user)
+var SysUserController = new(user)
 
 type user struct{}
 
 func (u *user) Login(c *gin.Context) {
-	loginUser := model.LoginUser{}
-	if err := c.ShouldBindJSON(&loginUser); err != nil {
+	loginSysUser := model.LoginSysUser{}
+	if err := c.ShouldBindJSON(&loginSysUser); err != nil {
 		c.JSON(http.StatusOK, common.ParamsInvalidResponse(err.Error(), nil))
 		return
 	}
-	info := service.UserService.Login(loginUser.Account, loginUser.PassWord)
+	info := service.SysUserService.Login(loginSysUser.UserName, loginSysUser.PassWord)
 	c.JSON(http.StatusOK, info)
 }
 
 func (u *user) GetPublicKey(c *gin.Context) {
-	key := service.UserService.GetPublicKey()
+	key := service.SysUserService.GetPublicKey()
+
+	r := rsa.RSA{}
+	publicKey := r.ReturnPublicKey()
+	fmt.Print("key", publicKey)
+	encryption := r.Encryption([]byte("123456"))
+
+	toString := base64.StdEncoding.EncodeToString(encryption)
+
+	fmt.Print("?????+++", toString)
 	c.JSON(http.StatusOK, key)
 }
 
-func (u *user) GetDeptUsers(c *gin.Context) {
+func (u *user) GetDeptSysUsers(c *gin.Context) {
 	depts := model.ReqDepts{}
 	err := c.ShouldBindJSON(&depts)
 	if err != nil {
 		c.JSON(http.StatusOK, common.ParamsInvalidResponse(err.Error(), nil))
 		return
 	}
-	users := service.UserService.GetDeptUsers(depts.Depts)
+	users := service.SysUserService.GetDeptSysUsers(depts.Depts)
 	c.JSON(http.StatusOK, users)
 }
 
 func (u *user) GetNewTokens(c *gin.Context) {
 	header := c.GetHeader("Authorization")
 	claims, _ := token.JwtClaims.ParseJwtToken(header)
-	nowUser, _ := cache.GetNowUser(claims.ID)
+	nowSysUser, _ := cache.GetNowSysUser(claims.ID)
 
-	UUID := uuid.New().String()
-	accessToken, _ := token.JwtClaims.CreateJwtToken(strconv.Itoa(nowUser.User.ID), nowUser.User.UserName, UUID, 1)
-	refreshToken, _ := token.JwtClaims.CreateJwtToken(strconv.Itoa(nowUser.User.ID), nowUser.User.UserName, UUID, 24*7)
+	accessToken, _ := token.JwtClaims.CreateJwtToken(strconv.Itoa(nowSysUser.ID), nowSysUser.Username, nowSysUser.UUID, 1)
+	refreshToken, _ := token.JwtClaims.CreateJwtToken(strconv.Itoa(nowSysUser.ID), nowSysUser.Username, nowSysUser.UUID, 24*7)
 	tokens := make(map[string]interface{})
 
 	tokens["accessToken"] = accessToken
@@ -73,6 +82,6 @@ func (u *user) Logout(c *gin.Context) {
 	c.JSON(http.StatusOK, common.SuccessResponse("退出成功", nil))
 }
 
-func (u *user) GetUser(c *gin.Context) {
+func (u *user) GetSysUser(c *gin.Context) {
 	fmt.Println("demo。。。")
 }

+ 1 - 1
app/user/dao/common.go

@@ -10,7 +10,7 @@ var Db *gorm.DB
 func InitDB(db *gorm.DB) {
 	Db = db
 	err := Db.AutoMigrate(
-		&User{},
+		&SysUser{},
 		&Dept{},
 	)
 	if err != nil {

+ 8 - 6
app/user/dao/dept.go

@@ -2,12 +2,14 @@ package dao
 
 // 部门
 type Dept struct {
-	ID        int    `gorm:"primary_key;type:int" json:"id"`    //部门id
-	DeptName  string `gorm:"type:varchar(12)" json:"dept_name"` //部门名称
-	ParentId  int    `gorm:"type:int" json:"parent_id"`         //父部门id
-	IsDeleted int    `gorm:"type:int" json:"isDeleted"`         //是否删除
-	Remark    string `gorm:"type:varchar(45)" json:"remark"`    //备注
-	Users     []User `gorm:"-" json:"users"`                    //用户们
+	ID          int       `gorm:"primary_key;type:int" json:"id"`      //部门id
+	DeptName    string    `gorm:"type:varchar(12)" json:"dept_name"`   //部门名称
+	ParentId    int       `gorm:"type:int" json:"parent_id"`           //父部门id
+	IsDeleted   int       `gorm:"type:int;default:0" json:"isDeleted"` //是否删除
+	Remark      string    `gorm:"type:varchar(45)" json:"remark"`      //备注
+	Responsible string    `gorm:"type:varchar(25)" json:"responsible"` //负责人"
+	Phone       string    `gorm:"type:varchar(25)" json:"phone"`       //联系电话"
+	SysUsers    []SysUser `gorm:"-" json:"users"`                      //用户们
 }
 
 func (*Dept) TableName() string {

+ 32 - 102
app/user/dao/user.go

@@ -1,126 +1,56 @@
 package dao
 
 import (
+	"github.com/google/uuid"
+	"gorm.io/gorm"
 	"time"
 )
 
-// User 用户
-type User struct {
-	ID         int       `gorm:"primary_key;type:int" json:"id"`                                    //编号
-	UserName   string    `gorm:"type:varchar(12)" json:"userName"`                                  //姓名
-	Sex        int       `gorm:"type:smallint;default:1" json:"sex"`                                //性别                                      //用户编号
-	Account    string    `gorm:"type:varchar(45)" json:"account"`                                   //账号
-	Password   string    `gorm:"type:text" json:"password"`                                         //密码
-	Avatar     string    `gorm:"type:varchar(500)" json:"avatar"`                                   //头像
-	Email      string    `gorm:"type:varchar(45)" json:"email"`                                     //邮箱
-	Phone      string    `gorm:"type:varchar(45)" json:"phone"`                                     //手机
-	RoleName   string    `gorm:"type:varchar(12)" json:"roleName"`                                  //角色名
-	Birthday   time.Time `gorm:"type:datetime" json:"birthday"`                                     //生日
-	DeptId     int       `gorm:"type:int" json:"deptId"`                                            //部门id
-	Status     int       `gorm:"type:int;default:0" json:"status"`                                  //状态 0=可用,1禁用
-	IsDeleted  int       `gorm:"type:int" json:"isDeleted"`                                         //是否删除 0=未删除,1=删除
-	CreateTime time.Time `gorm:"autoCreateTime;column:create_time;type:datetime" json:"createTime"` //新增时间
-	AuthId     string    `gorm:"type:varchar(12);default:'100'" json:"authId"`                      //权限id
+// SysUser 用户
+type SysUser struct {
+	ID          int            `gorm:"primary_key;type:int" json:"id"` //编号
+	CreatedAt   time.Time      // 创建时间
+	UpdatedAt   time.Time      // 更新时间
+	DeletedAt   gorm.DeletedAt `gorm:"index" json:"-"`                                                                       // 删除时间
+	UUID        uuid.UUID      `json:"uuid" gorm:"index;comment:用户UUID"`                                                     // 用户UUID
+	Username    string         `json:"userName" gorm:"index;comment:用户登录名"`                                                  // 用户登录名
+	Password    string         `json:"password"  gorm:"type:varchar(191);comment:用户登录密码"`                                    // 用户登录密码
+	NickName    string         `json:"nickName" gorm:"default:App端用户;comment:用户昵称"`                                          // 用户昵称
+	SideMode    string         `json:"sideMode" gorm:"default:dark;comment:用户侧边主题"`                                          // 用户侧边主题
+	HeaderImg   string         `json:"headerImg" gorm:"default:https://qmplusimg.henrongyi.top/gva_header.jpg;comment:用户头像"` // 用户头像
+	BaseColor   string         `json:"baseColor" gorm:"default:#fff;comment:基础颜色"`                                           // 基础颜色
+	ActiveColor string         `json:"activeColor" gorm:"default:#1890ff;comment:活跃颜色"`                                      // 活跃颜色
+	AuthorityId uint           `json:"authorityId" gorm:"default:888;comment:用户角色ID"`                                        // 用户角色ID
+	Phone       string         `json:"phone"  gorm:"type:varchar(191);comment:用户手机号"`                                        // 用户手机号
+	Email       string         `json:"email"  gorm:"type:varchar(191);comment:用户邮箱"`                                         // 用户邮箱
+	Enable      int            `json:"enable" gorm:"default:1;comment:用户是否被冻结 1正常 2冻结"`                                      //用户是否被冻结 1正常 2冻结
+	AuthId      string         `json:"authId" gorm:"type:varchar(191);comment:权限id" `                                        //权限id
+	DeptId      int            `json:"deptId" gorm:"comment:部门id"`
 }
 
-func (*User) TableName() string {
-	return "user"
+func (*SysUser) TableName() string {
+	return "sys_users"
 }
 
-func (c *User) LoginFindAccount(acc string) (*User, error) {
-	var user User
-	err := Db.Debug().Model(&user).Where("account = ? and status = 0", acc).First(&user).Error
+func (c *SysUser) LoginFindUserName(username string) (*SysUser, error) {
+	var user SysUser
+	err := Db.Model(&user).Debug().Where("username = ?", username).First(&user).Error
 	return &user, err
 }
 
-func (c *User) GetUsers() ([]User, error) {
-	var users []User
+func (c *SysUser) GetSysUsers() ([]SysUser, error) {
+	var users []SysUser
 	err := Db.Model(&c).Find(&users).Error
 	return users, err
 }
 
-func (c *User) GetNowUser(id int) (*User, error) {
+func (c *SysUser) GetNowSysUser(id int) (*SysUser, error) {
 	err := Db.Model(&c).Where("id = ?", id).First(&c).Error
 	return c, err
 }
 
-func (c *User) GetDeptsUsers(depts []int) ([]User, error) {
-	var users []User
+func (c *SysUser) GetDeptsSysUsers(depts []int) ([]SysUser, error) {
+	var users []SysUser
 	err := Db.Model(&c).Where("dept_id in ?", depts).Find(&users).Error
 	return users, err
 }
-
-//func (c *User) GetUsers1(id int) ([]User, error) {
-//	var users []User
-//	err := Db.Model(&c).Where("dept_id = ?", id).Find(&users).Error
-//	return users, err
-//}
-
-//func (c *User) GetUser() error {
-//	return Db.Model(&c).Where(" is_deleted = 0").Find(&c).Error
-//}
-//
-//func (c *User) GetUserByTenantId() error {
-//	return Db.Model(&c).Where("tenant_id = ? and is_deleted = 0", c.TenantId).Find(&c).Error
-//}
-//
-//func (c *User) GetUserByPwd() error {
-//	return Db.Model(&c).Where("tenant_id = ? and account = ? and password = ? and is_deleted = 0", c.TenantId, c.Account, c.Password).First(&c).Error
-//}
-//
-//func (c *User) GetUsers(offset, limit int) ([]User, int, error) {
-//	var users []User
-//	var counts int64
-//	db := Db.Model(&c)
-//
-//	if c.Account != "" {
-//		db = db.Where("account like ?", "%"+c.Account+"%")
-//	}
-//	if c.RealName != "" {
-//		db = db.Where("real_name like ?", "%"+c.RealName+"%")
-//	}
-//	err := db.Where("is_deleted = 0").Offset(offset).Limit(limit).Find(&users).Error
-//	db1 := Db.Model(&c)
-//	db1.Where("is_deleted = 0").Count(&counts)
-//	return users, int(counts), err
-//}
-//
-//func (c *User) Save() error {
-//	return Db.Model(&c).Save(&c).Error
-//}
-//
-//func (c *User) Update() error {
-//	return Db.Model(&c).Where(" id = ? ", c.ID).Updates(&c).Error
-//}
-//
-//func (c *User) Remove() error {
-//	return Db.Model(&c).Where("id = ?", c.ID).Updates(map[string]interface{}{"update_time": c.UpdateTime, "update_user": c.UpdateUser, "is_deleted": c.IsDeleted}).Error
-//}
-//
-//func (c *User) UpdatePwd(pwd string) error {
-//	return Db.Model(&c).Where(" id = ? ", c.ID).Updates(map[string]interface{}{"password": pwd}).Error
-//}
-//
-//func (c *User) GetAll() ([]User, error) {
-//	var users []User
-//	err := Db.Model(&c).Where("is_deleted = 0").Find(&users).Error
-//	return users, err
-//}
-//
-//func (c *User) UpdateRoles(userIds []string, roleIds string) error {
-//	err := Db.Model(&c).Where("id in ?", userIds).Updates(map[string]interface{}{"role_id": roleIds}).Error
-//	return err
-//}
-//
-//// IsExist :account是否已存在 true为存在,false不存在
-//func (c *User) IsExist() bool {
-//	var s string
-//	Db.Model(&c).Select("account").Where("account = ?", c.Account).First(&s)
-//	return s != ""
-//}
-//
-//// GetAvatar 查 avatar
-//func (c *User) GetAvatar() {
-//	tx := Db.Model(&c)
-//	tx.Select("avatar").Where("tenant_id = ?", c.TenantId).Find(&c)
-//}

+ 2 - 9
app/user/model/user.go

@@ -1,14 +1,7 @@
 package model
 
-import "iot_manager_service/app/user/dao"
-
 // 登录用户
-type LoginUser struct {
-	Account  string `json:"account"`  //账号
+type LoginSysUser struct {
+	UserName string `json:"userName"` //账号
 	PassWord string `json:"password"` //密码
 }
-
-type NowUser struct {
-	UUID string   `json:"uuid"`
-	User dao.User `json:"user"`
-}

+ 31 - 45
app/user/service/userService.go

@@ -1,97 +1,83 @@
 package service
 
 import (
-	"bytes"
-	"encoding/base64"
 	"github.com/gin-gonic/gin"
-	"github.com/google/uuid"
 	"gorm.io/gorm"
 	"iot_manager_service/app/user/dao"
 	"iot_manager_service/util/cache"
 	"iot_manager_service/util/common"
+	"iot_manager_service/util/md5"
 	"iot_manager_service/util/rsa"
 	"iot_manager_service/util/token"
 	"strconv"
 )
 
 // 用户管理服务
-var UserService = new(userService)
+var SysUserService = new(userService)
 
 type userService struct{}
 
-func (s *userService) Login(acc string, pwd string) *common.Errors {
-	userdao := &dao.User{}
-	USER, err := userdao.LoginFindAccount(acc)
+func (s *userService) Login(username string, pwd string) *common.Errors {
+	userdao := &dao.SysUser{}
+	USER, err := userdao.LoginFindUserName(username)
 	if err != nil {
 		if err == gorm.ErrRecordNotFound {
-			return common.ParamsInvalidResponse("很抱歉,由于您的账号未完成注册或已被禁用,暂时无法使用。", nil)
+			return common.ParamsInvalidResponse("登录失败,账号不存在", nil)
 		}
 		return common.FailResponse(err.Error(), nil)
 	}
-
-	//加密
-	//encryption := rsa.Encryption([]byte("123456"))
-	//base64.StdEncoding.EncodeToString(encryption))
+	if USER.Enable != 1 {
+		return common.ParamsInvalidResponse("登录失败,用户被禁止登录", nil)
+	}
 	//解密前端密文
-	a, _ := base64.StdEncoding.DecodeString(pwd)
-	client := rsa.Decryption(a)
-
+	r := rsa.RSA{}
+	decrypt := r.Decrypt(pwd)
 	//解密数据库密文
-	b, _ := base64.StdEncoding.DecodeString(USER.Password)
-	mysql := rsa.Decryption(b)
-	if !bytes.Equal(client, mysql) {
-		return common.ParamsInvalidResponse("密码错误", err)
+	ok := md5.BcryptCheck(decrypt, USER.Password)
+	if !ok {
+		return common.ParamsInvalidResponse("密码错误", nil)
 	}
-
 	//登录成功则生成token
-	UUID := uuid.New().String()
 	USERID := strconv.Itoa(USER.ID)
-	accessToken, _ := token.JwtClaims.CreateJwtToken(USERID, USER.UserName, UUID, 1)
-	refreshToken, _ := token.JwtClaims.CreateJwtToken(USERID, USER.UserName, UUID, 24*7)
-	cache.SetNowUser(USERID, UUID, USER)
+	accessToken, _ := token.JwtClaims.CreateJwtToken(USERID, USER.Username, USER.UUID, 1)
+	refreshToken, _ := token.JwtClaims.CreateJwtToken(USERID, USER.Username, USER.UUID, 24*7)
+	cache.SetNowSysUser(USERID, USER)
 
 	tokens := make(map[string]interface{})
 	tokens["accessToken"] = accessToken
 	tokens["refreshToken"] = refreshToken
 
 	//TODO:到时候记得修改服务器域名
-	urlWebSocket := "ws://localhost:8085/notice/websocket?userID=" + USERID
+	urlWebSocket := "ws://localhost:8085/notice/webSocket?userID=" + USERID
 	return common.SuccessResponse("登录成功", gin.H{"token": tokens, "websocket": urlWebSocket})
 }
 
 func (s *userService) GetPublicKey() *common.Errors {
-	pub, err := rsa.GetPubKey()
-	if err != nil {
-		return common.FailResponse(err.Error(), nil)
-	}
-	return common.SuccessResponse("获取公钥成功", gin.H{"publicKey": pub})
+	r := rsa.RSA{}
+	publicKey := r.ReturnPublicKey()
+	return common.SuccessResponse("获取公钥成功", gin.H{"publicKey": publicKey})
 }
 
-func (s *userService) GetDeptUsers(deptIDs []int) *common.Errors {
+func (s *userService) GetDeptSysUsers(deptIDs []int) *common.Errors {
 	deptdao := &dao.Dept{}
 	depts, _ := deptdao.GetDepts(deptIDs)
 
-	userdao := &dao.User{}
-	users, _ := userdao.GetUsers()
+	userdao := &dao.SysUser{}
+	users, _ := userdao.GetSysUsers()
 
-	deptUsersMap := make(map[int][]dao.User)
+	deptSysUsersMap := make(map[int][]dao.SysUser)
 	for _, user := range users {
-		deptUsersMap[user.DeptId] = append(deptUsersMap[user.DeptId], user)
+		deptSysUsersMap[user.DeptId] = append(deptSysUsersMap[user.DeptId], user)
 	}
 
-	var deptUsers []dao.Dept
+	var deptSysUsers []dao.Dept
 	for _, dept := range depts {
-		users := deptUsersMap[dept.ID]
-		deptUsers = append(deptUsers, dao.Dept{
+		users := deptSysUsersMap[dept.ID]
+		deptSysUsers = append(deptSysUsers, dao.Dept{
 			ID:       dept.ID,
 			DeptName: dept.DeptName,
-			Users:    users,
+			SysUsers: users,
 		})
 	}
-	//for i, dept := range depts {
-	//	users1, _ := userdao.GetUsers1(dept.ID)
-	//	depts[i].Users = users1
-	//}
-
-	return common.SuccessResponse("获取成功", gin.H{"deptUsers": deptUsers})
+	return common.SuccessResponse("获取成功", gin.H{"deptSysUsers": deptSysUsers})
 }

+ 0 - 15
config/private.pem

@@ -1,15 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgQD5VdURNBvulnBXj13ZFCsDhNkV6xZc5q28VYUgWTFuVWbFsNmx
-feQJDpZOQ2jLW9MRJU1q+AubYtX9oVtLeGDzqGJs3oj0W2CkShy4JWzNoPC/O5JX
-txrQSImIilp4S0mOmhclcrKpQZtA8PSyewB/5FWZ4erGLqFFWcZ9sAHniwIDAQAB
-AoGAMFEtxPOwJgAJLS6fJR3/Z+MqnlC8OKyLJl/8OFSQe60ZCV5IEVkwA4FMJ0Zw
-3FejA0OTSRNgTHBOv6OxKWLehndDydKJyG/soDsWXqgWo9b7ZoxX0nEi7oxkaVgD
-/orOvceBZ4iVCeGXsclel3ZmwQixlxQAeqG2LVhQATanOKECQQD81hd47vi1HwCz
-5Z14RpswjrMtNEFgEIQMYPKLR5WgaeECX0sH4cz7J49qaTSJWykmHvwwJU02wLCR
-8N4WcXi1AkEA/HSGnWfFboUK4SYOXv4gGnJiVdanSxRNYJ/Ndg561x0bNDzALCem
-MzrxSEp8y4s54336YwE/MW5EV6aqgw9HPwJAECU3wIA6H47IQ7Sg9qJDnLkwFe3l
-UtYbKJM0SdKbam/4b2dYajtwFIW1Mc1gDnlkyktmPUjUgm+RlvAzrmk2lQJBAKT5
-VPrJ1GgbwvdM0jlbYglGVGJ5yosysjoBU9fhMH8ggyWIyaBRLLfvvbsbCiBNVEAI
-lDZcmzonL7wDqwvIUSsCQD8MnZmP14uMTHHSay+pJiMR5gbj4Z3cPZfjQdofGDH+
-E1wcg6Om9XZshU3PgpLoF1WSGF6wCahOXChjW9AZWv4=
------END RSA PRIVATE KEY-----

+ 0 - 6
config/public.pem

@@ -1,6 +0,0 @@
------BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD5VdURNBvulnBXj13ZFCsDhNkV
-6xZc5q28VYUgWTFuVWbFsNmxfeQJDpZOQ2jLW9MRJU1q+AubYtX9oVtLeGDzqGJs
-3oj0W2CkShy4JWzNoPC/O5JXtxrQSImIilp4S0mOmhclcrKpQZtA8PSyewB/5FWZ
-4erGLqFFWcZ9sAHniwIDAQAB
------END PUBLIC KEY-----

+ 9 - 8
go.mod

@@ -1,6 +1,6 @@
 module iot_manager_service
 
-go 1.17
+go 1.20
 
 require (
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
@@ -15,6 +15,9 @@ require (
 	github.com/sirupsen/logrus v1.9.0
 	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.572
 	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.572
+	golang.org/x/crypto v0.23.0
+	google.golang.org/grpc v1.64.0
+	google.golang.org/protobuf v1.33.0
 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 	gopkg.in/yaml.v2 v2.4.0
 	gorm.io/driver/mysql v1.4.4
@@ -27,13 +30,12 @@ require (
 	github.com/fogleman/gg v1.3.0 // indirect
 	github.com/fortytw2/leaktest v1.3.0 // indirect
 	github.com/gin-contrib/sse v0.1.0 // indirect
-	github.com/go-playground/locales v0.14.0 // indirect
+	github.com/go-playground/locales v0.14.1 // indirect
 	github.com/go-playground/universal-translator v0.18.0 // indirect
 	github.com/go-playground/validator/v10 v10.10.0 // indirect
 	github.com/go-sql-driver/mysql v1.6.0 // indirect
 	github.com/goccy/go-json v0.9.7 // indirect
 	github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
-	github.com/google/go-cmp v0.5.8 // indirect
 	github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect
 	github.com/jinzhu/inflection v1.0.0 // indirect
 	github.com/jinzhu/now v1.1.5 // indirect
@@ -58,12 +60,11 @@ require (
 	github.com/rs/xid v1.4.0 // indirect
 	github.com/tebeka/strftime v0.1.5 // indirect
 	github.com/ugorji/go/codec v1.2.7 // indirect
-	golang.org/x/crypto v0.14.0 // indirect
 	golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d // indirect
-	golang.org/x/net v0.17.0 // indirect
-	golang.org/x/sys v0.13.0 // indirect
-	golang.org/x/text v0.13.0 // indirect
-	google.golang.org/protobuf v1.28.0 // indirect
+	golang.org/x/net v0.25.0 // indirect
+	golang.org/x/sys v0.20.0 // indirect
+	golang.org/x/text v0.15.0 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
 	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
 	gopkg.in/ini.v1 v1.66.6 // indirect
 )

+ 17 - 69
go.sum

@@ -1,6 +1,3 @@
-github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
-github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
-github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -26,8 +23,9 @@ github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8=
 github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
 github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
 github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
-github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
 github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
 github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
 github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
 github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0=
@@ -48,24 +46,17 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
 github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
 github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
-github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
 github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
-github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4=
 github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag=
 github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
@@ -123,15 +114,10 @@ github.com/olivere/elastic v6.2.37+incompatible h1:UfSGJem5czY+x/LqxgeCBgjDn6St+
 github.com/olivere/elastic v6.2.37+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGeB5G1iqDKVBWLNSYW8yfJ8=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
-github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
 github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
 github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
-github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
-github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
-github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
-github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
 github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q=
 github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
 github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU=
@@ -161,110 +147,73 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.572 h1:xbcb
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.572/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.572 h1:5IabGGTl7RtsX8XqwXc73owsc7HhCeTUWS+Ckr8RXCM=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.572/go.mod h1:6KS1IykRCgQlfnkANnQ/uUv3l8/zEVF0LVQd7TKpp/I=
-github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
 github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
 github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
 github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
 golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs=
 golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
-golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
+google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
+google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
 google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
 google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
-google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
+google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
 gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
 gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -287,7 +236,6 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
-gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gorm.io/driver/mysql v1.4.4 h1:MX0K9Qvy0Na4o7qSC/YI7XxqUw5KDw01umqgID+svdQ=
 gorm.io/driver/mysql v1.4.4/go.mod h1:BCg8cKI+R0j/rZRQxeKis/forqRwRSYOR8OM3Wo6hOM=
 gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=

+ 7 - 0
main.go

@@ -9,6 +9,7 @@ import (
 	user "iot_manager_service/app/user/dao"
 	"iot_manager_service/config"
 	_ "iot_manager_service/config"
+	proto "iot_manager_service/proto"
 	"iot_manager_service/router"
 	"iot_manager_service/util/cache"
 	"iot_manager_service/util/logger"
@@ -33,6 +34,8 @@ func main() {
 	}
 	engine := gin.Default()
 
+	//放行静态文件
+	engine.Static("/uploadfiles", "./uploadfiles")
 	router.InitRouter(engine)
 
 	if cfg.Logger.DbShowLog == 1 {
@@ -40,6 +43,10 @@ func main() {
 	} else {
 		println(gin.ReleaseMode)
 	}
+
+	//开启grpc服务
+	go proto.InitGrpcServer()
+
 	_ = engine.Run(config.Instance().Server.Address)
 
 }

+ 37 - 0
proto/enter.go

@@ -0,0 +1,37 @@
+package service
+
+import (
+	"context"
+	"fmt"
+	"google.golang.org/grpc"
+	"iot_manager_service/util/websocket"
+	"net"
+	"strconv"
+)
+
+type server struct {
+	UnimplementedSendMessageServer
+}
+
+func (s server) Distribution(ctx context.Context, req *DistributionRequest) (*DistributionResponse, error) {
+	for _, user := range req.Users {
+		websocket.SendMessage(strconv.FormatInt(user, 10), "您有新的文件,请注意查收!")
+	}
+	return &DistributionResponse{Code: 200}, nil
+}
+
+func InitGrpcServer() {
+	//开启端口监听
+	listen, _ := net.Listen("tcp", "127.0.0.1:9090")
+	//创建grpc服务
+	grpcServer := grpc.NewServer()
+	//注册服务
+	RegisterSendMessageServer(grpcServer, &server{})
+
+	//启动服务
+	err := grpcServer.Serve(listen)
+	if err != nil {
+		fmt.Printf("failed to serve: %v", err)
+		return
+	}
+}

+ 20 - 0
proto/serve.proto

@@ -0,0 +1,20 @@
+syntax = "proto3"; // 指定proto版本
+
+// 指定golang包名
+option go_package = ".;service";
+
+//定义rpc服务
+service SendMessage {
+  rpc Distribution (DistributionRequest) returns (DistributionResponse) {}
+}
+
+// HelloRequest 请求内容
+message DistributionRequest {
+  repeated int64 Users = 1;
+}
+
+// HelloResponse 响应内容
+message DistributionResponse{
+  int64 code = 1;
+}
+

+ 10 - 10
router/router.go

@@ -25,21 +25,22 @@ func InitRouter(engine *gin.Engine) {
 	//用户
 	sys := engine.Group("/user")
 	{
-		sys.GET("/getpublickey", user.UserController.GetPublicKey)
-		sys.POST("/login", user.UserController.Login)
-		sys.POST("/logout", user.UserController.Logout)
-		sys.GET("/getdeptusers", user.UserController.GetDeptUsers)
-		sys.GET("/getnewtokens", user.UserController.GetNewTokens)
+		sys.GET("/getPublicKey", user.SysUserController.GetPublicKey)
+		sys.POST("/login", user.SysUserController.Login)
+		sys.POST("/logout", user.SysUserController.Logout)
+		sys.POST("/getDeptUsers", user.SysUserController.GetDeptSysUsers)
+		sys.GET("/getNewTokens", user.SysUserController.GetNewTokens)
+		sys.GET("/getUser", user.SysUserController.GetSysUser)
 	}
 
 	//文件
 	files := engine.Group("/file")
 	{
 		files.POST("/distribute", file.FileController.Distribute)
-		files.GET("/getuserfiles", file.FileController.GetUserFiles)
-		files.GET("/viewfile", middleware.CheckAuth(), file.FileController.ViewFile)
-		files.GET("/downloadfile", middleware.CheckAuth(), file.FileController.DownloadFile)
-		files.POST("/forwardingfile", middleware.CheckAuth(), file.FileController.ForwardingFile)
+		files.POST("/getUserFiles", file.FileController.GetSysUserFiles)
+		files.GET("/viewFile", middleware.CheckAuth(), file.FileController.ViewFile)
+		files.GET("/downloadFile", middleware.CheckAuth(), file.FileController.DownloadFile)
+		files.POST("/forwardingFile", middleware.CheckAuth(), file.FileController.ForwardingFile)
 	}
 
 	//下发通知
@@ -47,7 +48,6 @@ func InitRouter(engine *gin.Engine) {
 	{
 		//请求Websocket连接
 		notice.GET("/websocket", websocket.HandleWebSocket)
-		notice.GET("/demo", user.UserController.GetUser)
 	}
 
 }

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 0
uploadfiles/1717136976.txt


+ 1 - 0
uploadfiles/1717137002.txt

@@ -0,0 +1 @@
+U2FsdGVkX1+mGCiAOAdr0Povl0egjMU/MgZ6+L/216IXCpW1WGRLeWW0OkPmqtxP3Uv2We6qOuUlT1npoUI/tN2tnqgRQgEWQ7KUoXDwGlxYn5RqV/ZLBg8vOYC3pnrDxgFlwgYTBeZYUzjiiau5G3LGiha0++E5rTlg4OKZN0CpYdvBOuKURoMjXQmskLyQ0LG7dURgJ22o53J5qRA8Zvlq7Y/AtkdEUV01prB8hTwZ/nl5vSCbs4c2CWycRPZSBiIPzTxkaBmCLMH486rx/QjxbcuPpCWI/vyD55L88UQ31QanZxrPrF7BOCgnBJfLQdJqyLKNtwCY479zWjbGb3nUUSGAPn3HgDDXlgJaJ0zwqN8LA5tfyNxQaJJpbvE9l7kBQatCVcM7Yx9gsV326GjM6kvckrHvU0EqVnzLY0hhDWDDJ9C4MbwMQZc/yXQN8nF+r5ykB8mcMqp6R6VcB0Cik42NEcpEE1A2+hmHink=

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 0
uploadfiles/1717401556.pptx


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 0
uploadfiles/1717401644.docx


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 0
uploadfiles/1717401661.xlsx


BIN
uploadfiles/doc.png


BIN
uploadfiles/docx.png


BIN
uploadfiles/ppt.png


BIN
uploadfiles/pptx.png


BIN
uploadfiles/txt.png


BIN
uploadfiles/xls.png


BIN
uploadfiles/xlsx.png


+ 4 - 15
util/cache/redis.go

@@ -4,7 +4,6 @@ import (
 	"encoding/json"
 	"github.com/go-redis/redis"
 	"iot_manager_service/app/user/dao"
-	"iot_manager_service/app/user/model"
 	"iot_manager_service/config"
 	"time"
 )
@@ -42,20 +41,16 @@ const (
 )
 
 // 将当前用户存入到redis中
-func SetNowUser(uid string, uuid string, user *dao.User) {
-	nowuser := model.NowUser{
-		uuid,
-		*user,
-	}
-	marshal, _ := json.Marshal(nowuser)
+func SetNowSysUser(uid string, user *dao.SysUser) {
+	marshal, _ := json.Marshal(user)
 	Redis.Set("login:"+uid, marshal, time.Hour*24*7)
 }
 
 // 从redis中取出当前用户
-func GetNowUser(uid string) (*model.NowUser, error) {
+func GetNowSysUser(uid string) (*dao.SysUser, error) {
 	result, _ := Redis.Get("login:" + uid).Result()
 	str := []byte(result)
-	nowuser := model.NowUser{}
+	nowuser := dao.SysUser{}
 	err := json.Unmarshal(str, &nowuser)
 	return &nowuser, err
 }
@@ -65,12 +60,6 @@ func DeleteToken(uid string) error {
 	return Redis.Del("login:" + uid).Err()
 }
 
-// 刷新redis存储的用户信息过期时间
-func RefreshRedisKey(id string) error {
-	_, err := Redis.Expire("login:"+id, time.Hour*1).Result()
-	return err
-}
-
 // 存储离线用户的消息
 func StoreMessages(id, msg string) error {
 	return Redis.LPush("offline:"+id, msg).Err()

+ 25 - 0
util/md5/md5.go

@@ -0,0 +1,25 @@
+package md5
+
+import (
+	"crypto/md5"
+	"encoding/hex"
+	"golang.org/x/crypto/bcrypt"
+)
+
+// BcryptHash 使用 bcrypt 对密码进行加密
+func BcryptHash(password string) string {
+	bytes, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
+	return string(bytes)
+}
+
+// BcryptCheck 对比明文密码和数据库的哈希值
+func BcryptCheck(password, hash string) bool {
+	err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
+	return err == nil
+}
+
+func MD5V(str []byte, b ...byte) string {
+	h := md5.New()
+	h.Write(str)
+	return hex.EncodeToString(h.Sum(b))
+}

+ 45 - 81
util/rsa/rsa.go

@@ -4,110 +4,74 @@ import (
 	"crypto/rand"
 	"crypto/rsa"
 	"crypto/x509"
+	"encoding/base64"
 	"encoding/pem"
-	"io/ioutil"
+	"fmt"
 )
 
-// RSA公钥私钥产生
-func GeneratePrivAndPubKey() (prvkey, pubkey []byte) {
-	// 生成私钥文件
-	privateKey, err := rsa.GenerateKey(rand.Reader, 1024)
-	if err != nil {
-		panic(err)
-	}
-	derStream := x509.MarshalPKCS1PrivateKey(privateKey)
-	block := &pem.Block{
-		Type:  "RSA PRIVATE KEY",
-		Bytes: derStream,
-	}
-	prvkey = pem.EncodeToMemory(block)
-	//保存到文件
-	err = savePEMToFile(prvkey, "config/private.pem")
+type RSA struct {
+}
+
+// 创建私钥
+var privateKey, _ = rsa.GenerateKey(rand.Reader, 2048)
+
+// 私钥解密
+func (r *RSA) Decrypt(password string) string {
+
+	encrypted, _ := base64.StdEncoding.DecodeString(password)
+
+	decryptedText, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, encrypted)
 	if err != nil {
-		panic(err)
+		fmt.Println("Failed to decrypt data:", err)
+		return ""
 	}
+	return string(decryptedText)
+}
 
+// 返回公钥
+func (r *RSA) ReturnPublicKey() string {
 	publicKey := &privateKey.PublicKey
-	derPkix, err := x509.MarshalPKIXPublicKey(publicKey)
+	publicKeyDer, err := x509.MarshalPKIXPublicKey(publicKey)
 	if err != nil {
-		panic(err)
+		fmt.Println("Failed to convert public key to DER format:", err)
+		return ""
 	}
-	block = &pem.Block{
+	publicKeyPem := &pem.Block{
 		Type:  "PUBLIC KEY",
-		Bytes: derPkix,
+		Bytes: publicKeyDer,
 	}
-	pubkey = pem.EncodeToMemory(block)
-	err = savePEMToFile(pubkey, "config/public.pem")
-	if err != nil {
-		panic(err)
-	}
-	return
+	publicKeyPemBytes := pem.EncodeToMemory(publicKeyPem)
+	return string(publicKeyPemBytes)
 }
 
-// 保存文件
-func savePEMToFile(data []byte, filename string) error {
-	err := ioutil.WriteFile(filename, data, 0644)
-	if err != nil {
-		return err
+func parsePublicKey(pemData string) *rsa.PublicKey {
+	// 将字符串转换为字节切片
+	block, _ := pem.Decode([]byte(pemData))
+	if block == nil || block.Type != "PUBLIC KEY" {
+		return nil
 	}
-	//fmt.Println("Saved", filename)
-	return nil
-}
 
-// 加密
-func Encryption(data []byte) []byte {
-	publickKeyDecoded, err2 := GetPubKey()
-	if err2 != nil {
-		panic(err2)
-	}
-	encryptedData, err := rsa.EncryptPKCS1v15(rand.Reader, publickKeyDecoded.(*rsa.PublicKey), data)
+	// 解析DER编码的公钥
+	pub, err := x509.ParsePKIXPublicKey(block.Bytes)
 	if err != nil {
-		panic(err)
+		return nil
 	}
-	return encryptedData
-}
-
-// 解密
-func Decryption(encryptedData []byte) []byte {
-	privateKeyDecoded := GetPrivKey()
-	decryptedData, _ := rsa.DecryptPKCS1v15(rand.Reader, privateKeyDecoded, encryptedData)
-	return decryptedData
-}
 
-// 加载文件
-func loadPEMFromFile(filename string) ([]byte, error) {
-	data, err := ioutil.ReadFile(filename)
-	if err != nil {
-		return nil, err
+	// 类型断言为*rsa.PublicKey
+	rsaPub, ok := pub.(*rsa.PublicKey)
+	if !ok {
+		return nil
 	}
-	return data, nil
-}
 
-// 读取私钥
-func GetPrivKey() *rsa.PrivateKey {
-	privateKeyBytes, err := loadPEMFromFile("config/private.pem")
-	if err != nil {
-		panic(err)
-	}
-	privateKeyBlock, _ := pem.Decode(privateKeyBytes)
-	privateKeyDecoded, err := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
-	if err != nil {
-		panic(err)
-	}
-	return privateKeyDecoded
+	return rsaPub
 }
 
-// 读取公钥
-func GetPubKey() (interface{}, error) {
-	publicKeyBytes, err := loadPEMFromFile("config/public.pem")
-	if err != nil {
-		panic(err)
-	}
-	//publicKeyBlock, _ := pem.Decode(publicKeyBytes)
-	//publicKeyDecoded, err := x509.ParsePKIXPublicKey(publicKeyBlock.Bytes)
-	s := string(publicKeyBytes)
+func (r *RSA) Encryption(data []byte) []byte {
+	key := parsePublicKey(r.ReturnPublicKey())
+
+	encryptedData, err := rsa.EncryptPKCS1v15(rand.Reader, key, data)
 	if err != nil {
 		panic(err)
 	}
-	return s, nil
+	return encryptedData
 }

+ 6 - 5
util/token/token.go

@@ -3,6 +3,7 @@ package token
 import (
 	"errors"
 	"github.com/dgrijalva/jwt-go"
+	"github.com/google/uuid"
 	"time"
 )
 
@@ -12,10 +13,10 @@ var JwtClaims = new(jwtClaims)
 type jwtClaims struct {
 	*jwt.StandardClaims
 	//用户编号
-	ID       string
-	UserName string
-	UUID     string
-	Time     time.Time
+	ID          string
+	SysUserName string
+	UUID        uuid.UUID
+	Time        time.Time
 }
 
 var (
@@ -28,7 +29,7 @@ var (
 )
 
 // CreateJwtToken 生成一个jwttoken
-func (jwtClaims) CreateJwtToken(id, userName, uuid string, ti time.Duration) (string, error) {
+func (jwtClaims) CreateJwtToken(id, userName string, uuid uuid.UUID, ti time.Duration) (string, error) {
 
 	// 定义过期时间
 	expireToken := time.Now().Add(time.Hour * ti).Unix()

+ 1 - 1
util/websocket/websocket.go

@@ -46,7 +46,7 @@ func HandleWebSocket(c *gin.Context) {
 	mutex.Lock()
 	client[userID] = conn
 	mutex.Unlock()
-	log.Println("User connected:", userID)
+	log.Println("SysUser connected:", userID)
 
 	//从redis中获取离线缓存的信息
 	messages := cache.GetStoreMessages(userID)