mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-08-26 16:46:14 +08:00
This commit is contained in:
33
server/internal/cmd/auth.go
Normal file
33
server/internal/cmd/auth.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"hotgo/internal/service"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
Auth = &gcmd.Command{
|
||||
Name: "auth",
|
||||
Brief: "系统授权,当为第三方客户开发应用项目不想将源码和可执行文件让其随意使用时,可以通过授权的方式约束使用方。",
|
||||
Description: `目前已实现,一对一、一对多、有效期授权,具体使用可以参考现有逻辑结合实际场景进行改造`,
|
||||
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
||||
service.TCPAuth().Start(ctx)
|
||||
|
||||
// 退出信号监听
|
||||
signalListen(ctx, func(sig os.Signal) {
|
||||
service.TCPAuth().Stop(ctx)
|
||||
})
|
||||
|
||||
// 信号监听
|
||||
signalListen(ctx, signalHandlerForOverall)
|
||||
select {
|
||||
case <-serverCloseSignal:
|
||||
// ...
|
||||
}
|
||||
|
||||
return
|
||||
},
|
||||
}
|
||||
)
|
@@ -80,7 +80,7 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := Main.AddCommand(Http, Queue, Tools, All, Help); err != nil {
|
||||
if err := Main.AddCommand(Http, Queue, Tools, Auth, All, Help); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
serverCloseSignal = make(chan struct{}, 1)
|
||||
|
@@ -9,20 +9,10 @@ package cmd
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/os/gproc"
|
||||
"hotgo/internal/crons"
|
||||
"hotgo/internal/websocket"
|
||||
"hotgo/utility/simple"
|
||||
"os"
|
||||
)
|
||||
|
||||
func signalHandlerForCron(sig os.Signal) {
|
||||
crons.StopALL()
|
||||
}
|
||||
|
||||
func signalHandlerForWebSocket(sig os.Signal) {
|
||||
websocket.Stop()
|
||||
}
|
||||
|
||||
func signalHandlerForOverall(sig os.Signal) {
|
||||
serverCloseSignal <- struct{}{}
|
||||
}
|
||||
|
@@ -10,10 +10,13 @@ import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"hotgo/internal/crons"
|
||||
"hotgo/internal/library/addons"
|
||||
"hotgo/internal/library/casbin"
|
||||
"hotgo/internal/router"
|
||||
"hotgo/internal/service"
|
||||
"hotgo/internal/websocket"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -68,12 +71,20 @@ var (
|
||||
// 启动定时任务
|
||||
service.SysCron().StartCron(ctx)
|
||||
|
||||
// 信号监听
|
||||
signalListen(ctx, signalHandlerForCron, signalHandlerForWebSocket)
|
||||
//// 启动TCP服务
|
||||
//service.TCPServer().Start(ctx)
|
||||
|
||||
// https
|
||||
setSSL(ctx, s)
|
||||
|
||||
// 退出信号监听
|
||||
signalListen(ctx, func(sig os.Signal) {
|
||||
s.Shutdown()
|
||||
crons.StopALL()
|
||||
websocket.Stop()
|
||||
//service.TCPServer().Stop(ctx)
|
||||
})
|
||||
|
||||
// Just run the server.
|
||||
s.Run()
|
||||
|
||||
|
@@ -7,5 +7,5 @@ package consts
|
||||
|
||||
// VersionApp HotGo版本
|
||||
const (
|
||||
VersionApp = "2.3.5"
|
||||
VersionApp = "2.4.2"
|
||||
)
|
||||
|
@@ -16,6 +16,7 @@ import (
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/utility/simple"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
@@ -161,7 +162,9 @@ func Stop(sysCron *entity.SysCron) (err error) {
|
||||
func Once(ctx context.Context, sysCron *entity.SysCron) error {
|
||||
for _, v := range cronList {
|
||||
if v.GetName() == sysCron.Name {
|
||||
go v.Execute(ctx)
|
||||
simple.SafeGo(ctx, func(ctx context.Context) {
|
||||
v.Execute(ctx)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
109
server/internal/dao/internal/sys_serve_license.go
Normal file
109
server/internal/dao/internal/sys_serve_license.go
Normal file
@@ -0,0 +1,109 @@
|
||||
// ==========================================================================
|
||||
// Code generated by GoFrame CLI tool. DO NOT EDIT.
|
||||
// ==========================================================================
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// SysServeLicenseDao is the data access object for table hg_sys_serve_license.
|
||||
type SysServeLicenseDao struct {
|
||||
table string // table is the underlying table name of the DAO.
|
||||
group string // group is the database configuration group name of current DAO.
|
||||
columns SysServeLicenseColumns // columns contains all the column names of Table for convenient usage.
|
||||
}
|
||||
|
||||
// SysServeLicenseColumns defines and stores column names for table hg_sys_serve_license.
|
||||
type SysServeLicenseColumns struct {
|
||||
Id string // 许可ID
|
||||
Group string // 分组
|
||||
Name string // 许可名称
|
||||
Appid string // 应用ID
|
||||
SecretKey string // 应用秘钥
|
||||
Desc string // 授权说明
|
||||
RemoteAddr string // 最后连接地址
|
||||
Online string // 在线数量
|
||||
OnlineLimit string // 在线数量限制,默认1
|
||||
LoginTimes string // 登录次数
|
||||
LastLoginAt string // 最后登录时间
|
||||
LastActiveAt string // 最后活跃时间
|
||||
Routes string // 路由表,空使用默认分组路由
|
||||
AllowedIps string // 白名单,*代表所有,只有允许的IP才能连接到tcp服务
|
||||
EndAt string // 授权结束时间
|
||||
Remark string // 备注
|
||||
Status string // 状态
|
||||
CreatedAt string // 创建时间
|
||||
UpdatedAt string // 修改时间
|
||||
}
|
||||
|
||||
// sysServeLicenseColumns holds the columns for table hg_sys_serve_license.
|
||||
var sysServeLicenseColumns = SysServeLicenseColumns{
|
||||
Id: "id",
|
||||
Group: "group",
|
||||
Name: "name",
|
||||
Appid: "appid",
|
||||
SecretKey: "secret_key",
|
||||
Desc: "desc",
|
||||
RemoteAddr: "remote_addr",
|
||||
Online: "online",
|
||||
OnlineLimit: "online_limit",
|
||||
LoginTimes: "login_times",
|
||||
LastLoginAt: "last_login_at",
|
||||
LastActiveAt: "last_active_at",
|
||||
Routes: "routes",
|
||||
AllowedIps: "allowed_ips",
|
||||
EndAt: "end_at",
|
||||
Remark: "remark",
|
||||
Status: "status",
|
||||
CreatedAt: "created_at",
|
||||
UpdatedAt: "updated_at",
|
||||
}
|
||||
|
||||
// NewSysServeLicenseDao creates and returns a new DAO object for table data access.
|
||||
func NewSysServeLicenseDao() *SysServeLicenseDao {
|
||||
return &SysServeLicenseDao{
|
||||
group: "default",
|
||||
table: "hg_sys_serve_license",
|
||||
columns: sysServeLicenseColumns,
|
||||
}
|
||||
}
|
||||
|
||||
// DB retrieves and returns the underlying raw database management object of current DAO.
|
||||
func (dao *SysServeLicenseDao) DB() gdb.DB {
|
||||
return g.DB(dao.group)
|
||||
}
|
||||
|
||||
// Table returns the table name of current dao.
|
||||
func (dao *SysServeLicenseDao) Table() string {
|
||||
return dao.table
|
||||
}
|
||||
|
||||
// Columns returns all column names of current dao.
|
||||
func (dao *SysServeLicenseDao) Columns() SysServeLicenseColumns {
|
||||
return dao.columns
|
||||
}
|
||||
|
||||
// Group returns the configuration group name of database of current dao.
|
||||
func (dao *SysServeLicenseDao) Group() string {
|
||||
return dao.group
|
||||
}
|
||||
|
||||
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
|
||||
func (dao *SysServeLicenseDao) Ctx(ctx context.Context) *gdb.Model {
|
||||
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
|
||||
}
|
||||
|
||||
// Transaction wraps the transaction logic using function f.
|
||||
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
|
||||
// It commits the transaction and returns nil if function f returns nil.
|
||||
//
|
||||
// Note that, you should not Commit or Rollback the transaction in function f
|
||||
// as it is automatically handled by this function.
|
||||
func (dao *SysServeLicenseDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
|
||||
return dao.Ctx(ctx).Transaction(ctx, f)
|
||||
}
|
27
server/internal/dao/sys_serve_license.go
Normal file
27
server/internal/dao/sys_serve_license.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// =================================================================================
|
||||
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
// =================================================================================
|
||||
|
||||
package dao
|
||||
|
||||
import (
|
||||
"hotgo/internal/dao/internal"
|
||||
)
|
||||
|
||||
// internalSysServeLicenseDao is internal type for wrapping internal DAO implements.
|
||||
type internalSysServeLicenseDao = *internal.SysServeLicenseDao
|
||||
|
||||
// sysServeLicenseDao is the data access object for table hg_sys_serve_license.
|
||||
// You can define custom methods on it to extend its functionality as you wish.
|
||||
type sysServeLicenseDao struct {
|
||||
internalSysServeLicenseDao
|
||||
}
|
||||
|
||||
var (
|
||||
// SysServeLicense is globally public accessible object for table hg_sys_serve_license operations.
|
||||
SysServeLicense = sysServeLicenseDao{
|
||||
internal.NewSysServeLicenseDao(),
|
||||
}
|
||||
)
|
||||
|
||||
// Fill with you ideas below.
|
@@ -9,13 +9,13 @@ import (
|
||||
"hotgo/internal/library/hggen/internal/utility/utils"
|
||||
)
|
||||
|
||||
func doClear(ctx context.Context, dirPath string) {
|
||||
func doClear(ctx context.Context, dirPath string, force bool) {
|
||||
files, err := gfile.ScanDirFile(dirPath, "*.go", true)
|
||||
if err != nil {
|
||||
mlog.Fatal(err)
|
||||
}
|
||||
for _, file := range files {
|
||||
if utils.IsFileDoNotEdit(file) {
|
||||
if force || utils.IsFileDoNotEdit(file) {
|
||||
if err = gfile.Remove(file); err != nil {
|
||||
mlog.Print(err)
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ func generateDao(ctx context.Context, in CGenDaoInternalInput) {
|
||||
dirPathDaoInternal = gfile.Join(dirPathDao, "internal")
|
||||
)
|
||||
if in.Clear {
|
||||
doClear(ctx, dirPathDao)
|
||||
doClear(ctx, dirPathDao, true)
|
||||
}
|
||||
for i := 0; i < len(in.TableNames); i++ {
|
||||
generateDaoSingle(ctx, generateDaoSingleInput{
|
||||
|
@@ -18,7 +18,7 @@ import (
|
||||
func generateDo(ctx context.Context, in CGenDaoInternalInput) {
|
||||
var dirPathDo = gfile.Join(in.Path, in.DoPath)
|
||||
if in.Clear {
|
||||
doClear(ctx, dirPathDo)
|
||||
doClear(ctx, dirPathDo, false)
|
||||
}
|
||||
in.NoJsonTag = true
|
||||
in.DescriptionTag = false
|
||||
|
@@ -16,7 +16,7 @@ import (
|
||||
func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
|
||||
var dirPathEntity = gfile.Join(in.Path, in.EntityPath)
|
||||
if in.Clear {
|
||||
doClear(ctx, dirPathEntity)
|
||||
doClear(ctx, dirPathEntity, false)
|
||||
}
|
||||
// Model content.
|
||||
for i, tableName := range in.TableNames {
|
||||
|
322
server/internal/library/network/tcp/client.go
Normal file
322
server/internal/library/network/tcp/client.go
Normal file
@@ -0,0 +1,322 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/gtcp"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/glog"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"hotgo/utility/simple"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ClientConfig 客户端配置
|
||||
type ClientConfig struct {
|
||||
Addr string
|
||||
Auth *AuthMeta
|
||||
Timeout time.Duration
|
||||
ConnectInterval time.Duration
|
||||
MaxConnectCount uint
|
||||
ConnectCount uint
|
||||
AutoReconnect bool
|
||||
LoginEvent CallbackEvent
|
||||
CloseEvent CallbackEvent
|
||||
}
|
||||
|
||||
// Client 客户端
|
||||
type Client struct {
|
||||
Ctx context.Context
|
||||
Logger *glog.Logger
|
||||
IsLogin bool // 是否已登录
|
||||
addr string
|
||||
auth *AuthMeta
|
||||
timeout time.Duration
|
||||
connectInterval time.Duration
|
||||
maxConnectCount uint
|
||||
connectCount uint
|
||||
autoReconnect bool
|
||||
loginEvent CallbackEvent
|
||||
closeEvent CallbackEvent
|
||||
sync.Mutex
|
||||
heartbeat int64
|
||||
routers map[string]RouterHandler
|
||||
conn *gtcp.Conn
|
||||
wg sync.WaitGroup
|
||||
closeFlag bool // 关闭标签,关闭以后可以重连
|
||||
stopFlag bool // 停止标签,停止以后不能重连
|
||||
}
|
||||
|
||||
func NewClient(config *ClientConfig) (client *Client, err error) {
|
||||
client = new(Client)
|
||||
|
||||
if config == nil {
|
||||
err = gerror.New("config is nil")
|
||||
return
|
||||
}
|
||||
|
||||
if config.Addr == "" {
|
||||
err = gerror.New("client address is not set")
|
||||
return
|
||||
}
|
||||
|
||||
if config.Auth == nil {
|
||||
err = gerror.New("client auth cannot be empty")
|
||||
return
|
||||
}
|
||||
|
||||
if config.Auth.Group == "" || config.Auth.Name == "" {
|
||||
err = gerror.New("Auth.Group or Auth.Group is nil")
|
||||
return
|
||||
}
|
||||
|
||||
client.Ctx = gctx.New()
|
||||
client.autoReconnect = true
|
||||
client.addr = config.Addr
|
||||
client.auth = config.Auth
|
||||
client.loginEvent = config.LoginEvent
|
||||
client.closeEvent = config.CloseEvent
|
||||
|
||||
logger := glog.New()
|
||||
path := g.Cfg().MustGet(client.Ctx, "logger.path", "logs/logger").String()
|
||||
if err = logger.SetPath(fmt.Sprintf("%s/tcp.client/%s.%s", path, config.Auth.Group, config.Auth.Name)); err != nil {
|
||||
return
|
||||
}
|
||||
client.Logger = logger
|
||||
|
||||
if config.ConnectInterval <= 0 {
|
||||
client.connectInterval = 5 * time.Second
|
||||
client.Logger.Debugf(client.Ctx, "invalid connectInterval, reset to %v", client.connectInterval)
|
||||
} else {
|
||||
client.connectInterval = config.ConnectInterval
|
||||
}
|
||||
|
||||
if config.Timeout <= 0 {
|
||||
client.timeout = 10 * time.Second
|
||||
client.Logger.Debugf(client.Ctx, "invalid timeout, reset to %v", client.timeout)
|
||||
} else {
|
||||
client.timeout = config.Timeout
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Start 启动
|
||||
func (client *Client) Start() (err error) {
|
||||
client.Lock()
|
||||
defer client.Unlock()
|
||||
|
||||
if client.stopFlag {
|
||||
err = gerror.New("client is stop")
|
||||
return
|
||||
}
|
||||
|
||||
if client.conn != nil {
|
||||
return gerror.New("client is running")
|
||||
}
|
||||
|
||||
client.IsLogin = false
|
||||
client.connectCount = 0
|
||||
client.closeFlag = false
|
||||
client.stopFlag = false
|
||||
|
||||
client.wg.Add(1)
|
||||
simple.SafeGo(client.Ctx, func(ctx context.Context) {
|
||||
client.connect()
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// RegisterRouter 注册路由
|
||||
func (client *Client) RegisterRouter(routers map[string]RouterHandler) (err error) {
|
||||
if client.conn != nil {
|
||||
return gerror.New("client is running")
|
||||
}
|
||||
|
||||
client.Lock()
|
||||
defer client.Unlock()
|
||||
|
||||
if client.routers == nil {
|
||||
client.routers = make(map[string]RouterHandler)
|
||||
// 默认路由
|
||||
client.routers = map[string]RouterHandler{
|
||||
"ResponseServerHeartbeat": client.onResponseServerHeartbeat,
|
||||
"ResponseServerLogin": client.onResponseServerLogin,
|
||||
}
|
||||
}
|
||||
|
||||
for i, router := range routers {
|
||||
_, ok := client.routers[i]
|
||||
if ok {
|
||||
return gerror.Newf("client route duplicate registration:%v", i)
|
||||
}
|
||||
client.routers[i] = router
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (client *Client) dial() *gtcp.Conn {
|
||||
for {
|
||||
conn, err := gtcp.NewConn(client.addr, client.timeout)
|
||||
if err == nil || client.closeFlag {
|
||||
return conn
|
||||
}
|
||||
|
||||
if client.maxConnectCount > 0 {
|
||||
if client.connectCount < client.maxConnectCount {
|
||||
client.connectCount += 1
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
client.Logger.Debugf(client.Ctx, "connect to %v error: %v", client.addr, err)
|
||||
time.Sleep(client.connectInterval)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
func (client *Client) connect() {
|
||||
defer client.wg.Done()
|
||||
|
||||
goto reconnect
|
||||
reconnect:
|
||||
conn := client.dial()
|
||||
if conn == nil {
|
||||
client.Logger.Debugf(client.Ctx, "client dial failed")
|
||||
return
|
||||
}
|
||||
|
||||
client.Lock()
|
||||
if client.closeFlag {
|
||||
client.Unlock()
|
||||
conn.Close()
|
||||
client.Logger.Debugf(client.Ctx, "client connect but closeFlag is true")
|
||||
return
|
||||
}
|
||||
|
||||
client.conn = conn
|
||||
client.connectCount = 0
|
||||
client.heartbeat = gtime.Timestamp()
|
||||
|
||||
client.read()
|
||||
client.Unlock()
|
||||
|
||||
client.serverLogin()
|
||||
client.startCron()
|
||||
}
|
||||
|
||||
func (client *Client) read() {
|
||||
simple.SafeGo(client.Ctx, func(ctx context.Context) {
|
||||
defer func() {
|
||||
client.Close()
|
||||
client.Logger.Debugf(client.Ctx, "client are about to be reconnected..")
|
||||
time.Sleep(client.connectInterval)
|
||||
client.Start()
|
||||
}()
|
||||
|
||||
for {
|
||||
if client.conn == nil {
|
||||
client.Logger.Debugf(client.Ctx, "client client.conn is nil, server closed")
|
||||
break
|
||||
}
|
||||
|
||||
msg, err := RecvPkg(client.conn)
|
||||
if err != nil {
|
||||
client.Logger.Debugf(client.Ctx, "client RecvPkg err:%+v, server closed", err)
|
||||
break
|
||||
}
|
||||
|
||||
if client.routers == nil {
|
||||
client.Logger.Debugf(client.Ctx, "client RecvPkg routers is nil")
|
||||
break
|
||||
}
|
||||
|
||||
if msg == nil {
|
||||
client.Logger.Debugf(client.Ctx, "client RecvPkg msg is nil")
|
||||
break
|
||||
}
|
||||
|
||||
f, ok := client.routers[msg.Router]
|
||||
if !ok {
|
||||
client.Logger.Debugf(client.Ctx, "client RecvPkg invalid message: %+v", msg)
|
||||
continue
|
||||
}
|
||||
f(msg.Data, client.conn)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Close 关闭同服务器的链接
|
||||
func (client *Client) Close() {
|
||||
client.Lock()
|
||||
defer client.Unlock()
|
||||
|
||||
client.IsLogin = false
|
||||
client.closeFlag = true
|
||||
if client.conn != nil {
|
||||
client.conn.Close()
|
||||
client.conn = nil
|
||||
}
|
||||
|
||||
if client.closeEvent != nil {
|
||||
client.closeEvent()
|
||||
}
|
||||
client.wg.Wait()
|
||||
}
|
||||
|
||||
// Stop 停止服务
|
||||
func (client *Client) Stop() {
|
||||
if client.stopFlag {
|
||||
return
|
||||
}
|
||||
client.stopFlag = true
|
||||
client.stopCron()
|
||||
client.Close()
|
||||
}
|
||||
|
||||
// Destroy 销毁当前连接
|
||||
func (client *Client) Destroy() {
|
||||
client.stopCron()
|
||||
if client.conn != nil {
|
||||
client.conn.Close()
|
||||
client.conn = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Write
|
||||
func (client *Client) Write(data interface{}) error {
|
||||
client.Lock()
|
||||
defer client.Unlock()
|
||||
|
||||
if client.conn == nil {
|
||||
return gerror.New("client conn is nil")
|
||||
}
|
||||
|
||||
if client.closeFlag {
|
||||
return gerror.New("client conn is closed")
|
||||
}
|
||||
|
||||
if data == nil {
|
||||
return gerror.New("client Write message is nil")
|
||||
}
|
||||
|
||||
// 签名
|
||||
SetSign(data, gctx.CtxId(client.Ctx), client.auth.AppId, client.auth.SecretKey)
|
||||
|
||||
msgType := reflect.TypeOf(data)
|
||||
if msgType == nil || msgType.Kind() != reflect.Ptr {
|
||||
return gerror.Newf("client json message pointer required: %+v", data)
|
||||
}
|
||||
msg := &Message{Router: msgType.Elem().Name(), Data: data}
|
||||
|
||||
client.Logger.Debugf(client.Ctx, "client Write Router:%v, data:%+v", msg.Router, gjson.New(data).String())
|
||||
|
||||
return SendPkg(client.conn, msg)
|
||||
}
|
37
server/internal/library/network/tcp/client_cron.go
Normal file
37
server/internal/library/network/tcp/client_cron.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/os/gcron"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
func (client *Client) getCronKey(s string) string {
|
||||
return fmt.Sprintf("tcp.client_%s_%s:%s", s, client.auth.Group, client.auth.Name)
|
||||
}
|
||||
|
||||
func (client *Client) stopCron() {
|
||||
for _, v := range gcron.Entries() {
|
||||
gcron.Remove(v.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func (client *Client) startCron() {
|
||||
// 心跳超时检查
|
||||
if gcron.Search(client.getCronKey(cronHeartbeatVerify)) == nil {
|
||||
gcron.AddSingleton(client.Ctx, "@every 600s", func(ctx context.Context) {
|
||||
if client.heartbeat < gtime.Timestamp()-600 {
|
||||
client.Logger.Debugf(client.Ctx, "client heartbeat timeout, about to reconnect..")
|
||||
client.Destroy()
|
||||
}
|
||||
}, client.getCronKey(cronHeartbeatVerify))
|
||||
}
|
||||
|
||||
// 心跳
|
||||
if gcron.Search(client.getCronKey(cronHeartbeat)) == nil {
|
||||
gcron.AddSingleton(client.Ctx, "@every 120s", func(ctx context.Context) {
|
||||
client.serverHeartbeat()
|
||||
}, client.getCronKey(cronHeartbeat))
|
||||
}
|
||||
}
|
61
server/internal/library/network/tcp/client_handle.go
Normal file
61
server/internal/library/network/tcp/client_handle.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"hotgo/internal/model/input/msgin"
|
||||
)
|
||||
|
||||
// serverLogin 心跳
|
||||
func (client *Client) serverHeartbeat() {
|
||||
if err := client.Write(&msgin.ServerHeartbeat{}); err != nil {
|
||||
client.Logger.Debugf(client.Ctx, "client WriteMsg ServerHeartbeat err:%+v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// serverLogin 服务登陆
|
||||
func (client *Client) serverLogin() {
|
||||
data := &msgin.ServerLogin{
|
||||
Group: client.auth.Group,
|
||||
Name: client.auth.Name,
|
||||
}
|
||||
|
||||
if err := client.Write(data); err != nil {
|
||||
client.Logger.Debugf(client.Ctx, "client WriteMsg ServerLogin err:%+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if client.loginEvent != nil {
|
||||
client.loginEvent()
|
||||
}
|
||||
}
|
||||
|
||||
func (client *Client) onResponseServerLogin(args ...interface{}) {
|
||||
var in *msgin.ResponseServerLogin
|
||||
if err := gconv.Scan(args[0], &in); err != nil {
|
||||
client.Logger.Infof(client.Ctx, "onResponseServerLogin message Scan failed:%+v, args:%+v", err, args[0])
|
||||
return
|
||||
}
|
||||
client.Logger.Infof(client.Ctx, "onResponseServerLogin in:%+v", *in)
|
||||
|
||||
if in.Code != gcode.CodeOK.Code() {
|
||||
client.IsLogin = false
|
||||
client.Logger.Warningf(client.Ctx, "onResponseServerLogin quit err:%v", in.Message)
|
||||
client.Destroy()
|
||||
return
|
||||
}
|
||||
client.IsLogin = true
|
||||
}
|
||||
|
||||
func (client *Client) onResponseServerHeartbeat(args ...interface{}) {
|
||||
var in *msgin.ResponseServerHeartbeat
|
||||
if err := gconv.Scan(args[0], &in); err != nil {
|
||||
client.Logger.Infof(client.Ctx, "onResponseServerHeartbeat message Scan failed:%+v, args:%+v", err, args)
|
||||
return
|
||||
}
|
||||
|
||||
client.heartbeat = gtime.Timestamp()
|
||||
client.Logger.Infof(client.Ctx, "onResponseServerHeartbeat in:%+v", *in)
|
||||
}
|
25
server/internal/library/network/tcp/model.go
Normal file
25
server/internal/library/network/tcp/model.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package tcp
|
||||
|
||||
// 定时任务
|
||||
const (
|
||||
cronHeartbeatVerify = "tcpHeartbeatVerify"
|
||||
cronHeartbeat = "tcpHeartbeat"
|
||||
)
|
||||
|
||||
// 认证分组
|
||||
const (
|
||||
ClientGroupCron = "cron" // 定时任务
|
||||
ClientGroupQueue = "queue" // 消息队列
|
||||
ClientGroupAuth = "auth" // 服务授权
|
||||
)
|
||||
|
||||
// AuthMeta 认证元数据
|
||||
type AuthMeta struct {
|
||||
Group string `json:"group"`
|
||||
Name string `json:"name"`
|
||||
AppId string `json:"appId"`
|
||||
SecretKey string `json:"secretKey"`
|
||||
}
|
||||
|
||||
// CallbackEvent 回调事件
|
||||
type CallbackEvent func()
|
39
server/internal/library/network/tcp/router.go
Normal file
39
server/internal/library/network/tcp/router.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/net/gtcp"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
type RouterHandler func(args ...interface{})
|
||||
|
||||
// Message 路由消息
|
||||
type Message struct {
|
||||
Router string `json:"router"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
func SendPkg(conn *gtcp.Conn, message *Message) error {
|
||||
b, err := json.Marshal(message)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return conn.SendPkg(b)
|
||||
}
|
||||
|
||||
func RecvPkg(conn *gtcp.Conn) (*Message, error) {
|
||||
if data, err := conn.RecvPkg(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
var msg = new(Message)
|
||||
if err = gconv.Scan(data, &msg); err != nil {
|
||||
return nil, gerror.Newf("invalid package structure: %s", err.Error())
|
||||
}
|
||||
if msg.Router == "" {
|
||||
return nil, gerror.Newf("message is not routed: %+v", msg)
|
||||
}
|
||||
return msg, err
|
||||
}
|
||||
}
|
278
server/internal/library/network/tcp/server.go
Normal file
278
server/internal/library/network/tcp/server.go
Normal file
@@ -0,0 +1,278 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/gtcp"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/glog"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ClientConn struct {
|
||||
Conn *gtcp.Conn
|
||||
Auth *AuthMeta
|
||||
heartbeat int64
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
Name string // 服务名称
|
||||
Addr string // 监听地址
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
Ctx context.Context
|
||||
Logger *glog.Logger
|
||||
addr string
|
||||
name string
|
||||
ln *gtcp.Server
|
||||
wgLn sync.WaitGroup
|
||||
mutex sync.Mutex
|
||||
closeFlag bool
|
||||
clients map[string]*ClientConn // 已登录的认证客户端
|
||||
mutexConns sync.Mutex
|
||||
wgConns sync.WaitGroup
|
||||
cronRouters map[string]RouterHandler // 路由
|
||||
queueRouters map[string]RouterHandler
|
||||
authRouters map[string]RouterHandler
|
||||
}
|
||||
|
||||
func NewServer(config *ServerConfig) (server *Server, err error) {
|
||||
if config == nil {
|
||||
err = gerror.New("config is nil")
|
||||
return
|
||||
}
|
||||
|
||||
if config.Addr == "" {
|
||||
err = gerror.New("server address is not set")
|
||||
return
|
||||
}
|
||||
|
||||
if config.Name == "" {
|
||||
config.Name = "hotgo"
|
||||
}
|
||||
|
||||
server = new(Server)
|
||||
server.Ctx = gctx.New()
|
||||
server.addr = config.Addr
|
||||
server.name = config.Name
|
||||
server.ln = gtcp.NewServer(server.addr, server.accept, config.Name)
|
||||
server.clients = make(map[string]*ClientConn)
|
||||
server.closeFlag = false
|
||||
|
||||
logger := glog.New()
|
||||
path := g.Cfg().MustGet(server.Ctx, "logger.path", "logs/logger").String()
|
||||
if err = logger.SetPath(fmt.Sprintf("%s/tcp.server/%s", path, config.Name)); err != nil {
|
||||
return
|
||||
}
|
||||
server.Logger = logger
|
||||
|
||||
server.startCron()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (server *Server) accept(conn *gtcp.Conn) {
|
||||
defer func() {
|
||||
server.mutexConns.Lock()
|
||||
conn.Close()
|
||||
// 从登录列表中移除
|
||||
if _, ok := server.clients[conn.RemoteAddr().String()]; ok {
|
||||
delete(server.clients, conn.RemoteAddr().String())
|
||||
}
|
||||
server.mutexConns.Unlock()
|
||||
}()
|
||||
|
||||
for {
|
||||
msg, err := RecvPkg(conn)
|
||||
if err != nil {
|
||||
server.Logger.Debugf(server.Ctx, "RecvPkg err:%+v, client closed.", err)
|
||||
break
|
||||
}
|
||||
|
||||
client := server.getLoginConn(conn)
|
||||
|
||||
switch msg.Router {
|
||||
case "ServerLogin": // 服务登录
|
||||
server.onServerLogin(msg.Data, conn)
|
||||
case "ServerHeartbeat": // 心跳
|
||||
if client == nil {
|
||||
server.Logger.Infof(server.Ctx, "conn not connected, ignore the heartbeat, msg:%+v", msg)
|
||||
continue
|
||||
}
|
||||
server.onServerHeartbeat(msg, client)
|
||||
default: // 通用路由消息处理
|
||||
if client == nil {
|
||||
server.Logger.Warningf(server.Ctx, "conn is not logged in but sends a routing message. actively conn disconnect, msg:%+v", msg)
|
||||
time.Sleep(time.Second)
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
server.handleRouterMsg(msg, client)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handleRouterMsg 处理路由消息
|
||||
func (server *Server) handleRouterMsg(msg *Message, client *ClientConn) {
|
||||
|
||||
// 验证签名
|
||||
err := VerifySign(msg.Data, client.Auth.AppId, client.Auth.SecretKey)
|
||||
if err != nil {
|
||||
server.Logger.Warningf(server.Ctx, "handleRouterMsg VerifySign err:%+v message: %+v", err, msg)
|
||||
return
|
||||
}
|
||||
|
||||
handle := func(routers map[string]RouterHandler, group string) {
|
||||
if routers == nil {
|
||||
server.Logger.Debugf(server.Ctx, "handleRouterMsg route is not initialized %v message: %+v", group, msg)
|
||||
return
|
||||
}
|
||||
f, ok := routers[msg.Router]
|
||||
if !ok {
|
||||
server.Logger.Debugf(server.Ctx, "handleRouterMsg invalid %v message: %+v", group, msg)
|
||||
return
|
||||
}
|
||||
f(msg.Data, client)
|
||||
}
|
||||
|
||||
switch client.Auth.Group {
|
||||
case ClientGroupCron:
|
||||
handle(server.cronRouters, client.Auth.Group)
|
||||
case ClientGroupQueue:
|
||||
handle(server.queueRouters, client.Auth.Group)
|
||||
case ClientGroupAuth:
|
||||
handle(server.authRouters, client.Auth.Group)
|
||||
default:
|
||||
server.Logger.Warningf(server.Ctx, "group is not registered: %+v", client.Auth.Group)
|
||||
}
|
||||
}
|
||||
|
||||
// getLoginConn 获取指定已登录的连接
|
||||
func (server *Server) getLoginConn(conn *gtcp.Conn) *ClientConn {
|
||||
client, ok := server.clients[conn.RemoteAddr().String()]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// getLoginConn 获取指定appid的所有连接
|
||||
func (server *Server) getAppIdClients(appid string) (list []*ClientConn) {
|
||||
for _, v := range server.clients {
|
||||
if v.Auth.AppId == appid {
|
||||
list = append(list, v)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// RegisterAuthRouter 注册授权路由
|
||||
func (server *Server) RegisterAuthRouter(routers map[string]RouterHandler) {
|
||||
server.mutex.Lock()
|
||||
defer server.mutex.Unlock()
|
||||
|
||||
if server.authRouters == nil {
|
||||
server.authRouters = make(map[string]RouterHandler)
|
||||
}
|
||||
|
||||
for i, router := range routers {
|
||||
_, ok := server.authRouters[i]
|
||||
if ok {
|
||||
server.Logger.Debugf(server.Ctx, "server authRouters duplicate registration:%v", i)
|
||||
continue
|
||||
}
|
||||
server.authRouters[i] = router
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterCronRouter 注册任务路由
|
||||
func (server *Server) RegisterCronRouter(routers map[string]RouterHandler) {
|
||||
server.mutex.Lock()
|
||||
defer server.mutex.Unlock()
|
||||
|
||||
if server.cronRouters == nil {
|
||||
server.cronRouters = make(map[string]RouterHandler)
|
||||
}
|
||||
|
||||
for i, router := range routers {
|
||||
_, ok := server.cronRouters[i]
|
||||
if ok {
|
||||
server.Logger.Debugf(server.Ctx, "server cronRouters duplicate registration:%v", i)
|
||||
continue
|
||||
}
|
||||
server.cronRouters[i] = router
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterQueueRouter 注册队列路由
|
||||
func (server *Server) RegisterQueueRouter(routers map[string]RouterHandler) {
|
||||
server.mutex.Lock()
|
||||
defer server.mutex.Unlock()
|
||||
|
||||
if server.queueRouters == nil {
|
||||
server.queueRouters = make(map[string]RouterHandler)
|
||||
}
|
||||
|
||||
for i, router := range routers {
|
||||
_, ok := server.queueRouters[i]
|
||||
if ok {
|
||||
server.Logger.Debugf(server.Ctx, "server queueRouters duplicate registration:%v", i)
|
||||
continue
|
||||
}
|
||||
server.queueRouters[i] = router
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) Listen() (err error) {
|
||||
server.wgLn.Add(1)
|
||||
defer server.wgLn.Done()
|
||||
return server.ln.Run()
|
||||
}
|
||||
|
||||
// Close 关闭服务
|
||||
func (server *Server) Close() {
|
||||
if server.closeFlag {
|
||||
return
|
||||
}
|
||||
server.closeFlag = true
|
||||
|
||||
server.stopCron()
|
||||
|
||||
server.mutexConns.Lock()
|
||||
for _, client := range server.clients {
|
||||
client.Conn.Close()
|
||||
}
|
||||
server.clients = nil
|
||||
server.mutexConns.Unlock()
|
||||
server.wgConns.Wait()
|
||||
|
||||
if server.ln != nil {
|
||||
server.ln.Close()
|
||||
}
|
||||
server.wgLn.Wait()
|
||||
}
|
||||
|
||||
// Write 向指定客户端发送消息
|
||||
func (server *Server) Write(conn *gtcp.Conn, data interface{}) (err error) {
|
||||
if server.closeFlag {
|
||||
return gerror.New("service is down")
|
||||
}
|
||||
|
||||
msgType := reflect.TypeOf(data)
|
||||
if msgType == nil || msgType.Kind() != reflect.Ptr {
|
||||
return gerror.Newf("json message pointer required: %+v", data)
|
||||
}
|
||||
|
||||
msg := &Message{Router: msgType.Elem().Name(), Data: data}
|
||||
|
||||
server.Logger.Debugf(server.Ctx, "server Write Router:%v, data:%+v", msg.Router, gjson.New(data).String())
|
||||
|
||||
return SendPkg(conn, msg)
|
||||
}
|
35
server/internal/library/network/tcp/server_cron.go
Normal file
35
server/internal/library/network/tcp/server_cron.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/os/gcron"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
func (server *Server) getCronKey(s string) string {
|
||||
return fmt.Sprintf("tcp.server_%s_%s", s, server.name)
|
||||
}
|
||||
|
||||
func (server *Server) stopCron() {
|
||||
for _, v := range gcron.Entries() {
|
||||
gcron.Remove(v.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) startCron() {
|
||||
// 心跳超时检查
|
||||
if gcron.Search(server.getCronKey(cronHeartbeatVerify)) == nil {
|
||||
gcron.AddSingleton(server.Ctx, "@every 300s", func(ctx context.Context) {
|
||||
if server.clients == nil {
|
||||
return
|
||||
}
|
||||
for _, client := range server.clients {
|
||||
if client.heartbeat < gtime.Timestamp()-300 {
|
||||
client.Conn.Close()
|
||||
server.Logger.Debugf(server.Ctx, "client heartbeat timeout, about to reconnect.. auth:%+v", client.Auth)
|
||||
}
|
||||
}
|
||||
}, server.getCronKey(cronHeartbeatVerify))
|
||||
}
|
||||
}
|
150
server/internal/library/network/tcp/server_handle.go
Normal file
150
server/internal/library/network/tcp/server_handle.go
Normal file
@@ -0,0 +1,150 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/gtcp"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/msgin"
|
||||
"hotgo/utility/convert"
|
||||
)
|
||||
|
||||
func (server *Server) onServerLogin(args ...interface{}) {
|
||||
var (
|
||||
in = new(msgin.ServerLogin)
|
||||
conn = args[1].(*gtcp.Conn)
|
||||
res = new(msgin.ResponseServerLogin)
|
||||
models *entity.SysServeLicense
|
||||
)
|
||||
|
||||
if err := gconv.Scan(args[0], &in); err != nil {
|
||||
server.Logger.Infof(server.Ctx, "onServerLogin message Scan failed:%+v, args:%+v", err, args)
|
||||
return
|
||||
}
|
||||
server.Logger.Infof(server.Ctx, "onServerLogin in:%+v", *in)
|
||||
|
||||
err := g.Model("sys_serve_license").
|
||||
Ctx(server.Ctx).
|
||||
Where("appid = ?", in.AppId).
|
||||
Scan(&models)
|
||||
|
||||
if err != nil {
|
||||
res.Code = 1
|
||||
res.Message = err.Error()
|
||||
server.Write(conn, res)
|
||||
return
|
||||
}
|
||||
|
||||
if models == nil {
|
||||
res.Code = 2
|
||||
res.Message = "授权信息不存在"
|
||||
server.Write(conn, res)
|
||||
return
|
||||
}
|
||||
|
||||
// 验证签名
|
||||
if err = VerifySign(in, models.Appid, models.SecretKey); err != nil {
|
||||
res.Code = 3
|
||||
res.Message = "签名错误,请联系管理员"
|
||||
server.Write(conn, res)
|
||||
return
|
||||
}
|
||||
|
||||
if models.Status != consts.StatusEnabled {
|
||||
res.Code = 4
|
||||
res.Message = "授权已禁用,请联系管理员"
|
||||
server.Write(conn, res)
|
||||
return
|
||||
}
|
||||
|
||||
if models.Group != in.Group {
|
||||
res.Code = 5
|
||||
res.Message = "你登录的授权分组未得到授权,请联系管理员"
|
||||
server.Write(conn, res)
|
||||
return
|
||||
}
|
||||
|
||||
if models.EndAt.Before(gtime.Now()) {
|
||||
res.Code = 6
|
||||
res.Message = "授权已过期,请联系管理员"
|
||||
server.Write(conn, res)
|
||||
return
|
||||
}
|
||||
|
||||
allowedIps := convert.IpFilterStrategy(models.AllowedIps)
|
||||
if _, ok := allowedIps["*"]; !ok {
|
||||
ip := gstr.StrTillEx(conn.RemoteAddr().String(), ":")
|
||||
if _, ok2 := allowedIps[ip]; !ok2 {
|
||||
res.Code = 7
|
||||
res.Message = "IP(" + ip + ")未授权,请联系管理员"
|
||||
server.Write(conn, res)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否存在多地登录,如果连接超出上限,直接将所有已连接断开,然后在吧新的连接加入进来
|
||||
clients := server.getAppIdClients(models.Appid)
|
||||
online := len(clients) + 1
|
||||
if online > models.OnlineLimit {
|
||||
online = 1
|
||||
res2 := new(msgin.ResponseServerLogin)
|
||||
res2.Code = 8
|
||||
res2.Message = "授权登录端超出上限,请联系管理员"
|
||||
for _, client := range clients {
|
||||
server.Write(client.Conn, res2)
|
||||
client.Conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
server.mutexConns.Lock()
|
||||
server.clients[conn.RemoteAddr().String()] = &ClientConn{
|
||||
Conn: conn,
|
||||
Auth: &AuthMeta{
|
||||
Group: in.Group,
|
||||
Name: in.Name,
|
||||
AppId: in.AppId,
|
||||
SecretKey: models.SecretKey,
|
||||
},
|
||||
heartbeat: gtime.Timestamp(),
|
||||
}
|
||||
server.mutexConns.Unlock()
|
||||
|
||||
server.Write(conn, res)
|
||||
|
||||
_, err = g.Model("sys_serve_license").
|
||||
Ctx(server.Ctx).
|
||||
Where("id = ?", models.Id).Data(g.Map{
|
||||
"online": online,
|
||||
"login_times": models.LoginTimes + 1,
|
||||
"last_login_at": gtime.Now(),
|
||||
"last_active_at": gtime.Now(),
|
||||
"remote_addr": conn.RemoteAddr().String(),
|
||||
}).Update()
|
||||
if err != nil {
|
||||
server.Logger.Warningf(server.Ctx, "onServerLogin Update err:%+v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) onServerHeartbeat(args ...interface{}) {
|
||||
var in *msgin.ServerHeartbeat
|
||||
if err := gconv.Scan(args, &in); err != nil {
|
||||
server.Logger.Infof(server.Ctx, "onServerHeartbeat message Scan failed:%+v, args:%+v", err, args)
|
||||
return
|
||||
}
|
||||
client := args[1].(*ClientConn)
|
||||
client.heartbeat = gtime.Timestamp()
|
||||
|
||||
server.Write(client.Conn, &msgin.ResponseServerHeartbeat{})
|
||||
|
||||
_, err := g.Model("sys_serve_license").
|
||||
Ctx(server.Ctx).
|
||||
Where("appid = ?", client.Auth.AppId).Data(g.Map{
|
||||
"last_active_at": gtime.Now(),
|
||||
}).Update()
|
||||
if err != nil {
|
||||
server.Logger.Warningf(server.Ctx, "onServerHeartbeat Update err:%+v", err)
|
||||
}
|
||||
}
|
41
server/internal/library/network/tcp/sign.go
Normal file
41
server/internal/library/network/tcp/sign.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"hotgo/internal/model/input/msgin"
|
||||
)
|
||||
|
||||
type Sign interface {
|
||||
SetSign(traceID, appId, secretKey string)
|
||||
}
|
||||
|
||||
// SetSign 设置签名
|
||||
func SetSign(data interface{}, traceID, appId, secretKey string) {
|
||||
if c, ok := data.(Sign); ok {
|
||||
c.SetSign(traceID, appId, secretKey)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// VerifySign 验证签名
|
||||
func VerifySign(data interface{}, appId, secretKey string) (err error) {
|
||||
// 无密钥,无需签名
|
||||
if secretKey == "" {
|
||||
return
|
||||
}
|
||||
|
||||
var in *msgin.Request
|
||||
if err = gconv.Scan(data, &in); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if appId != in.AppId {
|
||||
return gerror.New("appId invalid")
|
||||
}
|
||||
|
||||
if in.Sign != in.GetSign(secretKey) {
|
||||
return gerror.New("sign invalid")
|
||||
}
|
||||
return
|
||||
}
|
@@ -10,5 +10,7 @@ import (
|
||||
_ "hotgo/internal/logic/hook"
|
||||
_ "hotgo/internal/logic/middleware"
|
||||
_ "hotgo/internal/logic/sys"
|
||||
_ "hotgo/internal/logic/tcpclient"
|
||||
_ "hotgo/internal/logic/tcpserver"
|
||||
_ "hotgo/internal/logic/view"
|
||||
)
|
||||
|
@@ -3,7 +3,6 @@
|
||||
// @Copyright Copyright (c) 2023 HotGo CLI
|
||||
// @Author Ms <133814250@qq.com>
|
||||
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
|
||||
//
|
||||
package sys
|
||||
|
||||
import (
|
||||
@@ -11,13 +10,12 @@ import (
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/global"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
"hotgo/internal/service"
|
||||
"hotgo/utility/convert"
|
||||
"hotgo/utility/validate"
|
||||
)
|
||||
|
||||
@@ -176,91 +174,12 @@ func (s *sSysBlacklist) Load(ctx context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
matchStrategy := func(originIp string) {
|
||||
// 多个IP
|
||||
if gstr.Contains(originIp, ",") {
|
||||
ips := gstr.Explode(",", originIp)
|
||||
if len(ips) > 0 {
|
||||
for _, ip := range ips {
|
||||
if !validate.IsIp(ip) {
|
||||
continue
|
||||
}
|
||||
global.Blacklists[ip] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// IP段
|
||||
if gstr.Contains(originIp, "/24") {
|
||||
segment := gstr.Replace(originIp, "/24", "")
|
||||
if !validate.IsIp(segment) {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
start = gstr.Explode(".", segment)
|
||||
prefix = gstr.Implode(".", start[:len(start)-1]) + "."
|
||||
index = gconv.Int(start[len(start)-1])
|
||||
)
|
||||
|
||||
if index < 1 {
|
||||
index = 1
|
||||
}
|
||||
|
||||
for i := index; i <= 254; i++ {
|
||||
global.Blacklists[prefix+gconv.String(i)] = struct{}{}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// IP范围
|
||||
if gstr.Contains(originIp, "-") {
|
||||
originIps := gstr.Explode("-", originIp)
|
||||
if len(originIps) != 2 {
|
||||
return
|
||||
}
|
||||
|
||||
if !validate.IsIp(originIps[0]) || !validate.IsIp(originIps[1]) {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
start = gstr.Explode(".", originIps[0])
|
||||
prefix = gstr.Implode(".", start[:len(start)-1]) + "."
|
||||
startIndex = gconv.Int(gstr.SubStrFromREx(originIps[0], "."))
|
||||
endIndex = gconv.Int(gstr.SubStrFromREx(originIps[1], "."))
|
||||
)
|
||||
|
||||
if startIndex >= endIndex {
|
||||
global.Blacklists[originIps[0]] = struct{}{}
|
||||
return
|
||||
}
|
||||
|
||||
if startIndex < 1 {
|
||||
startIndex = 1
|
||||
}
|
||||
|
||||
if endIndex > 254 {
|
||||
endIndex = 254
|
||||
}
|
||||
|
||||
for i := startIndex; i <= endIndex; i++ {
|
||||
global.Blacklists[prefix+gconv.String(i)] = struct{}{}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 指定IP
|
||||
if validate.IsIp(originIp) {
|
||||
global.Blacklists[originIp] = struct{}{}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range array {
|
||||
matchStrategy(v.String())
|
||||
list := convert.IpFilterStrategy(v.String())
|
||||
if len(list) > 0 {
|
||||
for k, _ := range list {
|
||||
global.Blacklists[k] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
110
server/internal/logic/tcpclient/auth.go
Normal file
110
server/internal/logic/tcpclient/auth.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package tcpclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcron"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"hotgo/internal/library/network/tcp"
|
||||
"hotgo/internal/model/input/msgin"
|
||||
"hotgo/internal/service"
|
||||
"hotgo/utility/simple"
|
||||
)
|
||||
|
||||
// tcp授权
|
||||
type sTCPAuth struct {
|
||||
client *tcp.Client
|
||||
}
|
||||
|
||||
func init() {
|
||||
service.RegisterTCPAuth(newTCPAuth())
|
||||
}
|
||||
|
||||
func newTCPAuth() *sTCPAuth {
|
||||
return &sTCPAuth{}
|
||||
}
|
||||
|
||||
// Start 启动服务
|
||||
func (s *sTCPAuth) Start(ctx context.Context) {
|
||||
g.Log().Debug(ctx, "TCPAuth start..")
|
||||
simple.SafeGo(ctx, func(ctx context.Context) {
|
||||
client, err := tcp.NewClient(&tcp.ClientConfig{
|
||||
Addr: "127.0.0.1:8099",
|
||||
Auth: &tcp.AuthMeta{
|
||||
Group: "auth",
|
||||
Name: "auth1",
|
||||
AppId: "mengshuai",
|
||||
SecretKey: "123456",
|
||||
},
|
||||
LoginEvent: s.loginEvent,
|
||||
CloseEvent: s.closeEvent,
|
||||
})
|
||||
if err != nil {
|
||||
g.Log().Infof(ctx, "TCPAuth NewClient fail:%+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
s.client = client
|
||||
|
||||
err = s.client.RegisterRouter(map[string]tcp.RouterHandler{
|
||||
"ResponseAuthSummary": s.onResponseAuthSummary, // 获取授权信息
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
g.Log().Infof(ctx, "TCPAuth RegisterRouter fail:%+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = s.client.Start(); err != nil {
|
||||
g.Log().Infof(ctx, "TCPAuth Start fail:%+v", err)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Stop 关闭服务
|
||||
func (s *sTCPAuth) Stop(ctx context.Context) {
|
||||
if s.client != nil {
|
||||
s.client.Stop()
|
||||
g.Log().Debug(ctx, "TCPAuth stop..")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sTCPAuth) loginEvent() {
|
||||
// 登录成功后立即请求一次授权信息
|
||||
s.client.Write(&msgin.AuthSummary{})
|
||||
|
||||
// 定时检查授权
|
||||
gcron.Add(s.client.Ctx, "@every 1200s", func(ctx context.Context) {
|
||||
if !s.client.IsLogin {
|
||||
g.Log().Infof(ctx, "TCPAuthVerify client is not logged in, skipped")
|
||||
return
|
||||
}
|
||||
s.client.Write(&msgin.AuthSummary{})
|
||||
}, "TCPAuthVerify")
|
||||
}
|
||||
|
||||
func (s *sTCPAuth) closeEvent() {
|
||||
// 关闭连接后,删除定时检查授权
|
||||
gcron.Remove("TCPAuthVerify")
|
||||
}
|
||||
|
||||
func (s *sTCPAuth) onResponseAuthSummary(args ...interface{}) {
|
||||
var in *msgin.ResponseAuthSummary
|
||||
if err := gconv.Scan(args[0], &in); err != nil {
|
||||
s.client.Logger.Infof(s.client.Ctx, "ResponseAuthSummary message Scan failed:%+v, args:%+v", err, args[0])
|
||||
return
|
||||
}
|
||||
s.client.Logger.Infof(s.client.Ctx, "onResponseAuthSummary in:%+v", *in)
|
||||
|
||||
// 授权异常
|
||||
if in.Code != gcode.CodeOK.Code() {
|
||||
s.client.Logger.Infof(s.client.Ctx, "onResponseAuthSummary authorization verification failed:%+v", in.Message)
|
||||
s.client.Destroy()
|
||||
return
|
||||
}
|
||||
|
||||
// 授权通过
|
||||
// 后续可以做一些操作...
|
||||
}
|
73
server/internal/logic/tcpserver/auth_handle.go
Normal file
73
server/internal/logic/tcpserver/auth_handle.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package tcpserver
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/network/tcp"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/msgin"
|
||||
)
|
||||
|
||||
// onAuthSummary 获取授权信息
|
||||
func (s *sTCPServer) onAuthSummary(args ...interface{}) {
|
||||
var (
|
||||
in *msgin.AuthSummary
|
||||
client = args[1].(*tcp.ClientConn)
|
||||
res = new(msgin.ResponseAuthSummary)
|
||||
models *entity.SysServeLicense
|
||||
)
|
||||
|
||||
if err := gconv.Scan(args, &in); err != nil {
|
||||
s.serv.Logger.Infof(s.serv.Ctx, "onAuthSummary message Scan failed:%+v, args:%+v", err, args)
|
||||
return
|
||||
}
|
||||
|
||||
if client.Auth == nil {
|
||||
res.Code = 1
|
||||
res.Message = "登录信息获取失败,请重新登录"
|
||||
s.serv.Write(client.Conn, res)
|
||||
return
|
||||
}
|
||||
|
||||
if err := dao.SysServeLicense.Ctx(s.serv.Ctx).Where("appid = ?", client.Auth.AppId).Scan(&models); err != nil {
|
||||
res.Code = 2
|
||||
res.Message = err.Error()
|
||||
s.serv.Write(client.Conn, res)
|
||||
return
|
||||
}
|
||||
|
||||
if models == nil {
|
||||
res.Code = 3
|
||||
res.Message = "授权信息不存在"
|
||||
s.serv.Write(client.Conn, res)
|
||||
return
|
||||
}
|
||||
|
||||
if models.Status != consts.StatusEnabled {
|
||||
res.Code = 4
|
||||
res.Message = "授权已禁用,请联系管理员"
|
||||
s.serv.Write(client.Conn, res)
|
||||
return
|
||||
}
|
||||
|
||||
if models.Group != client.Auth.Group {
|
||||
res.Code = 5
|
||||
res.Message = "你登录的授权分组未得到授权,请联系管理员"
|
||||
s.serv.Write(client.Conn, res)
|
||||
return
|
||||
}
|
||||
|
||||
if models.EndAt.Before(gtime.Now()) {
|
||||
res.Code = 6
|
||||
res.Message = "授权已过期,请联系管理员"
|
||||
s.serv.Write(client.Conn, res)
|
||||
return
|
||||
}
|
||||
|
||||
res.Data = new(msgin.AuthSummaryData)
|
||||
res.Data.EndAt = models.EndAt
|
||||
res.Data.Online = models.Online
|
||||
s.serv.Write(client.Conn, res)
|
||||
}
|
68
server/internal/logic/tcpserver/init.go
Normal file
68
server/internal/logic/tcpserver/init.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package tcpserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"hotgo/internal/library/network/tcp"
|
||||
"hotgo/internal/service"
|
||||
"hotgo/utility/simple"
|
||||
)
|
||||
|
||||
type sTCPServer struct {
|
||||
serv *tcp.Server
|
||||
}
|
||||
|
||||
func init() {
|
||||
service.RegisterTCPServer(newTCPServer())
|
||||
}
|
||||
|
||||
func newTCPServer() *sTCPServer {
|
||||
return &sTCPServer{}
|
||||
}
|
||||
|
||||
// Start 启动服务
|
||||
func (s *sTCPServer) Start(ctx context.Context) {
|
||||
simple.SafeGo(ctx, func(ctx context.Context) {
|
||||
g.Log().Debug(ctx, "TCPServer start..")
|
||||
|
||||
server, err := tcp.NewServer(&tcp.ServerConfig{
|
||||
Name: "hotgo",
|
||||
Addr: g.Cfg().MustGet(ctx, "tcpServe.address").String(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
g.Log().Warningf(ctx, "TCPServer start fail:%+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
s.serv = server
|
||||
|
||||
// 消息队列路由
|
||||
s.serv.RegisterQueueRouter(map[string]tcp.RouterHandler{
|
||||
// ...
|
||||
})
|
||||
|
||||
// 定时任务路由
|
||||
s.serv.RegisterCronRouter(map[string]tcp.RouterHandler{
|
||||
// ...
|
||||
})
|
||||
|
||||
// 授权服务路由
|
||||
s.serv.RegisterAuthRouter(map[string]tcp.RouterHandler{
|
||||
"AuthSummary": s.onAuthSummary, // 获取授权信息
|
||||
})
|
||||
|
||||
// 服务监听
|
||||
if err := s.serv.Listen(); err != nil {
|
||||
g.Log().Warningf(ctx, "TCPServer Listen err:%v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Stop 关闭服务
|
||||
func (s *sTCPServer) Stop(ctx context.Context) {
|
||||
if s.serv != nil {
|
||||
s.serv.Close()
|
||||
g.Log().Debug(ctx, "TCPServer stop..")
|
||||
}
|
||||
}
|
35
server/internal/model/do/sys_serve_license.go
Normal file
35
server/internal/model/do/sys_serve_license.go
Normal file
@@ -0,0 +1,35 @@
|
||||
// =================================================================================
|
||||
// Code generated by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// SysServeLicense is the golang structure of table hg_sys_serve_license for DAO operations like Where/Data.
|
||||
type SysServeLicense struct {
|
||||
g.Meta `orm:"table:hg_sys_serve_license, do:true"`
|
||||
Id interface{} // 许可ID
|
||||
Group interface{} // 分组
|
||||
Name interface{} // 许可名称
|
||||
Appid interface{} // 应用ID
|
||||
SecretKey interface{} // 应用秘钥
|
||||
Desc interface{} // 授权说明
|
||||
RemoteAddr interface{} // 最后连接地址
|
||||
Online interface{} // 在线数量
|
||||
OnlineLimit interface{} // 在线数量限制,默认1
|
||||
LoginTimes interface{} // 登录次数
|
||||
LastLoginAt *gtime.Time // 最后登录时间
|
||||
LastActiveAt *gtime.Time // 最后活跃时间
|
||||
Routes *gjson.Json // 路由表,空使用默认分组路由
|
||||
AllowedIps interface{} // 白名单,*代表所有,只有允许的IP才能连接到tcp服务
|
||||
EndAt *gtime.Time // 授权结束时间
|
||||
Remark interface{} // 备注
|
||||
Status interface{} // 状态
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
UpdatedAt *gtime.Time // 修改时间
|
||||
}
|
33
server/internal/model/entity/sys_serve_license.go
Normal file
33
server/internal/model/entity/sys_serve_license.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// =================================================================================
|
||||
// Code generated by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package entity
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// SysServeLicense is the golang structure for table sys_serve_license.
|
||||
type SysServeLicense struct {
|
||||
Id int64 `json:"id" description:"许可ID"`
|
||||
Group string `json:"group" description:"分组"`
|
||||
Name string `json:"name" description:"许可名称"`
|
||||
Appid string `json:"appid" description:"应用ID"`
|
||||
SecretKey string `json:"secretKey" description:"应用秘钥"`
|
||||
Desc string `json:"desc" description:"授权说明"`
|
||||
RemoteAddr string `json:"remoteAddr" description:"最后连接地址"`
|
||||
Online int `json:"online" description:"在线数量"`
|
||||
OnlineLimit int `json:"onlineLimit" description:"在线数量限制,默认1"`
|
||||
LoginTimes int64 `json:"loginTimes" description:"登录次数"`
|
||||
LastLoginAt *gtime.Time `json:"lastLoginAt" description:"最后登录时间"`
|
||||
LastActiveAt *gtime.Time `json:"lastActiveAt" description:"最后活跃时间"`
|
||||
Routes *gjson.Json `json:"routes" description:"路由表,空使用默认分组路由"`
|
||||
AllowedIps string `json:"allowedIps" description:"白名单,*代表所有,只有允许的IP才能连接到tcp服务"`
|
||||
EndAt *gtime.Time `json:"endAt" description:"授权结束时间"`
|
||||
Remark string `json:"remark" description:"备注"`
|
||||
Status int `json:"status" description:"状态"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" description:"修改时间"`
|
||||
}
|
19
server/internal/model/input/msgin/auth.go
Normal file
19
server/internal/model/input/msgin/auth.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package msgin
|
||||
|
||||
import "github.com/gogf/gf/v2/os/gtime"
|
||||
|
||||
// AuthSummary 授权摘要
|
||||
type AuthSummary struct {
|
||||
Request
|
||||
}
|
||||
|
||||
// ResponseAuthSummary 响应授权摘要
|
||||
type ResponseAuthSummary struct {
|
||||
Response
|
||||
Data *AuthSummaryData `json:"data,omitempty" description:"数据集"`
|
||||
}
|
||||
|
||||
type AuthSummaryData struct {
|
||||
EndAt *gtime.Time `json:"end_at" description:"授权过期时间"`
|
||||
Online int `json:"online" description:"在线人数"`
|
||||
}
|
61
server/internal/model/input/msgin/common.go
Normal file
61
server/internal/model/input/msgin/common.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package msgin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"hotgo/utility/encrypt"
|
||||
)
|
||||
|
||||
type Request struct {
|
||||
AppId string `json:"appID" v:"0" example:"d0bb93048bc5c9164cdee845dcb7f820" description:"应用ID"`
|
||||
TraceID string `json:"traceID" v:"0" example:"d0bb93048bc5c9164cdee845dcb7f820" description:"链路ID"`
|
||||
Timestamp int64 `json:"timestamp" example:"1640966400" description:"服务器时间戳"`
|
||||
Sign string `json:"sign" example:"d0bb93048bc5c9164cdee845dcb7f820" description:"签名"`
|
||||
}
|
||||
|
||||
func (i *Request) SetSign(traceID, appId, secretKey string) {
|
||||
i.AppId = appId
|
||||
i.TraceID = traceID
|
||||
i.Timestamp = gtime.Timestamp()
|
||||
i.Sign = i.GetSign(secretKey)
|
||||
}
|
||||
|
||||
func (i *Request) GetSign(secretKey string) string {
|
||||
return encrypt.Md5ToString(fmt.Sprintf("%s%s%s%s", i.AppId, i.TraceID, i.Timestamp, secretKey))
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
Code int `json:"code" example:"0" description:"状态码"`
|
||||
Message string `json:"message,omitempty" example:"操作成功" description:"提示消息"`
|
||||
//Data interface{} `json:"data,omitempty" description:"数据集"`
|
||||
}
|
||||
|
||||
// ServerHeartbeat 心跳
|
||||
type ServerHeartbeat struct {
|
||||
}
|
||||
|
||||
// ResponseServerHeartbeat 响应心跳
|
||||
type ResponseServerHeartbeat struct {
|
||||
Response
|
||||
}
|
||||
|
||||
// ServerLogin 服务登录
|
||||
type ServerLogin struct {
|
||||
Request
|
||||
Group string
|
||||
Name string
|
||||
}
|
||||
|
||||
// ResponseServerLogin 响应服务登录
|
||||
type ResponseServerLogin struct {
|
||||
Response
|
||||
}
|
||||
|
||||
// ServerOffline 服务离线
|
||||
type ServerOffline struct {
|
||||
}
|
||||
|
||||
// ResponseServerOffline 响应服务离线
|
||||
type ResponseServerOffline struct {
|
||||
Response
|
||||
}
|
@@ -114,7 +114,6 @@ type (
|
||||
)
|
||||
|
||||
var (
|
||||
localAdminPost IAdminPost
|
||||
localAdminRole IAdminRole
|
||||
localAdminDept IAdminDept
|
||||
localAdminMember IAdminMember
|
||||
@@ -122,41 +121,9 @@ var (
|
||||
localAdminMenu IAdminMenu
|
||||
localAdminMonitor IAdminMonitor
|
||||
localAdminNotice IAdminNotice
|
||||
localAdminPost IAdminPost
|
||||
)
|
||||
|
||||
func AdminDept() IAdminDept {
|
||||
if localAdminDept == nil {
|
||||
panic("implement not found for interface IAdminDept, forgot register?")
|
||||
}
|
||||
return localAdminDept
|
||||
}
|
||||
|
||||
func RegisterAdminDept(i IAdminDept) {
|
||||
localAdminDept = i
|
||||
}
|
||||
|
||||
func AdminMember() IAdminMember {
|
||||
if localAdminMember == nil {
|
||||
panic("implement not found for interface IAdminMember, forgot register?")
|
||||
}
|
||||
return localAdminMember
|
||||
}
|
||||
|
||||
func RegisterAdminMember(i IAdminMember) {
|
||||
localAdminMember = i
|
||||
}
|
||||
|
||||
func AdminMemberPost() IAdminMemberPost {
|
||||
if localAdminMemberPost == nil {
|
||||
panic("implement not found for interface IAdminMemberPost, forgot register?")
|
||||
}
|
||||
return localAdminMemberPost
|
||||
}
|
||||
|
||||
func RegisterAdminMemberPost(i IAdminMemberPost) {
|
||||
localAdminMemberPost = i
|
||||
}
|
||||
|
||||
func AdminMenu() IAdminMenu {
|
||||
if localAdminMenu == nil {
|
||||
panic("implement not found for interface IAdminMenu, forgot register?")
|
||||
@@ -211,3 +178,36 @@ func AdminRole() IAdminRole {
|
||||
func RegisterAdminRole(i IAdminRole) {
|
||||
localAdminRole = i
|
||||
}
|
||||
|
||||
func AdminDept() IAdminDept {
|
||||
if localAdminDept == nil {
|
||||
panic("implement not found for interface IAdminDept, forgot register?")
|
||||
}
|
||||
return localAdminDept
|
||||
}
|
||||
|
||||
func RegisterAdminDept(i IAdminDept) {
|
||||
localAdminDept = i
|
||||
}
|
||||
|
||||
func AdminMember() IAdminMember {
|
||||
if localAdminMember == nil {
|
||||
panic("implement not found for interface IAdminMember, forgot register?")
|
||||
}
|
||||
return localAdminMember
|
||||
}
|
||||
|
||||
func RegisterAdminMember(i IAdminMember) {
|
||||
localAdminMember = i
|
||||
}
|
||||
|
||||
func AdminMemberPost() IAdminMemberPost {
|
||||
if localAdminMemberPost == nil {
|
||||
panic("implement not found for interface IAdminMemberPost, forgot register?")
|
||||
}
|
||||
return localAdminMemberPost
|
||||
}
|
||||
|
||||
func RegisterAdminMemberPost(i IAdminMemberPost) {
|
||||
localAdminMemberPost = i
|
||||
}
|
||||
|
@@ -17,148 +17,6 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
ISysAddonsConfig interface {
|
||||
GetConfigByGroup(ctx context.Context, in sysin.GetAddonsConfigInp) (res *sysin.GetAddonsConfigModel, err error)
|
||||
ConversionType(ctx context.Context, models *entity.SysAddonsConfig) (value interface{}, err error)
|
||||
UpdateConfigByGroup(ctx context.Context, in sysin.UpdateAddonsConfigInp) error
|
||||
}
|
||||
ISysAttachment interface {
|
||||
Delete(ctx context.Context, in sysin.AttachmentDeleteInp) error
|
||||
Edit(ctx context.Context, in sysin.AttachmentEditInp) (err error)
|
||||
Status(ctx context.Context, in sysin.AttachmentStatusInp) (err error)
|
||||
MaxSort(ctx context.Context, in sysin.AttachmentMaxSortInp) (*sysin.AttachmentMaxSortModel, error)
|
||||
View(ctx context.Context, in sysin.AttachmentViewInp) (res *sysin.AttachmentViewModel, err error)
|
||||
List(ctx context.Context, in sysin.AttachmentListInp) (list []*sysin.AttachmentListModel, totalCount int, err error)
|
||||
Add(ctx context.Context, meta *sysin.UploadFileMeta, fullPath, drive string) (data *entity.SysAttachment, err error)
|
||||
}
|
||||
ISysBlacklist interface {
|
||||
Delete(ctx context.Context, in sysin.BlacklistDeleteInp) (err error)
|
||||
Edit(ctx context.Context, in sysin.BlacklistEditInp) (err error)
|
||||
Status(ctx context.Context, in sysin.BlacklistStatusInp) (err error)
|
||||
MaxSort(ctx context.Context, in sysin.BlacklistMaxSortInp) (*sysin.BlacklistMaxSortModel, error)
|
||||
View(ctx context.Context, in sysin.BlacklistViewInp) (res *sysin.BlacklistViewModel, err error)
|
||||
List(ctx context.Context, in sysin.BlacklistListInp) (list []*sysin.BlacklistListModel, totalCount int, err error)
|
||||
VariableLoad(ctx context.Context, err error)
|
||||
Load(ctx context.Context)
|
||||
}
|
||||
ISysEmsLog interface {
|
||||
Delete(ctx context.Context, in sysin.EmsLogDeleteInp) error
|
||||
Edit(ctx context.Context, in sysin.EmsLogEditInp) (err error)
|
||||
Status(ctx context.Context, in sysin.EmsLogStatusInp) (err error)
|
||||
View(ctx context.Context, in sysin.EmsLogViewInp) (res *sysin.EmsLogViewModel, err error)
|
||||
List(ctx context.Context, in sysin.EmsLogListInp) (list []*sysin.EmsLogListModel, totalCount int, err error)
|
||||
Send(ctx context.Context, in sysin.SendEmsInp) (err error)
|
||||
GetTemplate(ctx context.Context, template string, config *model.EmailConfig) (val string, err error)
|
||||
AllowSend(ctx context.Context, models *entity.SysEmsLog, config *model.EmailConfig) (err error)
|
||||
VerifyCode(ctx context.Context, in sysin.VerifyEmsCodeInp) (err error)
|
||||
}
|
||||
ISysGenCodes interface {
|
||||
Delete(ctx context.Context, in sysin.GenCodesDeleteInp) error
|
||||
Edit(ctx context.Context, in sysin.GenCodesEditInp) (res *sysin.GenCodesEditModel, err error)
|
||||
Status(ctx context.Context, in sysin.GenCodesStatusInp) (err error)
|
||||
MaxSort(ctx context.Context, in sysin.GenCodesMaxSortInp) (*sysin.GenCodesMaxSortModel, error)
|
||||
View(ctx context.Context, in sysin.GenCodesViewInp) (res *sysin.GenCodesViewModel, err error)
|
||||
List(ctx context.Context, in sysin.GenCodesListInp) (list []*sysin.GenCodesListModel, totalCount int, err error)
|
||||
Selects(ctx context.Context, in sysin.GenCodesSelectsInp) (res *sysin.GenCodesSelectsModel, err error)
|
||||
TableSelect(ctx context.Context, in sysin.GenCodesTableSelectInp) (res []*sysin.GenCodesTableSelectModel, err error)
|
||||
ColumnSelect(ctx context.Context, in sysin.GenCodesColumnSelectInp) (res []*sysin.GenCodesColumnSelectModel, err error)
|
||||
ColumnList(ctx context.Context, in sysin.GenCodesColumnListInp) (res []*sysin.GenCodesColumnListModel, err error)
|
||||
Preview(ctx context.Context, in sysin.GenCodesPreviewInp) (res *sysin.GenCodesPreviewModel, err error)
|
||||
Build(ctx context.Context, in sysin.GenCodesBuildInp) (err error)
|
||||
}
|
||||
ISysServeLog interface {
|
||||
Model(ctx context.Context) *gdb.Model
|
||||
List(ctx context.Context, in sysin.ServeLogListInp) (list []*sysin.ServeLogListModel, totalCount int, err error)
|
||||
Export(ctx context.Context, in sysin.ServeLogListInp) (err error)
|
||||
Delete(ctx context.Context, in sysin.ServeLogDeleteInp) (err error)
|
||||
View(ctx context.Context, in sysin.ServeLogViewInp) (res *sysin.ServeLogViewModel, err error)
|
||||
RealWrite(ctx context.Context, models entity.SysServeLog) (err error)
|
||||
}
|
||||
ISysSmsLog interface {
|
||||
Delete(ctx context.Context, in sysin.SmsLogDeleteInp) error
|
||||
Edit(ctx context.Context, in sysin.SmsLogEditInp) (err error)
|
||||
Status(ctx context.Context, in sysin.SmsLogStatusInp) (err error)
|
||||
MaxSort(ctx context.Context, in sysin.SmsLogMaxSortInp) (*sysin.SmsLogMaxSortModel, error)
|
||||
View(ctx context.Context, in sysin.SmsLogViewInp) (res *sysin.SmsLogViewModel, err error)
|
||||
List(ctx context.Context, in sysin.SmsLogListInp) (list []*sysin.SmsLogListModel, totalCount int, err error)
|
||||
SendCode(ctx context.Context, in sysin.SendCodeInp) (err error)
|
||||
GetTemplate(ctx context.Context, template string, config *model.SmsConfig) (val string, err error)
|
||||
AllowSend(ctx context.Context, models *entity.SysSmsLog, config *model.SmsConfig) (err error)
|
||||
VerifyCode(ctx context.Context, in sysin.VerifyCodeInp) (err error)
|
||||
}
|
||||
ISysAddons interface {
|
||||
List(ctx context.Context, in sysin.AddonsListInp) (list []*sysin.AddonsListModel, totalCount int, err error)
|
||||
Selects(ctx context.Context, in sysin.AddonsSelectsInp) (res *sysin.AddonsSelectsModel, err error)
|
||||
Build(ctx context.Context, in sysin.AddonsBuildInp) (err error)
|
||||
Install(ctx context.Context, in sysin.AddonsInstallInp) (err error)
|
||||
Upgrade(ctx context.Context, in sysin.AddonsUpgradeInp) (err error)
|
||||
UnInstall(ctx context.Context, in sysin.AddonsUnInstallInp) (err error)
|
||||
}
|
||||
ISysConfig interface {
|
||||
GetLoadCache(ctx context.Context) (conf *model.CacheConfig, err error)
|
||||
GetLoadGenerate(ctx context.Context) (conf *model.GenerateConfig, err error)
|
||||
GetSms(ctx context.Context) (conf *model.SmsConfig, err error)
|
||||
GetGeo(ctx context.Context) (conf *model.GeoConfig, err error)
|
||||
GetUpload(ctx context.Context) (conf *model.UploadConfig, err error)
|
||||
GetSmtp(ctx context.Context) (conf *model.EmailConfig, err error)
|
||||
GetBasic(ctx context.Context) (conf *model.BasicConfig, err error)
|
||||
GetLoadSSL(ctx context.Context) (conf *model.SSLConfig, err error)
|
||||
GetLoadLog(ctx context.Context) (conf *model.LogConfig, err error)
|
||||
GetLoadServeLog(ctx context.Context) (conf *model.ServeLogConfig, err error)
|
||||
GetConfigByGroup(ctx context.Context, in sysin.GetConfigInp) (*sysin.GetConfigModel, error)
|
||||
ConversionType(ctx context.Context, models *entity.SysConfig) (value interface{}, err error)
|
||||
UpdateConfigByGroup(ctx context.Context, in sysin.UpdateConfigInp) error
|
||||
}
|
||||
ISysLog interface {
|
||||
Export(ctx context.Context, in sysin.LogListInp) (err error)
|
||||
RealWrite(ctx context.Context, commonLog entity.SysLog) (err error)
|
||||
AutoLog(ctx context.Context) error
|
||||
AnalysisLog(ctx context.Context) entity.SysLog
|
||||
View(ctx context.Context, in sysin.LogViewInp) (res *sysin.LogViewModel, err error)
|
||||
Delete(ctx context.Context, in sysin.LogDeleteInp) (err error)
|
||||
List(ctx context.Context, in sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error)
|
||||
}
|
||||
ISysLoginLog interface {
|
||||
Model(ctx context.Context) *gdb.Model
|
||||
List(ctx context.Context, in sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error)
|
||||
Export(ctx context.Context, in sysin.LoginLogListInp) (err error)
|
||||
Delete(ctx context.Context, in sysin.LoginLogDeleteInp) (err error)
|
||||
View(ctx context.Context, in sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error)
|
||||
Push(ctx context.Context, in sysin.LoginLogPushInp)
|
||||
RealWrite(ctx context.Context, models entity.SysLoginLog) (err error)
|
||||
}
|
||||
ISysCronGroup interface {
|
||||
Delete(ctx context.Context, in sysin.CronGroupDeleteInp) error
|
||||
Edit(ctx context.Context, in sysin.CronGroupEditInp) (err error)
|
||||
Status(ctx context.Context, in sysin.CronGroupStatusInp) (err error)
|
||||
MaxSort(ctx context.Context, in sysin.CronGroupMaxSortInp) (*sysin.CronGroupMaxSortModel, error)
|
||||
View(ctx context.Context, in sysin.CronGroupViewInp) (res *sysin.CronGroupViewModel, err error)
|
||||
List(ctx context.Context, in sysin.CronGroupListInp) (list []*sysin.CronGroupListModel, totalCount int, err error)
|
||||
Select(ctx context.Context, in sysin.CronGroupSelectInp) (res *sysin.CronGroupSelectModel, err error)
|
||||
}
|
||||
ISysCurdDemo interface {
|
||||
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
|
||||
List(ctx context.Context, in sysin.CurdDemoListInp) (list []*sysin.CurdDemoListModel, totalCount int, err error)
|
||||
Export(ctx context.Context, in sysin.CurdDemoListInp) (err error)
|
||||
Edit(ctx context.Context, in sysin.CurdDemoEditInp) (err error)
|
||||
Delete(ctx context.Context, in sysin.CurdDemoDeleteInp) (err error)
|
||||
MaxSort(ctx context.Context, in sysin.CurdDemoMaxSortInp) (res *sysin.CurdDemoMaxSortModel, err error)
|
||||
View(ctx context.Context, in sysin.CurdDemoViewInp) (res *sysin.CurdDemoViewModel, err error)
|
||||
Status(ctx context.Context, in sysin.CurdDemoStatusInp) (err error)
|
||||
Switch(ctx context.Context, in sysin.CurdDemoSwitchInp) (err error)
|
||||
}
|
||||
ISysDictData interface {
|
||||
Delete(ctx context.Context, in sysin.DictDataDeleteInp) error
|
||||
Edit(ctx context.Context, in sysin.DictDataEditInp) (err error)
|
||||
List(ctx context.Context, in sysin.DictDataListInp) (list []*sysin.DictDataListModel, totalCount int, err error)
|
||||
Select(ctx context.Context, in sysin.DataSelectInp) (list sysin.DataSelectModel, err error)
|
||||
}
|
||||
ISysDictType interface {
|
||||
Tree(ctx context.Context) (list []*sysin.DictTypeTree, err error)
|
||||
Delete(ctx context.Context, in sysin.DictTypeDeleteInp) error
|
||||
Edit(ctx context.Context, in sysin.DictTypeEditInp) (err error)
|
||||
TreeSelect(ctx context.Context, in sysin.DictTreeSelectInp) (list []*sysin.DictTypeTree, err error)
|
||||
}
|
||||
ISysProvinces interface {
|
||||
Tree(ctx context.Context) (list []g.Map, err error)
|
||||
Delete(ctx context.Context, in sysin.ProvincesDeleteInp) error
|
||||
@@ -181,28 +39,302 @@ type (
|
||||
List(ctx context.Context, in sysin.CronListInp) (list []*sysin.CronListModel, totalCount int, err error)
|
||||
OnlineExec(ctx context.Context, in sysin.OnlineExecInp) (err error)
|
||||
}
|
||||
ISysCronGroup interface {
|
||||
Delete(ctx context.Context, in sysin.CronGroupDeleteInp) error
|
||||
Edit(ctx context.Context, in sysin.CronGroupEditInp) (err error)
|
||||
Status(ctx context.Context, in sysin.CronGroupStatusInp) (err error)
|
||||
MaxSort(ctx context.Context, in sysin.CronGroupMaxSortInp) (*sysin.CronGroupMaxSortModel, error)
|
||||
View(ctx context.Context, in sysin.CronGroupViewInp) (res *sysin.CronGroupViewModel, err error)
|
||||
List(ctx context.Context, in sysin.CronGroupListInp) (list []*sysin.CronGroupListModel, totalCount int, err error)
|
||||
Select(ctx context.Context, in sysin.CronGroupSelectInp) (res *sysin.CronGroupSelectModel, err error)
|
||||
}
|
||||
ISysEmsLog interface {
|
||||
Delete(ctx context.Context, in sysin.EmsLogDeleteInp) error
|
||||
Edit(ctx context.Context, in sysin.EmsLogEditInp) (err error)
|
||||
Status(ctx context.Context, in sysin.EmsLogStatusInp) (err error)
|
||||
View(ctx context.Context, in sysin.EmsLogViewInp) (res *sysin.EmsLogViewModel, err error)
|
||||
List(ctx context.Context, in sysin.EmsLogListInp) (list []*sysin.EmsLogListModel, totalCount int, err error)
|
||||
Send(ctx context.Context, in sysin.SendEmsInp) (err error)
|
||||
GetTemplate(ctx context.Context, template string, config *model.EmailConfig) (val string, err error)
|
||||
AllowSend(ctx context.Context, models *entity.SysEmsLog, config *model.EmailConfig) (err error)
|
||||
VerifyCode(ctx context.Context, in sysin.VerifyEmsCodeInp) (err error)
|
||||
}
|
||||
ISysLoginLog interface {
|
||||
Model(ctx context.Context) *gdb.Model
|
||||
List(ctx context.Context, in sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error)
|
||||
Export(ctx context.Context, in sysin.LoginLogListInp) (err error)
|
||||
Delete(ctx context.Context, in sysin.LoginLogDeleteInp) (err error)
|
||||
View(ctx context.Context, in sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error)
|
||||
Push(ctx context.Context, in sysin.LoginLogPushInp)
|
||||
RealWrite(ctx context.Context, models entity.SysLoginLog) (err error)
|
||||
}
|
||||
ISysAddons interface {
|
||||
List(ctx context.Context, in sysin.AddonsListInp) (list []*sysin.AddonsListModel, totalCount int, err error)
|
||||
Selects(ctx context.Context, in sysin.AddonsSelectsInp) (res *sysin.AddonsSelectsModel, err error)
|
||||
Build(ctx context.Context, in sysin.AddonsBuildInp) (err error)
|
||||
Install(ctx context.Context, in sysin.AddonsInstallInp) (err error)
|
||||
Upgrade(ctx context.Context, in sysin.AddonsUpgradeInp) (err error)
|
||||
UnInstall(ctx context.Context, in sysin.AddonsUnInstallInp) (err error)
|
||||
}
|
||||
ISysGenCodes interface {
|
||||
Delete(ctx context.Context, in sysin.GenCodesDeleteInp) error
|
||||
Edit(ctx context.Context, in sysin.GenCodesEditInp) (res *sysin.GenCodesEditModel, err error)
|
||||
Status(ctx context.Context, in sysin.GenCodesStatusInp) (err error)
|
||||
MaxSort(ctx context.Context, in sysin.GenCodesMaxSortInp) (*sysin.GenCodesMaxSortModel, error)
|
||||
View(ctx context.Context, in sysin.GenCodesViewInp) (res *sysin.GenCodesViewModel, err error)
|
||||
List(ctx context.Context, in sysin.GenCodesListInp) (list []*sysin.GenCodesListModel, totalCount int, err error)
|
||||
Selects(ctx context.Context, in sysin.GenCodesSelectsInp) (res *sysin.GenCodesSelectsModel, err error)
|
||||
TableSelect(ctx context.Context, in sysin.GenCodesTableSelectInp) (res []*sysin.GenCodesTableSelectModel, err error)
|
||||
ColumnSelect(ctx context.Context, in sysin.GenCodesColumnSelectInp) (res []*sysin.GenCodesColumnSelectModel, err error)
|
||||
ColumnList(ctx context.Context, in sysin.GenCodesColumnListInp) (res []*sysin.GenCodesColumnListModel, err error)
|
||||
Preview(ctx context.Context, in sysin.GenCodesPreviewInp) (res *sysin.GenCodesPreviewModel, err error)
|
||||
Build(ctx context.Context, in sysin.GenCodesBuildInp) (err error)
|
||||
}
|
||||
ISysAddonsConfig interface {
|
||||
GetConfigByGroup(ctx context.Context, in sysin.GetAddonsConfigInp) (res *sysin.GetAddonsConfigModel, err error)
|
||||
ConversionType(ctx context.Context, models *entity.SysAddonsConfig) (value interface{}, err error)
|
||||
UpdateConfigByGroup(ctx context.Context, in sysin.UpdateAddonsConfigInp) error
|
||||
}
|
||||
ISysAttachment interface {
|
||||
Delete(ctx context.Context, in sysin.AttachmentDeleteInp) error
|
||||
Edit(ctx context.Context, in sysin.AttachmentEditInp) (err error)
|
||||
Status(ctx context.Context, in sysin.AttachmentStatusInp) (err error)
|
||||
MaxSort(ctx context.Context, in sysin.AttachmentMaxSortInp) (*sysin.AttachmentMaxSortModel, error)
|
||||
View(ctx context.Context, in sysin.AttachmentViewInp) (res *sysin.AttachmentViewModel, err error)
|
||||
List(ctx context.Context, in sysin.AttachmentListInp) (list []*sysin.AttachmentListModel, totalCount int, err error)
|
||||
Add(ctx context.Context, meta *sysin.UploadFileMeta, fullPath, drive string) (data *entity.SysAttachment, err error)
|
||||
}
|
||||
ISysServeLog interface {
|
||||
Model(ctx context.Context) *gdb.Model
|
||||
List(ctx context.Context, in sysin.ServeLogListInp) (list []*sysin.ServeLogListModel, totalCount int, err error)
|
||||
Export(ctx context.Context, in sysin.ServeLogListInp) (err error)
|
||||
Delete(ctx context.Context, in sysin.ServeLogDeleteInp) (err error)
|
||||
View(ctx context.Context, in sysin.ServeLogViewInp) (res *sysin.ServeLogViewModel, err error)
|
||||
RealWrite(ctx context.Context, models entity.SysServeLog) (err error)
|
||||
}
|
||||
ISysSmsLog interface {
|
||||
Delete(ctx context.Context, in sysin.SmsLogDeleteInp) error
|
||||
Edit(ctx context.Context, in sysin.SmsLogEditInp) (err error)
|
||||
Status(ctx context.Context, in sysin.SmsLogStatusInp) (err error)
|
||||
MaxSort(ctx context.Context, in sysin.SmsLogMaxSortInp) (*sysin.SmsLogMaxSortModel, error)
|
||||
View(ctx context.Context, in sysin.SmsLogViewInp) (res *sysin.SmsLogViewModel, err error)
|
||||
List(ctx context.Context, in sysin.SmsLogListInp) (list []*sysin.SmsLogListModel, totalCount int, err error)
|
||||
SendCode(ctx context.Context, in sysin.SendCodeInp) (err error)
|
||||
GetTemplate(ctx context.Context, template string, config *model.SmsConfig) (val string, err error)
|
||||
AllowSend(ctx context.Context, models *entity.SysSmsLog, config *model.SmsConfig) (err error)
|
||||
VerifyCode(ctx context.Context, in sysin.VerifyCodeInp) (err error)
|
||||
}
|
||||
ISysDictType interface {
|
||||
Tree(ctx context.Context) (list []*sysin.DictTypeTree, err error)
|
||||
Delete(ctx context.Context, in sysin.DictTypeDeleteInp) error
|
||||
Edit(ctx context.Context, in sysin.DictTypeEditInp) (err error)
|
||||
TreeSelect(ctx context.Context, in sysin.DictTreeSelectInp) (list []*sysin.DictTypeTree, err error)
|
||||
}
|
||||
ISysLog interface {
|
||||
Export(ctx context.Context, in sysin.LogListInp) (err error)
|
||||
RealWrite(ctx context.Context, commonLog entity.SysLog) (err error)
|
||||
AutoLog(ctx context.Context) error
|
||||
AnalysisLog(ctx context.Context) entity.SysLog
|
||||
View(ctx context.Context, in sysin.LogViewInp) (res *sysin.LogViewModel, err error)
|
||||
Delete(ctx context.Context, in sysin.LogDeleteInp) (err error)
|
||||
List(ctx context.Context, in sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error)
|
||||
}
|
||||
ISysBlacklist interface {
|
||||
Delete(ctx context.Context, in sysin.BlacklistDeleteInp) (err error)
|
||||
Edit(ctx context.Context, in sysin.BlacklistEditInp) (err error)
|
||||
Status(ctx context.Context, in sysin.BlacklistStatusInp) (err error)
|
||||
MaxSort(ctx context.Context, in sysin.BlacklistMaxSortInp) (*sysin.BlacklistMaxSortModel, error)
|
||||
View(ctx context.Context, in sysin.BlacklistViewInp) (res *sysin.BlacklistViewModel, err error)
|
||||
List(ctx context.Context, in sysin.BlacklistListInp) (list []*sysin.BlacklistListModel, totalCount int, err error)
|
||||
VariableLoad(ctx context.Context, err error)
|
||||
Load(ctx context.Context)
|
||||
}
|
||||
ISysConfig interface {
|
||||
GetLoadCache(ctx context.Context) (conf *model.CacheConfig, err error)
|
||||
GetLoadGenerate(ctx context.Context) (conf *model.GenerateConfig, err error)
|
||||
GetSms(ctx context.Context) (conf *model.SmsConfig, err error)
|
||||
GetGeo(ctx context.Context) (conf *model.GeoConfig, err error)
|
||||
GetUpload(ctx context.Context) (conf *model.UploadConfig, err error)
|
||||
GetSmtp(ctx context.Context) (conf *model.EmailConfig, err error)
|
||||
GetBasic(ctx context.Context) (conf *model.BasicConfig, err error)
|
||||
GetLoadSSL(ctx context.Context) (conf *model.SSLConfig, err error)
|
||||
GetLoadLog(ctx context.Context) (conf *model.LogConfig, err error)
|
||||
GetLoadServeLog(ctx context.Context) (conf *model.ServeLogConfig, err error)
|
||||
GetConfigByGroup(ctx context.Context, in sysin.GetConfigInp) (*sysin.GetConfigModel, error)
|
||||
ConversionType(ctx context.Context, models *entity.SysConfig) (value interface{}, err error)
|
||||
UpdateConfigByGroup(ctx context.Context, in sysin.UpdateConfigInp) error
|
||||
}
|
||||
ISysCurdDemo interface {
|
||||
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
|
||||
List(ctx context.Context, in sysin.CurdDemoListInp) (list []*sysin.CurdDemoListModel, totalCount int, err error)
|
||||
Export(ctx context.Context, in sysin.CurdDemoListInp) (err error)
|
||||
Edit(ctx context.Context, in sysin.CurdDemoEditInp) (err error)
|
||||
Delete(ctx context.Context, in sysin.CurdDemoDeleteInp) (err error)
|
||||
MaxSort(ctx context.Context, in sysin.CurdDemoMaxSortInp) (res *sysin.CurdDemoMaxSortModel, err error)
|
||||
View(ctx context.Context, in sysin.CurdDemoViewInp) (res *sysin.CurdDemoViewModel, err error)
|
||||
Status(ctx context.Context, in sysin.CurdDemoStatusInp) (err error)
|
||||
Switch(ctx context.Context, in sysin.CurdDemoSwitchInp) (err error)
|
||||
}
|
||||
ISysDictData interface {
|
||||
Delete(ctx context.Context, in sysin.DictDataDeleteInp) error
|
||||
Edit(ctx context.Context, in sysin.DictDataEditInp) (err error)
|
||||
List(ctx context.Context, in sysin.DictDataListInp) (list []*sysin.DictDataListModel, totalCount int, err error)
|
||||
Select(ctx context.Context, in sysin.DataSelectInp) (list sysin.DataSelectModel, err error)
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
localSysCron ISysCron
|
||||
localSysAddonsConfig ISysAddonsConfig
|
||||
localSysAttachment ISysAttachment
|
||||
localSysBlacklist ISysBlacklist
|
||||
localSysEmsLog ISysEmsLog
|
||||
localSysGenCodes ISysGenCodes
|
||||
localSysServeLog ISysServeLog
|
||||
localSysSmsLog ISysSmsLog
|
||||
localSysAddonsConfig ISysAddonsConfig
|
||||
localSysBlacklist ISysBlacklist
|
||||
localSysConfig ISysConfig
|
||||
localSysLog ISysLog
|
||||
localSysLoginLog ISysLoginLog
|
||||
localSysAddons ISysAddons
|
||||
localSysCurdDemo ISysCurdDemo
|
||||
localSysDictData ISysDictData
|
||||
localSysDictType ISysDictType
|
||||
localSysProvinces ISysProvinces
|
||||
localSysLog ISysLog
|
||||
localSysCron ISysCron
|
||||
localSysCronGroup ISysCronGroup
|
||||
localSysEmsLog ISysEmsLog
|
||||
localSysLoginLog ISysLoginLog
|
||||
localSysProvinces ISysProvinces
|
||||
localSysAddons ISysAddons
|
||||
localSysGenCodes ISysGenCodes
|
||||
)
|
||||
|
||||
func SysDictData() ISysDictData {
|
||||
if localSysDictData == nil {
|
||||
panic("implement not found for interface ISysDictData, forgot register?")
|
||||
}
|
||||
return localSysDictData
|
||||
}
|
||||
|
||||
func RegisterSysDictData(i ISysDictData) {
|
||||
localSysDictData = i
|
||||
}
|
||||
|
||||
func SysDictType() ISysDictType {
|
||||
if localSysDictType == nil {
|
||||
panic("implement not found for interface ISysDictType, forgot register?")
|
||||
}
|
||||
return localSysDictType
|
||||
}
|
||||
|
||||
func RegisterSysDictType(i ISysDictType) {
|
||||
localSysDictType = i
|
||||
}
|
||||
|
||||
func SysLog() ISysLog {
|
||||
if localSysLog == nil {
|
||||
panic("implement not found for interface ISysLog, forgot register?")
|
||||
}
|
||||
return localSysLog
|
||||
}
|
||||
|
||||
func RegisterSysLog(i ISysLog) {
|
||||
localSysLog = i
|
||||
}
|
||||
|
||||
func SysBlacklist() ISysBlacklist {
|
||||
if localSysBlacklist == nil {
|
||||
panic("implement not found for interface ISysBlacklist, forgot register?")
|
||||
}
|
||||
return localSysBlacklist
|
||||
}
|
||||
|
||||
func RegisterSysBlacklist(i ISysBlacklist) {
|
||||
localSysBlacklist = i
|
||||
}
|
||||
|
||||
func SysConfig() ISysConfig {
|
||||
if localSysConfig == nil {
|
||||
panic("implement not found for interface ISysConfig, forgot register?")
|
||||
}
|
||||
return localSysConfig
|
||||
}
|
||||
|
||||
func RegisterSysConfig(i ISysConfig) {
|
||||
localSysConfig = i
|
||||
}
|
||||
|
||||
func SysCurdDemo() ISysCurdDemo {
|
||||
if localSysCurdDemo == nil {
|
||||
panic("implement not found for interface ISysCurdDemo, forgot register?")
|
||||
}
|
||||
return localSysCurdDemo
|
||||
}
|
||||
|
||||
func RegisterSysCurdDemo(i ISysCurdDemo) {
|
||||
localSysCurdDemo = i
|
||||
}
|
||||
|
||||
func SysLoginLog() ISysLoginLog {
|
||||
if localSysLoginLog == nil {
|
||||
panic("implement not found for interface ISysLoginLog, forgot register?")
|
||||
}
|
||||
return localSysLoginLog
|
||||
}
|
||||
|
||||
func RegisterSysLoginLog(i ISysLoginLog) {
|
||||
localSysLoginLog = i
|
||||
}
|
||||
|
||||
func SysProvinces() ISysProvinces {
|
||||
if localSysProvinces == nil {
|
||||
panic("implement not found for interface ISysProvinces, forgot register?")
|
||||
}
|
||||
return localSysProvinces
|
||||
}
|
||||
|
||||
func RegisterSysProvinces(i ISysProvinces) {
|
||||
localSysProvinces = i
|
||||
}
|
||||
|
||||
func SysCron() ISysCron {
|
||||
if localSysCron == nil {
|
||||
panic("implement not found for interface ISysCron, forgot register?")
|
||||
}
|
||||
return localSysCron
|
||||
}
|
||||
|
||||
func RegisterSysCron(i ISysCron) {
|
||||
localSysCron = i
|
||||
}
|
||||
|
||||
func SysCronGroup() ISysCronGroup {
|
||||
if localSysCronGroup == nil {
|
||||
panic("implement not found for interface ISysCronGroup, forgot register?")
|
||||
}
|
||||
return localSysCronGroup
|
||||
}
|
||||
|
||||
func RegisterSysCronGroup(i ISysCronGroup) {
|
||||
localSysCronGroup = i
|
||||
}
|
||||
|
||||
func SysEmsLog() ISysEmsLog {
|
||||
if localSysEmsLog == nil {
|
||||
panic("implement not found for interface ISysEmsLog, forgot register?")
|
||||
}
|
||||
return localSysEmsLog
|
||||
}
|
||||
|
||||
func RegisterSysEmsLog(i ISysEmsLog) {
|
||||
localSysEmsLog = i
|
||||
}
|
||||
|
||||
func SysAddons() ISysAddons {
|
||||
if localSysAddons == nil {
|
||||
panic("implement not found for interface ISysAddons, forgot register?")
|
||||
}
|
||||
return localSysAddons
|
||||
}
|
||||
|
||||
func RegisterSysAddons(i ISysAddons) {
|
||||
localSysAddons = i
|
||||
}
|
||||
|
||||
func SysGenCodes() ISysGenCodes {
|
||||
if localSysGenCodes == nil {
|
||||
panic("implement not found for interface ISysGenCodes, forgot register?")
|
||||
@@ -214,17 +346,6 @@ func RegisterSysGenCodes(i ISysGenCodes) {
|
||||
localSysGenCodes = i
|
||||
}
|
||||
|
||||
func SysServeLog() ISysServeLog {
|
||||
if localSysServeLog == nil {
|
||||
panic("implement not found for interface ISysServeLog, forgot register?")
|
||||
}
|
||||
return localSysServeLog
|
||||
}
|
||||
|
||||
func RegisterSysServeLog(i ISysServeLog) {
|
||||
localSysServeLog = i
|
||||
}
|
||||
|
||||
func SysSmsLog() ISysSmsLog {
|
||||
if localSysSmsLog == nil {
|
||||
panic("implement not found for interface ISysSmsLog, forgot register?")
|
||||
@@ -258,134 +379,13 @@ func RegisterSysAttachment(i ISysAttachment) {
|
||||
localSysAttachment = i
|
||||
}
|
||||
|
||||
func SysBlacklist() ISysBlacklist {
|
||||
if localSysBlacklist == nil {
|
||||
panic("implement not found for interface ISysBlacklist, forgot register?")
|
||||
func SysServeLog() ISysServeLog {
|
||||
if localSysServeLog == nil {
|
||||
panic("implement not found for interface ISysServeLog, forgot register?")
|
||||
}
|
||||
return localSysBlacklist
|
||||
return localSysServeLog
|
||||
}
|
||||
|
||||
func RegisterSysBlacklist(i ISysBlacklist) {
|
||||
localSysBlacklist = i
|
||||
}
|
||||
|
||||
func SysEmsLog() ISysEmsLog {
|
||||
if localSysEmsLog == nil {
|
||||
panic("implement not found for interface ISysEmsLog, forgot register?")
|
||||
}
|
||||
return localSysEmsLog
|
||||
}
|
||||
|
||||
func RegisterSysEmsLog(i ISysEmsLog) {
|
||||
localSysEmsLog = i
|
||||
}
|
||||
|
||||
func SysAddons() ISysAddons {
|
||||
if localSysAddons == nil {
|
||||
panic("implement not found for interface ISysAddons, forgot register?")
|
||||
}
|
||||
return localSysAddons
|
||||
}
|
||||
|
||||
func RegisterSysAddons(i ISysAddons) {
|
||||
localSysAddons = i
|
||||
}
|
||||
|
||||
func SysConfig() ISysConfig {
|
||||
if localSysConfig == nil {
|
||||
panic("implement not found for interface ISysConfig, forgot register?")
|
||||
}
|
||||
return localSysConfig
|
||||
}
|
||||
|
||||
func RegisterSysConfig(i ISysConfig) {
|
||||
localSysConfig = i
|
||||
}
|
||||
|
||||
func SysLog() ISysLog {
|
||||
if localSysLog == nil {
|
||||
panic("implement not found for interface ISysLog, forgot register?")
|
||||
}
|
||||
return localSysLog
|
||||
}
|
||||
|
||||
func RegisterSysLog(i ISysLog) {
|
||||
localSysLog = i
|
||||
}
|
||||
|
||||
func SysLoginLog() ISysLoginLog {
|
||||
if localSysLoginLog == nil {
|
||||
panic("implement not found for interface ISysLoginLog, forgot register?")
|
||||
}
|
||||
return localSysLoginLog
|
||||
}
|
||||
|
||||
func RegisterSysLoginLog(i ISysLoginLog) {
|
||||
localSysLoginLog = i
|
||||
}
|
||||
|
||||
func SysProvinces() ISysProvinces {
|
||||
if localSysProvinces == nil {
|
||||
panic("implement not found for interface ISysProvinces, forgot register?")
|
||||
}
|
||||
return localSysProvinces
|
||||
}
|
||||
|
||||
func RegisterSysProvinces(i ISysProvinces) {
|
||||
localSysProvinces = i
|
||||
}
|
||||
|
||||
func SysCronGroup() ISysCronGroup {
|
||||
if localSysCronGroup == nil {
|
||||
panic("implement not found for interface ISysCronGroup, forgot register?")
|
||||
}
|
||||
return localSysCronGroup
|
||||
}
|
||||
|
||||
func RegisterSysCronGroup(i ISysCronGroup) {
|
||||
localSysCronGroup = i
|
||||
}
|
||||
|
||||
func SysCurdDemo() ISysCurdDemo {
|
||||
if localSysCurdDemo == nil {
|
||||
panic("implement not found for interface ISysCurdDemo, forgot register?")
|
||||
}
|
||||
return localSysCurdDemo
|
||||
}
|
||||
|
||||
func RegisterSysCurdDemo(i ISysCurdDemo) {
|
||||
localSysCurdDemo = i
|
||||
}
|
||||
|
||||
func SysDictData() ISysDictData {
|
||||
if localSysDictData == nil {
|
||||
panic("implement not found for interface ISysDictData, forgot register?")
|
||||
}
|
||||
return localSysDictData
|
||||
}
|
||||
|
||||
func RegisterSysDictData(i ISysDictData) {
|
||||
localSysDictData = i
|
||||
}
|
||||
|
||||
func SysDictType() ISysDictType {
|
||||
if localSysDictType == nil {
|
||||
panic("implement not found for interface ISysDictType, forgot register?")
|
||||
}
|
||||
return localSysDictType
|
||||
}
|
||||
|
||||
func RegisterSysDictType(i ISysDictType) {
|
||||
localSysDictType = i
|
||||
}
|
||||
|
||||
func SysCron() ISysCron {
|
||||
if localSysCron == nil {
|
||||
panic("implement not found for interface ISysCron, forgot register?")
|
||||
}
|
||||
return localSysCron
|
||||
}
|
||||
|
||||
func RegisterSysCron(i ISysCron) {
|
||||
localSysCron = i
|
||||
func RegisterSysServeLog(i ISysServeLog) {
|
||||
localSysServeLog = i
|
||||
}
|
||||
|
32
server/internal/service/tcpclient.go
Normal file
32
server/internal/service/tcpclient.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// ================================================================================
|
||||
// Code generated by GoFrame CLI tool. DO NOT EDIT.
|
||||
// You can delete these comments if you wish manually maintain this interface file.
|
||||
// ================================================================================
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type (
|
||||
ITCPAuth interface {
|
||||
Start(ctx context.Context)
|
||||
Stop(ctx context.Context)
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
localTCPAuth ITCPAuth
|
||||
)
|
||||
|
||||
func TCPAuth() ITCPAuth {
|
||||
if localTCPAuth == nil {
|
||||
panic("implement not found for interface ITCPAuth, forgot register?")
|
||||
}
|
||||
return localTCPAuth
|
||||
}
|
||||
|
||||
func RegisterTCPAuth(i ITCPAuth) {
|
||||
localTCPAuth = i
|
||||
}
|
32
server/internal/service/tcpserver.go
Normal file
32
server/internal/service/tcpserver.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// ================================================================================
|
||||
// Code generated by GoFrame CLI tool. DO NOT EDIT.
|
||||
// You can delete these comments if you wish manually maintain this interface file.
|
||||
// ================================================================================
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type (
|
||||
ITCPServer interface {
|
||||
Start(ctx context.Context)
|
||||
Stop(ctx context.Context)
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
localTCPServer ITCPServer
|
||||
)
|
||||
|
||||
func TCPServer() ITCPServer {
|
||||
if localTCPServer == nil {
|
||||
panic("implement not found for interface ITCPServer, forgot register?")
|
||||
}
|
||||
return localTCPServer
|
||||
}
|
||||
|
||||
func RegisterTCPServer(i ITCPServer) {
|
||||
localTCPServer = i
|
||||
}
|
Reference in New Issue
Block a user