- 修复「修改接入网关失败」的问题
- 完成「[功能请求]审计的历史会话建议添加“已阅”的功能」close #194 - 增加一键删除登录日志和历史会话的功能
This commit is contained in:
@ -78,8 +78,7 @@ func AccessGatewayUpdateEndpoint(c echo.Context) error {
|
||||
if err := accessGatewayRepository.UpdateById(&item, id); err != nil {
|
||||
return err
|
||||
}
|
||||
accessGatewayService.DisconnectById(id)
|
||||
_, _ = accessGatewayService.GetGatewayAndReconnectById(id)
|
||||
accessGatewayService.ReConnect(&item)
|
||||
return Success(c, nil)
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"next-terminal/server/constant"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -49,8 +50,6 @@ func LoginEndpoint(c echo.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
user, err := userRepository.FindByUsername(loginAccount.Username)
|
||||
|
||||
// 存储登录失败次数信息
|
||||
loginFailCountKey := c.RealIP() + loginAccount.Username
|
||||
v, ok := cache.GlobalCache.Get(loginFailCountKey)
|
||||
@ -62,6 +61,7 @@ func LoginEndpoint(c echo.Context) error {
|
||||
return Fail(c, -1, "登录失败次数过多,请等待5分钟后再试")
|
||||
}
|
||||
|
||||
user, err := userRepository.FindByUsername(loginAccount.Username)
|
||||
if err != nil {
|
||||
count++
|
||||
cache.GlobalCache.Set(loginFailCountKey, count, time.Minute*time.Duration(5))
|
||||
@ -72,6 +72,10 @@ func LoginEndpoint(c echo.Context) error {
|
||||
return FailWithData(c, -1, "您输入的账号或密码不正确", count)
|
||||
}
|
||||
|
||||
if user.Status == constant.StatusDisabled {
|
||||
return Fail(c, -1, "该账户已停用")
|
||||
}
|
||||
|
||||
if err := utils.Encoder.Match([]byte(user.Password), []byte(loginAccount.Password)); err != nil {
|
||||
count++
|
||||
cache.GlobalCache.Set(loginFailCountKey, count, time.Minute*time.Duration(5))
|
||||
@ -172,6 +176,10 @@ func loginWithTotpEndpoint(c echo.Context) error {
|
||||
return FailWithData(c, -1, "您输入的账号或密码不正确", count)
|
||||
}
|
||||
|
||||
if user.Status == constant.StatusDisabled {
|
||||
return Fail(c, -1, "该账户已停用")
|
||||
}
|
||||
|
||||
if err := utils.Encoder.Match([]byte(user.Password), []byte(loginAccount.Password)); err != nil {
|
||||
count++
|
||||
cache.GlobalCache.Set(loginFailCountKey, count, time.Minute*time.Duration(5))
|
||||
@ -206,9 +214,7 @@ func loginWithTotpEndpoint(c echo.Context) error {
|
||||
|
||||
func LogoutEndpoint(c echo.Context) error {
|
||||
token := GetToken(c)
|
||||
cacheKey := userService.BuildCacheKeyByToken(token)
|
||||
cache.GlobalCache.Delete(cacheKey)
|
||||
err := userService.Logout(token)
|
||||
err := userService.LogoutByToken(token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
102
server/api/backup.go
Normal file
102
server/api/backup.go
Normal file
@ -0,0 +1,102 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
"next-terminal/server/model"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Backup struct {
|
||||
Users []model.User `json:"users"`
|
||||
UserGroups []model.UserGroup `json:"user_groups"`
|
||||
UserGroupMembers []model.UserGroupMember `json:"user_group_members"`
|
||||
|
||||
Strategies []model.Strategy `json:"strategies"`
|
||||
Jobs []model.Job `json:"jobs"`
|
||||
AccessSecurities []model.AccessSecurity `json:"access_securities"`
|
||||
AccessGateways []model.AccessGateway `json:"access_gateways"`
|
||||
Commands []model.Command `json:"commands"`
|
||||
Credentials []model.Credential `json:"credentials"`
|
||||
Assets []model.Asset `json:"assets"`
|
||||
ResourceSharers []model.ResourceSharer `json:"resource_sharers"`
|
||||
}
|
||||
|
||||
func BackupExportEndpoint(c echo.Context) error {
|
||||
users, err := userRepository.FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range users {
|
||||
users[i].Password = ""
|
||||
}
|
||||
userGroups, err := userGroupRepository.FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userGroupMembers, err := userGroupRepository.FindAllUserGroupMembers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
strategies, err := strategyRepository.FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
jobs, err := jobRepository.FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
accessSecurities, err := accessSecurityRepository.FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
accessGateways, err := accessGatewayRepository.FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
commands, err := commandRepository.FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
credentials, err := credentialRepository.FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
assets, err := assetRepository.FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resourceSharers, err := resourceSharerRepository.FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
backup := Backup{
|
||||
Users: users,
|
||||
UserGroups: userGroups,
|
||||
UserGroupMembers: userGroupMembers,
|
||||
Strategies: strategies,
|
||||
Jobs: jobs,
|
||||
AccessSecurities: accessSecurities,
|
||||
AccessGateways: accessGateways,
|
||||
Commands: commands,
|
||||
Credentials: credentials,
|
||||
Assets: assets,
|
||||
ResourceSharers: resourceSharers,
|
||||
}
|
||||
|
||||
jsonBytes, err := json.Marshal(backup)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Response().Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=next-terminal_backup_%s.json", time.Now().Format("20060102150405")))
|
||||
return c.Stream(http.StatusOK, echo.MIMEOctetStream, bytes.NewReader(jsonBytes))
|
||||
}
|
||||
|
||||
func BackupImportEndpoint(c echo.Context) error {
|
||||
return nil
|
||||
}
|
@ -4,9 +4,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"next-terminal/server/global/cache"
|
||||
"next-terminal/server/log"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
@ -31,24 +28,26 @@ func LoginLogPagingEndpoint(c echo.Context) error {
|
||||
|
||||
func LoginLogDeleteEndpoint(c echo.Context) error {
|
||||
ids := c.Param("id")
|
||||
split := strings.Split(ids, ",")
|
||||
for i := range split {
|
||||
token := split[i]
|
||||
cache.GlobalCache.Delete(token)
|
||||
if err := userService.Logout(token); err != nil {
|
||||
log.WithError(err).Error("Cache Delete Failed")
|
||||
}
|
||||
}
|
||||
if err := loginLogRepository.DeleteByIdIn(split); err != nil {
|
||||
tokens := strings.Split(ids, ",")
|
||||
if err := userService.DeleteLoginLogs(tokens); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return Success(c, nil)
|
||||
}
|
||||
|
||||
//func LoginLogClearEndpoint(c echo.Context) error {
|
||||
// loginLogs, err := loginLogRepository.FindAliveLoginLogs()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//}
|
||||
func LoginLogClearEndpoint(c echo.Context) error {
|
||||
loginLogs, err := loginLogRepository.FindAllLoginLogs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var tokens = make([]string, 0)
|
||||
for i := range loginLogs {
|
||||
tokens = append(tokens, loginLogs[i].ID)
|
||||
}
|
||||
|
||||
if err := userService.DeleteLoginLogs(tokens); err != nil {
|
||||
return err
|
||||
}
|
||||
return Success(c, nil)
|
||||
}
|
||||
|
@ -110,6 +110,7 @@ func SetupRoutes(db *gorm.DB) *echo.Echo {
|
||||
users.POST("", UserCreateEndpoint)
|
||||
users.GET("/paging", UserPagingEndpoint)
|
||||
users.PUT("/:id", UserUpdateEndpoint)
|
||||
users.PATCH("/:id/status", UserUpdateStatusEndpoint)
|
||||
users.DELETE("/:id", UserDeleteEndpoint)
|
||||
users.GET("/:id", UserGetEndpoint)
|
||||
users.POST("/:id/change-password", UserChangePasswordEndpoint)
|
||||
@ -169,6 +170,10 @@ func SetupRoutes(db *gorm.DB) *echo.Echo {
|
||||
sessions.DELETE("/:id", Admin(SessionDeleteEndpoint))
|
||||
sessions.GET("/:id/recording", Admin(SessionRecordingEndpoint))
|
||||
sessions.GET("/:id", Admin(SessionGetEndpoint))
|
||||
sessions.POST("/:id/reviewed", Admin(SessionReviewedEndpoint))
|
||||
sessions.POST("/:id/unreviewed", Admin(SessionUnViewedEndpoint))
|
||||
sessions.POST("/clear", Admin(SessionClearEndpoint))
|
||||
sessions.POST("/reviewed", Admin(SessionReviewedAllEndpoint))
|
||||
|
||||
sessions.POST("", SessionCreateEndpoint)
|
||||
sessions.POST("/:id/connect", SessionConnectEndpoint)
|
||||
@ -195,7 +200,7 @@ func SetupRoutes(db *gorm.DB) *echo.Echo {
|
||||
{
|
||||
loginLogs.GET("/paging", LoginLogPagingEndpoint)
|
||||
loginLogs.DELETE("/:id", LoginLogDeleteEndpoint)
|
||||
//loginLogs.DELETE("/clear", LoginLogClearEndpoint)
|
||||
loginLogs.POST("/clear", LoginLogClearEndpoint)
|
||||
}
|
||||
|
||||
e.GET("/properties", Admin(PropertyGetEndpoint))
|
||||
@ -268,6 +273,12 @@ func SetupRoutes(db *gorm.DB) *echo.Echo {
|
||||
accessGateways.POST("/:id/reconnect", AccessGatewayReconnectEndpoint)
|
||||
}
|
||||
|
||||
backup := e.Group("/backup", Admin)
|
||||
{
|
||||
backup.GET("/export", BackupExportEndpoint)
|
||||
backup.POST("/import", BackupImportEndpoint)
|
||||
}
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ func SecurityCreateEndpoint(c echo.Context) error {
|
||||
}
|
||||
|
||||
func ReloadAccessSecurity() error {
|
||||
rules, err := accessSecurityRepository.FindAllAccessSecurities()
|
||||
rules, err := accessSecurityRepository.FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -35,8 +35,9 @@ func SessionPagingEndpoint(c echo.Context) error {
|
||||
clientIp := c.QueryParam("clientIp")
|
||||
assetId := c.QueryParam("assetId")
|
||||
protocol := c.QueryParam("protocol")
|
||||
reviewed := c.QueryParam("reviewed")
|
||||
|
||||
items, total, err := sessionRepository.Find(pageIndex, pageSize, status, userId, clientIp, assetId, protocol)
|
||||
items, total, err := sessionRepository.Find(pageIndex, pageSize, status, userId, clientIp, assetId, protocol, reviewed)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
@ -69,9 +70,8 @@ func SessionPagingEndpoint(c echo.Context) error {
|
||||
}
|
||||
|
||||
func SessionDeleteEndpoint(c echo.Context) error {
|
||||
sessionIds := c.Param("id")
|
||||
split := strings.Split(sessionIds, ",")
|
||||
err := sessionRepository.DeleteByIds(split)
|
||||
sessionIds := strings.Split(c.Param("id"), ",")
|
||||
err := sessionRepository.DeleteByIds(sessionIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -79,6 +79,37 @@ func SessionDeleteEndpoint(c echo.Context) error {
|
||||
return Success(c, nil)
|
||||
}
|
||||
|
||||
func SessionClearEndpoint(c echo.Context) error {
|
||||
err := sessionService.ClearOfflineSession()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return Success(c, nil)
|
||||
}
|
||||
|
||||
func SessionReviewedEndpoint(c echo.Context) error {
|
||||
sessionIds := strings.Split(c.Param("id"), ",")
|
||||
if err := sessionRepository.UpdateReadByIds(true, sessionIds); err != nil {
|
||||
return err
|
||||
}
|
||||
return Success(c, nil)
|
||||
}
|
||||
|
||||
func SessionUnViewedEndpoint(c echo.Context) error {
|
||||
sessionIds := strings.Split(c.Param("id"), ",")
|
||||
if err := sessionRepository.UpdateReadByIds(false, sessionIds); err != nil {
|
||||
return err
|
||||
}
|
||||
return Success(c, nil)
|
||||
}
|
||||
|
||||
func SessionReviewedAllEndpoint(c echo.Context) error {
|
||||
if err := sessionService.ReviewedAll(); err != nil {
|
||||
return err
|
||||
}
|
||||
return Success(c, nil)
|
||||
}
|
||||
|
||||
func SessionConnectEndpoint(c echo.Context) error {
|
||||
sessionId := c.Param("id")
|
||||
|
||||
@ -299,6 +330,7 @@ func SessionCreateEndpoint(c echo.Context) error {
|
||||
Edit: edit,
|
||||
StorageId: storageId,
|
||||
AccessGatewayId: asset.AccessGatewayId,
|
||||
Reviewed: false,
|
||||
}
|
||||
|
||||
if asset.AccountType == "credential" {
|
||||
@ -645,6 +677,7 @@ func SessionRecordingEndpoint(c echo.Context) error {
|
||||
} else {
|
||||
recording = s.Recording + "/recording"
|
||||
}
|
||||
_ = sessionRepository.UpdateReadByIds(true, []string{sessionId})
|
||||
|
||||
log.Debugf("读取录屏文件:%v,是否存在: %v, 是否为文件: %v", recording, utils.FileExists(recording), utils.IsFile(recording))
|
||||
return c.File(recording)
|
||||
|
@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"next-terminal/server/constant"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@ -29,6 +30,7 @@ func UserCreateEndpoint(c echo.Context) (err error) {
|
||||
|
||||
item.ID = utils.UUID()
|
||||
item.Created = utils.NowJsonTime()
|
||||
item.Status = constant.StatusEnabled
|
||||
|
||||
if err := userRepository.Create(&item); err != nil {
|
||||
return err
|
||||
@ -82,6 +84,21 @@ func UserUpdateEndpoint(c echo.Context) error {
|
||||
return Success(c, nil)
|
||||
}
|
||||
|
||||
func UserUpdateStatusEndpoint(c echo.Context) error {
|
||||
id := c.Param("id")
|
||||
status := c.QueryParam("status")
|
||||
account, _ := GetCurrentAccount(c)
|
||||
if account.ID == id {
|
||||
return Fail(c, -1, "不能操作自身账户")
|
||||
}
|
||||
|
||||
if err := userService.UpdateStatusById(id, status); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return Success(c, nil)
|
||||
}
|
||||
|
||||
func UserDeleteEndpoint(c echo.Context) error {
|
||||
ids := c.Param("id")
|
||||
account, found := GetCurrentAccount(c)
|
||||
@ -94,26 +111,10 @@ func UserDeleteEndpoint(c echo.Context) error {
|
||||
if account.ID == userId {
|
||||
return Fail(c, -1, "不允许删除自身账户")
|
||||
}
|
||||
user, err := userRepository.FindById(userId)
|
||||
if err != nil {
|
||||
// 下线该用户
|
||||
if err := userService.LogoutById(userId); err != nil {
|
||||
return err
|
||||
}
|
||||
// 将用户强制下线
|
||||
loginLogs, err := loginLogRepository.FindAliveLoginLogsByUsername(user.Username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for j := range loginLogs {
|
||||
token := loginLogs[j].ID
|
||||
cacheKey := userService.BuildCacheKeyByToken(token)
|
||||
cache.GlobalCache.Delete(cacheKey)
|
||||
if err := userService.Logout(token); err != nil {
|
||||
log.WithError(err).WithField("id:", token).Error("Cache Deleted Error")
|
||||
return Fail(c, 500, "强制下线错误")
|
||||
}
|
||||
}
|
||||
|
||||
// 删除用户
|
||||
if err := userRepository.DeleteById(userId); err != nil {
|
||||
return err
|
||||
|
@ -56,6 +56,9 @@ const (
|
||||
|
||||
TypeUser = "user" // 普通用户
|
||||
TypeAdmin = "admin" // 管理员
|
||||
|
||||
StatusEnabled = "enabled"
|
||||
StatusDisabled = "disabled"
|
||||
)
|
||||
|
||||
var SSHParameterNames = []string{guacd.FontName, guacd.FontSize, guacd.ColorScheme, guacd.Backspace, guacd.TerminalType, SshMode}
|
||||
|
@ -34,6 +34,7 @@ type Session struct {
|
||||
CreateDir string `gorm:"type:varchar(1)" json:"createDir"`
|
||||
StorageId string `gorm:"type:varchar(36)" json:"storageId"`
|
||||
AccessGatewayId string `gorm:"type:varchar(36)" json:"accessGatewayId"`
|
||||
Reviewed bool `gorm:"type:tinyint(1)" json:"reviewed"`
|
||||
}
|
||||
|
||||
func (r *Session) TableName() string {
|
||||
@ -61,6 +62,7 @@ type SessionForPage struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Mode string `json:"mode"`
|
||||
Reviewed bool `json:"reviewed"`
|
||||
}
|
||||
|
||||
type SessionForAccess struct {
|
||||
|
@ -11,7 +11,7 @@ type User struct {
|
||||
Nickname string `gorm:"type:varchar(500)" json:"nickname"`
|
||||
TOTPSecret string `json:"-"`
|
||||
Online bool `json:"online"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Status string `gorm:"type:varchar(10)" json:"status"`
|
||||
Created utils.JsonTime `json:"created"`
|
||||
Type string `gorm:"type:varchar(20)" json:"type"`
|
||||
Mail string `gorm:"type:varchar(500)" json:"mail"`
|
||||
@ -24,7 +24,7 @@ type UserForPage struct {
|
||||
TOTPSecret string `json:"totpSecret"`
|
||||
Mail string `json:"mail"`
|
||||
Online bool `json:"online"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Status string `json:"status"`
|
||||
Created utils.JsonTime `json:"created"`
|
||||
Type string `json:"type"`
|
||||
SharerAssetCount int64 `json:"sharerAssetCount"`
|
||||
|
@ -75,11 +75,6 @@ func (r AccessGatewayRepository) FindById(id string) (o model.AccessGateway, err
|
||||
}
|
||||
|
||||
func (r AccessGatewayRepository) FindAll() (o []model.AccessGateway, err error) {
|
||||
t := model.AccessGateway{}
|
||||
db := r.DB.Table(t.TableName())
|
||||
err = db.Find(&o).Error
|
||||
if o == nil {
|
||||
o = make([]model.AccessGateway, 0)
|
||||
}
|
||||
err = r.DB.Find(&o).Error
|
||||
return
|
||||
}
|
||||
|
@ -15,9 +15,8 @@ func NewAccessSecurityRepository(db *gorm.DB) *AccessSecurityRepository {
|
||||
return accessSecurityRepository
|
||||
}
|
||||
|
||||
func (r AccessSecurityRepository) FindAllAccessSecurities() (o []model.AccessSecurity, err error) {
|
||||
db := r.DB
|
||||
err = db.Order("priority asc").Find(&o).Error
|
||||
func (r AccessSecurityRepository) FindAll() (o []model.AccessSecurity, err error) {
|
||||
err = r.DB.Order("priority asc").Find(&o).Error
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -94,3 +94,8 @@ func (r CommandRepository) FindByUser(account model.User) (o []model.CommandForP
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r CommandRepository) FindAll() (o []model.Command, err error) {
|
||||
err = r.DB.Find(&o).Error
|
||||
return
|
||||
}
|
||||
|
@ -54,6 +54,11 @@ func (r LoginLogRepository) FindAliveLoginLogs() (o []model.LoginLog, err error)
|
||||
return
|
||||
}
|
||||
|
||||
func (r LoginLogRepository) FindAllLoginLogs() (o []model.LoginLog, err error) {
|
||||
err = r.DB.Find(&o).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (r LoginLogRepository) FindAliveLoginLogsByUsername(username string) (o []model.LoginLog, err error) {
|
||||
err = r.DB.Where("state = '1' and logout_time is null and username = ?", username).Find(&o).Error
|
||||
return
|
||||
|
@ -218,3 +218,8 @@ func (r *ResourceSharerRepository) Find(resourceId, resourceType, userId, userGr
|
||||
err = db.Find(&resourceSharers).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (r *ResourceSharerRepository) FindAll() (o []model.ResourceSharer, err error) {
|
||||
err = r.DB.Find(&o).Error
|
||||
return
|
||||
}
|
||||
|
@ -23,14 +23,14 @@ func NewSessionRepository(db *gorm.DB) *SessionRepository {
|
||||
return sessionRepository
|
||||
}
|
||||
|
||||
func (r SessionRepository) Find(pageIndex, pageSize int, status, userId, clientIp, assetId, protocol string) (results []model.SessionForPage, total int64, err error) {
|
||||
func (r SessionRepository) Find(pageIndex, pageSize int, status, userId, clientIp, assetId, protocol, reviewed string) (results []model.SessionForPage, total int64, err error) {
|
||||
|
||||
db := r.DB
|
||||
var params []interface{}
|
||||
|
||||
params = append(params, status)
|
||||
|
||||
itemSql := "SELECT s.id,s.mode, s.protocol,s.recording, s.connection_id, s.asset_id, s.creator, s.client_ip, s.width, s.height, s.ip, s.port, s.username, s.status, s.connected_time, s.disconnected_time,s.code, s.message, a.name AS asset_name, u.nickname AS creator_name FROM sessions s LEFT JOIN assets a ON s.asset_id = a.id LEFT JOIN users u ON s.creator = u.id WHERE s.STATUS = ? "
|
||||
itemSql := "SELECT s.id,s.mode, s.protocol,s.recording, s.connection_id, s.asset_id, s.creator, s.client_ip, s.width, s.height, s.ip, s.port, s.username, s.status, s.connected_time, s.disconnected_time,s.code,s.reviewed, s.message, a.name AS asset_name, u.nickname AS creator_name FROM sessions s LEFT JOIN assets a ON s.asset_id = a.id LEFT JOIN users u ON s.creator = u.id WHERE s.STATUS = ? "
|
||||
countSql := "select count(*) from sessions as s where s.status = ? "
|
||||
|
||||
if len(userId) > 0 {
|
||||
@ -57,6 +57,13 @@ func (r SessionRepository) Find(pageIndex, pageSize int, status, userId, clientI
|
||||
params = append(params, protocol)
|
||||
}
|
||||
|
||||
if reviewed != "" {
|
||||
bReviewed := reviewed == "true"
|
||||
itemSql += " and s.reviewed = ?"
|
||||
countSql += " and s.reviewed = ?"
|
||||
params = append(params, bReviewed)
|
||||
}
|
||||
|
||||
params = append(params, (pageIndex-1)*pageSize, pageSize)
|
||||
itemSql += " order by s.connected_time desc LIMIT ?, ?"
|
||||
|
||||
@ -209,3 +216,13 @@ func (r SessionRepository) OverviewAccess(account model.User) (o []model.Session
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r SessionRepository) UpdateReadByIds(reviewed bool, ids []string) error {
|
||||
sql := "update sessions set reviewed = ? where id in ?"
|
||||
return r.DB.Exec(sql, reviewed, ids).Error
|
||||
}
|
||||
|
||||
func (r SessionRepository) FindAllUnReviewed() (o []model.Session, err error) {
|
||||
err = r.DB.Where("reviewed = false or reviewed is null").Find(&o).Error
|
||||
return
|
||||
}
|
||||
|
@ -16,15 +16,13 @@ func NewUserRepository(db *gorm.DB) *UserRepository {
|
||||
return userRepository
|
||||
}
|
||||
|
||||
func (r UserRepository) FindAll() (o []model.User) {
|
||||
if r.DB.Find(&o).Error != nil {
|
||||
return nil
|
||||
}
|
||||
func (r UserRepository) FindAll() (o []model.User, err error) {
|
||||
err = r.DB.Find(&o).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (r UserRepository) Find(pageIndex, pageSize int, username, nickname, mail, order, field string, account model.User) (o []model.UserForPage, total int64, err error) {
|
||||
db := r.DB.Table("users").Select("users.id,users.username,users.nickname,users.mail,users.online,users.enabled,users.created,users.type, count(resource_sharers.user_id) as sharer_asset_count, users.totp_secret").Joins("left join resource_sharers on users.id = resource_sharers.user_id and resource_sharers.resource_type = 'asset'").Group("users.id")
|
||||
db := r.DB.Table("users").Select("users.id,users.username,users.nickname,users.mail,users.online,users.created,users.type,users.status, count(resource_sharers.user_id) as sharer_asset_count, users.totp_secret").Joins("left join resource_sharers on users.id = resource_sharers.user_id and resource_sharers.resource_type = 'asset'").Group("users.id")
|
||||
dbCounter := r.DB.Table("users")
|
||||
|
||||
if constant.TypeUser == account.Type {
|
||||
|
@ -16,10 +16,8 @@ func NewUserGroupRepository(db *gorm.DB) *UserGroupRepository {
|
||||
return userGroupRepository
|
||||
}
|
||||
|
||||
func (r UserGroupRepository) FindAll() (o []model.UserGroup) {
|
||||
if r.DB.Find(&o).Error != nil {
|
||||
return nil
|
||||
}
|
||||
func (r UserGroupRepository) FindAll() (o []model.UserGroup, err error) {
|
||||
err = r.DB.Find(&o).Error
|
||||
return
|
||||
}
|
||||
|
||||
@ -141,3 +139,8 @@ func AddUserGroupMembers(tx *gorm.DB, userIds []string, userGroupId string) erro
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r UserGroupRepository) FindAllUserGroupMembers() (o []model.UserGroupMember, err error) {
|
||||
err = r.DB.Find(&o).Error
|
||||
return
|
||||
}
|
||||
|
@ -39,9 +39,12 @@ func (r AccessGatewayService) ReConnectAll() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range gateways {
|
||||
r.ReConnect(&gateways[i])
|
||||
if len(gateways) > 0 {
|
||||
for i := range gateways {
|
||||
r.ReConnect(&gateways[i])
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -37,3 +37,41 @@ func (r SessionService) FixSessionState() error {
|
||||
func (r SessionService) EmptyPassword() error {
|
||||
return r.sessionRepository.EmptyPassword()
|
||||
}
|
||||
|
||||
func (r SessionService) ClearOfflineSession() error {
|
||||
sessions, err := r.sessionRepository.FindByStatus(constant.Disconnected)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sessionIds := make([]string, 0)
|
||||
for i := range sessions {
|
||||
sessionIds = append(sessionIds, sessions[i].ID)
|
||||
}
|
||||
return r.sessionRepository.DeleteByIds(sessionIds)
|
||||
}
|
||||
|
||||
func (r SessionService) ReviewedAll() error {
|
||||
sessions, err := r.sessionRepository.FindAllUnReviewed()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var sessionIds = make([]string, 0)
|
||||
total := len(sessions)
|
||||
for i := range sessions {
|
||||
sessionIds = append(sessionIds, sessions[i].ID)
|
||||
if i >= 100 && i%100 == 0 {
|
||||
if err := r.sessionRepository.UpdateReadByIds(true, sessionIds); err != nil {
|
||||
return err
|
||||
}
|
||||
sessionIds = nil
|
||||
} else {
|
||||
if i == total-1 {
|
||||
if err := r.sessionRepository.UpdateReadByIds(true, sessionIds); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -26,7 +26,10 @@ func NewStorageService(storageRepository *repository.StorageRepository, userRepo
|
||||
}
|
||||
|
||||
func (r StorageService) InitStorages() error {
|
||||
users := r.userRepository.FindAll()
|
||||
users, err := r.userRepository.FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range users {
|
||||
userId := users[i].ID
|
||||
_, err := r.storageRepository.FindByOwnerIdAndDefault(userId, true)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"next-terminal/server/global/cache"
|
||||
"strings"
|
||||
|
||||
"next-terminal/server/constant"
|
||||
@ -21,7 +22,10 @@ func NewUserService(userRepository *repository.UserRepository, loginLogRepositor
|
||||
|
||||
func (r UserService) InitUser() (err error) {
|
||||
|
||||
users := r.userRepository.FindAll()
|
||||
users, err := r.userRepository.FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(users) == 0 {
|
||||
initPassword := "admin"
|
||||
@ -37,6 +41,7 @@ func (r UserService) InitUser() (err error) {
|
||||
Nickname: "超级管理员",
|
||||
Type: constant.TypeAdmin,
|
||||
Created: utils.NowJsonTime(),
|
||||
Status: constant.StatusEnabled,
|
||||
}
|
||||
if err := r.userRepository.Create(&user); err != nil {
|
||||
return err
|
||||
@ -83,12 +88,14 @@ func (r UserService) FixUserOnlineState() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r UserService) Logout(token string) (err error) {
|
||||
func (r UserService) LogoutByToken(token string) (err error) {
|
||||
loginLog, err := r.loginLogRepository.FindById(token)
|
||||
if err != nil {
|
||||
log.Warnf("登录日志「%v」获取失败", token)
|
||||
return
|
||||
}
|
||||
cacheKey := r.BuildCacheKeyByToken(token)
|
||||
cache.GlobalCache.Delete(cacheKey)
|
||||
|
||||
loginLogForUpdate := &model.LoginLog{LogoutTime: utils.NowJsonTime(), ID: token}
|
||||
err = r.loginLogRepository.Update(loginLogForUpdate)
|
||||
@ -107,6 +114,26 @@ func (r UserService) Logout(token string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (r UserService) LogoutById(id string) error {
|
||||
user, err := r.userRepository.FindById(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
username := user.Username
|
||||
loginLogs, err := r.loginLogRepository.FindAliveLoginLogsByUsername(username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for j := range loginLogs {
|
||||
token := loginLogs[j].ID
|
||||
if err := r.LogoutByToken(token); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r UserService) BuildCacheKeyByToken(token string) string {
|
||||
cacheKey := strings.Join([]string{constant.Token, token}, ":")
|
||||
return cacheKey
|
||||
@ -121,9 +148,36 @@ func (r UserService) OnEvicted(key string, value interface{}) {
|
||||
if strings.HasPrefix(key, constant.Token) {
|
||||
token := r.GetTokenFormCacheKey(key)
|
||||
log.Debugf("用户Token「%v」过期", token)
|
||||
err := r.Logout(token)
|
||||
err := r.LogoutByToken(token)
|
||||
if err != nil {
|
||||
log.Errorf("退出登录失败 %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r UserService) UpdateStatusById(id string, status string) error {
|
||||
if constant.StatusDisabled == status {
|
||||
// 将该用户下线
|
||||
if err := r.LogoutById(id); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
u := model.User{
|
||||
ID: id,
|
||||
Status: status,
|
||||
}
|
||||
return r.userRepository.Update(&u)
|
||||
}
|
||||
|
||||
func (r UserService) DeleteLoginLogs(tokens []string) error {
|
||||
for i := range tokens {
|
||||
token := tokens[i]
|
||||
if err := r.LogoutByToken(token); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := r.loginLogRepository.DeleteById(token); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -49,6 +49,29 @@ func NewSshClient(ip string, port int, username, password, privateKey, passphras
|
||||
}
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", ip, port)
|
||||
//
|
||||
//socks5, err := proxy.SOCKS5("tcp", "",
|
||||
// &proxy.Auth{User: "username", Password: "password"},
|
||||
// &net.Dialer{
|
||||
// Timeout: 30 * time.Second,
|
||||
// KeepAlive: 30 * time.Second,
|
||||
// },
|
||||
//)
|
||||
//if err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
//
|
||||
//conn, err := socks5.Dial("tcp", addr)
|
||||
//if err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
//
|
||||
//clientConn, channels, requests, err := ssh.NewClientConn(conn, addr, config)
|
||||
//if err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
//
|
||||
//ssh.NewClient(clientConn, channels, requests)
|
||||
|
||||
return ssh.Dial("tcp", addr, config)
|
||||
}
|
||||
|
Reference in New Issue
Block a user