完成重构数据库操作代码
This commit is contained in:
@ -111,7 +111,7 @@ func LoginSuccess(c echo.Context, loginAccount LoginAccount, user model.User) (t
|
||||
Remember: authorization.Remember,
|
||||
}
|
||||
|
||||
if model.CreateNewLoginLog(&loginLog) != nil {
|
||||
if loginLogRepository.Create(&loginLog) != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@ -179,7 +179,7 @@ func LogoutEndpoint(c echo.Context) error {
|
||||
token := GetToken(c)
|
||||
cacheKey := BuildCacheKeyByToken(token)
|
||||
global.Cache.Delete(cacheKey)
|
||||
err := model.Logout(token)
|
||||
err := userService.Logout(token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
75
server/api/api.go
Normal file
75
server/api/api.go
Normal file
@ -0,0 +1,75 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"next-terminal/server/constant"
|
||||
"next-terminal/server/global"
|
||||
"next-terminal/server/model"
|
||||
)
|
||||
|
||||
type H map[string]interface{}
|
||||
|
||||
func Fail(c echo.Context, code int, message string) error {
|
||||
return c.JSON(200, H{
|
||||
"code": code,
|
||||
"message": message,
|
||||
})
|
||||
}
|
||||
|
||||
func FailWithData(c echo.Context, code int, message string, data interface{}) error {
|
||||
return c.JSON(200, H{
|
||||
"code": code,
|
||||
"message": message,
|
||||
"data": data,
|
||||
})
|
||||
}
|
||||
|
||||
func Success(c echo.Context, data interface{}) error {
|
||||
return c.JSON(200, H{
|
||||
"code": 1,
|
||||
"message": "success",
|
||||
"data": data,
|
||||
})
|
||||
}
|
||||
|
||||
func NotFound(c echo.Context, message string) error {
|
||||
return c.JSON(200, H{
|
||||
"code": -1,
|
||||
"message": message,
|
||||
})
|
||||
}
|
||||
|
||||
func GetToken(c echo.Context) string {
|
||||
token := c.Request().Header.Get(Token)
|
||||
if len(token) > 0 {
|
||||
return token
|
||||
}
|
||||
return c.QueryParam(Token)
|
||||
}
|
||||
|
||||
func GetCurrentAccount(c echo.Context) (model.User, bool) {
|
||||
token := GetToken(c)
|
||||
cacheKey := BuildCacheKeyByToken(token)
|
||||
get, b := global.Cache.Get(cacheKey)
|
||||
if b {
|
||||
return get.(Authorization).User, true
|
||||
}
|
||||
return model.User{}, false
|
||||
}
|
||||
|
||||
func HasPermission(c echo.Context, owner string) bool {
|
||||
// 检测是否登录
|
||||
account, found := GetCurrentAccount(c)
|
||||
if !found {
|
||||
return false
|
||||
}
|
||||
// 检测是否为管理人员
|
||||
if constant.TypeAdmin == account.Type {
|
||||
return true
|
||||
}
|
||||
// 检测是否为所有者
|
||||
if owner == account.ID {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
@ -32,18 +32,18 @@ func AssetCreateEndpoint(c echo.Context) error {
|
||||
item.ID = utils.UUID()
|
||||
item.Created = utils.NowJsonTime()
|
||||
|
||||
if err := model.CreateNewAsset(&item); err != nil {
|
||||
if err := assetRepository.Create(&item); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := model.UpdateAssetAttributes(item.ID, item.Protocol, m); err != nil {
|
||||
if err := assetRepository.UpdateAttributes(item.ID, item.Protocol, m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 创建后自动检测资产是否存活
|
||||
go func() {
|
||||
active := utils.Tcping(item.IP, item.Port)
|
||||
model.UpdateAssetActiveById(active, item.ID)
|
||||
assetRepository.UpdateActiveById(active, item.ID)
|
||||
}()
|
||||
|
||||
return Success(c, item)
|
||||
@ -98,7 +98,7 @@ func AssetImportEndpoint(c echo.Context) error {
|
||||
Owner: account.ID,
|
||||
}
|
||||
|
||||
err := model.CreateNewAsset(&asset)
|
||||
err := assetRepository.Create(&asset)
|
||||
if err != nil {
|
||||
errorCount++
|
||||
m[strconv.Itoa(i)] = err.Error()
|
||||
@ -107,7 +107,7 @@ func AssetImportEndpoint(c echo.Context) error {
|
||||
// 创建后自动检测资产是否存活
|
||||
go func() {
|
||||
active := utils.Tcping(asset.IP, asset.Port)
|
||||
model.UpdateAssetActiveById(active, asset.ID)
|
||||
assetRepository.UpdateActiveById(active, asset.ID)
|
||||
}()
|
||||
}
|
||||
}
|
||||
@ -135,7 +135,7 @@ func AssetPagingEndpoint(c echo.Context) error {
|
||||
field := c.QueryParam("field")
|
||||
|
||||
account, _ := GetCurrentAccount(c)
|
||||
items, total, err := model.FindPageAsset(pageIndex, pageSize, name, protocol, tags, account, owner, sharer, userGroupId, ip, order, field)
|
||||
items, total, err := assetRepository.Find(pageIndex, pageSize, name, protocol, tags, account, owner, sharer, userGroupId, ip, order, field)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -149,7 +149,7 @@ func AssetPagingEndpoint(c echo.Context) error {
|
||||
func AssetAllEndpoint(c echo.Context) error {
|
||||
protocol := c.QueryParam("protocol")
|
||||
account, _ := GetCurrentAccount(c)
|
||||
items, _ := model.FindAssetByConditions(protocol, account)
|
||||
items, _ := assetRepository.FindByProtocolAndUser(protocol, account)
|
||||
return Success(c, items)
|
||||
}
|
||||
|
||||
@ -199,8 +199,10 @@ func AssetUpdateEndpoint(c echo.Context) error {
|
||||
item.Description = "-"
|
||||
}
|
||||
|
||||
model.UpdateAssetById(&item, id)
|
||||
if err := model.UpdateAssetAttributes(id, item.Protocol, m); err != nil {
|
||||
if err := assetRepository.UpdateById(&item, id); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := assetRepository.UpdateAttributes(id, item.Protocol, m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -214,7 +216,7 @@ func AssetGetAttributeEndpoint(c echo.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
attributeMap, err := model.FindAssetAttrMapByAssetId(assetId)
|
||||
attributeMap, err := assetRepository.FindAssetAttrMapByAssetId(assetId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -229,7 +231,7 @@ func AssetUpdateAttributeEndpoint(c echo.Context) error {
|
||||
|
||||
assetId := c.Param("id")
|
||||
protocol := c.QueryParam("protocol")
|
||||
err := model.UpdateAssetAttributes(assetId, protocol, m)
|
||||
err := assetRepository.UpdateAttributes(assetId, protocol, m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -243,11 +245,11 @@ func AssetDeleteEndpoint(c echo.Context) error {
|
||||
if err := PreCheckAssetPermission(c, split[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := model.DeleteAssetById(split[i]); err != nil {
|
||||
if err := assetRepository.DeleteById(split[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
// 删除资产与用户的关系
|
||||
if err := model.DeleteResourceSharerByResourceId(split[i]); err != nil {
|
||||
if err := resourceSharerRepository.DeleteResourceSharerByResourceId(split[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -262,10 +264,10 @@ func AssetGetEndpoint(c echo.Context) (err error) {
|
||||
}
|
||||
|
||||
var item model.Asset
|
||||
if item, err = model.FindAssetById(id); err != nil {
|
||||
if item, err = assetRepository.FindById(id); err != nil {
|
||||
return err
|
||||
}
|
||||
attributeMap, err := model.FindAssetAttrMapByAssetId(id)
|
||||
attributeMap, err := assetRepository.FindAssetAttrMapByAssetId(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -281,19 +283,21 @@ func AssetTcpingEndpoint(c echo.Context) (err error) {
|
||||
id := c.Param("id")
|
||||
|
||||
var item model.Asset
|
||||
if item, err = model.FindAssetById(id); err != nil {
|
||||
if item, err = assetRepository.FindById(id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
active := utils.Tcping(item.IP, item.Port)
|
||||
|
||||
model.UpdateAssetActiveById(active, item.ID)
|
||||
if err := assetRepository.UpdateActiveById(active, item.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
return Success(c, active)
|
||||
}
|
||||
|
||||
func AssetTagsEndpoint(c echo.Context) (err error) {
|
||||
var items []string
|
||||
if items, err = model.FindAssetTags(); err != nil {
|
||||
if items, err = assetRepository.FindTags(); err != nil {
|
||||
return err
|
||||
}
|
||||
return Success(c, items)
|
||||
@ -307,12 +311,14 @@ func AssetChangeOwnerEndpoint(c echo.Context) (err error) {
|
||||
}
|
||||
|
||||
owner := c.QueryParam("owner")
|
||||
model.UpdateAssetById(&model.Asset{Owner: owner}, id)
|
||||
if err := assetRepository.UpdateById(&model.Asset{Owner: owner}, id); err != nil {
|
||||
return err
|
||||
}
|
||||
return Success(c, "")
|
||||
}
|
||||
|
||||
func PreCheckAssetPermission(c echo.Context, id string) error {
|
||||
item, err := model.FindAssetById(id)
|
||||
item, err := assetRepository.FindById(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -4,11 +4,9 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"next-terminal/server/global"
|
||||
"next-terminal/server/model"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/sirupsen/logrus"
|
||||
"next-terminal/server/global"
|
||||
)
|
||||
|
||||
func LoginLogPagingEndpoint(c echo.Context) error {
|
||||
@ -17,7 +15,7 @@ func LoginLogPagingEndpoint(c echo.Context) error {
|
||||
userId := c.QueryParam("userId")
|
||||
clientIp := c.QueryParam("clientIp")
|
||||
|
||||
items, total, err := model.FindPageLoginLog(pageIndex, pageSize, userId, clientIp)
|
||||
items, total, err := loginLogRepository.Find(pageIndex, pageSize, userId, clientIp)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
@ -35,11 +33,11 @@ func LoginLogDeleteEndpoint(c echo.Context) error {
|
||||
for i := range split {
|
||||
token := split[i]
|
||||
global.Cache.Delete(token)
|
||||
if err := model.Logout(token); err != nil {
|
||||
if err := userService.Logout(token); err != nil {
|
||||
logrus.WithError(err).Error("Cache Delete Failed")
|
||||
}
|
||||
}
|
||||
if err := model.DeleteLoginLogByIdIn(split); err != nil {
|
||||
if err := loginLogRepository.DeleteByIdIn(split); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,19 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/patrickmn/go-cache"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
"next-terminal/server/constant"
|
||||
"next-terminal/server/global"
|
||||
"next-terminal/server/log"
|
||||
"next-terminal/server/model"
|
||||
"next-terminal/server/repository"
|
||||
"next-terminal/server/service"
|
||||
"next-terminal/server/utils"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
@ -15,11 +22,32 @@ import (
|
||||
const Token = "X-Auth-Token"
|
||||
|
||||
var (
|
||||
userRepository repository.UserRepository
|
||||
userRepository *repository.UserRepository
|
||||
userGroupRepository *repository.UserGroupRepository
|
||||
resourceSharerRepository *repository.ResourceSharerRepository
|
||||
assetRepository *repository.AssetRepository
|
||||
credentialRepository *repository.CredentialRepository
|
||||
propertyRepository *repository.PropertyRepository
|
||||
commandRepository *repository.CommandRepository
|
||||
sessionRepository *repository.SessionRepository
|
||||
numRepository *repository.NumRepository
|
||||
accessSecurityRepository *repository.AccessSecurityRepository
|
||||
jobRepository *repository.JobRepository
|
||||
jobLogRepository *repository.JobLogRepository
|
||||
loginLogRepository *repository.LoginLogRepository
|
||||
|
||||
jobService *service.JobService
|
||||
propertyService *service.PropertyService
|
||||
userService *service.UserService
|
||||
sessionService *service.SessionService
|
||||
)
|
||||
|
||||
func SetupRoutes(ur repository.UserRepository) *echo.Echo {
|
||||
userRepository = ur
|
||||
func SetupRoutes(db *gorm.DB) *echo.Echo {
|
||||
|
||||
InitRepository(db)
|
||||
InitService()
|
||||
|
||||
InitDBData()
|
||||
|
||||
e := echo.New()
|
||||
e.HideBanner = true
|
||||
@ -178,69 +206,88 @@ func SetupRoutes(ur repository.UserRepository) *echo.Echo {
|
||||
return e
|
||||
}
|
||||
|
||||
type H map[string]interface{}
|
||||
func InitRepository(db *gorm.DB) {
|
||||
userRepository = repository.NewUserRepository(db)
|
||||
userGroupRepository = repository.NewUserGroupRepository(db)
|
||||
resourceSharerRepository = repository.NewResourceSharerRepository(db)
|
||||
assetRepository = repository.NewAssetRepository(db)
|
||||
credentialRepository = repository.NewCredentialRepository(db)
|
||||
propertyRepository = repository.NewPropertyRepository(db)
|
||||
commandRepository = repository.NewCommandRepository(db)
|
||||
sessionRepository = repository.NewSessionRepository(db)
|
||||
numRepository = repository.NewNumRepository(db)
|
||||
accessSecurityRepository = repository.NewAccessSecurityRepository(db)
|
||||
jobRepository = repository.NewJobRepository(db)
|
||||
jobLogRepository = repository.NewJobLogRepository(db)
|
||||
loginLogRepository = repository.NewLoginLogRepository(db)
|
||||
}
|
||||
|
||||
func Fail(c echo.Context, code int, message string) error {
|
||||
return c.JSON(200, H{
|
||||
"code": code,
|
||||
"message": message,
|
||||
func InitService() {
|
||||
jobService = service.NewJobService(jobRepository, jobLogRepository, assetRepository, credentialRepository)
|
||||
propertyService = service.NewPropertyService(propertyRepository)
|
||||
userService = service.NewUserService(userRepository)
|
||||
sessionService = service.NewSessionService(sessionRepository)
|
||||
}
|
||||
|
||||
func InitDBData() (err error) {
|
||||
if err := propertyService.InitProperties(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := userService.InitUser(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := userService.FixedOnlineState(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := jobService.InitJob(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sessionService.Fix()
|
||||
nums, _ := numRepository.FindAll()
|
||||
if nums == nil || len(nums) == 0 {
|
||||
for i := 0; i <= 30; i++ {
|
||||
if err := numRepository.Create(&model.Num{I: strconv.Itoa(i)}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ResetPassword() error {
|
||||
user, err := userRepository.FindByUsername(global.Config.ResetPassword)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
password := "next-terminal"
|
||||
passwd, err := utils.Encoder.Encode([]byte(password))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u := &model.User{
|
||||
Password: string(passwd),
|
||||
ID: user.ID,
|
||||
}
|
||||
if err := userRepository.Update(u); err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Debugf("用户「%v」密码初始化为: %v", user.Username, password)
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetupCache() *cache.Cache {
|
||||
// 配置缓存器
|
||||
mCache := cache.New(5*time.Minute, 10*time.Minute)
|
||||
mCache.OnEvicted(func(key string, value interface{}) {
|
||||
if strings.HasPrefix(key, Token) {
|
||||
token := GetTokenFormCacheKey(key)
|
||||
logrus.Debugf("用户Token「%v」过期", token)
|
||||
err := userService.Logout(token)
|
||||
if err != nil {
|
||||
logrus.Errorf("退出登录失败 %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func FailWithData(c echo.Context, code int, message string, data interface{}) error {
|
||||
return c.JSON(200, H{
|
||||
"code": code,
|
||||
"message": message,
|
||||
"data": data,
|
||||
})
|
||||
}
|
||||
|
||||
func Success(c echo.Context, data interface{}) error {
|
||||
return c.JSON(200, H{
|
||||
"code": 1,
|
||||
"message": "success",
|
||||
"data": data,
|
||||
})
|
||||
}
|
||||
|
||||
func NotFound(c echo.Context, message string) error {
|
||||
return c.JSON(200, H{
|
||||
"code": -1,
|
||||
"message": message,
|
||||
})
|
||||
}
|
||||
|
||||
func GetToken(c echo.Context) string {
|
||||
token := c.Request().Header.Get(Token)
|
||||
if len(token) > 0 {
|
||||
return token
|
||||
}
|
||||
return c.QueryParam(Token)
|
||||
}
|
||||
|
||||
func GetCurrentAccount(c echo.Context) (model.User, bool) {
|
||||
token := GetToken(c)
|
||||
cacheKey := BuildCacheKeyByToken(token)
|
||||
get, b := global.Cache.Get(cacheKey)
|
||||
if b {
|
||||
return get.(Authorization).User, true
|
||||
}
|
||||
return model.User{}, false
|
||||
}
|
||||
|
||||
func HasPermission(c echo.Context, owner string) bool {
|
||||
// 检测是否登录
|
||||
account, found := GetCurrentAccount(c)
|
||||
if !found {
|
||||
return false
|
||||
}
|
||||
// 检测是否为管理人员
|
||||
if constant.TypeAdmin == account.Type {
|
||||
return true
|
||||
}
|
||||
// 检测是否为所有者
|
||||
if owner == account.ID {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return mCache
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ func SecurityCreateEndpoint(c echo.Context) error {
|
||||
item.ID = utils.UUID()
|
||||
item.Source = "管理员添加"
|
||||
|
||||
if err := model.CreateNewSecurity(&item); err != nil {
|
||||
if err := accessSecurityRepository.Create(&item); err != nil {
|
||||
return err
|
||||
}
|
||||
// 更新内存中的安全规则
|
||||
@ -31,7 +31,7 @@ func SecurityCreateEndpoint(c echo.Context) error {
|
||||
}
|
||||
|
||||
func ReloadAccessSecurity() error {
|
||||
rules, err := model.FindAllAccessSecurities()
|
||||
rules, err := accessSecurityRepository.FindAllAccessSecurities()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -58,7 +58,7 @@ func SecurityPagingEndpoint(c echo.Context) error {
|
||||
order := c.QueryParam("order")
|
||||
field := c.QueryParam("field")
|
||||
|
||||
items, total, err := model.FindPageSecurity(pageIndex, pageSize, ip, rule, order, field)
|
||||
items, total, err := accessSecurityRepository.Find(pageIndex, pageSize, ip, rule, order, field)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -77,7 +77,7 @@ func SecurityUpdateEndpoint(c echo.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := model.UpdateSecurityById(&item, id); err != nil {
|
||||
if err := accessSecurityRepository.UpdateById(&item, id); err != nil {
|
||||
return err
|
||||
}
|
||||
// 更新内存中的安全规则
|
||||
@ -93,7 +93,7 @@ func SecurityDeleteEndpoint(c echo.Context) error {
|
||||
split := strings.Split(ids, ",")
|
||||
for i := range split {
|
||||
jobId := split[i]
|
||||
if err := model.DeleteSecurityById(jobId); err != nil {
|
||||
if err := accessSecurityRepository.DeleteById(jobId); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -107,7 +107,7 @@ func SecurityDeleteEndpoint(c echo.Context) error {
|
||||
func SecurityGetEndpoint(c echo.Context) error {
|
||||
id := c.Param("id")
|
||||
|
||||
item, err := model.FindSecurityById(id)
|
||||
item, err := accessSecurityRepository.FindById(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
62
server/api/ticker.go
Normal file
62
server/api/ticker.go
Normal file
@ -0,0 +1,62 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"next-terminal/server/constant"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func SetupTicker() {
|
||||
|
||||
// 每隔一小时删除一次未使用的会话信息
|
||||
unUsedSessionTicker := time.NewTicker(time.Minute * 60)
|
||||
go func() {
|
||||
for range unUsedSessionTicker.C {
|
||||
sessions, _ := sessionRepository.FindByStatusIn([]string{constant.NoConnect, constant.Connecting})
|
||||
if len(sessions) > 0 {
|
||||
now := time.Now()
|
||||
for i := range sessions {
|
||||
if now.Sub(sessions[i].ConnectedTime.Time) > time.Hour*1 {
|
||||
_ = sessionRepository.DeleteById(sessions[i].ID)
|
||||
s := sessions[i].Username + "@" + sessions[i].IP + ":" + strconv.Itoa(sessions[i].Port)
|
||||
logrus.Infof("会话「%v」ID「%v」超过1小时未打开,已删除。", s, sessions[i].ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// 每日凌晨删除超过时长限制的会话
|
||||
timeoutSessionTicker := time.NewTicker(time.Hour * 24)
|
||||
go func() {
|
||||
for range timeoutSessionTicker.C {
|
||||
property, err := propertyRepository.FindByName("session-saved-limit")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if property.Value == "" || property.Value == "-" {
|
||||
return
|
||||
}
|
||||
limit, err := strconv.Atoi(property.Value)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
sessions, err := sessionRepository.FindOutTimeSessions(limit)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(sessions) > 0 {
|
||||
var sessionIds []string
|
||||
for i := range sessions {
|
||||
sessionIds = append(sessionIds, sessions[i].ID)
|
||||
}
|
||||
err := sessionRepository.DeleteByIds(sessionIds)
|
||||
if err != nil {
|
||||
logrus.Errorf("删除离线会话失败 %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
Reference in New Issue
Block a user