Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v3.8.0 #1247

Merged
merged 20 commits into from
Oct 19, 2023
Merged

v3.8.0 #1247

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ do
echo "wait for jms_core $CORE_HOST ready"
sleep 2
done
# 限制所有可执行目录的权限
chmod -R 700 /usr/local/sbin/* && chmod -R 700 /usr/local/bin/* && chmod -R 700 /usr/bin/*
chmod -R 700 /usr/sbin/* && chmod -R 700 /sbin/* && chmod -R 700 /bin/*


# 放开部分需要的可执行权限
chmod 755 `which mysql` `which psql` `which mongosh` `which tsql` `which redis` `which clickhouse-client`
chmod 755 `which kubectl` `which rawkubectl` `which helm` `which rawhelm`
chmod 755 `which jq` `which less` `which vim` `which ls` `which bash`
# k8s 集群连接需要的命令
chmod 755 `which grep`
cd /opt/koko
./koko
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ require (
github.com/spf13/viper v1.12.0
github.com/xlab/treeprint v1.1.0
go.mongodb.org/mongo-driver v1.8.3
golang.org/x/crypto v0.9.0
golang.org/x/term v0.8.0
golang.org/x/text v0.9.0
golang.org/x/crypto v0.14.0
golang.org/x/term v0.13.0
golang.org/x/text v0.13.0
gopkg.in/natefinch/lumberjack.v2 v2.0.0
k8s.io/api v0.23.1
k8s.io/apimachinery v0.23.1
Expand Down Expand Up @@ -103,10 +103,10 @@ require (
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect
google.golang.org/appengine v1.6.7 // indirect
Expand All @@ -125,6 +125,6 @@ require (
)

replace (
github.com/gliderlabs/ssh => github.com/LeeEirc/ssh v0.1.2-0.20220323091501-23b956e1e5a8
github.com/gliderlabs/ssh => github.com/LeeEirc/ssh v0.1.2-0.20231007053448-a6110c0dfc4a
golang.org/x/crypto => github.com/LeeEirc/crypto v0.0.0-20230919154755-059031d26b68
)
20 changes: 10 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ github.com/LeeEirc/elfinder v0.0.14 h1:6ObxwIoC5zmrnKArUU5Mz++/T3lzgl1Ja0pS1Smd3
github.com/LeeEirc/elfinder v0.0.14/go.mod h1:d1bMAAydkZSBxSN/EuQjBg6B0xcPP3boHuYEpzEHYTs=
github.com/LeeEirc/httpsig v1.2.1 h1:GGmCc2Bug3KeCchlZHwrfyjyAnw+JlzMjKDobPypirs=
github.com/LeeEirc/httpsig v1.2.1/go.mod h1:aoLZLXCSNDgkzsH2sGLWn3hlVbF+Voe8fCArxLt9nWA=
github.com/LeeEirc/ssh v0.1.2-0.20220323091501-23b956e1e5a8 h1:UxED5pKJd9yel/LXEUHDn8C+pYhDogxwx7G9HZcov4w=
github.com/LeeEirc/ssh v0.1.2-0.20220323091501-23b956e1e5a8/go.mod h1:bSl4MzlGJ2FbMCzfyuwruG2mrWY0dxE8wqWoAIhKe8k=
github.com/LeeEirc/ssh v0.1.2-0.20231007053448-a6110c0dfc4a h1:/EdJeCK6cTaKNgftQLP9uyBL4Q86MFawU0WsK22yn2A=
github.com/LeeEirc/ssh v0.1.2-0.20231007053448-a6110c0dfc4a/go.mod h1:O9BMs9PYwCJbftRP9O2Ig5Wd3hbLSpzhvP0bqU9EONg=
github.com/LeeEirc/tclientlib v0.0.3-0.20230803101925-fb52a90cb08d h1:4qUSGc/34IALiDs2kBrjbCKfx7zvAt16K+gTRzNN8Fo=
github.com/LeeEirc/tclientlib v0.0.3-0.20230803101925-fb52a90cb08d/go.mod h1:TF2v0XZYyRcZfx4NmA/EEFRkdKZLsQd8YnlhGKl1KUA=
github.com/LeeEirc/terminalparser v0.0.0-20220328021224-de16b7643ea4 h1:Gk7m4Nu2jqVqJAJqNlTYqkiq96WkANAtB4fVi+t7Xv8=
Expand Down Expand Up @@ -523,8 +523,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
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/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand Down Expand Up @@ -612,16 +612,16 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
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/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand All @@ -634,8 +634,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
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/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down
29 changes: 28 additions & 1 deletion pkg/auth/ssh.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package auth

import (
"errors"
"net"
"strings"

"github.com/gliderlabs/ssh"
"github.com/jumpserver/koko/pkg/config"
gossh "golang.org/x/crypto/ssh"

"github.com/jumpserver/koko/pkg/jms-sdk-go/model"
Expand Down Expand Up @@ -36,12 +38,15 @@ func SSHPasswordAndPublicKeyAuth(jmsService *service.JMService) SSHAuthFunc {
userAuthClient, ok := ctx.Value(ContextKeyClient).(*UserAuthClient)
if !ok {
newClient := jmsService.CloneClient()

var accessKey model.AccessKey
conf := config.GetConf()
_ = accessKey.LoadFromFile(conf.AccessKeyFilePath)
userClient := service.NewUserClient(
service.UserClientUsername(username),
service.UserClientRemoteAddr(remoteAddr),
service.UserClientLoginType("T"),
service.UserClientHttpClient(&newClient),
service.UserClientSvcSignKey(accessKey),
)
userAuthClient = &UserAuthClient{
UserClient: userClient,
Expand Down Expand Up @@ -78,6 +83,13 @@ func SSHKeyboardInteractiveAuth(ctx ssh.Context, challenger gossh.KeyboardIntera
if value, ok := ctx.Value(ContextKeyAuthFailed).(*bool); ok && *value {
return ssh.AuthFailed
}
// 2 steps auth must have a partial success method
if val := ctx.Value(ContextKeyPartialSuccessMethod); val == nil {
logger.Errorf("SSH conn[%s] user %s Mfa Auth failed: not found partial success method.",
ctx.SessionID(), ctx.User())
return ssh.AuthFailed
}

username := GetUsernameFromSSHCtx(ctx)
res = ssh.AuthFailed
client, ok := ctx.Value(ContextKeyClient).(*UserAuthClient)
Expand All @@ -104,6 +116,19 @@ func SSHKeyboardInteractiveAuth(ctx ssh.Context, challenger gossh.KeyboardIntera
return
}

func SSHAuthLogCallback(ctx ssh.Context, method string, err error) {
if err == nil {
logger.Errorf("SSH conn[%s] auth method %s success", ctx.SessionID(), method)
return
}
if errors.Is(err, gossh.ErrPartialSuccess) {
ctx.SetValue(ContextKeyPartialSuccessMethod, method)
logger.Infof("SSH conn[%s] auth method %s partially success", ctx.SessionID(), method)
} else {
logger.Errorf("SSH conn[%s] auth method %s failed: %s", ctx.SessionID(), method, err)
}
}

const (
ContextKeyUser = "CONTEXT_USER"
ContextKeyClient = "CONTEXT_CLIENT"
Expand All @@ -113,6 +138,8 @@ const (
ContextKeyAuthFailed = "CONTEXT_AUTH_FAILED"

ContextKeyDirectLoginFormat = "CONTEXT_DIRECT_LOGIN_FORMAT"

ContextKeyPartialSuccessMethod = "CONTEXT_PARTIAL_SUCCESS_METHOD"
)

type DirectLoginAssetReq struct {
Expand Down
2 changes: 2 additions & 0 deletions pkg/exchange/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ func newRedisManager(cfg Config) (*redisRoomManager, error) {
sentinelOpts = append(sentinelOpts, dialOptions...)
if cfg.SentinelPassword != "" {
sentinelOpts = append(sentinelOpts, radix.DialAuthPass(cfg.SentinelPassword))
} else {
sentinelOpts = append(sentinelOpts, radix.DialAuthUser("", ""))
}
sentinelConnFunc := func(network, addr string) (radix.Conn, error) {
conn, err := radix.Dial(network, addr, sentinelOpts...)
Expand Down
1 change: 1 addition & 0 deletions pkg/handler/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ func (u *UserSelectHandler) proxyAsset(asset model.Asset) {
Account: selectedAccount.Alias,
Protocol: protocol,
ConnectMethod: "ssh",
RemoteAddr: u.h.sess.RemoteAddr(),
}
tokenInfo, err := u.h.jmsService.CreateSuperConnectToken(&req)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/handler/direct_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ func (d *DirectHandler) Proxy(asset model.Asset) {
Account: selectAccount.Alias,
Protocol: protocol,
ConnectMethod: model.ProtocolSSH,
RemoteAddr: d.wrapperSess.RemoteAddr(),
}
tokenInfo, err := d.jmsService.CreateSuperConnectToken(&req)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions pkg/handler/server_ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,12 +239,14 @@ func (s *Server) SessionHandler(sess ssh.Session) {
func (s *Server) proxyDirectRequest(sess ssh.Session, user *model.User, asset model.Asset,
permAccount model.PermAccount) {
// 仅支持 ssh 的协议资产
remoteAddr, _, _ := net.SplitHostPort(sess.RemoteAddr().String())
req := &service.SuperConnectTokenReq{
UserId: user.ID,
AssetId: asset.ID,
Account: permAccount.Alias,
Protocol: model.ProtocolSSH,
ConnectMethod: model.ProtocolSSH,
RemoteAddr: remoteAddr,
}
// ssh 非交互式的直连格式,不支持资产的登录复核
tokenInfo, err := s.jmsService.CreateSuperConnectToken(req)
Expand Down
11 changes: 10 additions & 1 deletion pkg/httpd/message.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package httpd

import (
"github.com/jumpserver/koko/pkg/exchange"
"time"

"github.com/jumpserver/koko/pkg/exchange"

"github.com/jumpserver/koko/pkg/jms-sdk-go/model"
)

Expand Down Expand Up @@ -40,7 +41,11 @@ const (

TerminalShareUserRemove = "TERMINAL_SHARE_USER_REMOVE"

TerminalSyncUserPreference = "TERMINAL_SYNC_USER_PREFERENCE"

TerminalError = "TERMINAL_ERROR"

MessageNotify = "MESSAGE_NOTIFY"
)

type WindowSize struct {
Expand Down Expand Up @@ -80,6 +85,10 @@ type ShareInfo struct {
Record model.ShareRecord
}

type UserKoKoPreferenceParam struct {
ThemeName string `json:"terminal_theme_name"`
}

const (
TargetTypeMonitor = "monitor"

Expand Down
47 changes: 46 additions & 1 deletion pkg/httpd/tty.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"sync"

"github.com/gliderlabs/ssh"

"github.com/jumpserver/koko/pkg/exchange"
"github.com/jumpserver/koko/pkg/jms-sdk-go/common"
"github.com/jumpserver/koko/pkg/jms-sdk-go/model"
Expand Down Expand Up @@ -186,6 +185,17 @@ func (h *tty) handleTerminalMessage(msg *Message) {
logger.Debugf("Ws[%s] receive share remove user request %s", h.ws.Uuid, msg.Data)
go h.removeShareUser(&query)
return
case TerminalSyncUserPreference:
var preference UserKoKoPreferenceParam
err := json.Unmarshal([]byte(msg.Data), &preference)
if err != nil {
logger.Errorf("Ws[%s] message(%s) data unmarshal err: %s", h.ws.Uuid,
msg.Type, msg.Data)
return
}
logger.Debugf("Ws[%s] receive sync user preference request %s", h.ws.Uuid, msg.Data)
go h.syncUserPreference(&preference)
return
case CLOSE:
_ = h.backendClient.Close()
default:
Expand All @@ -209,6 +219,41 @@ func (h *tty) removeShareUser(query *RemoveSharingUserParams) {
}
}

func (h *tty) syncUserPreference(preference *UserKoKoPreferenceParam) {
/*
{"basic":{"file_name_conflict_resolution":"replace","terminal_theme_name":"Flat"}}
*/
reqCookies := h.ws.ctx.Request.Cookies()
var cookies = make(map[string]string)
for _, cookie := range reqCookies {
cookies[cookie.Name] = cookie.Value
}
data := model.UserKokoPreference{
Basic: model.KokoBasic{
ThemeName: preference.ThemeName,
},
}
var msg struct {
EventName string `json:"event_name"`
}
msg.EventName = "sync_user_preference"
errMsg := ""
err := h.ws.apiClient.SyncUserKokoPreference(cookies, data)
if err != nil {
logger.Errorf("Ws[%s] sync user preference err: %s", h.ws.Uuid, err)
errMsg = err.Error()
}
msgNotify, _ := json.Marshal(msg)

