feat(api):share & fix(api):gateway;idletime

This commit is contained in:
ttk
2024-09-12 09:58:22 +08:00
parent dfd22e3314
commit de9129703a
41 changed files with 1140 additions and 1396 deletions

0
.github/config.yml vendored
View File

View File

@@ -128,6 +128,14 @@ func RunApi() error {
history.GET("", c.GetHistories) history.GET("", c.GetHistories)
history.GET("/type/mapping", c.GetHistoryTypeMapping) history.GET("/type/mapping", c.GetHistoryTypeMapping)
} }
share := v1.Group("/share")
{
share.POST("", c.CreateShare, authAdmin())
share.DELETE("/:id", c.DeleteShare, authAdmin())
share.GET("", c.GetShare, authAdmin())
}
r.GET("/api/oneterm/v1/share/connect/:uuid", Error2Resp(),c.ConnectShare)
} }
srv.Addr = fmt.Sprintf("%s:%d", conf.Cfg.Http.Host, conf.Cfg.Http.Port) srv.Addr = fmt.Sprintf("%s:%d", conf.Cfg.Http.Host, conf.Cfg.Http.Port)

View File

@@ -21,15 +21,8 @@ import (
var ( var (
assetPreHooks = []preHook[*model.Asset]{ assetPreHooks = []preHook[*model.Asset]{
func(ctx *gin.Context, data *model.Asset) { func(ctx *gin.Context, data *model.Asset) {
if data.AccessAuth == nil { data.Ip = strings.TrimSpace(data.Ip)
data.AccessAuth = &model.AccessAuth{ data.Protocols = lo.Map(data.Protocols, func(s string, _ int) string { return strings.TrimSpace(s) })
Start: nil,
End: nil,
CmdIds: make(model.Slice[int], 0),
Ranges: make(model.Slice[model.Range], 0),
Allow: true,
}
}
if data.Authorization == nil { if data.Authorization == nil {
data.Authorization = make(model.Map[int, model.Slice[int]]) data.Authorization = make(model.Map[int, model.Slice[int]])
} }
@@ -48,7 +41,7 @@ func (c *Controller) CreateAsset(ctx *gin.Context) {
asset := &model.Asset{} asset := &model.Asset{}
doCreate(ctx, true, asset, conf.RESOURCE_ASSET, assetPreHooks...) doCreate(ctx, true, asset, conf.RESOURCE_ASSET, assetPreHooks...)
schedule.CheckUpdate(asset.Id) schedule.UpdateConnectables(asset.Id)
} }
// DeleteAsset godoc // DeleteAsset godoc
@@ -70,7 +63,7 @@ func (c *Controller) DeleteAsset(ctx *gin.Context) {
// @Router /asset/:id [put] // @Router /asset/:id [put]
func (c *Controller) UpdateAsset(ctx *gin.Context) { func (c *Controller) UpdateAsset(ctx *gin.Context) {
doUpdate(ctx, true, &model.Asset{}) doUpdate(ctx, true, &model.Asset{})
schedule.CheckUpdate(cast.ToInt(ctx.Param("id"))) schedule.UpdateConnectables(cast.ToInt(ctx.Param("id")))
} }
// GetAssets godoc // GetAssets godoc

View File

@@ -3,12 +3,14 @@ package controller
import ( import (
"errors" "errors"
"net/http" "net/http"
"time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/spf13/cast" "github.com/spf13/cast"
"gorm.io/gorm" "gorm.io/gorm"
"github.com/veops/oneterm/acl" "github.com/veops/oneterm/acl"
redis "github.com/veops/oneterm/cache"
mysql "github.com/veops/oneterm/db" mysql "github.com/veops/oneterm/db"
"github.com/veops/oneterm/model" "github.com/veops/oneterm/model"
) )
@@ -45,6 +47,9 @@ func (c *Controller) PostConfig(ctx *gin.Context) {
return return
} }
model.GlobalConfig.Store(cfg)
redis.SetEx(ctx, "config", cfg, time.Hour)
ctx.JSON(http.StatusOK, defaultHttpResponse) ctx.JSON(http.StatusOK, defaultHttpResponse)
} }

View File

@@ -61,12 +61,12 @@ func read(sess *gsession.Session) error {
switch t { switch t {
case websocket.TextMessage: case websocket.TextMessage:
chs.InChan <- msg chs.InChan <- msg
if sess.IsSsh() || guacd.IsActive(msg) { if (sess.IsSsh() && len(msg) > 0 && msg[0] != '9') || guacd.IsActive(msg) {
sess.IdleTk.Reset(sess.IdleTimout) sess.SetIdle()
} }
} }
} else if sess.SessionType == model.SESSIONTYPE_CLIENT { } else if sess.SessionType == model.SESSIONTYPE_CLIENT {
sess.IdleTk.Reset(sess.IdleTimout) sess.SetIdle()
chs.InChan <- sess.CliRw.Read() chs.InChan <- sess.CliRw.Read()
} }
} }
@@ -110,8 +110,6 @@ func HandleSsh(sess *gsession.Session) (err error) {
} }
}() }()
chs := sess.Chans chs := sess.Chans
sess.IdleTimout = idleTime()
sess.IdleTk = time.NewTicker(sess.IdleTimout)
tk, tk1s, tk1m := time.NewTicker(time.Millisecond*100), time.NewTicker(time.Second), time.NewTicker(time.Minute) tk, tk1s, tk1m := time.NewTicker(time.Millisecond*100), time.NewTicker(time.Second), time.NewTicker(time.Minute)
sess.G.Go(func() error { sess.G.Go(func() error {
return read(sess) return read(sess)
@@ -127,7 +125,7 @@ func HandleSsh(sess *gsession.Session) (err error) {
return nil return nil
case <-sess.IdleTk.C: case <-sess.IdleTk.C:
writeErrMsg(sess, "idle timeout\n\n") writeErrMsg(sess, "idle timeout\n\n")
return &ApiError{Code: ErrIdleTimeout, Data: map[string]any{"second": int64(sess.IdleTimout.Seconds())}} return &ApiError{Code: ErrIdleTimeout, Data: map[string]any{"second": model.GlobalConfig.Load().Timeout}}
case <-tk1m.C: case <-tk1m.C:
if mysql.DB.Model(asset).Where("id = ?", sess.AssetId).First(asset).Error != nil { if mysql.DB.Model(asset).Where("id = ?", sess.AssetId).First(asset).Error != nil {
continue continue
@@ -142,6 +140,7 @@ func HandleSsh(sess *gsession.Session) (err error) {
logger.L().Info("closed by", zap.String("admin", closeBy)) logger.L().Info("closed by", zap.String("admin", closeBy))
return &ApiError{Code: ErrAdminClose, Data: map[string]any{"admin": closeBy}} return &ApiError{Code: ErrAdminClose, Data: map[string]any{"admin": closeBy}}
case err := <-chs.ErrChan: case err := <-chs.ErrChan:
writeErrMsg(sess, err.Error())
return err return err
case in := <-chs.InChan: case in := <-chs.InChan:
if sess.SessionType == model.SESSIONTYPE_WEB { if sess.SessionType == model.SESSIONTYPE_WEB {
@@ -195,8 +194,6 @@ func handleGuacd(sess *gsession.Session) (err error) {
} }
}() }()
chs := sess.Chans chs := sess.Chans
sess.IdleTimout = idleTime()
sess.IdleTk = time.NewTicker(sess.IdleTimout)
tk := time.NewTicker(time.Minute) tk := time.NewTicker(time.Minute)
asset := &model.Asset{} asset := &model.Asset{}
sess.G.Go(func() error { sess.G.Go(func() error {
@@ -208,7 +205,7 @@ func handleGuacd(sess *gsession.Session) (err error) {
case <-sess.Gctx.Done(): case <-sess.Gctx.Done():
return nil return nil
case <-sess.IdleTk.C: case <-sess.IdleTk.C:
return &ApiError{Code: ErrIdleTimeout, Data: map[string]any{"second": int64(sess.IdleTimout.Seconds())}} return &ApiError{Code: ErrIdleTimeout, Data: map[string]any{"second": model.GlobalConfig.Load().Timeout}}
case <-tk.C: case <-tk.C:
if mysql.DB.Model(asset).Where("id = ?", sess.AssetId).First(asset).Error != nil { if mysql.DB.Model(asset).Where("id = ?", sess.AssetId).First(asset).Error != nil {
continue continue
@@ -269,6 +266,7 @@ func DoConnect(ctx *gin.Context, ws *websocket.Conn) (sess *gsession.Session, er
GatewayInfo: lo.Ternary(asset.GatewayId == 0, "", fmt.Sprintf("%s(%s)", gateway.Name, gateway.Host)), GatewayInfo: lo.Ternary(asset.GatewayId == 0, "", fmt.Sprintf("%s(%s)", gateway.Name, gateway.Host)),
Protocol: ctx.Param("protocol"), Protocol: ctx.Param("protocol"),
Status: model.SESSIONSTATUS_ONLINE, Status: model.SESSIONSTATUS_ONLINE,
ShareId: cast.ToInt(ctx.Value("shareId")),
} }
if sess.IsSsh() { if sess.IsSsh() {
w, h := cast.ToInt(ctx.Query("w")), cast.ToInt(ctx.Query("h")) w, h := cast.ToInt(ctx.Query("w")), cast.ToInt(ctx.Query("h"))
@@ -324,7 +322,7 @@ func connectSsh(ctx *gin.Context, sess *gsession.Session, asset *model.Asset, ac
} }
}() }()
ip, port, err := util.Proxy(uuid.New().String(), "ssh", asset, gateway) ip, port, err := util.Proxy(sess.SessionId, "ssh", asset, gateway)
if err != nil { if err != nil {
return return
} }
@@ -484,8 +482,8 @@ func connectGuacd(ctx *gin.Context, sess *gsession.Session, asset *model.Asset,
// @Param w query int false "width" // @Param w query int false "width"
// @Param h query int false "height" // @Param h query int false "height"
// @Param dpi query int false "dpi" // @Param dpi query int false "dpi"
// @Success 200 {object} HttpResponse{data=gsession.Session} // @Success 200 {object} HttpResponse{}
// @Router /connect/:asset_id/:account_id/:protocol [post] // @Router /connect/:asset_id/:account_id/:protocol [get]
func (c *Controller) Connect(ctx *gin.Context) { func (c *Controller) Connect(ctx *gin.Context) {
ctx.Set("sessionType", model.SESSIONTYPE_WEB) ctx.Set("sessionType", model.SESSIONTYPE_WEB)
@@ -711,7 +709,7 @@ func offlineSession(ctx *gin.Context, sessionId string, closer string) {
}) })
} }
func checkTime(data *model.AccessAuth) bool { func checkTime(data model.AccessAuth) bool {
now := time.Now() now := time.Now()
in := true in := true
if (data.Start != nil && now.Before(*data.Start)) || (data.End != nil && now.After(*data.End)) { if (data.Start != nil && now.Before(*data.Start)) || (data.End != nil && now.After(*data.End)) {
@@ -759,13 +757,3 @@ func handleError(ctx *gin.Context, sess *gsession.Session, err error, ws *websoc
ws.WriteMessage(websocket.TextMessage, guacd.NewInstruction("error", lo.Ternary(ok, (ae).MessageBase64(ctx), err.Error()), cast.ToString(ErrAdminClose)).Bytes()) ws.WriteMessage(websocket.TextMessage, guacd.NewInstruction("error", lo.Ternary(ok, (ae).MessageBase64(ctx), err.Error()), cast.ToString(ErrAdminClose)).Bytes())
} }
} }
func idleTime() (d time.Duration) {
d = time.Hour * 2
cfg := &model.Config{}
if err := mysql.DB.Where(cfg).First(cfg).Error; err != nil {
return
}
d = time.Second * time.Duration(cfg.Timeout)
return
}

View File

@@ -106,7 +106,7 @@ func doCreate[T model.Model](ctx *gin.Context, needAcl bool, md T, resourceType
} }
if err = tx.Create(&model.History{ if err = tx.Create(&model.History{
RemoteIp: ctx.RemoteIP(), RemoteIp: ctx.ClientIP(),
Type: md.TableName(), Type: md.TableName(),
TargetId: md.GetId(), TargetId: md.GetId(),
ActionType: model.ACTION_CREATE, ActionType: model.ACTION_CREATE,
@@ -401,7 +401,7 @@ func filterSearch(ctx *gin.Context, db *gorm.DB, fields ...string) *gorm.DB {
return db return db
} }
func filterStartEnd(ctx *gin.Context, db *gorm.DB, fields ...string) (*gorm.DB, error) { func filterStartEnd(ctx *gin.Context, db *gorm.DB) (*gorm.DB, error) {
if q, ok := ctx.GetQuery("start"); ok { if q, ok := ctx.GetQuery("start"); ok {
t, err := time.Parse(time.RFC3339, q) t, err := time.Parse(time.RFC3339, q)
if err != nil { if err != nil {

View File

@@ -1,7 +1,6 @@
package controller package controller
import ( import (
"net"
"net/http" "net/http"
"strings" "strings"
@@ -22,9 +21,6 @@ var (
} else { } else {
data.Pk = strings.TrimSpace(strings.TrimSuffix(data.Pk, comment)) data.Pk = strings.TrimSpace(strings.TrimSuffix(data.Pk, comment))
} }
if _, err := net.ParseMAC(data.Mac); err != nil {
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrWrongMac, Data: nil})
}
}, },
func(ctx *gin.Context, data *model.PublicKey) { func(ctx *gin.Context, data *model.PublicKey) {
data.Pk = util.EncryptAES(data.Pk) data.Pk = util.EncryptAES(data.Pk)

View File

@@ -103,7 +103,7 @@ func (c *Controller) GetSessions(ctx *gin.Context) {
} }
db = filterEqual(ctx, db, "status", "uid", "asset_id", "client_ip") db = filterEqual(ctx, db, "status", "uid", "asset_id", "client_ip")
doGet[*model.Session](ctx, false, db, "", sessionPostHooks...) doGet(ctx, false, db, "", sessionPostHooks...)
} }
// GetSessionCmds godoc // GetSessionCmds godoc

View File

@@ -0,0 +1,121 @@
package controller
import (
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/samber/lo"
"github.com/spf13/cast"
"gorm.io/gorm"
"github.com/veops/oneterm/acl"
mysql "github.com/veops/oneterm/db"
"github.com/veops/oneterm/model"
)
// CreateShare godoc
//
// @Tags share
// @Param share body model.Share true "share"
// @Success 200 {object} HttpResponse{data=ListData{list=[]string}}
// @Router /share [post]
func (c *Controller) CreateShare(ctx *gin.Context) {
shares := make([]*model.Share, 0)
if err := ctx.ShouldBindBodyWithJSON(&shares); err != nil {
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrInvalidArgument, Data: map[string]any{"err": err}})
return
}
uuids := lo.Map(shares, func(s *model.Share, _ int) string {
s.Uuid = uuid.New().String()
return s.Uuid
})
if err := mysql.DB.Create(shares); err != nil {
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
return
}
ctx.JSON(http.StatusOK, toListData(uuids))
}
// DeleteAsset godoc
//
// @Tags share
// @Param id path int true "share id"
// @Success 200 {object} HttpResponse
// @Router /share/:id [delete]
func (c *Controller) DeleteShare(ctx *gin.Context) {
doDelete(ctx, false, &model.Share{})
}
// GetAssets godoc
//
// @Tags share
// @Param page_index query int true "page_index"
// @Param page_size query int true "page_size"
// @Param search query string false "name or ip"
// @Param start query string false "start, RFC3339"
// @Param end query string false "end, RFC3339"
// @Param asset_id query string false "asset id"
// @Param account_id query string false "account id"
// @Success 200 {object} HttpResponse{data=ListData{list=[]model.Share}}
// @Router /share [get]
func (c *Controller) GetShare(ctx *gin.Context) {
db := mysql.DB.Model(&model.Share{})
db = filterSearch(ctx, db)
db, err := filterStartEnd(ctx, db)
if err != nil {
return
}
db = filterEqual(ctx, db, "asset_id", "account_id")
doGet[*model.Share](ctx, false, db, "")
}
// Connect godoc
//
// @Tags connect
// @Success 200 {object} HttpResponse
// @Param w query int false "width"
// @Param h query int false "height"
// @Param dpi query int false "dpi"
// @Success 200 {object} HttpResponse{}
// @Router /share/connect/:uuid [get]
func (c *Controller) ConnectShare(ctx *gin.Context) {
share := &model.Share{}
if err := mysql.DB.Transaction(func(tx *gorm.DB) (err error) {
if err = tx.Where("uuid=?", ctx.Param("uuid")).First(share).Error; err != nil {
return
}
now := time.Now()
if now.Before(share.Start) || now.After(share.End) {
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrBadRequest, Data: map[string]any{"err": "share expired or not started"}})
return
}
if share.NoLimit {
return
}
db := tx.Model(share).Where("uuid=? AND times>0", share.Uuid).Update("times", gorm.Expr("times-?", 1))
if db.Error != nil {
return
}
if db.RowsAffected != 1 {
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrBadRequest, Data: map[string]any{"err": "no times left"}})
return
}
return
}); err != nil {
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrBadRequest, Data: map[string]any{"err": err}})
return
}
ctx.Params = lo.Filter(ctx.Params, func(p gin.Param, _ int) bool {
return !lo.Contains([]string{"account_id", "asset_id", "protocol"}, p.Key)
})
ctx.Params = append(ctx.Params, gin.Param{Key: "account_id", Value: cast.ToString(share.AccountId)})
ctx.Params = append(ctx.Params, gin.Param{Key: "asset_id", Value: cast.ToString(share.AssetId)})
ctx.Params = append(ctx.Params, gin.Param{Key: "protocol", Value: cast.ToString(share.Protocol)})
ctx.Set("shareId", share.Id)
ctx.Set("session", &acl.Session{})
c.Connect(ctx)
}

View File

@@ -50,6 +50,7 @@ func NewTunnel(connectionId, sessionId string, w, h, dpi int, protocol string, a
} }
ss := strings.Split(protocol, ":") ss := strings.Split(protocol, ":")
protocol, port := ss[0], ss[1] protocol, port := ss[0], ss[1]
cfg := model.GlobalConfig.Load()
t = &Tunnel{ t = &Tunnel{
conn: conn, conn: conn,
reader: bufio.NewReader(conn), reader: bufio.NewReader(conn),
@@ -73,8 +74,8 @@ func NewTunnel(connectionId, sessionId string, w, h, dpi int, protocol string, a
"port": port, "port": port,
"username": account.Account, "username": account.Account,
"password": account.Password, "password": account.Password,
"disable-copy": "false", "disable-copy": cast.ToString(lo.Ternary(strings.Contains(protocol, "rdp"), !cfg.RdpConfig.Copy, !cfg.VncConfig.Copy)),
"disable-paste": "false", "disable-paste": cast.ToString(lo.Ternary(strings.Contains(protocol, "rdp"), !cfg.RdpConfig.Paste, !cfg.VncConfig.Paste)),
} }
}, func() map[string]string { }, func() map[string]string {
return map[string]string{ return map[string]string{

View File

@@ -81,6 +81,16 @@ func auth() gin.HandlerFunc {
} }
} }
func authAdmin() gin.HandlerFunc {
return func(ctx *gin.Context) {
currentUser, _ := acl.GetSessionFromCtx(ctx)
if !acl.IsAdmin(currentUser) {
ctx.AbortWithStatus(http.StatusUnauthorized)
return
}
}
}
type bodyWriter struct { type bodyWriter struct {
gin.ResponseWriter gin.ResponseWriter
body *bytes.Buffer body *bytes.Buffer

View File

@@ -31,9 +31,6 @@ var (
Path: "app.log", Path: "app.log",
ConsoleEnable: true, ConsoleEnable: true,
}, },
Auth: Auth{
Custom: map[string]string{},
},
} }
) )
@@ -86,6 +83,11 @@ type AclConfig struct {
ResourceNames []*KV `yaml:"resourceNames"` ResourceNames []*KV `yaml:"resourceNames"`
} }
type AesConfig struct {
Key []byte `yaml:"key"`
Iv []byte `yaml:"iv"`
}
type LogConfig struct { type LogConfig struct {
Level string `yaml:"level"` Level string `yaml:"level"`
Path string `yaml:"path"` Path string `yaml:"path"`
@@ -104,8 +106,8 @@ type LogConfig struct {
} }
type Auth struct { type Auth struct {
Acl *AclConfig `yaml:"acl"` Acl AclConfig `yaml:"acl"`
Custom map[string]string `yaml:"custom"` Aes AesConfig `yaml:"aes"`
} }
type SshConfig struct { type SshConfig struct {

View File

@@ -9,6 +9,7 @@ import (
"github.com/veops/oneterm/conf" "github.com/veops/oneterm/conf"
"github.com/veops/oneterm/logger" "github.com/veops/oneterm/logger"
"github.com/veops/oneterm/model"
) )
var ( var (
@@ -19,7 +20,19 @@ func init() {
var err error var err error
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/oneterm?charset=utf8mb4&parseTime=True&loc=Local", dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/oneterm?charset=utf8mb4&parseTime=True&loc=Local",
conf.Cfg.Mysql.User, conf.Cfg.Mysql.Password, conf.Cfg.Mysql.Host, conf.Cfg.Mysql.Port) conf.Cfg.Mysql.User, conf.Cfg.Mysql.Password, conf.Cfg.Mysql.Host, conf.Cfg.Mysql.Port)
if DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}); err != nil { DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
DisableForeignKeyConstraintWhenMigrating: true,
})
if err != nil {
logger.L().Fatal("init mysql failed", zap.Error(err)) logger.L().Fatal("init mysql failed", zap.Error(err))
} }
err = DB.AutoMigrate(
&model.Account{}, &model.Asset{}, &model.Authorization{}, &model.Command{},
&model.Config{}, &model.FileHistory{}, &model.Gateway{}, &model.History{},
&model.Node{}, &model.PublicKey{}, &model.Session{}, &model.Share{},
)
if err != nil {
logger.L().Fatal("auto migrate mysql failed", zap.Error(err))
}
} }

