修复 「1.2.2 用户管理-用户列表勾选单一用户会全选 」 close #216
This commit is contained in:
@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user