- 替换 sqlite 驱动为 github.com/glebarez/sqlite
- 修复数据库锁定的问题 - 修复部分代码不完善的问题 - 修复策略显示不完整的问题 - 修复编辑文件换行符的问题 - 优化guacd连接
This commit is contained in:
@ -168,10 +168,7 @@ func (api AccountApi) LoginWithTotpEndpoint(c echo.Context) error {
|
||||
|
||||
func (api AccountApi) LogoutEndpoint(c echo.Context) error {
|
||||
token := GetToken(c)
|
||||
err := service.UserService.LogoutByToken(token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
service.UserService.Logout(token)
|
||||
return Success(c, nil)
|
||||
}
|
||||
|
||||
@ -317,6 +314,10 @@ func (api AccountApi) AccountAssetEndpoint(c echo.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range items {
|
||||
items[i].IP = ""
|
||||
items[i].Port = 0
|
||||
}
|
||||
|
||||
return Success(c, Map{
|
||||
"total": total,
|
||||
|
@ -28,7 +28,7 @@ func (assetApi AssetApi) AssetCreateEndpoint(c echo.Context) error {
|
||||
account, _ := GetCurrentAccount(c)
|
||||
m["owner"] = account.ID
|
||||
|
||||
if _, err := service.AssetService.Create(m); err != nil {
|
||||
if _, err := service.AssetService.Create(context.TODO(), m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ func (api BackupApi) BackupExportEndpoint(c echo.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Response().Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=next-terminal_backup_%s.json", time.Now().Format("20060102150405")))
|
||||
c.Response().Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=backup_%s.json", time.Now().Format("20060102150405")))
|
||||
return c.Stream(http.StatusOK, echo.MIMEOctetStream, bytes.NewReader(jsonBytes))
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ func (api CredentialApi) CredentialCreateEndpoint(c echo.Context) error {
|
||||
|
||||
item.Encrypted = true
|
||||
|
||||
if err := service.CredentialService.Create(&item); err != nil {
|
||||
if err := service.CredentialService.Create(context.TODO(), &item); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -159,6 +159,7 @@ func (api GuacamoleApi) Guacamole(c echo.Context) error {
|
||||
|
||||
guacamoleHandler := NewGuacamoleHandler(ws, guacdTunnel)
|
||||
guacamoleHandler.Start()
|
||||
defer guacamoleHandler.Stop()
|
||||
|
||||
for {
|
||||
_, message, err := ws.ReadMessage()
|
||||
@ -168,7 +169,6 @@ func (api GuacamoleApi) Guacamole(c echo.Context) error {
|
||||
_ = guacdTunnel.Close()
|
||||
|
||||
service.SessionService.CloseSessionById(sessionId, Normal, "用户正常退出")
|
||||
guacamoleHandler.Stop()
|
||||
return nil
|
||||
}
|
||||
_, err = guacdTunnel.WriteAndFlush(message)
|
||||
@ -193,7 +193,7 @@ func (api GuacamoleApi) setAssetConfig(attributes map[string]string, s model.Ses
|
||||
}
|
||||
realPath := path.Join(service.StorageService.GetBaseDrivePath(), storageId)
|
||||
configuration.SetParameter(guacd.EnableDrive, "true")
|
||||
configuration.SetParameter(guacd.DriveName, "Next Terminal Filesystem")
|
||||
configuration.SetParameter(guacd.DriveName, "Filesystem")
|
||||
configuration.SetParameter(guacd.DrivePath, realPath)
|
||||
log.Debugf("[%v] 会话 %v:%v 映射目录地址为 %v", s.ID, s.IP, s.Port, realPath)
|
||||
} else {
|
||||
@ -258,6 +258,7 @@ func (api GuacamoleApi) GuacamoleMonitor(c echo.Context) error {
|
||||
|
||||
guacamoleHandler := NewGuacamoleHandler(ws, guacdTunnel)
|
||||
guacamoleHandler.Start()
|
||||
defer guacamoleHandler.Stop()
|
||||
|
||||
for {
|
||||
_, message, err := ws.ReadMessage()
|
||||
@ -269,7 +270,6 @@ func (api GuacamoleApi) GuacamoleMonitor(c echo.Context) error {
|
||||
observerId := nextSession.ID
|
||||
forObsSession.Observer.Del <- observerId
|
||||
log.Debugf("[%v:%v] 观察者[%v]退出会话", sessionId, connectionId, observerId)
|
||||
guacamoleHandler.Stop()
|
||||
return nil
|
||||
}
|
||||
_, err = guacdTunnel.WriteAndFlush(message)
|
||||
|
@ -2,7 +2,6 @@ package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"next-terminal/server/guacd"
|
||||
"next-terminal/server/log"
|
||||
@ -12,73 +11,47 @@ import (
|
||||
)
|
||||
|
||||
type GuacamoleHandler struct {
|
||||
ws *websocket.Conn
|
||||
tunnel *guacd.Tunnel
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
dataChan chan []byte
|
||||
tick *time.Ticker
|
||||
ws *websocket.Conn
|
||||
tunnel *guacd.Tunnel
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
func NewGuacamoleHandler(ws *websocket.Conn, tunnel *guacd.Tunnel) *GuacamoleHandler {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
tick := time.NewTicker(time.Millisecond * time.Duration(60))
|
||||
return &GuacamoleHandler{
|
||||
ws: ws,
|
||||
tunnel: tunnel,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
dataChan: make(chan []byte),
|
||||
tick: tick,
|
||||
ws: ws,
|
||||
tunnel: tunnel,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
}
|
||||
}
|
||||
|
||||
func (r GuacamoleHandler) Start() {
|
||||
go r.readFormTunnel()
|
||||
go r.writeToWebsocket()
|
||||
}
|
||||
|
||||
func (r GuacamoleHandler) Stop() {
|
||||
r.tick.Stop()
|
||||
r.cancel()
|
||||
}
|
||||
|
||||
func (r GuacamoleHandler) readFormTunnel() {
|
||||
for {
|
||||
select {
|
||||
case <-r.ctx.Done():
|
||||
return
|
||||
default:
|
||||
instruction, err := r.tunnel.Read()
|
||||
if err != nil {
|
||||
utils.Disconnect(r.ws, TunnelClosed, "远程连接已关闭")
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-r.ctx.Done():
|
||||
return
|
||||
}
|
||||
if len(instruction) == 0 {
|
||||
continue
|
||||
}
|
||||
r.dataChan <- instruction
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r GuacamoleHandler) writeToWebsocket() {
|
||||
var buf []byte
|
||||
for {
|
||||
select {
|
||||
case <-r.ctx.Done():
|
||||
return
|
||||
case <-r.tick.C:
|
||||
if len(buf) > 0 {
|
||||
err := r.ws.WriteMessage(websocket.TextMessage, buf)
|
||||
default:
|
||||
instruction, err := r.tunnel.Read()
|
||||
if err != nil {
|
||||
utils.Disconnect(r.ws, TunnelClosed, "远程连接已关闭")
|
||||
return
|
||||
}
|
||||
if len(instruction) == 0 {
|
||||
continue
|
||||
}
|
||||
err = r.ws.WriteMessage(websocket.TextMessage, instruction)
|
||||
if err != nil {
|
||||
log.Debugf("WebSocket写入失败,即将关闭Guacd连接...")
|
||||
return
|
||||
}
|
||||
buf = []byte{}
|
||||
}
|
||||
case data := <-r.dataChan:
|
||||
buf = append(buf, data...)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (r GuacamoleHandler) Stop() {
|
||||
r.cancel()
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ func (api JobApi) JobCreateEndpoint(c echo.Context) error {
|
||||
item.ID = utils.UUID()
|
||||
item.Created = utils.NowJsonTime()
|
||||
|
||||
if err := service.JobService.Create(&item); err != nil {
|
||||
if err := service.JobService.Create(context.TODO(), &item); err != nil {
|
||||
return err
|
||||
}
|
||||
return Success(c, "")
|
||||
|
@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"next-terminal/server/service"
|
||||
|
||||
"next-terminal/server/dto"
|
||||
"next-terminal/server/repository"
|
||||
@ -42,7 +43,7 @@ func (api ResourceSharerApi) ResourceAddByUserIdAssignEndPoint(c echo.Context) e
|
||||
return err
|
||||
}
|
||||
|
||||
if err := repository.ResourceSharerRepository.AddSharerResources(ru.UserGroupId, ru.UserId, ru.StrategyId, ru.ResourceType, ru.ResourceIds); err != nil {
|
||||
if err := service.UserService.AddSharerResources(context.TODO(), ru.UserGroupId, ru.UserId, ru.StrategyId, ru.ResourceType, ru.ResourceIds); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -312,16 +312,16 @@ func (api SessionApi) SessionDownloadEndpoint(c echo.Context) error {
|
||||
if s.Download != "1" {
|
||||
return errors.New("禁止操作")
|
||||
}
|
||||
remoteFile := c.QueryParam("file")
|
||||
file := c.QueryParam("file")
|
||||
// 获取带后缀的文件名称
|
||||
filenameWithSuffix := path.Base(remoteFile)
|
||||
filenameWithSuffix := path.Base(file)
|
||||
if "ssh" == s.Protocol {
|
||||
nextSession := session.GlobalSessionManager.GetById(sessionId)
|
||||
if nextSession == nil {
|
||||
return errors.New("获取会话失败")
|
||||
}
|
||||
|
||||
dstFile, err := nextSession.NextTerminal.SftpClient.Open(remoteFile)
|
||||
dstFile, err := nextSession.NextTerminal.SftpClient.Open(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -337,7 +337,7 @@ func (api SessionApi) 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 service.StorageService.StorageDownload(c, remoteFile, storageId)
|
||||
return service.StorageService.StorageDownload(c, file, storageId)
|
||||
}
|
||||
|
||||
return err
|
||||
@ -541,7 +541,9 @@ func (api SessionApi) SessionRecordingEndpoint(c echo.Context) error {
|
||||
_ = repository.SessionRepository.UpdateReadByIds(context.TODO(), true, []string{sessionId})
|
||||
|
||||
log.Debugf("读取录屏文件:%v,是否存在: %v, 是否为文件: %v", recording, utils.FileExists(recording), utils.IsFile(recording))
|
||||
return c.File(recording)
|
||||
|
||||
http.ServeFile(c.Response(), c.Request(), recording)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (api SessionApi) SessionGetEndpoint(c echo.Context) error {
|
||||
|
@ -134,7 +134,7 @@ func (api StorageApi) StorageDeleteEndpoint(c echo.Context) error {
|
||||
split := strings.Split(ids, ",")
|
||||
for i := range split {
|
||||
id := split[i]
|
||||
if err := service.StorageService.DeleteStorageById(id, false); err != nil {
|
||||
if err := service.StorageService.DeleteStorageById(context.TODO(), id, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -173,8 +173,8 @@ func (api StorageApi) StorageDownloadEndpoint(c echo.Context) error {
|
||||
if err := api.PermissionCheck(c, storageId); err != nil {
|
||||
return err
|
||||
}
|
||||
remoteFile := c.QueryParam("file")
|
||||
return service.StorageService.StorageDownload(c, remoteFile, storageId)
|
||||
file := c.QueryParam("file")
|
||||
return service.StorageService.StorageDownload(c, file, storageId)
|
||||
}
|
||||
|
||||
func (api StorageApi) StorageUploadEndpoint(c echo.Context) error {
|
||||
|
@ -157,6 +157,7 @@ func (api WebTerminalApi) SshEndpoint(c echo.Context) error {
|
||||
|
||||
termHandler := NewTermHandler(sessionId, isRecording, ws, nextTerminal)
|
||||
termHandler.Start()
|
||||
defer termHandler.Stop()
|
||||
|
||||
for {
|
||||
_, message, err := ws.ReadMessage()
|
||||
@ -164,7 +165,6 @@ func (api WebTerminalApi) SshEndpoint(c echo.Context) error {
|
||||
// web socket会话关闭后主动关闭ssh会话
|
||||
log.Debugf("WebSocket已关闭")
|
||||
service.SessionService.CloseSessionById(sessionId, Normal, "用户正常退出")
|
||||
termHandler.Stop()
|
||||
break
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ func (userGroupApi UserGroupApi) UserGroupCreateEndpoint(c echo.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := service.UserGroupService.Create(item.Name, item.Members); err != nil {
|
||||
if _, err := service.UserGroupService.Create(context.TODO(), item.Name, item.Members); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@ -141,7 +141,11 @@ func (userApi UserApi) UserChangePasswordEndpoint(c echo.Context) error {
|
||||
}
|
||||
|
||||
if user.Mail != "" {
|
||||
go service.MailService.SendMail(user.Mail, "[Next Terminal] 密码修改通知", "你好,"+user.Nickname+"。管理员已将你的密码修改为:"+password)
|
||||
subject := "密码修改通知"
|
||||
text := fmt.Sprintf(`您好,%s。
|
||||
管理员已将你的密码修改为:%s。
|
||||
`, user.Username, password)
|
||||
go service.MailService.SendMail(user.Mail, subject, text)
|
||||
}
|
||||
|
||||
return Success(c, "")
|
||||
|
Reference in New Issue
Block a user