h.ws.SendMessage(&Message{
Id: h.ws.Uuid,
Type: MessageNotify,
Data: string(msgNotify),
Err: errMsg,
})

}

func (h *tty) createShareSession(shareData *ShareRequestParams) {
// 创建 共享连接
res, err := h.handleShareRequest(shareData)
Expand Down
12 changes: 12 additions & 0 deletions pkg/jms-sdk-go/model/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,15 @@ func ParseReplayVersion(gzFile string, defaultValue ReplayVersion) ReplayVersion
}
return defaultValue
}

type ReplayError LabelField

func (r ReplayError) Error() string {
return string(r)
}

const (
SessionReplayErrConnectFailed ReplayError = "connect_failed"
SessionReplayErrCreatedFailed ReplayError = "replay_create_failed"
SessionReplayErrUploadFailed ReplayError = "replay_upload_failed"
)
1 change: 1 addition & 0 deletions pkg/jms-sdk-go/model/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,5 @@ type ConnectOptions struct {
BackspaceAsCtrlH *bool `json:"backspaceAsCtrlH,omitempty"`

FilenameConflictResolution string `json:"file_name_conflict_resolution,omitempty"`
TerminalThemeName string `json:"terminal_theme_name,omitempty"`
}
12 changes: 5 additions & 7 deletions pkg/jms-sdk-go/model/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ func (u *User) String() string {
return fmt.Sprintf("%s(%s)", u.Name, u.Username)
}

