修复 「1.2.2 用户管理-用户列表勾选单一用户会全选 」 close #216

This commit is contained in:
dushixiang
2022-01-23 17:53:22 +08:00
parent 29c066ca3a
commit d35b348a33
130 changed files with 5467 additions and 4554 deletions

View File

@ -3,6 +3,7 @@ package api
import (
"bufio"
"bytes"
"context"
"errors"
"fmt"
"io"
@ -11,23 +12,22 @@ import (
"path"
"strconv"
"strings"
"sync"
"next-terminal/server/constant"
"next-terminal/server/global/session"
"next-terminal/server/guacd"
"next-terminal/server/log"
"next-terminal/server/model"
"next-terminal/server/repository"
"next-terminal/server/service"
"next-terminal/server/utils"
"github.com/gorilla/websocket"
"github.com/labstack/echo/v4"
"github.com/pkg/sftp"
"gorm.io/gorm"
)
func SessionPagingEndpoint(c echo.Context) error {
type SessionApi struct{}
func (api SessionApi) SessionPagingEndpoint(c echo.Context) error {
pageIndex, _ := strconv.Atoi(c.QueryParam("pageIndex"))
pageSize, _ := strconv.Atoi(c.QueryParam("pageSize"))
status := c.QueryParam("status")
@ -37,7 +37,7 @@ func SessionPagingEndpoint(c echo.Context) error {
protocol := c.QueryParam("protocol")
reviewed := c.QueryParam("reviewed")
items, total, err := sessionRepository.Find(pageIndex, pageSize, status, userId, clientIp, assetId, protocol, reviewed)
items, total, err := repository.SessionRepository.Find(context.TODO(), pageIndex, pageSize, status, userId, clientIp, assetId, protocol, reviewed)
if err != nil {
return err
@ -63,15 +63,15 @@ func SessionPagingEndpoint(c echo.Context) error {
}
}
return Success(c, H{
return Success(c, Map{
"total": total,
"items": items,
})
}
func SessionDeleteEndpoint(c echo.Context) error {
func (api SessionApi) SessionDeleteEndpoint(c echo.Context) error {
sessionIds := strings.Split(c.Param("id"), ",")
err := sessionRepository.DeleteByIds(sessionIds)
err := repository.SessionRepository.DeleteByIds(context.TODO(), sessionIds)
if err != nil {
return err
}
@ -79,38 +79,38 @@ func SessionDeleteEndpoint(c echo.Context) error {
return Success(c, nil)
}
func SessionClearEndpoint(c echo.Context) error {
err := sessionService.ClearOfflineSession()
func (api SessionApi) SessionClearEndpoint(c echo.Context) error {
err := service.SessionService.ClearOfflineSession()
if err != nil {
return err
}
return Success(c, nil)
}
func SessionReviewedEndpoint(c echo.Context) error {
func (api SessionApi) SessionReviewedEndpoint(c echo.Context) error {
sessionIds := strings.Split(c.Param("id"), ",")
if err := sessionRepository.UpdateReadByIds(true, sessionIds); err != nil {
if err := repository.SessionRepository.UpdateReadByIds(context.TODO(), true, sessionIds); err != nil {
return err
}
return Success(c, nil)
}
func SessionUnViewedEndpoint(c echo.Context) error {
func (api SessionApi) SessionUnViewedEndpoint(c echo.Context) error {
sessionIds := strings.Split(c.Param("id"), ",")
if err := sessionRepository.UpdateReadByIds(false, sessionIds); err != nil {
if err := repository.SessionRepository.UpdateReadByIds(context.TODO(), false, sessionIds); err != nil {
return err
}
return Success(c, nil)
}
func SessionReviewedAllEndpoint(c echo.Context) error {
if err := sessionService.ReviewedAll(); err != nil {
func (api SessionApi) SessionReviewedAllEndpoint(c echo.Context) error {
if err := service.SessionService.ReviewedAll(); err != nil {
return err
}
return Success(c, nil)
}
func SessionConnectEndpoint(c echo.Context) error {
func (api SessionApi) SessionConnectEndpoint(c echo.Context) error {
sessionId := c.Param("id")
s := model.Session{}
@ -118,112 +118,37 @@ func SessionConnectEndpoint(c echo.Context) error {
s.Status = constant.Connected
s.ConnectedTime = utils.NowJsonTime()
if err := sessionRepository.UpdateById(&s, sessionId); err != nil {
if err := repository.SessionRepository.UpdateById(context.TODO(), &s, sessionId); err != nil {
return err
}
o, err := sessionRepository.FindById(sessionId)
o, err := repository.SessionRepository.FindById(context.TODO(), sessionId)
if err != nil {
return err
}
asset, err := assetRepository.FindById(o.AssetId)
asset, err := repository.AssetRepository.FindById(context.TODO(), o.AssetId)
if err != nil {
return err
}
if !asset.Active {
asset.Active = true
_ = assetRepository.UpdateById(&asset, asset.ID)
_ = repository.AssetRepository.UpdateById(context.TODO(), &asset, asset.ID)
}
return Success(c, nil)
}
func SessionDisconnectEndpoint(c echo.Context) error {
func (api SessionApi) SessionDisconnectEndpoint(c echo.Context) error {
sessionIds := c.Param("id")
split := strings.Split(sessionIds, ",")
for i := range split {
CloseSessionById(split[i], ForcedDisconnect, "管理员强制关闭了此会话")
service.SessionService.CloseSessionById(split[i], ForcedDisconnect, "管理员强制关闭了此会话")
}
return Success(c, nil)
}
var mutex sync.Mutex
func CloseSessionById(sessionId string, code int, reason string) {
mutex.Lock()
defer mutex.Unlock()
nextSession := session.GlobalSessionManager.GetById(sessionId)
if nextSession != nil {
log.Debugf("[%v] 会话关闭,原因:%v", sessionId, reason)
WriteCloseMessage(nextSession.WebSocket, nextSession.Mode, code, reason)
if nextSession.Observer != nil {
obs := nextSession.Observer.All()
for _, ob := range obs {
WriteCloseMessage(ob.WebSocket, ob.Mode, code, reason)
log.Debugf("[%v] 强制踢出会话的观察者: %v", sessionId, ob.ID)
}
}
}
session.GlobalSessionManager.Del <- sessionId
DisDBSess(sessionId, code, reason)
}
func WriteCloseMessage(ws *websocket.Conn, mode string, code int, reason string) {
switch mode {
case constant.Guacd:
if ws != nil {
err := guacd.NewInstruction("error", "", strconv.Itoa(code))
_ = ws.WriteMessage(websocket.TextMessage, []byte(err.String()))
disconnect := guacd.NewInstruction("disconnect")
_ = ws.WriteMessage(websocket.TextMessage, []byte(disconnect.String()))
}
case constant.Naive:
if ws != nil {
msg := `0` + reason
_ = ws.WriteMessage(websocket.TextMessage, []byte(msg))
}
case constant.Terminal:
// 这里是关闭观察者的ssh会话
if ws != nil {
msg := `0` + reason
_ = ws.WriteMessage(websocket.TextMessage, []byte(msg))
}
}
}
func DisDBSess(sessionId string, code int, reason string) {
s, err := sessionRepository.FindById(sessionId)
if err != nil {
return
}
if s.Status == constant.Disconnected {
return
}
if s.Status == constant.Connecting {
// 会话还未建立成功,无需保留数据
_ = sessionRepository.DeleteById(sessionId)
return
}
ss := model.Session{}
ss.ID = sessionId
ss.Status = constant.Disconnected
ss.DisconnectedTime = utils.NowJsonTime()
ss.Code = code
ss.Message = reason
ss.Password = "-"
ss.PrivateKey = "-"
ss.Passphrase = "-"
_ = sessionRepository.UpdateById(&ss, sessionId)
}
func SessionResizeEndpoint(c echo.Context) error {
func (api SessionApi) SessionResizeEndpoint(c echo.Context) error {
width := c.QueryParam("width")
height := c.QueryParam("height")
sessionId := c.Param("id")
@ -235,13 +160,13 @@ func SessionResizeEndpoint(c echo.Context) error {
intWidth, _ := strconv.Atoi(width)
intHeight, _ := strconv.Atoi(height)
if err := sessionRepository.UpdateWindowSizeById(intWidth, intHeight, sessionId); err != nil {
if err := repository.SessionRepository.UpdateWindowSizeById(context.TODO(), intWidth, intHeight, sessionId); err != nil {
return err
}
return Success(c, "")
}
func SessionCreateEndpoint(c echo.Context) error {
func (api SessionApi) SessionCreateEndpoint(c echo.Context) error {
assetId := c.QueryParam("assetId")
mode := c.QueryParam("mode")
@ -253,106 +178,11 @@ func SessionCreateEndpoint(c echo.Context) error {
user, _ := GetCurrentAccount(c)
asset, err := assetRepository.FindById(assetId)
s, err := service.SessionService.Create(c.RealIP(), assetId, mode, user)
if err != nil {
return err
}
var (
upload = "1"
download = "1"
_delete = "1"
rename = "1"
edit = "1"
fileSystem = "1"
)
if asset.Owner != user.ID && constant.TypeUser == user.Type {
// 普通用户访问非自己创建的资产需要校验权限
resourceSharers, err := resourceSharerRepository.FindByResourceIdAndUserId(assetId, user.ID)
if err != nil {
return err
}
if len(resourceSharers) == 0 {
return errors.New("您没有权限访问此资产")
}
strategyId := resourceSharers[0].StrategyId
if strategyId != "" {
strategy, err := strategyRepository.FindById(strategyId)
if err != nil {
if !errors.Is(gorm.ErrRecordNotFound, err) {
return err
}
} else {
upload = strategy.Upload
download = strategy.Download
_delete = strategy.Delete
rename = strategy.Rename
edit = strategy.Edit
}
}
}
var storageId = ""
if constant.RDP == asset.Protocol {
attr, err := assetRepository.FindAssetAttrMapByAssetId(assetId)
if err != nil {
return err
}
if "true" == attr[guacd.EnableDrive] {
fileSystem = "1"
storageId = attr[guacd.DrivePath]
if storageId == "" {
storageId = user.ID
}
} else {
fileSystem = "0"
}
}
s := &model.Session{
ID: utils.UUID(),
AssetId: asset.ID,
Username: asset.Username,
Password: asset.Password,
PrivateKey: asset.PrivateKey,
Passphrase: asset.Passphrase,
Protocol: asset.Protocol,
IP: asset.IP,
Port: asset.Port,
Status: constant.NoConnect,
Creator: user.ID,
ClientIP: c.RealIP(),
Mode: mode,
Upload: upload,
Download: download,
Delete: _delete,
Rename: rename,
Edit: edit,
StorageId: storageId,
AccessGatewayId: asset.AccessGatewayId,
Reviewed: false,
}
if asset.AccountType == "credential" {
credential, err := credentialRepository.FindById(asset.CredentialId)
if err != nil {
return err
}
if credential.Type == constant.Custom {
s.Username = credential.Username
s.Password = credential.Password
} else {
s.Username = credential.Username
s.PrivateKey = credential.PrivateKey
s.Passphrase = credential.Passphrase
}
}
if err := sessionRepository.Create(s); err != nil {
return err
}
return Success(c, echo.Map{
"id": s.ID,
"upload": s.Upload,
@ -361,13 +191,15 @@ func SessionCreateEndpoint(c echo.Context) error {
"rename": s.Rename,
"edit": s.Edit,
"storageId": s.StorageId,
"fileSystem": fileSystem,
"fileSystem": s.FileSystem,
"copy": s.Copy,
"paste": s.Paste,
})
}
func SessionUploadEndpoint(c echo.Context) error {
func (api SessionApi) SessionUploadEndpoint(c echo.Context) error {
sessionId := c.Param("id")
s, err := sessionRepository.FindById(sessionId)
s, err := repository.SessionRepository.FindById(context.TODO(), sessionId)
if err != nil {
return err
}
@ -414,15 +246,18 @@ func SessionUploadEndpoint(c echo.Context) error {
}
return Success(c, nil)
} else if "rdp" == s.Protocol {
return StorageUpload(c, file, s.StorageId)
if err := service.StorageService.StorageUpload(c, file, s.StorageId); err != nil {
return err
}
return Success(c, nil)
}
return err
}
func SessionEditEndpoint(c echo.Context) error {
func (api SessionApi) SessionEditEndpoint(c echo.Context) error {
sessionId := c.Param("id")
s, err := sessionRepository.FindById(sessionId)
s, err := repository.SessionRepository.FindById(context.TODO(), sessionId)
if err != nil {
return err
}
@ -453,14 +288,17 @@ func SessionEditEndpoint(c echo.Context) error {
}
return Success(c, nil)
} else if "rdp" == s.Protocol {
return StorageEdit(c, file, fileContent, s.StorageId)
if err := service.StorageService.StorageEdit(file, fileContent, s.StorageId); err != nil {
return err
}
return Success(c, nil)
}
return err
}
func SessionDownloadEndpoint(c echo.Context) error {
func (api SessionApi) SessionDownloadEndpoint(c echo.Context) error {
sessionId := c.Param("id")
s, err := sessionRepository.FindById(sessionId)
s, err := repository.SessionRepository.FindById(context.TODO(), sessionId)
if err != nil {
return err
}
@ -492,15 +330,15 @@ func SessionDownloadEndpoint(c echo.Context) error {
return c.Stream(http.StatusOK, echo.MIMEOctetStream, bytes.NewReader(buff.Bytes()))
} else if "rdp" == s.Protocol {
storageId := s.StorageId
return StorageDownload(c, remoteFile, storageId)
return service.StorageService.StorageDownload(c, remoteFile, storageId)
}
return err
}
func SessionLsEndpoint(c echo.Context) error {
func (api SessionApi) SessionLsEndpoint(c echo.Context) error {
sessionId := c.Param("id")
s, err := sessionRepository.FindByIdAndDecrypt(sessionId)
s, err := service.SessionService.FindByIdAndDecrypt(context.TODO(), sessionId)
if err != nil {
return err
}
@ -550,15 +388,19 @@ func SessionLsEndpoint(c echo.Context) error {
return Success(c, files)
} else if "rdp" == s.Protocol {
storageId := s.StorageId
return StorageLs(c, remoteDir, storageId)
err, files := service.StorageService.StorageLs(remoteDir, storageId)
if err != nil {
return err
}
return Success(c, files)
}
return errors.New("当前协议不支持此操作")
}
func SessionMkDirEndpoint(c echo.Context) error {
func (api SessionApi) SessionMkDirEndpoint(c echo.Context) error {
sessionId := c.Param("id")
s, err := sessionRepository.FindById(sessionId)
s, err := repository.SessionRepository.FindById(context.TODO(), sessionId)
if err != nil {
return err
}
@ -576,14 +418,18 @@ func SessionMkDirEndpoint(c echo.Context) error {
}
return Success(c, nil)
} else if "rdp" == s.Protocol {
return StorageMkDir(c, remoteDir, s.StorageId)
storageId := s.StorageId
if err := service.StorageService.StorageMkDir(remoteDir, storageId); err != nil {
return err
}
return Success(c, nil)
}
return errors.New("当前协议不支持此操作")
}
func SessionRmEndpoint(c echo.Context) error {
func (api SessionApi) SessionRmEndpoint(c echo.Context) error {
sessionId := c.Param("id")
s, err := sessionRepository.FindById(sessionId)
s, err := repository.SessionRepository.FindById(context.TODO(), sessionId)
if err != nil {
return err
}
@ -628,15 +474,19 @@ func SessionRmEndpoint(c echo.Context) error {
return Success(c, nil)
} else if "rdp" == s.Protocol {
return StorageRm(c, file, s.StorageId)
storageId := s.StorageId
if err := service.StorageService.StorageRm(file, storageId); err != nil {
return err
}
return Success(c, nil)
}
return errors.New("当前协议不支持此操作")
}
func SessionRenameEndpoint(c echo.Context) error {
func (api SessionApi) SessionRenameEndpoint(c echo.Context) error {
sessionId := c.Param("id")
s, err := sessionRepository.FindById(sessionId)
s, err := repository.SessionRepository.FindById(context.TODO(), sessionId)
if err != nil {
return err
}
@ -659,14 +509,18 @@ func SessionRenameEndpoint(c echo.Context) error {
return Success(c, nil)
} else if "rdp" == s.Protocol {
return StorageRename(c, oldName, newName, s.StorageId)
storageId := s.StorageId
if err := service.StorageService.StorageRename(oldName, newName, storageId); err != nil {
return err
}
return Success(c, nil)
}
return errors.New("当前协议不支持此操作")
}
func SessionRecordingEndpoint(c echo.Context) error {
func (api SessionApi) SessionRecordingEndpoint(c echo.Context) error {
sessionId := c.Param("id")
s, err := sessionRepository.FindById(sessionId)
s, err := repository.SessionRepository.FindById(context.TODO(), sessionId)
if err != nil {
return err
}
@ -677,24 +531,24 @@ func SessionRecordingEndpoint(c echo.Context) error {
} else {
recording = s.Recording + "/recording"
}
_ = sessionRepository.UpdateReadByIds(true, []string{sessionId})
_ = repository.SessionRepository.UpdateReadByIds(context.TODO(), true, []string{sessionId})
log.Debugf("读取录屏文件:%v,是否存在: %v, 是否为文件: %v", recording, utils.FileExists(recording), utils.IsFile(recording))
return c.File(recording)
}
func SessionGetEndpoint(c echo.Context) error {
func (api SessionApi) SessionGetEndpoint(c echo.Context) error {
sessionId := c.Param("id")
s, err := sessionRepository.FindById(sessionId)
s, err := repository.SessionRepository.FindById(context.TODO(), sessionId)
if err != nil {
return err
}
return Success(c, s)
}
func SessionStatsEndpoint(c echo.Context) error {
func (api SessionApi) SessionStatsEndpoint(c echo.Context) error {
sessionId := c.Param("id")
s, err := sessionRepository.FindByIdAndDecrypt(sessionId)
s, err := service.SessionService.FindByIdAndDecrypt(context.TODO(), sessionId)
if err != nil {
return err
}