mirror of
https://github.com/lzh-1625/go_process_manager.git
synced 2025-11-03 10:20:53 +08:00
初次提交
This commit is contained in:
33
api/api.go
Normal file
33
api/api.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"msm/consts/ctxflag"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func rOk(ctx *gin.Context, message string, data any) {
|
||||
jsonData := map[string]any{
|
||||
"code": 0,
|
||||
"msg": message,
|
||||
}
|
||||
if data != nil {
|
||||
jsonData["data"] = data
|
||||
}
|
||||
ctx.JSON(http.StatusOK, jsonData)
|
||||
}
|
||||
|
||||
func errCheck(ctx *gin.Context, isErr bool, errData any) {
|
||||
if !isErr {
|
||||
return
|
||||
}
|
||||
if err, ok := errData.(error); ok {
|
||||
ctx.Set(ctxflag.ERR, err)
|
||||
}
|
||||
if err, ok := errData.(string); ok {
|
||||
ctx.Set(ctxflag.ERR, errors.New(err))
|
||||
}
|
||||
panic(0)
|
||||
}
|
||||
94
api/config.go
Normal file
94
api/config.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"msm/config"
|
||||
"msm/dao"
|
||||
"msm/model"
|
||||
"msm/service/es"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type configApi struct{}
|
||||
|
||||
var ConfigApi = new(configApi)
|
||||
|
||||
func (c *configApi) GetSystemConfiguration(ctx *gin.Context) {
|
||||
typeElem := reflect.TypeOf(config.CF).Elem()
|
||||
valueElem := reflect.ValueOf(config.CF).Elem()
|
||||
result := []model.SystemConfigurationResp{}
|
||||
for i := 0; i < typeElem.NumField(); i++ {
|
||||
typeField := typeElem.Field(i)
|
||||
valueField := valueElem.Field(i)
|
||||
var value any
|
||||
switch typeField.Type.Kind() {
|
||||
case reflect.Int64, reflect.Int:
|
||||
value = valueField.Int()
|
||||
case reflect.String:
|
||||
value = valueField.String()
|
||||
case reflect.Bool:
|
||||
value = valueField.Bool()
|
||||
case reflect.Float64:
|
||||
value = valueField.Float()
|
||||
default:
|
||||
continue
|
||||
}
|
||||
result = append(result, model.SystemConfigurationResp{
|
||||
Key: typeField.Name,
|
||||
Value: value,
|
||||
Default: typeField.Tag.Get("default"),
|
||||
Describe: typeField.Tag.Get("describe"),
|
||||
})
|
||||
}
|
||||
rOk(ctx, "获取系统配置成功", result)
|
||||
}
|
||||
|
||||
func (c *configApi) SetSystemConfiguration(ctx *gin.Context) {
|
||||
data := map[string]string{}
|
||||
errCheck(ctx, ctx.ShouldBindJSON(&data) != nil, "请求参数错误")
|
||||
typeElem := reflect.TypeOf(config.CF).Elem()
|
||||
valueElem := reflect.ValueOf(config.CF).Elem()
|
||||
for i := 0; i < typeElem.NumField(); i++ {
|
||||
typeField := typeElem.Field(i)
|
||||
valueField := valueElem.Field(i)
|
||||
for k, v := range data {
|
||||
if typeField.Name == k {
|
||||
var err error
|
||||
switch typeField.Type.Kind() {
|
||||
case reflect.String:
|
||||
valueField.SetString(v)
|
||||
case reflect.Bool:
|
||||
value, errV := strconv.ParseBool(v)
|
||||
err = errV
|
||||
if err == nil {
|
||||
valueField.SetBool(value)
|
||||
}
|
||||
case reflect.Float64:
|
||||
value, errV := strconv.ParseFloat(v, 64)
|
||||
err = errV
|
||||
if err == nil {
|
||||
valueField.SetFloat(value)
|
||||
}
|
||||
case reflect.Int64, reflect.Int:
|
||||
value, errV := strconv.ParseInt(v, 10, 64)
|
||||
err = errV
|
||||
if err == nil {
|
||||
valueField.SetInt(value)
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
errCheck(ctx, err != nil, k+"类似错误")
|
||||
errCheck(ctx, dao.ConfigDao.SetConfigValue(k, v) != nil, "修改配置失败")
|
||||
}
|
||||
}
|
||||
}
|
||||
rOk(ctx, "修改配置成功", nil)
|
||||
}
|
||||
|
||||
func (c *configApi) EsConfigReload(ctx *gin.Context) {
|
||||
errCheck(ctx, !es.InitEs(), "es连接失败,请检查是否启用es或账号密码是否存在错误")
|
||||
rOk(ctx, "已连接上es", nil)
|
||||
}
|
||||
34
api/file.go
Normal file
34
api/file.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
FileService "msm/service/file"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type file struct{}
|
||||
|
||||
var FileApi = new(file)
|
||||
|
||||
func (f *file) FilePathHandler(ctx *gin.Context) {
|
||||
data, err := FileService.FileService.GetFileAndDirByPath(ctx.Query("path"))
|
||||
errCheck(ctx, err != nil, "文件路径查询失败")
|
||||
rOk(ctx, "文件路径查询成功", data)
|
||||
}
|
||||
|
||||
func (f *file) FileWriteHandler(ctx *gin.Context) {
|
||||
path := ctx.PostForm("filePath")
|
||||
fi, err := ctx.FormFile("data")
|
||||
errCheck(ctx, err != nil, "文件读取失败")
|
||||
fiReader, _ := fi.Open()
|
||||
err = FileService.FileService.UpdateFileData(path, fiReader, fi.Size)
|
||||
errCheck(ctx, err != nil, "文件数据更新失败")
|
||||
rOk(ctx, "文件更新成功", nil)
|
||||
}
|
||||
|
||||
func (f *file) FileReadHandler(ctx *gin.Context) {
|
||||
path := ctx.Query("filePath")
|
||||
bytes, err := FileService.FileService.ReadFileFromPath(path)
|
||||
errCheck(ctx, err != nil, "文件数据读取失败")
|
||||
rOk(ctx, "文件数据读取成功", string(bytes))
|
||||
}
|
||||
20
api/log.go
Normal file
20
api/log.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"msm/config"
|
||||
"msm/model"
|
||||
"msm/service/es"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type logApi struct{}
|
||||
|
||||
var LogApi = new(logApi)
|
||||
|
||||
func (a *logApi) GetLog(ctx *gin.Context) {
|
||||
req := model.GetLogReq{}
|
||||
errCheck(ctx, !config.CF.EsEnable, "elasticsearch未启用或账号密码错误")
|
||||
errCheck(ctx, ctx.ShouldBindJSON(&req) != nil, "请求体格式错误")
|
||||
rOk(ctx, "查询成功", es.EsService.Search(req))
|
||||
}
|
||||
27
api/permission.go
Normal file
27
api/permission.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"msm/model"
|
||||
|
||||
"msm/dao"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var PermissionApi = new(permissionApi)
|
||||
|
||||
type permissionApi struct{}
|
||||
|
||||
func (p *permissionApi) EditPermssion(ctx *gin.Context) {
|
||||
per := model.Permission{}
|
||||
err := ctx.ShouldBindJSON(&per)
|
||||
errCheck(ctx, err != nil, err)
|
||||
err = dao.PermissionDao.EditPermssion(per)
|
||||
errCheck(ctx, err != nil, err)
|
||||
rOk(ctx, "权限修改成功", nil)
|
||||
}
|
||||
|
||||
func (p *permissionApi) GetPermissionList(ctx *gin.Context) {
|
||||
result := dao.PermissionDao.GetPermssionList(ctx.Query("account"))
|
||||
rOk(ctx, "查询成功", result)
|
||||
}
|
||||
101
api/proc.go
Normal file
101
api/proc.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"msm/consts/ctxflag"
|
||||
"msm/consts/role"
|
||||
"msm/dao"
|
||||
"msm/model"
|
||||
"msm/service/process"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type procApi struct{}
|
||||
|
||||
var ProcApi = new(procApi)
|
||||
|
||||
func (p *procApi) CreateNewProcess(ctx *gin.Context) {
|
||||
req := model.Process{}
|
||||
ctx.ShouldBindJSON(&req)
|
||||
index, err := dao.ProcessDao.AddProcessConfig(req)
|
||||
errCheck(ctx, err != nil, err)
|
||||
req.Uuid = index
|
||||
proc, err := process.RunNewProcess(req)
|
||||
errCheck(ctx, err != nil, err)
|
||||
process.ProcessCtlService.AddProcess(req.Uuid, proc)
|
||||
rOk(ctx, "创建成功", gin.H{
|
||||
"id": req.Uuid,
|
||||
})
|
||||
}
|
||||
|
||||
func (p *procApi) DeleteNewProcess(ctx *gin.Context) {
|
||||
uuid, err := strconv.Atoi(ctx.Query("uuid"))
|
||||
errCheck(ctx, err != nil, "参数有误")
|
||||
process.ProcessCtlService.KillProcess(uuid)
|
||||
process.ProcessCtlService.DeleteProcess(uuid)
|
||||
err = dao.ProcessDao.DeleteProcessConfig(uuid)
|
||||
errCheck(ctx, err != nil, err)
|
||||
rOk(ctx, "删除成功", nil)
|
||||
}
|
||||
|
||||
func (p *procApi) KillProcess(ctx *gin.Context) {
|
||||
uuid, err := strconv.Atoi(ctx.Query("uuid"))
|
||||
errCheck(ctx, err != nil, "参数有误")
|
||||
err = process.ProcessCtlService.KillProcess(uuid)
|
||||
errCheck(ctx, err != nil, err)
|
||||
rOk(ctx, "成功", nil)
|
||||
}
|
||||
|
||||
func (p *procApi) StartProcess(ctx *gin.Context) {
|
||||
uuid, err := strconv.Atoi(ctx.Query("uuid"))
|
||||
errCheck(ctx, err != nil, "参数有误")
|
||||
prod, err := process.ProcessCtlService.GetProcess(uuid)
|
||||
if err != nil { // 进程不存在则创建
|
||||
proc, err := process.RunNewProcess(dao.ProcessDao.GetProcessConfigById(uuid))
|
||||
errCheck(ctx, err != nil, err)
|
||||
process.ProcessCtlService.AddProcess(uuid, proc)
|
||||
rOk(ctx, "成功", nil)
|
||||
return
|
||||
}
|
||||
errCheck(ctx, prod.GetStateState() == 1, "进程还在运行中")
|
||||
prod.ResetRestartTimes()
|
||||
prod.ReStart()
|
||||
// dao.UpdateServerAutoStart(uuid, true)
|
||||
rOk(ctx, "成功", nil)
|
||||
}
|
||||
|
||||
func (p *procApi) GetProcessList(ctx *gin.Context) {
|
||||
if ctx.GetInt(ctxflag.ROLE) < int(role.USER) {
|
||||
rOk(ctx, "进程列表获取成功", process.ProcessCtlService.GetProcessList())
|
||||
} else {
|
||||
rOk(ctx, "进程列表获取成功", process.ProcessCtlService.GetProcessListByUser(ctx.GetString(ctxflag.USER_NAME)))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *procApi) UpdateProcessConfig(ctx *gin.Context) {
|
||||
req := model.Process{}
|
||||
ctx.ShouldBindJSON(&req)
|
||||
process.ProcessCtlService.UpdateProcessConfig(req)
|
||||
err := dao.ProcessDao.UpdateProcessConfig(req)
|
||||
errCheck(ctx, err != nil, err)
|
||||
rOk(ctx, "更改配置成功", nil)
|
||||
}
|
||||
|
||||
func (p *procApi) GetProcessConfig(ctx *gin.Context) {
|
||||
uuid, err := strconv.Atoi(ctx.Query("uuid"))
|
||||
errCheck(ctx, err != nil, "参数有误")
|
||||
data := dao.ProcessDao.GetProcessConfigById(uuid)
|
||||
errCheck(ctx, data.Uuid == 0, "未查询到信息")
|
||||
rOk(ctx, "success", data)
|
||||
}
|
||||
|
||||
func (p *procApi) ProcessControl(ctx *gin.Context) {
|
||||
user := ctx.GetString(ctxflag.USER_NAME)
|
||||
uuid, err := strconv.Atoi(ctx.Query("uuid"))
|
||||
errCheck(ctx, err != nil, "参数有误")
|
||||
proc, err := process.ProcessCtlService.GetProcess(uuid)
|
||||
errCheck(ctx, err != nil, "进程控制权获取失败")
|
||||
proc.ProcessControl(user)
|
||||
rOk(ctx, "获取进程控权成功", nil)
|
||||
}
|
||||
50
api/push.go
Normal file
50
api/push.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"msm/model"
|
||||
"strconv"
|
||||
|
||||
"msm/dao"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type pushApi struct{}
|
||||
|
||||
var PushApi = new(pushApi)
|
||||
|
||||
func (p *pushApi) GetPushList(ctx *gin.Context) {
|
||||
rOk(ctx, "查询成功", dao.PushDao.GetPushList())
|
||||
}
|
||||
|
||||
func (p *pushApi) GetPushById(ctx *gin.Context) {
|
||||
id, err := strconv.Atoi(ctx.Query("id"))
|
||||
errCheck(ctx, err != nil, err)
|
||||
rOk(ctx, "查询成功", dao.PushDao.GetPushConfigById(id))
|
||||
}
|
||||
|
||||
func (p *pushApi) AddPushConfig(ctx *gin.Context) {
|
||||
data := model.Push{}
|
||||
err := ctx.ShouldBindJSON(&data)
|
||||
errCheck(ctx, err != nil, err)
|
||||
err = dao.PushDao.AddPushConfig(data)
|
||||
errCheck(ctx, err != nil, err)
|
||||
rOk(ctx, "添加成功", nil)
|
||||
}
|
||||
|
||||
func (p *pushApi) UpdatePushConfig(ctx *gin.Context) {
|
||||
data := model.Push{}
|
||||
err := ctx.ShouldBindJSON(&data)
|
||||
errCheck(ctx, err != nil, err)
|
||||
err = dao.PushDao.UpdatePushConfig(data)
|
||||
errCheck(ctx, err != nil, err)
|
||||
rOk(ctx, "更新成功", nil)
|
||||
}
|
||||
|
||||
func (p *pushApi) DeletePushConfig(ctx *gin.Context) {
|
||||
id, err := strconv.Atoi(ctx.Query("id"))
|
||||
errCheck(ctx, err != nil, err)
|
||||
err = dao.PushDao.DeletePushConfig(id)
|
||||
errCheck(ctx, err != nil, err)
|
||||
rOk(ctx, "删除成功", nil)
|
||||
}
|
||||
86
api/user.go
Normal file
86
api/user.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"msm/consts/ctxflag"
|
||||
"msm/consts/role"
|
||||
"msm/dao"
|
||||
"msm/model"
|
||||
"msm/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type userApi struct{}
|
||||
|
||||
var UserApi = new(userApi)
|
||||
|
||||
const DEFAULT_ROOT_PASSWORD = "root"
|
||||
|
||||
func (u *userApi) LoginHandler(ctx *gin.Context) {
|
||||
info := map[string]string{}
|
||||
ctx.ShouldBindJSON(&info)
|
||||
account := info["account"]
|
||||
password := info["password"]
|
||||
errCheck(ctx, !u.checkLoginInfo(account, password), "登入失败,账号或密码错误")
|
||||
token, err := utils.GenToken(account)
|
||||
errCheck(ctx, err != nil, err)
|
||||
ctx.JSON(200, gin.H{
|
||||
"code": 0,
|
||||
"msg": "登入成功!",
|
||||
"token": token,
|
||||
"username": account,
|
||||
"role": dao.UserDao.GetUserByName(account).Role,
|
||||
})
|
||||
}
|
||||
|
||||
func (u *userApi) CreateUser(ctx *gin.Context) {
|
||||
user := model.User{}
|
||||
err := ctx.ShouldBindJSON(&user)
|
||||
errCheck(ctx, err != nil, err)
|
||||
errCheck(ctx, user.Role == int(role.ROOT), "不能添加root账号")
|
||||
err = dao.UserDao.CreateUser(user)
|
||||
errCheck(ctx, err != nil, err)
|
||||
rOk(ctx, "注册成功", nil)
|
||||
}
|
||||
|
||||
func (u *userApi) ChangePassword(ctx *gin.Context) {
|
||||
user := model.User{}
|
||||
err := ctx.ShouldBindJSON(&user)
|
||||
errCheck(ctx, err != nil, err)
|
||||
reqUser := ctx.GetString(ctxflag.USER_NAME)
|
||||
errCheck(ctx, ctx.GetInt(ctxflag.ROLE) != int(role.ROOT) && user.Account != "", "参数错误")
|
||||
var userName string
|
||||
if user.Account != "" {
|
||||
userName = user.Account
|
||||
} else {
|
||||
userName = reqUser
|
||||
}
|
||||
err = dao.UserDao.UpdatePassword(userName, user.Password)
|
||||
errCheck(ctx, err != nil, err)
|
||||
rOk(ctx, "修改密码成功", nil)
|
||||
|
||||
}
|
||||
|
||||
func (u *userApi) DeleteUser(ctx *gin.Context) {
|
||||
errCheck(ctx, ctx.Query("account") == "root", "无法删除root账户")
|
||||
err := dao.UserDao.DeleteUser(ctx.Query("account"))
|
||||
errCheck(ctx, err != nil, "无法删除root账户")
|
||||
rOk(ctx, "删除成功", nil)
|
||||
}
|
||||
|
||||
func (u *userApi) GetUserList(ctx *gin.Context) {
|
||||
rOk(ctx, "查询成功", dao.UserDao.GetUserList())
|
||||
}
|
||||
|
||||
func (u *userApi) checkLoginInfo(account, password string) bool {
|
||||
user := dao.UserDao.GetUserByName(account)
|
||||
if account == "root" && user.Account == "" {
|
||||
dao.UserDao.CreateUser(model.User{
|
||||
Account: "root",
|
||||
Password: DEFAULT_ROOT_PASSWORD,
|
||||
Role: int(role.ROOT),
|
||||
})
|
||||
return password == DEFAULT_ROOT_PASSWORD
|
||||
}
|
||||
return user.Password == utils.Md5(password)
|
||||
}
|
||||
96
api/ws.go
Normal file
96
api/ws.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"msm/consts/ctxflag"
|
||||
"msm/log"
|
||||
"msm/service/process"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type wsApi struct{}
|
||||
|
||||
var WsApi = new(wsApi)
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
func (w *wsApi) WebsocketHandle(ctx *gin.Context) {
|
||||
reqUser := ctx.GetString(ctxflag.USER_NAME)
|
||||
uuid, err := strconv.Atoi(ctx.Query("uuid"))
|
||||
errCheck(ctx, err != nil, "参数有误")
|
||||
proc, err := process.ProcessCtlService.GetProcess(uuid)
|
||||
errCheck(ctx, err != nil, "进程获取失败")
|
||||
errCheck(ctx, proc.GetStateState() != 1, "进程未运行")
|
||||
errCheck(ctx, proc.GetControlController() != reqUser && !proc.VerifyControl(), "进程权限不足")
|
||||
errCheck(ctx, !proc.TryLock(), "进程已被占用")
|
||||
proc.SetWhoUsing(reqUser)
|
||||
conn, err := upgrader.Upgrade(ctx.Writer, ctx.Request, nil)
|
||||
errCheck(ctx, err != nil, "ws升级失败")
|
||||
log.Logger.Infow("ws连接成功", "进程名称", proc.GetName(), "连接者", proc.GetWhoUsing())
|
||||
proc.SetControlController("")
|
||||
wsCtx, cancel := context.WithCancel(context.Background())
|
||||
w.startWsConnect(conn, proc, cancel)
|
||||
proc.SetWsConn(conn)
|
||||
proc.SetIsUsing(true)
|
||||
close := func(err string) {
|
||||
proc.SetWhoUsing("")
|
||||
proc.SetIsUsing(false)
|
||||
proc.SetWsConn(nil)
|
||||
conn.Close()
|
||||
proc.Unlock()
|
||||
log.Logger.Infow("ws连接断开", "操作类型", err, "进程名称", proc.GetName())
|
||||
}
|
||||
conn.SetCloseHandler(func(_ int, _ string) error {
|
||||
proc.ChangControlChan() <- 1
|
||||
close("ws连接被断开")
|
||||
return nil
|
||||
})
|
||||
select {
|
||||
case signal := <-proc.ChangControlChan():
|
||||
{
|
||||
if signal == 0 {
|
||||
close("强制断开ws连接")
|
||||
}
|
||||
}
|
||||
case <-proc.StopChan():
|
||||
{
|
||||
close("进程已停止,强制断开ws连接")
|
||||
}
|
||||
case <-time.After(time.Minute * 10):
|
||||
{
|
||||
close("连接时间超过最大时长限制")
|
||||
}
|
||||
case <-wsCtx.Done():
|
||||
{
|
||||
close("tcp连接建立已被关闭")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (w *wsApi) startWsConnect(conn *websocket.Conn, proc process.Process, cancel context.CancelFunc) {
|
||||
proc.ReadCache(conn)
|
||||
log.Logger.Debugw("ws读取线程已启动")
|
||||
go func() {
|
||||
for {
|
||||
_, b, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
log.Logger.Debugw("ws读取线程已退出", "info", err)
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
proc.WriteBytes(b)
|
||||
}
|
||||
}()
|
||||
}
|
||||
Reference in New Issue
Block a user