type TokenUser struct {
UserID string `json:"user"`
UserName string `json:"username"`
AssetID string `json:"asset"`
Hostname string `json:"hostname"`
SystemUserID string `json:"system_user"`
SystemUserName string `json:"system_user_name"`
type UserKokoPreference struct {
Basic KokoBasic `json:"basic"`
}
type KokoBasic struct {
ThemeName string `json:"terminal_theme_name"`
}
14 changes: 12 additions & 2 deletions pkg/jms-sdk-go/service/jms_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package service

import (
"fmt"

"github.com/jumpserver/koko/pkg/jms-sdk-go/common"
"github.com/jumpserver/koko/pkg/jms-sdk-go/model"
)
Expand Down Expand Up @@ -46,11 +47,20 @@ func (s *JMService) SessionSuccess(sid string) error {
}

func (s *JMService) SessionFailed(sid string, err error) error {
data := map[string]bool{
"is_success": false,
data := map[string]interface{}{
"is_success": false,
"error_reason": model.SessionReplayErrConnectFailed,
}
return s.sessionPatch(sid, data)
}

func (s *JMService) SessionReplayFailed(sid string, err model.ReplayError) error {
data := map[string]interface{}{
"error_reason": err,
}
return s.sessionPatch(sid, data)
}

func (s *JMService) SessionDisconnect(sid string) error {
return s.SessionFinished(sid, common.NewNowUTCTime())
}
Expand Down
Loading