View File

@@ -1,4 +1,4 @@
// Package docs Code generated by swaggo/swag. DO NOT EDIT // Package docs Code generated by swaggo/swag at 2024-09-11 13:36:52.1950431 +0800 CST m=+7.950178801. DO NOT EDIT
package docs package docs
import "github.com/swaggo/swag" import "github.com/swaggo/swag"
@@ -367,101 +367,6 @@ const docTemplate = `{
} }
} }
}, },
"/asset/query_by_server": {
"get": {
"tags": [
"asset"
],
"parameters": [
{
"type": "integer",
"description": "page index",
"name": "page_index",
"in": "query",
"required": true
},
{
"type": "integer",
"description": "page size",
"name": "page_size",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/controller.HttpResponse"
},
{
"type": "object",
"properties": {
"data": {
"allOf": [
{
"$ref": "#/definitions/controller.ListData"
},
{
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/definitions/model.Asset"
}
}
}
}
]
}
}
}
]
}
}
}
}
},
"/asset/update_by_server": {
"put": {
"tags": [
"asset"
],
"parameters": [
{
"type": "integer",
"description": "asset id",
"name": "id",
"in": "path",
"required": true
},
{
"description": "asset update request",
"name": "req",
"in": "body",
"required": true,
"schema": {
"type": "object",
"additionalProperties": {
"type": "object",
"additionalProperties": true
}
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controller.HttpResponse"
}
}
}
}
},
"/command": { "/command": {
"get": { "get": {
"tags": [ "tags": [
@@ -701,53 +606,6 @@ const docTemplate = `{
} }
}, },
"/connect/:asset_id/:account_id/:protocol": { "/connect/:asset_id/:account_id/:protocol": {
"post": {
"tags": [
"connect"
],
"parameters": [
{
"type": "integer",
"description": "width",
"name": "w",
"in": "query"
},
{
"type": "integer",
"description": "height",
"name": "h",
"in": "query"
},
{
"type": "integer",
"description": "dpi",
"name": "dpi",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/controller.HttpResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/session.Session"
}
}
}
]
}
}
}
}
},
"/connect/:session_id": {
"get": { "get": {
"tags": [ "tags": [
"connect" "connect"
@@ -770,13 +628,6 @@ const docTemplate = `{
"description": "dpi", "description": "dpi",
"name": "dpi", "name": "dpi",
"in": "query" "in": "query"
},
{
"type": "integer",
"description": "session id",
"name": "session_id",
"in": "path",
"required": true
} }
], ],
"responses": { "responses": {
@@ -1730,31 +1581,6 @@ const docTemplate = `{
} }
} }
}, },
"/public_key/auth": {
"post": {
"tags": [
"public_key"
],
"parameters": [
{
"description": "method 1password 2publickey",
"name": "req",
"in": "body",
"schema": {
"$ref": "#/definitions/model.ReqAuth"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controller.HttpResponse"
}
}
}
}
},
"/session": { "/session": {
"get": { "get": {
"tags": [ "tags": [
@@ -1853,30 +1679,6 @@ const docTemplate = `{
} }
} }
} }
},
"post": {
"tags": [
"session"
],
"parameters": [
{
"description": "session",
"name": "sessino",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/model.Session"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controller.HttpResponse"
}
}
}
} }
}, },
"/session/:session_id/cmd": { "/session/:session_id/cmd": {
@@ -2095,6 +1897,204 @@ const docTemplate = `{
} }
} }
}, },
"/share": {
"get": {
"tags": [
"share"
],
"parameters": [
{
"type": "integer",
"description": "page_index",
"name": "page_index",
"in": "query",
"required": true
},
{
"type": "integer",
"description": "page_size",
"name": "page_size",
"in": "query",
"required": true
},
{
"type": "string",
"description": "name or ip",
"name": "search",
"in": "query"
},
{
"type": "string",
"description": "start, RFC3339",
"name": "start",
"in": "query"
},
{
"type": "string",
"description": "end, RFC3339",
"name": "end",
"in": "query"
},
{
"type": "string",
"description": "asset id",
"name": "asset_id",
"in": "query"
},
{
"type": "string",
"description": "account id",
"name": "account_id",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/controller.HttpResponse"
},
{
"type": "object",
"properties": {
"data": {
"allOf": [
{
"$ref": "#/definitions/controller.ListData"
},
{
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/definitions/model.Share"
}
}
}
}
]
}
}
}
]
}
}
}
},
"post": {
"tags": [
"share"
],
"parameters": [
{
"description": "share",
"name": "share",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/model.Share"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/controller.HttpResponse"
},
{
"type": "object",
"properties": {
"data": {
"allOf": [
{
"$ref": "#/definitions/controller.ListData"
},
{
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
]
}
}
}
]
}
}
}
}
},
"/share/:id": {
"delete": {
"tags": [
"share"
],
"parameters": [
{
"type": "integer",
"description": "share id",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controller.HttpResponse"
}
}
}
}
},
"/share/connect/:uuid": {
"get": {
"tags": [
"connect"
],
"parameters": [
{
"type": "integer",
"description": "width",
"name": "w",
"in": "query"
},
{
"type": "integer",
"description": "height",
"name": "h",
"in": "query"
},
{
"type": "integer",
"description": "dpi",
"name": "dpi",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controller.HttpResponse"
}
}
}
}
},
"/stat/account": { "/stat/account": {
"get": { "get": {
"tags": [ "tags": [
@@ -2450,9 +2450,6 @@ const docTemplate = `{
"authorization": { "authorization": {
"$ref": "#/definitions/model.Map-int-model_Slice-int" "$ref": "#/definitions/model.Map-int-model_Slice-int"
}, },
"ci_id": {
"type": "integer"
},
"comment": { "comment": {
"type": "string" "type": "string"
}, },
@@ -2547,6 +2544,12 @@ const docTemplate = `{
"id": { "id": {
"type": "integer" "type": "integer"
}, },
"rdp_config": {
"$ref": "#/definitions/model.RdpConfig"
},
"ssh_config": {
"$ref": "#/definitions/model.SshConfig"
},
"timeout": { "timeout": {
"type": "integer" "type": "integer"
}, },
@@ -2555,6 +2558,9 @@ const docTemplate = `{
}, },
"updater_id": { "updater_id": {
"type": "integer" "type": "integer"
},
"vnc_config": {
"$ref": "#/definitions/model.VncConfig"
} }
} }
}, },
@@ -2653,12 +2659,6 @@ const docTemplate = `{
"type": "object", "type": "object",
"additionalProperties": {} "additionalProperties": {}
}, },
"model.Map-string-string": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"model.Node": { "model.Node": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -2702,9 +2702,6 @@ const docTemplate = `{
"type": "string" "type": "string"
} }
}, },
"sync": {
"$ref": "#/definitions/model.Sync"
},
"updated_at": { "updated_at": {
"type": "string" "type": "string"
}, },
@@ -2726,9 +2723,6 @@ const docTemplate = `{
"id": { "id": {
"type": "integer" "type": "integer"
}, },
"mac": {
"type": "string"
},
"name": { "name": {
"type": "string" "type": "string"
}, },
@@ -2763,20 +2757,14 @@ const docTemplate = `{
} }
} }
}, },
"model.ReqAuth": { "model.RdpConfig": {
"type": "object", "type": "object",
"properties": { "properties": {
"method": { "copy": {
"type": "integer" "type": "boolean"
}, },
"password": { "paste": {
"type": "string" "type": "boolean"
},
"pk": {
"type": "string"
},
"username": {
"type": "string"
} }
} }
}, },
@@ -2828,6 +2816,9 @@ const docTemplate = `{
"session_type": { "session_type": {
"type": "integer" "type": "integer"
}, },
"share_id": {
"type": "integer"
},
"status": { "status": {
"type": "integer" "type": "integer"
}, },
@@ -2876,6 +2867,61 @@ const docTemplate = `{
} }
} }
}, },
"model.Share": {
"type": "object",
"properties": {
"account_id": {
"type": "integer"
},
"asset_id": {
"type": "integer"
},
"created_at": {
"type": "string"
},
"creator_id": {
"type": "integer"
},
"end": {
"type": "string"
},
"id": {
"type": "integer"
},
"no_limit": {
"type": "boolean"
},
"protocol": {
"type": "string"
},
"start": {
"type": "string"
},
"times": {
"type": "integer"
},
"updated_at": {
"type": "string"
},
"updater_id": {
"type": "integer"
},
"uuid": {
"type": "string"
}
}
},
"model.SshConfig": {
"type": "object",
"properties": {
"copy": {
"type": "boolean"
},
"paste": {
"type": "boolean"
}
}
},
"model.StatAccount": { "model.StatAccount": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -2965,85 +3011,14 @@ const docTemplate = `{
} }
} }
}, },
"model.Sync": { "model.VncConfig": {
"type": "object", "type": "object",
"properties": { "properties": {
"enable": { "copy": {
"type": "boolean" "type": "boolean"
}, },
"filters": { "paste": {
"type": "string" "type": "boolean"
},
"frequency": {
"type": "number"
},
"mapping": {
"$ref": "#/definitions/model.Map-string-string"
},
"type_id": {
"type": "integer"
}
}
},
"session.Session": {
"type": "object",
"properties": {
"account_id": {
"type": "integer"
},
"account_info": {
"type": "string"
},
"asset_id": {
"type": "integer"
},
"asset_info": {
"type": "string"
},
"client_ip": {
"type": "string"
},
"closed_at": {
"type": "string"
},
"cmd_count": {
"type": "integer"
},
"created_at": {
"type": "string"
},
"duration": {
"type": "integer"
},
"gateway_id": {
"type": "integer"
},
"gateway_info": {
"type": "string"
},
"id": {
"type": "integer"
},
"protocol": {
"type": "string"
},
"session_id": {
"type": "string"
},
"session_type": {
"type": "integer"
},
"status": {
"type": "integer"
},
"uid": {
"type": "integer"
},
"updated_at": {
"type": "string"
},
"user_name": {
"type": "string"
} }
} }
} }

View File

@@ -1,13 +0,0 @@
#!/bin/sh
KEY_PATH="$HOME/.ssh/id_ed25519"
if [ -f "$KEY_PATH" ]; then
echo "SSH key already exists at $KEY_PATH. Skipping key generation."
else
echo "SSH key does not exist. Generating new key."
mkdir -p ~/.ssh
ssh-keygen -t ed25519 -f "$KEY_PATH" -N ''
fi
./ssh ssh -c config.yaml

View File

@@ -356,101 +356,6 @@
} }
} }
}, },
"/asset/query_by_server": {
"get": {
"tags": [
"asset"
],
"parameters": [
{
"type": "integer",
"description": "page index",
"name": "page_index",
"in": "query",
"required": true
},
{
"type": "integer",
"description": "page size",
"name": "page_size",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/controller.HttpResponse"
},
{
"type": "object",
"properties": {
"data": {
"allOf": [
{
"$ref": "#/definitions/controller.ListData"
},
{
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/definitions/model.Asset"
}
}
}
}
]
}
}
}
]
}
}
}
}
},
"/asset/update_by_server": {
"put": {
"tags": [
"asset"
],
"parameters": [
{
"type": "integer",
"description": "asset id",
"name": "id",
"in": "path",
"required": true
},
{
"description": "asset update request",
"name": "req",
"in": "body",
"required": true,
"schema": {
"type": "object",
"additionalProperties": {
"type": "object",
"additionalProperties": true
}
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controller.HttpResponse"
}
}
}
}
},
"/command": { "/command": {
"get": { "get": {
"tags": [ "tags": [
@@ -690,53 +595,6 @@
} }
}, },
"/connect/:asset_id/:account_id/:protocol": { "/connect/:asset_id/:account_id/:protocol": {
"post": {
"tags": [
"connect"
],
"parameters": [
{
"type": "integer",
"description": "width",
"name": "w",
"in": "query"
},
{
"type": "integer",
"description": "height",
"name": "h",
"in": "query"
},
{
"type": "integer",
"description": "dpi",
"name": "dpi",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/controller.HttpResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/session.Session"
}
}
}
]
}
}
}
}
},
"/connect/:session_id": {
"get": { "get": {
"tags": [ "tags": [
"connect" "connect"
@@ -759,13 +617,6 @@
"description": "dpi", "description": "dpi",
"name": "dpi", "name": "dpi",
"in": "query" "in": "query"
},
{
"type": "integer",
"description": "session id",
"name": "session_id",
"in": "path",
"required": true
} }
], ],
"responses": { "responses": {
@@ -1719,31 +1570,6 @@
} }
} }
}, },
"/public_key/auth": {
"post": {
"tags": [
"public_key"
],
"parameters": [
{
"description": "method 1password 2publickey",
"name": "req",
"in": "body",
"schema": {
"$ref": "#/definitions/model.ReqAuth"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controller.HttpResponse"
}
}
}
}
},
"/session": { "/session": {
"get": { "get": {
"tags": [ "tags": [
@@ -1842,30 +1668,6 @@
} }
} }
} }
},
"post": {
"tags": [
"session"
],
"parameters": [
{
"description": "session",
"name": "sessino",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/model.Session"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controller.HttpResponse"
}
}
}
} }
}, },
"/session/:session_id/cmd": { "/session/:session_id/cmd": {
@@ -2084,6 +1886,204 @@
} }
} }
}, },
"/share": {
"get": {
"tags": [
"share"
],
"parameters": [
{
"type": "integer",
"description": "page_index",
"name": "page_index",
"in": "query",
"required": true
},
{
"type": "integer",
"description": "page_size",
"name": "page_size",
"in": "query",
"required": true
},
{
"type": "string",
"description": "name or ip",
"name": "search",
"in": "query"
},
{
"type": "string",
"description": "start, RFC3339",
"name": "start",
"in": "query"
},
{
"type": "string",
"description": "end, RFC3339",
"name": "end",
"in": "query"
},
{
"type": "string",
"description": "asset id",
"name": "asset_id",
"in": "query"
},
{
"type": "string",
"description": "account id",
"name": "account_id",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/controller.HttpResponse"
},
{
"type": "object",
"properties": {
"data": {
"allOf": [
{
"$ref": "#/definitions/controller.ListData"
},
{
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/definitions/model.Share"
}
}
}
}
]
}
}
}
]
}
}
}
},
"post": {
"tags": [
"share"
],
"parameters": [
{
"description": "share",
"name": "share",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/model.Share"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/controller.HttpResponse"
},
{
"type": "object",
"properties": {
"data": {
"allOf": [
{
"$ref": "#/definitions/controller.ListData"
},
{
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
]
}
}
}
]
}
}
}
}
},
"/share/:id": {
"delete": {
"tags": [
"share"
],
"parameters": [
{
"type": "integer",
"description": "share id",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controller.HttpResponse"
}
}
}
}
},
"/share/connect/:uuid": {
"get": {
"tags": [
"connect"
],
"parameters": [
{
"type": "integer",
"description": "width",
"name": "w",
"in": "query"
},
{
"type": "integer",
"description": "height",
"name": "h",
"in": "query"
},
{
"type": "integer",
"description": "dpi",
"name": "dpi",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controller.HttpResponse"
}
}
}
}
},
"/stat/account": { "/stat/account": {
"get": { "get": {
"tags": [ "tags": [
@@ -2439,9 +2439,6 @@
"authorization": { "authorization": {
"$ref": "#/definitions/model.Map-int-model_Slice-int" "$ref": "#/definitions/model.Map-int-model_Slice-int"
}, },
"ci_id": {
"type": "integer"
},
"comment": { "comment": {
"type": "string" "type": "string"
}, },
@@ -2536,6 +2533,12 @@
"id": { "id": {
"type": "integer" "type": "integer"
}, },
"rdp_config": {
"$ref": "#/definitions/model.RdpConfig"
},
"ssh_config": {
"$ref": "#/definitions/model.SshConfig"
},
"timeout": { "timeout": {
"type": "integer" "type": "integer"
}, },
@@ -2544,6 +2547,9 @@
}, },
"updater_id": { "updater_id": {
"type": "integer" "type": "integer"
},
"vnc_config": {
"$ref": "#/definitions/model.VncConfig"
} }
} }
}, },
@@ -2642,12 +2648,6 @@
"type": "object", "type": "object",
"additionalProperties": {} "additionalProperties": {}
}, },
"model.Map-string-string": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"model.Node": { "model.Node": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -2691,9 +2691,6 @@
"type": "string" "type": "string"
} }
}, },
"sync": {
"$ref": "#/definitions/model.Sync"
},
"updated_at": { "updated_at": {
"type": "string" "type": "string"
}, },
@@ -2715,9 +2712,6 @@
"id": { "id": {
"type": "integer" "type": "integer"
}, },
"mac": {
"type": "string"
},
"name": { "name": {
"type": "string" "type": "string"
}, },
@@ -2752,20 +2746,14 @@
} }
} }
}, },
"model.ReqAuth": { "model.RdpConfig": {
"type": "object", "type": "object",
"properties": { "properties": {
"method": { "copy": {
"type": "integer" "type": "boolean"
}, },
"password": { "paste": {
"type": "string" "type": "boolean"
},
"pk": {
"type": "string"
},
"username": {
"type": "string"
} }
} }
}, },
@@ -2817,6 +2805,9 @@
"session_type": { "session_type": {
"type": "integer" "type": "integer"
}, },
"share_id": {
"type": "integer"
},
"status": { "status": {
"type": "integer" "type": "integer"
}, },
@@ -2865,6 +2856,61 @@
} }
} }
}, },
"model.Share": {
"type": "object",
"properties": {
"account_id": {
"type": "integer"
},
"asset_id": {
"type": "integer"
},
"created_at": {
"type": "string"
},
"creator_id": {
"type": "integer"
},
"end": {
"type": "string"
},
"id": {
"type": "integer"
},
"no_limit": {
"type": "boolean"
},
"protocol": {
"type": "string"
},
"start": {
"type": "string"
},
"times": {
"type": "integer"
},
"updated_at": {
"type": "string"
},
"updater_id": {
"type": "integer"
},
"uuid": {
"type": "string"
}
}
},
"model.SshConfig": {
"type": "object",
"properties": {
"copy": {
"type": "boolean"
},
"paste": {
"type": "boolean"
}
}
},
"model.StatAccount": { "model.StatAccount": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -2954,85 +3000,14 @@
} }
} }
}, },
"model.Sync": { "model.VncConfig": {
"type": "object", "type": "object",
"properties": { "properties": {
"enable": { "copy": {
"type": "boolean" "type": "boolean"
}, },
"filters": { "paste": {
"type": "string" "type": "boolean"
},
"frequency": {
"type": "number"
},
"mapping": {
"$ref": "#/definitions/model.Map-string-string"
},
"type_id": {
"type": "integer"
}
}
},
"session.Session": {
"type": "object",
"properties": {
"account_id": {
"type": "integer"
},
"account_info": {
"type": "string"
},
"asset_id": {
"type": "integer"
},
"asset_info": {
"type": "string"
},
"client_ip": {
"type": "string"
},
"closed_at": {
"type": "string"
},
"cmd_count": {
"type": "integer"
},
"created_at": {
"type": "string"
},
"duration": {
"type": "integer"
},
"gateway_id": {
"type": "integer"
},
"gateway_info": {
"type": "string"
},
"id": {
"type": "integer"
},
"protocol": {
"type": "string"
},
"session_id": {
"type": "string"
},
"session_type": {
"type": "integer"
},
"status": {
"type": "integer"
},
"uid": {
"type": "integer"
},
"updated_at": {
"type": "string"
},
"user_name": {
"type": "string"
} }
} }
} }

View File

@@ -67,8 +67,6 @@ definitions:
$ref: '#/definitions/model.AccessAuth' $ref: '#/definitions/model.AccessAuth'
authorization: authorization:
$ref: '#/definitions/model.Map-int-model_Slice-int' $ref: '#/definitions/model.Map-int-model_Slice-int'
ci_id:
type: integer
comment: comment:
type: string type: string
connectable: connectable:
@@ -131,12 +129,18 @@ definitions:
type: integer type: integer
id: id:
type: integer type: integer
rdp_config:
$ref: '#/definitions/model.RdpConfig'
ssh_config:
$ref: '#/definitions/model.SshConfig'
timeout: timeout:
type: integer type: integer
updated_at: updated_at:
type: string type: string
updater_id: updater_id:
type: integer type: integer
vnc_config:
$ref: '#/definitions/model.VncConfig'
type: object type: object
model.Gateway: model.Gateway:
properties: properties:
@@ -201,10 +205,6 @@ definitions:
model.Map-string-any: model.Map-string-any:
additionalProperties: {} additionalProperties: {}
type: object type: object
model.Map-string-string:
additionalProperties:
type: string
type: object
model.Node: model.Node:
properties: properties:
access_auth: access_auth:
@@ -234,8 +234,6 @@ definitions:
items: items:
type: string type: string
type: array type: array
sync:
$ref: '#/definitions/model.Sync'
updated_at: updated_at:
type: string type: string
updater_id: updater_id:
@@ -250,8 +248,6 @@ definitions:
type: integer type: integer
id: id:
type: integer type: integer
mac:
type: string
name: name:
type: string type: string
pk: pk:
@@ -274,16 +270,12 @@ definitions:
week: week:
type: integer type: integer
type: object type: object
model.ReqAuth: model.RdpConfig:
properties: properties:
method: copy:
type: integer type: boolean
password: paste:
type: string type: boolean
pk:
type: string
username:
type: string
type: object type: object
model.Session: model.Session:
properties: properties:
@@ -317,6 +309,8 @@ definitions:
type: string type: string
session_type: session_type:
type: integer type: integer
share_id:
type: integer
status: status:
type: integer type: integer
uid: uid:
@@ -348,6 +342,42 @@ definitions:
name: name:
type: string type: string
type: object type: object
model.Share:
properties:
account_id:
type: integer
asset_id:
type: integer
created_at:
type: string
creator_id:
type: integer
end:
type: string
id:
type: integer
no_limit:
type: boolean
protocol:
type: string
start:
type: string
times:
type: integer
updated_at:
type: string
updater_id:
type: integer
uuid:
type: string
type: object
model.SshConfig:
properties:
copy:
type: boolean
paste:
type: boolean
type: object
model.StatAccount: model.StatAccount:
properties: properties:
count: count:
@@ -406,59 +436,12 @@ definitions:
total_asset: total_asset:
type: integer type: integer
type: object type: object
model.Sync: model.VncConfig:
properties: properties:
enable: copy:
type: boolean
paste:
type: boolean type: boolean
filters:
type: string
frequency:
type: number
mapping:
$ref: '#/definitions/model.Map-string-string'
type_id:
type: integer
type: object
session.Session:
properties:
account_id:
type: integer
account_info:
type: string
asset_id:
type: integer
asset_info:
type: string
client_ip:
type: string
closed_at:
type: string
cmd_count:
type: integer
created_at:
type: string
duration:
type: integer
gateway_id:
type: integer
gateway_info:
type: string
id:
type: integer
protocol:
type: string
session_id:
type: string
session_type:
type: integer
status:
type: integer
uid:
type: integer
updated_at:
type: string
user_name:
type: string
type: object type: object
info: info:
contact: {} contact: {}
@@ -679,62 +662,6 @@ paths:
$ref: '#/definitions/controller.HttpResponse' $ref: '#/definitions/controller.HttpResponse'
tags: tags:
- asset - asset
/asset/query_by_server:
get:
parameters:
- description: page index
in: query
name: page_index
required: true
type: integer
- description: page size
in: query
name: page_size
required: true
type: integer
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/controller.HttpResponse'
- properties:
data:
allOf:
- $ref: '#/definitions/controller.ListData'
- properties:
list:
items:
$ref: '#/definitions/model.Asset'
type: array
type: object
type: object
tags:
- asset
/asset/update_by_server:
put:
parameters:
- description: asset id
in: path
name: id
required: true
type: integer
- description: asset update request
in: body
name: req
required: true
schema:
additionalProperties:
additionalProperties: true
type: object
type: object
responses:
"200":
description: OK
schema:
$ref: '#/definitions/controller.HttpResponse'
tags:
- asset
/command: /command:
get: get:
parameters: parameters:
@@ -880,33 +807,6 @@ paths:
tags: tags:
- config - config
/connect/:asset_id/:account_id/:protocol: /connect/:asset_id/:account_id/:protocol:
post:
parameters:
- description: width
in: query
name: w
type: integer
- description: height
in: query
name: h
type: integer
- description: dpi
in: query
name: dpi
type: integer
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/controller.HttpResponse'
- properties:
data:
$ref: '#/definitions/session.Session'
type: object
tags:
- connect
/connect/:session_id:
get: get:
parameters: parameters:
- description: width - description: width
@@ -921,11 +821,6 @@ paths:
in: query in: query
name: dpi name: dpi
type: integer type: integer
- description: session id
in: path
name: session_id
required: true
type: integer
responses: responses:
"200": "200":
description: OK description: OK
@@ -1514,21 +1409,6 @@ paths:
$ref: '#/definitions/controller.HttpResponse' $ref: '#/definitions/controller.HttpResponse'
tags: tags:
- public_key - public_key
/public_key/auth:
post:
parameters:
- description: method 1password 2publickey
in: body
name: req
schema:
$ref: '#/definitions/model.ReqAuth'
responses:
"200":
description: OK
schema:
$ref: '#/definitions/controller.HttpResponse'
tags:
- public_key
/session: /session:
get: get:
parameters: parameters:
@@ -1589,21 +1469,6 @@ paths:
type: object type: object
tags: tags:
- session - session
post:
parameters:
- description: session
in: body
name: sessino
required: true
schema:
$ref: '#/definitions/model.Session'
responses:
"200":
description: OK
schema:
$ref: '#/definitions/controller.HttpResponse'
tags:
- session
/session/:session_id/cmd: /session/:session_id/cmd:
get: get:
parameters: parameters:
@@ -1728,6 +1593,122 @@ paths:
$ref: '#/definitions/controller.HttpResponse' $ref: '#/definitions/controller.HttpResponse'
tags: tags:
- session - session
/share:
get:
parameters:
- description: page_index
in: query
name: page_index
required: true
type: integer
- description: page_size
in: query
name: page_size
required: true
type: integer
- description: name or ip
in: query
name: search
type: string
- description: start, RFC3339
in: query
name: start
type: string
- description: end, RFC3339
in: query
name: end
type: string
- description: asset id
in: query
name: asset_id
type: string
- description: account id
in: query
name: account_id
type: string
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/controller.HttpResponse'
- properties:
data:
allOf:
- $ref: '#/definitions/controller.ListData'
- properties:
list:
items:
$ref: '#/definitions/model.Share'
type: array
type: object
type: object
tags:
- share
post:
parameters:
- description: share
in: body
name: share
required: true
schema:
$ref: '#/definitions/model.Share'
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/controller.HttpResponse'
- properties:
data:
allOf:
- $ref: '#/definitions/controller.ListData'
- properties:
list:
items:
type: string
type: array
type: object
type: object
tags:
- share
/share/:id:
delete:
parameters:
- description: share id
in: path
name: id
required: true
type: integer
responses:
"200":
description: OK
schema:
$ref: '#/definitions/controller.HttpResponse'
tags:
- share
/share/connect/:uuid:
get:
parameters:
- description: width
in: query
name: w
type: integer
- description: height
in: query
name: h
type: integer
- description: dpi
in: query
name: dpi
type: integer
responses:
"200":
description: OK
schema:
$ref: '#/definitions/controller.HttpResponse'
tags:
- connect
/stat/account: /stat/account:
get: get:
parameters: parameters:

View File

@@ -97,6 +97,10 @@ func (gm *GateWayManager) Open(sessionId, remoteIp string, remotePort int, gatew
if err != nil { if err != nil {
return return
} }
go func() {
logger.L().Debug("ssh client closed", zap.Int("gatewayId", gateway.Id), zap.Error(sshCli.Wait()))
delete(gm.sshClients, gateway.Id)
}()
} }
gm.sshClients[gateway.Id] = sshCli gm.sshClients[gateway.Id] = sshCli
gm.sshClientsCount[gateway.Id] += 1 gm.sshClientsCount[gateway.Id] += 1

View File

@@ -40,9 +40,9 @@ func main() {
} }
{ {
rg.Add(func() error { rg.Add(func() error {
return schedule.RunConnectable() return schedule.RunSchedule()
}, func(err error) { }, func(err error) {
schedule.StopConnectable() schedule.StopSchedule()
}) })
} }

View File

@@ -7,8 +7,8 @@ import (
) )
type Account struct { type Account struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
Name string `json:"name" gorm:"column:name"` Name string `json:"name" gorm:"column:name;uniqueIndex:name_del;size:128"`
AccountType int `json:"account_type" gorm:"column:account_type"` AccountType int `json:"account_type" gorm:"column:account_type"`
Account string `json:"account" gorm:"column:account"` Account string `json:"account" gorm:"column:account"`
Password string `json:"password" gorm:"column:password"` Password string `json:"password" gorm:"column:password"`
@@ -20,7 +20,7 @@ type Account struct {
UpdaterId int `json:"updater_id" gorm:"column:updater_id"` UpdaterId int `json:"updater_id" gorm:"column:updater_id"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"` CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"` UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:deleted_at"` DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:deleted_at;uniqueIndex:name_del"`
AssetCount int64 `json:"asset_count" gorm:"-"` AssetCount int64 `json:"asset_count" gorm:"-"`
} }

View File

@@ -11,24 +11,24 @@ const (
) )
type Asset struct { type Asset struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
Name string `json:"name" gorm:"column:name"` Name string `json:"name" gorm:"column:name;uniqueIndex:name_del;size:128"`
Comment string `json:"comment" gorm:"column:comment"` Comment string `json:"comment" gorm:"column:comment"`
ParentId int `json:"parent_id" gorm:"column:parent_id"` ParentId int `json:"parent_id" gorm:"column:parent_id"`
Ip string `json:"ip" gorm:"column:ip"` Ip string `json:"ip" gorm:"column:ip"`
Protocols Slice[string] `json:"protocols" gorm:"column:protocols"` Protocols Slice[string] `json:"protocols" gorm:"column:protocols"`
GatewayId int `json:"gateway_id" gorm:"column:gateway_id"` GatewayId int `json:"gateway_id" gorm:"column:gateway_id"`
Authorization Map[int, Slice[int]] `json:"authorization" gorm:"column:authorization"` Authorization Map[int, Slice[int]] `json:"authorization" gorm:"column:authorization"`
*AccessAuth `json:"access_auth" gorm:"column:access_auth"` AccessAuth AccessAuth `json:"access_auth" gorm:"embedded;column:access_auth"`
Connectable bool `json:"connectable" gorm:"column:connectable"` Connectable bool `json:"connectable" gorm:"column:connectable"`
NodeChain string `json:"node_chain" gorm:"-"` NodeChain string `json:"node_chain" gorm:"-"`
ResourceId int `json:"resource_id" gorm:"column:resource_id"` ResourceId int `json:"resource_id" gorm:"column:resource_id"`
CreatorId int `json:"creator_id" gorm:"column:creator_id"` CreatorId int `json:"creator_id" gorm:"column:creator_id"`
UpdaterId int `json:"updater_id" gorm:"column:updater_id"` UpdaterId int `json:"updater_id" gorm:"column:updater_id"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"` CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"` UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:deleted_at"` DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:deleted_at;uniqueIndex:name_del"`
} }
type AccessAuth struct { type AccessAuth struct {

View File

@@ -7,16 +7,16 @@ import (
) )
type Authorization struct { type Authorization struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
AssetId int `json:"asset_id" gorm:"column:asset_id"` AssetId int `json:"asset_id" gorm:"column:asset_id;uniqueIndex:asset_account_id_del"`
AccountId int `json:"account_id" gorm:"column:account_id"` AccountId int `json:"account_id" gorm:"column:account_id;uniqueIndex:asset_account_id_del"`
ResourceId int `json:"resource_id" gorm:"column:resource_id"` ResourceId int `json:"resource_id" gorm:"column:resource_id"`
CreatorId int `json:"creator_id" gorm:"column:creator_id"` CreatorId int `json:"creator_id" gorm:"column:creator_id"`
UpdaterId int `json:"updater_id" gorm:"column:updater_id"` UpdaterId int `json:"updater_id" gorm:"column:updater_id"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"` CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"` UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:deleted_at"` DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:deleted_at;uniqueIndex:asset_account_id_del"`
} }
func (m *Authorization) TableName() string { func (m *Authorization) TableName() string {
@@ -28,7 +28,7 @@ type InfoModel interface {
} }
type AssetInfo struct { type AssetInfo struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
Name string `json:"name" gorm:"column:name"` Name string `json:"name" gorm:"column:name"`
Comment string `json:"comment" gorm:"column:comment"` Comment string `json:"comment" gorm:"column:comment"`
ParentId int `json:"parent_id" gorm:"column:parent_id"` ParentId int `json:"parent_id" gorm:"column:parent_id"`
@@ -49,7 +49,7 @@ func (m *AssetInfo) GetId() int {
} }
type AccountInfo struct { type AccountInfo struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
Name string `json:"name" gorm:"column:name"` Name string `json:"name" gorm:"column:name"`
Account string `json:"account" gorm:"column:account"` Account string `json:"account" gorm:"column:account"`
AccountType int `json:"account_type,omitempty" gorm:"column:account_type"` AccountType int `json:"account_type,omitempty" gorm:"column:account_type"`
@@ -61,7 +61,7 @@ func (m *AccountInfo) GetId() int {
} }
type GatewayInfo struct { type GatewayInfo struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
Name string `json:"name" gorm:"column:name"` Name string `json:"name" gorm:"column:name"`
Host string `json:"host" gorm:"column:host"` Host string `json:"host" gorm:"column:host"`
Port int `json:"port" gorm:"column:port"` Port int `json:"port" gorm:"column:port"`
@@ -75,7 +75,7 @@ func (m *GatewayInfo) GetId() int {
} }
type CmdInfo struct { type CmdInfo struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
Name string `json:"name" gorm:"column:name"` Name string `json:"name" gorm:"column:name"`
Cmds Slice[string] `json:"cmds" gorm:"column:cmds"` Cmds Slice[string] `json:"cmds" gorm:"column:cmds"`
Enable int `json:"enable" gorm:"column:enable"` Enable int `json:"enable" gorm:"column:enable"`

View File

@@ -7,8 +7,8 @@ import (
) )
type Command struct { type Command struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
Name string `json:"name" gorm:"column:name"` Name string `json:"name" gorm:"column:name;uniqueIndex:name_del;size:128"`
Cmds Slice[string] `json:"cmds" gorm:"column:cmds"` Cmds Slice[string] `json:"cmds" gorm:"column:cmds"`
Enable bool `json:"enable" gorm:"column:enable"` Enable bool `json:"enable" gorm:"column:enable"`
@@ -17,7 +17,7 @@ type Command struct {
UpdaterId int `json:"updater_id" gorm:"column:updater_id"` UpdaterId int `json:"updater_id" gorm:"column:updater_id"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"` CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"` UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:deleted_at"` DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:deleted_at;uniqueIndex:name_del"`
} }
func (m *Command) TableName() string { func (m *Command) TableName() string {

View File

@@ -1,20 +1,41 @@
package model package model
import ( import (
"sync/atomic"
"time" "time"
"gorm.io/plugin/soft_delete" "gorm.io/plugin/soft_delete"
) )
var (
GlobalConfig atomic.Pointer[Config]
)
type SshConfig struct {
Copy bool `json:"copy" gorm:"column:copy"`
Paste bool `json:"paste" gorm:"column:paste"`
}
type RdpConfig struct {
Copy bool `json:"copy" gorm:"column:copy"`
Paste bool `json:"paste" gorm:"column:paste"`
}
type VncConfig struct {
Copy bool `json:"copy" gorm:"column:copy"`
Paste bool `json:"paste" gorm:"column:paste"`
}
type Config struct { type Config struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
Timeout int `json:"timeout" gorm:"column:timeout"` Timeout int `json:"timeout" gorm:"column:timeout"`
SshConfig SshConfig `json:"ssh_config" gorm:"embedded;embeddedPrefix:ssh_;column:ssh_config"`
RdpConfig RdpConfig `json:"rdp_config" gorm:"embedded;embeddedPrefix:rdp_;column:rdp_config"`
VncConfig VncConfig `json:"vnc_config" gorm:"embedded;embeddedPrefix:vnc_;column:vnc_config"`
CreatorId int `json:"creator_id" gorm:"column:creator_id"` CreatorId int `json:"creator_id" gorm:"column:creator_id"`
UpdaterId int `json:"updater_id" gorm:"column:updater_id"` UpdaterId int `json:"updater_id" gorm:"column:updater_id"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"` CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"` UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:deleted_at"` DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:deleted_at;uniqueIndex:deleted_at"`
} }
func (m *Config) TableName() string { func (m *Config) TableName() string {

View File

@@ -12,7 +12,7 @@ const (
) )
type FileHistory struct { type FileHistory struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
Uid int `json:"uid" gorm:"column:uid"` Uid int `json:"uid" gorm:"column:uid"`
UserName string `json:"user_name" gorm:"column:user_name"` UserName string `json:"user_name" gorm:"column:user_name"`
AssetId int `json:"asset_id" gorm:"column:asset_id"` AssetId int `json:"asset_id" gorm:"column:asset_id"`

View File

@@ -7,8 +7,8 @@ import (
) )
type Gateway struct { type Gateway struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
Name string `json:"name" gorm:"column:name"` Name string `json:"name" gorm:"column:name;uniqueIndex:name_del;size:128"`
Host string `json:"host" gorm:"column:host"` Host string `json:"host" gorm:"column:host"`
Port int `json:"port" gorm:"column:port"` Port int `json:"port" gorm:"column:port"`
AccountType int `json:"account_type" gorm:"column:account_type"` AccountType int `json:"account_type" gorm:"column:account_type"`
@@ -22,7 +22,7 @@ type Gateway struct {
UpdaterId int `json:"updater_id" gorm:"column:updater_id"` UpdaterId int `json:"updater_id" gorm:"column:updater_id"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"` CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"` UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:deleted_at"` DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:deleted_at;uniqueIndex:name_del"`
AssetCount int64 `json:"asset_count" gorm:"-"` AssetCount int64 `json:"asset_count" gorm:"-"`
} }

View File

@@ -5,7 +5,7 @@ import (
) )
type History struct { type History struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
RemoteIp string `json:"remote_ip" gorm:"column:remote_ip"` RemoteIp string `json:"remote_ip" gorm:"column:remote_ip"`
Type string `json:"type" gorm:"column:type"` Type string `json:"type" gorm:"column:type"`
TargetId int `json:"target_id" gorm:"column:target_id"` TargetId int `json:"target_id" gorm:"column:target_id"`

View File

@@ -11,14 +11,14 @@ const (
) )
type Node struct { type Node struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
Name string `json:"name" gorm:"column:name"` Name string `json:"name" gorm:"column:name"`
Comment string `json:"comment" gorm:"column:comment"` Comment string `json:"comment" gorm:"column:comment"`
ParentId int `json:"parent_id" gorm:"column:parent_id"` ParentId int `json:"parent_id" gorm:"column:parent_id"`
Authorization Map[int, Slice[int]] `json:"authorization" gorm:"column:authorization"` Authorization Map[int, Slice[int]] `json:"authorization" gorm:"column:authorization"`
*AccessAuth `json:"access_auth" gorm:"column:access_auth"` AccessAuth AccessAuth `json:"access_auth" gorm:"embedded;column:access_auth"`
Protocols Slice[string] `json:"protocols" gorm:"column:protocols"` Protocols Slice[string] `json:"protocols" gorm:"column:protocols"`
GatewayId int `json:"gateway_id" gorm:"column:gateway_id"` GatewayId int `json:"gateway_id" gorm:"column:gateway_id"`
// ResourceId int `json:"resource_id"` // ResourceId int `json:"resource_id"`
CreatorId int `json:"creator_id" gorm:"column:creator_id"` CreatorId int `json:"creator_id" gorm:"column:creator_id"`

View File

@@ -12,19 +12,18 @@ const (
) )
type PublicKey struct { type PublicKey struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
Uid int `json:"uid" gorm:"column:uid"` Uid int `json:"uid" gorm:"column:uid"`
UserName string `json:"username" gorm:"column:username"` UserName string `json:"username" gorm:"column:username"`
Name string `json:"name" gorm:"column:name"` Name string `json:"name" gorm:"column:name;uniqueIndex:creator_id_name_del,priority:2;size:128"`
Mac string `json:"mac" gorm:"column:mac"`
Pk string `json:"pk" gorm:"column:pk"` Pk string `json:"pk" gorm:"column:pk"`
// ResourceId int `json:"resource_id"` // ResourceId int `json:"resource_id"`
CreatorId int `json:"creator_id" gorm:"column:creator_id"` CreatorId int `json:"creator_id" gorm:"column:creator_id;uniqueIndex:creator_id_name_del,priority:1"`
UpdaterId int `json:"updater_id" gorm:"column:updater_id"` UpdaterId int `json:"updater_id" gorm:"column:updater_id"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"` CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"` UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:deleted_at"` DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:deleted_at;uniqueIndex:creator_id_name_del,priority:3"`
} }
func (m *PublicKey) TableName() string { func (m *PublicKey) TableName() string {

View File

@@ -22,9 +22,9 @@ const (
) )
type Session struct { type Session struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
SessionType int `json:"session_type" gorm:"column:session_type"` SessionType int `json:"session_type" gorm:"column:session_type"`
SessionId string `json:"session_id" gorm:"column:session_id"` SessionId string `json:"session_id" gorm:"column:session_id;uniqueIndex:session_id;size:128"`
Uid int `json:"uid" gorm:"column:uid"` Uid int `json:"uid" gorm:"column:uid"`
UserName string `json:"user_name" gorm:"column:user_name"` UserName string `json:"user_name" gorm:"column:user_name"`
AssetId int `json:"asset_id" gorm:"column:asset_id"` AssetId int `json:"asset_id" gorm:"column:asset_id"`
@@ -38,6 +38,7 @@ type Session struct {
Status int `json:"status" gorm:"column:status"` Status int `json:"status" gorm:"column:status"`
Duration int64 `json:"duration" gorm:"-"` Duration int64 `json:"duration" gorm:"-"`
ClosedAt *time.Time `json:"closed_at" gorm:"column:closed_at"` ClosedAt *time.Time `json:"closed_at" gorm:"column:closed_at"`
ShareId int `json:"share_id" gorm:"column:share_id"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"` CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"` UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
@@ -50,7 +51,7 @@ func (m *Session) TableName() string {
} }
type SessionCmd struct { type SessionCmd struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
SessionId string `json:"session_id" gorm:"column:session_id"` SessionId string `json:"session_id" gorm:"column:session_id"`
Cmd string `json:"cmd" gorm:"column:cmd"` Cmd string `json:"cmd" gorm:"column:cmd"`
Result string `json:"result" gorm:"column:result"` Result string `json:"result" gorm:"column:result"`
@@ -73,6 +74,6 @@ type CmdCount struct {
} }
type SessionOptionAsset struct { type SessionOptionAsset struct {
Id int `json:"id" gorm:"column:id;primarykey"` Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
Name string `json:"name" gorm:"column:name"` Name string `json:"name" gorm:"column:name"`
} }

54
backend/model/share.go Normal file
View File

@@ -0,0 +1,54 @@
package model
import (
"time"
"gorm.io/plugin/soft_delete"
)
const (
TABLE_NAME_SHARE = "share"
)
type Share struct {
Id int `json:"id" gorm:"column:id;primarykey;autoIncrement"`
Uuid string `json:"uuid" gorm:"column:uuid;uniqueIndex:uuid;size:128"`
AssetId int `json:"asset_id" gorm:"column:asset_id"`
AccountId int `json:"account_id" gorm:"column:account_id"`
Protocol string `json:"protocol" gorm:"column:protocol"`
NoLimit bool `json:"no_limit" gorm:"column:no_limit"`
Times int `json:"times" gorm:"column:times"`
Start time.Time `json:"start" gorm:"column:start"`
End time.Time `json:"end" gorm:"column:end"`
CreatorId int `json:"creator_id" gorm:"column:creator_id"`
UpdaterId int `json:"updater_id" gorm:"column:updater_id"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:deleted_at"`
}
func (m *Share) TableName() string {
return TABLE_NAME_SHARE
}
func (m *Share) SetId(id int) {
m.Id = id
}
func (m *Share) SetCreatorId(creatorId int) {
m.CreatorId = creatorId
}
func (m *Share) SetUpdaterId(updaterId int) {
m.UpdaterId = updaterId
}
func (m *Share) SetResourceId(resourceId int) {
}
func (m *Share) GetResourceId() int {
return 0
}
func (m *Share) GetName() string {
return ""
}
func (m *Share) GetId() int {
return m.Id
}

View File

@@ -0,0 +1,27 @@
package schedule
import (
"fmt"
"time"
redis "github.com/veops/oneterm/cache"
mysql "github.com/veops/oneterm/db"
"github.com/veops/oneterm/model"
)
func UpdateConfig() {
cfg := &model.Config{}
err := redis.Get(ctx, "config", cfg)
if err == nil {
return
}
err = mysql.DB.Model(cfg).First(cfg).Error
if err != nil {
return
}
redis.SetEx(ctx, "config", cfg, time.Hour)
model.GlobalConfig.Store(cfg)
fmt.Println("--------------------------", *model.GlobalConfig.Load())
}

View File

@@ -1,7 +1,6 @@
package schedule package schedule
import ( import (
"context"
"fmt" "fmt"
"net" "net"
"strings" "strings"
@@ -19,28 +18,7 @@ import (
"github.com/veops/oneterm/util" "github.com/veops/oneterm/util"
) )
var ( func UpdateConnectables(ids ...int) (err error) {
ctx, cancel = context.WithCancel(context.Background())
d = time.Hour * 2
)
func RunConnectable() (err error) {
tk := time.NewTicker(d)
for {
select {
case <-tk.C:
CheckUpdate()
case <-ctx.Done():
return
}
}
}
func StopConnectable() {
defer cancel()
}
func CheckUpdate(ids ...int) (err error) {
defer func() { defer func() {
if err != nil { if err != nil {
logger.L().Warn("check connectable failed", zap.Error(err)) logger.L().Warn("check connectable failed", zap.Error(err))
@@ -52,7 +30,7 @@ func CheckUpdate(ids ...int) (err error) {
if len(ids) > 0 { if len(ids) > 0 {
db = db.Where("id IN ?", ids) db = db.Where("id IN ?", ids)
} else { } else {
db = db.Where("updated_at <= ?", time.Now().Add(-d).Unix()) db = db.Where("updated_at <= ?", time.Now().Add(time.Hour).Unix())
} }
if err = db. if err = db.
Find(&assets).Error; err != nil { Find(&assets).Error; err != nil {
@@ -80,7 +58,7 @@ func CheckUpdate(ids ...int) (err error) {
all, oks := lo.Map(assets, func(a *model.Asset, _ int) int { return a.Id }), make([]int, 0) all, oks := lo.Map(assets, func(a *model.Asset, _ int) int { return a.Id }), make([]int, 0)
sids := make([]string, 0) sids := make([]string, 0)
for _, a := range assets { for _, a := range assets {
sid, ok := checkOne(a, gatewayMap[a.GatewayId]) sid, ok := updateConnectable(a, gatewayMap[a.GatewayId])
if ok { if ok {
oks = append(oks, a.Id) oks = append(oks, a.Id)
} }
@@ -100,7 +78,7 @@ func CheckUpdate(ids ...int) (err error) {
return return
} }
func checkOne(asset *model.Asset, gateway *model.Gateway) (sid string, ok bool) { func updateConnectable(asset *model.Asset, gateway *model.Gateway) (sid string, ok bool) {
sid = uuid.New().String() sid = uuid.New().String()
for _, p := range asset.Protocols { for _, p := range asset.Protocols {
ip, port := asset.Ip, cast.ToInt(strings.Split(p, ":")[1]) ip, port := asset.Ip, cast.ToInt(strings.Split(p, ":")[1])

View File

@@ -0,0 +1,33 @@
package schedule
import (
"context"
"time"
)
var (
ctx, cancel = context.WithCancel(context.Background())
)
func init() {
UpdateConfig()
}
func RunSchedule() (err error) {
tk2h := time.NewTicker(time.Hour * 2)
tk1m := time.NewTicker(time.Minute)
for {
select {
case <-ctx.Done():
return
case <-tk2h.C:
UpdateConnectables()
case <-tk1m.C:
UpdateConfig()
}
}
}
func StopSchedule() {
defer cancel()
}

View File

@@ -118,19 +118,10 @@ type Session struct {
Chans *SessionChans `json:"-" gorm:"-"` Chans *SessionChans `json:"-" gorm:"-"`
ConnectionId string `json:"-" gorm:"-"` ConnectionId string `json:"-" gorm:"-"`
GuacdTunnel *guacd.Tunnel `json:"-" gorm:"-"` GuacdTunnel *guacd.Tunnel `json:"-" gorm:"-"`
IdleTimout time.Duration `json:"-" gorm:"-"`
IdleTk *time.Ticker `json:"-" gorm:"-"` IdleTk *time.Ticker `json:"-" gorm:"-"`
SshRecoder *Asciinema `json:"-" gorm:"-"` SshRecoder *Asciinema `json:"-" gorm:"-"`
} }
func NewSession(ctx context.Context) *Session {
s := &Session{}
s.G, s.Gctx = errgroup.WithContext(ctx)
s.Chans = NewSessionChans()
s.Monitors = &sync.Map{}
return s
}
func (m *Session) HasMonitors() (has bool) { func (m *Session) HasMonitors() (has bool) {
m.Monitors.Range(func(key, value any) bool { m.Monitors.Range(func(key, value any) bool {
has = true has = true
@@ -139,6 +130,29 @@ func (m *Session) HasMonitors() (has bool) {
return return
} }
func (m *Session) SetIdle() {
d := time.Hour
cfg := model.GlobalConfig.Load()
if cfg != nil && cfg.Timeout > 0 {
d = time.Second * time.Duration(cfg.Timeout)
}
if m.IdleTk == nil {
m.IdleTk = time.NewTicker(d)
} else {
m.IdleTk.Reset(d)
}
}
func NewSession(ctx context.Context) *Session {
s := &Session{}
s.G, s.Gctx = errgroup.WithContext(ctx)
s.Chans = NewSessionChans()
s.Monitors = &sync.Map{}
s.SetIdle()
return s
}
func UpsertSession(data *Session) (err error) { func UpsertSession(data *Session) (err error) {
return mysql.DB. return mysql.DB.
Clauses(clause.OnConflict{ Clauses(clause.OnConflict{

View File

@@ -1,215 +0,0 @@
-- Active: 1700721140603@@192.168.20.82@53306@oneterm
CREATE DATABASE IF NOT EXISTS oneterm;
CREATE TABLE
IF NOT EXISTS oneterm.account(
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(64) NOT NULL DEFAULT '',
`account_type` int NOT NULL DEFAULT 0,
`account` VARCHAR(64) NOT NULL DEFAULT '',
`password` TEXT NOT NULL,
`pk` TEXT NOT NULL,
`phrase` TEXT NOT NULL,
`resource_id` INT NOT NULL DEFAULT 0,
`creator_id` INT NOT NULL DEFAULT 0,
`updater_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `name_del` (`name`, `deleted_at`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.asset(
`id` INT NOT NULL AUTO_INCREMENT,
`ci_id` INT NOT NULL DEFAULT 0,
`name` VARCHAR(64) NOT NULL DEFAULT '',
`comment` VARCHAR(64) NOT NULL DEFAULT '',
`parent_id` INT NOT NULL DEFAULT 0,
`ip` VARCHAR(64) NOT NULL DEFAULT '',
`protocols` JSON NOT NULL,
`gateway_id` INT NOT NULL DEFAULT 0,
`authorization` JSON NOT NULL,
`start` TIMESTAMP,
`end` TIMESTAMP,
`cmd_ids` JSON NOT NULL,
`ranges` JSON NOT NULL,
`allow` TINYINT(1) NOT NULL DEFAULT 0,
`connectable` TINYINT(1) NOT NULL DEFAULT 0,
`resource_id` INT NOT NULL DEFAULT 0,
`creator_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updater_id` INT NOT NULL DEFAULT 0,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `name_del` (`name`, `deleted_at`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.command(
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(64) NOT NULL DEFAULT '',
`cmds` JSON NOT NULL,
`enable` TINYINT(1) NOT NULL DEFAULT 0,
`resource_id` INT NOT NULL DEFAULT 0,
`creator_id` INT NOT NULL DEFAULT 0,
`updater_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `name_del` (`name`, `deleted_at`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.gateway(
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(64) NOT NULL DEFAULT '',
`host` VARCHAR(64) NOT NULL DEFAULT '',
`port` INT NOT NULL DEFAULT 0,
`account_type` int NOT NULL DEFAULT 0,
`account` VARCHAR(64) NOT NULL DEFAULT '',
`password` TEXT NOT NULL,
`pk` TEXT NOT NULL,
`phrase` TEXT NOT NULL,
`resource_id` INT NOT NULL DEFAULT 0,
`creator_id` INT NOT NULL DEFAULT 0,
`updater_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `name_del` (`name`, `deleted_at`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.node(
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(64) NOT NULL DEFAULT '',
`comment` VARCHAR(64) NOT NULL DEFAULT '',
`parent_id` INT NOT NULL DEFAULT 0,
`ip` VARCHAR(64) NOT NULL DEFAULT '',
`protocols` JSON NOT NULL,
`gateway_id` INT NOT NULL DEFAULT 0,
`authorization` JSON NOT NULL,
`start` TIMESTAMP,
`end` TIMESTAMP,
`cmd_ids` JSON NOT NULL,
`ranges` JSON NOT NULL,
`allow` TINYINT(1) NOT NULL DEFAULT 0,
`type_id` INT NOT NULL DEFAULT 0,
`mapping` JSON NOT NULL,
`filters` TEXT NOT NULL,
`enable` TINYINT(1) NOT NULL DEFAULT 0,
`frequency` DOUBLE NOT NULL DEFAULT 0,
`creator_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updater_id` INT NOT NULL DEFAULT 0,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.public_key(
`id` INT NOT NULL AUTO_INCREMENT,
`uid` INT NOT NULL DEFAULT 0,
`username` VARCHAR(64) NOT NULL DEFAULT '',
`name` VARCHAR(64) NOT NULL DEFAULT '',
`mac` VARCHAR(64) NOT NULL DEFAULT '',
`pk` TEXT NOT NULL,
`creator_id` INT NOT NULL DEFAULT 0,
`updater_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `creator_id_name_del` (
`creator_id`,
`name`,
`deleted_at`
)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.history(
`id` INT NOT NULL AUTO_INCREMENT,
`remote_ip` VARCHAR(64) NOT NULL DEFAULT 0,
`type` VARCHAR(64) NOT NULL DEFAULT 0,
`target_id` INT NOT NULL DEFAULT 0,
`old` JSON NOT NULL,
`new` JSON NOT NULL,
`action_type` INT NOT NULL DEFAULT 0,
`creator_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.session(
`id` INT NOT NULL AUTO_INCREMENT,
`session_type` INT NOT NULL DEFAULT 0,
`session_id` VARCHAR(64) NOT NULL DEFAULT '',
`uid` INT NOT NULL DEFAULT 0,
`user_name` VARCHAR(64) NOT NULL DEFAULT '',
`asset_id` INT NOT NULL DEFAULT 0,
`asset_info` VARCHAR(64) NOT NULL DEFAULT '',
`account_id` INT NOT NULL DEFAULT 0,
`account_info` VARCHAR(64) NOT NULL DEFAULT '',
`gateway_id` INT NOT NULL DEFAULT 0,
`gateway_info` VARCHAR(64) NOT NULL DEFAULT '',
`protocol` VARCHAR(64) NOT NULL DEFAULT '',
`client_ip` VARCHAR(64) NOT NULL DEFAULT '',
`status` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updated_at` TIMESTAMP NOT NULL,
`closed_at` TIMESTAMP,
PRIMARY KEY(`id`),
UNIQUE KEY `session_id` (`session_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.session_cmd(
`id` INT NOT NULL AUTO_INCREMENT,
`session_id` VARCHAR(64) NOT NULL DEFAULT '',
`cmd` TEXT NOT NULL,
`result` TEXT NOT NULL,
`level` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
PRIMARY KEY(`id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.authorization(
`id` INT NOT NULL AUTO_INCREMENT,
`asset_id` INT NOT NULL DEFAULT 0,
`account_id` INT NOT NULL DEFAULT 0,
`resource_id` INT NOT NULL DEFAULT 0,
`creator_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updater_id` INT NOT NULL DEFAULT 0,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY(`id`),
UNIQUE KEY `asset_account_id_del` (
`asset_id`,
`account_id`,
`deleted_at`
)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.config(
`id` INT NOT NULL AUTO_INCREMENT,
`timeout` INT NOT NULL,
`creator_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updater_id` INT NOT NULL DEFAULT 0,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY(`id`),
UNIQUE KEY `deleted_at` (`deleted_at`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

View File

@@ -544,6 +544,21 @@ func (m Model) echoTransform(v string) string {
} }
} }
func (m Model) matchedCommonPrefix() []rune {
commonPrefix := m.matchedSuggestions[0]
for _, s := range m.matchedSuggestions {
str := make([]rune, 0)
for i := 0; i < min(len(commonPrefix), len(s)); i++ {
if commonPrefix[i] != s[i] {
break
}
str = append(str, commonPrefix[i])
}
commonPrefix = str
}
return commonPrefix
}
// Update is the Bubble Tea update loop. // Update is the Bubble Tea update loop.
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
if !m.focus { if !m.focus {
@@ -554,18 +569,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
keyMsg, ok := msg.(tea.KeyMsg) keyMsg, ok := msg.(tea.KeyMsg)
if ok && key.Matches(keyMsg, m.KeyMap.AcceptSuggestion) { if ok && key.Matches(keyMsg, m.KeyMap.AcceptSuggestion) {
if m.canAcceptSuggestion() { if m.canAcceptSuggestion() {
commonPrefix := m.matchedSuggestions[0] m.value = append(m.value, m.matchedCommonPrefix()[len(m.value):]...)
for _, s := range m.matchedSuggestions {
str := make([]rune, 0)
for i := 0; i < min(len(commonPrefix), len(s)); i++ {
if commonPrefix[i] != s[i] {
break
}
str = append(str, commonPrefix[i])
}
commonPrefix = str
}
m.value = append(m.value, commonPrefix[len(m.value):]...)
m.CursorEnd() m.CursorEnd()
} }
} }
@@ -672,9 +676,8 @@ func (m Model) View() string {
v += styleText(m.echoTransform(string(value[pos+1:]))) // text after cursor v += styleText(m.echoTransform(string(value[pos+1:]))) // text after cursor
v += m.completionView(0) // suggested completion v += m.completionView(0) // suggested completion
} else { } else {
if m.canAcceptSuggestion() && len(m.matchedSuggestions) <= 1 { if m.canAcceptSuggestion() {
suggestion := m.matchedCommonPrefix()
suggestion := m.matchedSuggestions[m.currentSuggestionIndex]
if len(value) < len(suggestion) { if len(value) < len(suggestion) {
m.Cursor.TextStyle = m.CompletionStyle m.Cursor.TextStyle = m.CompletionStyle
m.Cursor.SetChar(m.echoTransform(string(suggestion[pos]))) m.Cursor.SetChar(m.echoTransform(string(suggestion[pos])))
@@ -813,7 +816,7 @@ func (m Model) completionView(offset int) string {
) )
if m.canAcceptSuggestion() { if m.canAcceptSuggestion() {
suggestion := m.matchedSuggestions[m.currentSuggestionIndex] suggestion := m.matchedCommonPrefix()
if len(value) < len(suggestion) { if len(value) < len(suggestion) {
return style(string(suggestion[len(value)+offset:])) return style(string(suggestion[len(value)+offset:]))
} }

View File

@@ -5,19 +5,16 @@ import (
"crypto/aes" "crypto/aes"
"crypto/cipher" "crypto/cipher"
"encoding/base64" "encoding/base64"
)
var ( "github.com/veops/oneterm/conf"
key = []byte("thisis32bitlongpassphraseimusing")
iv = []byte("0123456789abcdef")
) )
func EncryptAES(plainText string) string { func EncryptAES(plainText string) string {
block, _ := aes.NewCipher(key) block, _ := aes.NewCipher(conf.Cfg.Auth.Aes.Key)
bs := []byte(plainText) bs := []byte(plainText)
bs = paddingPKCS7(bs, aes.BlockSize) bs = paddingPKCS7(bs, aes.BlockSize)
mode := cipher.NewCBCEncrypter(block, iv) mode := cipher.NewCBCEncrypter(block, conf.Cfg.Auth.Aes.Iv)
mode.CryptBlocks(bs, bs) mode.CryptBlocks(bs, bs)
return base64.StdEncoding.EncodeToString(bs) return base64.StdEncoding.EncodeToString(bs)
@@ -25,12 +22,12 @@ func EncryptAES(plainText string) string {
func DecryptAES(cipherText string) string { func DecryptAES(cipherText string) string {
bs, _ := base64.StdEncoding.DecodeString(cipherText) bs, _ := base64.StdEncoding.DecodeString(cipherText)
block, err := aes.NewCipher(key) block, err := aes.NewCipher(conf.Cfg.Auth.Aes.Key)
if err != nil { if err != nil {
panic(err) panic(err)
} }
mode := cipher.NewCBCDecrypter(block, iv) mode := cipher.NewCBCDecrypter(block, conf.Cfg.Auth.Aes.Iv)
mode.CryptBlocks(bs, bs) mode.CryptBlocks(bs, bs)
return string(unPaddingPKCS7(bs)) return string(unPaddingPKCS7(bs))

View File

@@ -1,229 +0,0 @@
-- Active: 1700721140603@@192.168.20.82@53306@oneterm
CREATE DATABASE IF NOT EXISTS oneterm;
CREATE TABLE
IF NOT EXISTS oneterm.account(
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(64) NOT NULL DEFAULT '',
`account_type` int NOT NULL DEFAULT 0,
`account` VARCHAR(64) NOT NULL DEFAULT '',
`password` TEXT NOT NULL,
`pk` TEXT NOT NULL,
`phrase` TEXT NOT NULL,
`resource_id` INT NOT NULL DEFAULT 0,
`creator_id` INT NOT NULL DEFAULT 0,
`updater_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `name_del` (`name`, `deleted_at`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.asset(
`id` INT NOT NULL AUTO_INCREMENT,
`ci_id` INT NOT NULL DEFAULT 0,
`name` VARCHAR(64) NOT NULL DEFAULT '',
`comment` VARCHAR(64) NOT NULL DEFAULT '',
`parent_id` INT NOT NULL DEFAULT 0,
`ip` VARCHAR(64) NOT NULL DEFAULT '',
`protocols` JSON NOT NULL,
`gateway_id` INT NOT NULL DEFAULT 0,
`authorization` JSON NOT NULL,
`start` TIMESTAMP,
`end` TIMESTAMP,
`cmd_ids` JSON NOT NULL,
`ranges` JSON NOT NULL,
`allow` TINYINT(1) NOT NULL DEFAULT 0,
`connectable` TINYINT(1) NOT NULL DEFAULT 0,
`resource_id` INT NOT NULL DEFAULT 0,
`creator_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updater_id` INT NOT NULL DEFAULT 0,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `name_del` (`name`, `deleted_at`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.command(
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(64) NOT NULL DEFAULT '',
`cmds` JSON NOT NULL,
`enable` TINYINT(1) NOT NULL DEFAULT 0,
`resource_id` INT NOT NULL DEFAULT 0,
`creator_id` INT NOT NULL DEFAULT 0,
`updater_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `name_del` (`name`, `deleted_at`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.gateway(
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(64) NOT NULL DEFAULT '',
`host` VARCHAR(64) NOT NULL DEFAULT '',
`port` INT NOT NULL DEFAULT 0,
`account_type` int NOT NULL DEFAULT 0,
`account` VARCHAR(64) NOT NULL DEFAULT '',
`password` TEXT NOT NULL,
`pk` TEXT NOT NULL,
`phrase` TEXT NOT NULL,
`resource_id` INT NOT NULL DEFAULT 0,
`creator_id` INT NOT NULL DEFAULT 0,
`updater_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `name_del` (`name`, `deleted_at`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.node(
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(64) NOT NULL DEFAULT '',
`comment` VARCHAR(64) NOT NULL DEFAULT '',
`parent_id` INT NOT NULL DEFAULT 0,
`ip` VARCHAR(64) NOT NULL DEFAULT '',
`protocols` JSON NOT NULL,
`gateway_id` INT NOT NULL DEFAULT 0,
`authorization` JSON NOT NULL,
`start` TIMESTAMP,
`end` TIMESTAMP,
`cmd_ids` JSON NOT NULL,
`ranges` JSON NOT NULL,
`allow` TINYINT(1) NOT NULL DEFAULT 0,
`creator_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updater_id` INT NOT NULL DEFAULT 0,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.public_key(
`id` INT NOT NULL AUTO_INCREMENT,
`uid` INT NOT NULL DEFAULT 0,
`username` VARCHAR(64) NOT NULL DEFAULT '',
`name` VARCHAR(64) NOT NULL DEFAULT '',
`mac` VARCHAR(64) NOT NULL DEFAULT '',
`pk` TEXT NOT NULL,
`creator_id` INT NOT NULL DEFAULT 0,
`updater_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `creator_id_name_del` (
`creator_id`,
`name`,
`deleted_at`
)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.history(
`id` INT NOT NULL AUTO_INCREMENT,
`remote_ip` VARCHAR(64) NOT NULL DEFAULT 0,
`type` VARCHAR(64) NOT NULL DEFAULT 0,
`target_id` INT NOT NULL DEFAULT 0,
`old` JSON NOT NULL,
`new` JSON NOT NULL,
`action_type` INT NOT NULL DEFAULT 0,
`creator_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.session(
`id` INT NOT NULL AUTO_INCREMENT,
`session_type` INT NOT NULL DEFAULT 0,
`session_id` VARCHAR(64) NOT NULL DEFAULT '',
`uid` INT NOT NULL DEFAULT 0,
`user_name` VARCHAR(64) NOT NULL DEFAULT '',
`asset_id` INT NOT NULL DEFAULT 0,
`asset_info` VARCHAR(64) NOT NULL DEFAULT '',
`account_id` INT NOT NULL DEFAULT 0,
`account_info` VARCHAR(64) NOT NULL DEFAULT '',
`gateway_id` INT NOT NULL DEFAULT 0,
`gateway_info` VARCHAR(64) NOT NULL DEFAULT '',
`protocol` VARCHAR(64) NOT NULL DEFAULT '',
`client_ip` VARCHAR(64) NOT NULL DEFAULT '',
`status` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updated_at` TIMESTAMP NOT NULL,
`closed_at` TIMESTAMP,
PRIMARY KEY(`id`),
UNIQUE KEY `session_id` (`session_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.session_cmd(
`id` INT NOT NULL AUTO_INCREMENT,
`session_id` VARCHAR(64) NOT NULL DEFAULT '',
`cmd` TEXT NOT NULL,
`result` TEXT NOT NULL,
`level` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
PRIMARY KEY(`id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.authorization(
`id` INT NOT NULL AUTO_INCREMENT,
`asset_id` INT NOT NULL DEFAULT 0,
`account_id` INT NOT NULL DEFAULT 0,
`resource_id` INT NOT NULL DEFAULT 0,
`creator_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updater_id` INT NOT NULL DEFAULT 0,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY(`id`),
UNIQUE KEY `asset_account_id_del` (
`asset_id`,
`account_id`,
`deleted_at`
)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
CREATE TABLE
IF NOT EXISTS oneterm.config(
`id` INT NOT NULL AUTO_INCREMENT,
`timeout` INT NOT NULL,
`creator_id` INT NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL,
`updater_id` INT NOT NULL DEFAULT 0,
`updated_at` TIMESTAMP NOT NULL,
`deleted_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY(`id`),
UNIQUE KEY `deleted_at` (`deleted_at`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
INSERT INTO oneterm.config (timeout) VALUES (7200);
CREATE TABLE
IF NOT EXISTS oneterm.file_history(
`id` INT NOT NULL AUTO_INCREMENT,
`uid` INT NOT NULL DEFAULT 0,
`user_name` VARCHAR(64) NOT NULL DEFAULT '',
`asset_id` INT NOT NULL DEFAULT 0,
`account_id` INT NOT NULL DEFAULT 0,
`client_ip` VARCHAR(64) NOT NULL DEFAULT '',
`action` INT NOT NULL DEFAULT 0,
`dir` VARCHAR(256) NOT NULL DEFAULT '',
`filename` VARCHAR(256) NOT NULL DEFAULT '',
`created_at` TIMESTAMP NOT NULL,
`updated_at` TIMESTAMP NOT NULL,
PRIMARY KEY(`id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

View File

@@ -54,5 +54,8 @@ auth:
value: gateway value: gateway
- key: authorization - key: authorization
value: authorization value: authorization
aes:
key: thisis32bitlongpassphraseimusing
iv: 0123456789abcdef
secretKey: xW2FAUfgffjmerTEBXADmURDOQ43ojLN secretKey: xW2FAUfgffjmerTEBXADmURDOQ43ojLN

View File

@@ -43,7 +43,6 @@ services:
- ./volume/mysql:/var/lib/mysql - ./volume/mysql:/var/lib/mysql
- ./mysqld.cnf:/etc/mysql/conf.d/mysqld.cnf - ./mysqld.cnf:/etc/mysql/conf.d/mysqld.cnf
- ./acl.sql:/docker-entrypoint-initdb.d/2-acl.sql - ./acl.sql:/docker-entrypoint-initdb.d/2-acl.sql
- ./api.sql:/docker-entrypoint-initdb.d/3-api.sql
- ./create-users.sql:/docker-entrypoint-initdb.d/1-create-users.sql - ./create-users.sql:/docker-entrypoint-initdb.d/1-create-users.sql
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
restart: always restart: always