Standardization

This commit is contained in:
akrike
2025-07-05 11:50:41 +08:00
parent efcf8d9ca6
commit 0fae7cac25
19 changed files with 343 additions and 286 deletions

View File

@@ -3,11 +3,9 @@ package api
import (
"net/http"
"reflect"
"strconv"
"github.com/lzh-1625/go_process_manager/internal/app/constants"
"github.com/lzh-1625/go_process_manager/internal/app/repository"
"github.com/lzh-1625/go_process_manager/log"
"github.com/gin-gonic/gin"
)
@@ -23,20 +21,6 @@ func rOk(ctx *gin.Context, message string, data any) {
ctx.JSON(http.StatusOK, jsonData)
}
func errCheck(ctx *gin.Context, isErr bool, errData any) {
if !isErr {
return
}
if err, ok := errData.(error); ok {
log.Logger.Warn(errData)
ctx.Set(constants.CTXFLG_ERR, err.Error())
}
if err, ok := errData.(string); ok {
ctx.Set(constants.CTXFLG_ERR, err)
}
panic(0)
}
func getRole(ctx *gin.Context) constants.Role {
if v, ok := ctx.Get(constants.CTXFLG_ROLE); ok {
return v.(constants.Role)
@@ -55,21 +39,3 @@ func isAdmin(ctx *gin.Context) bool {
func hasOprPermission(ctx *gin.Context, uuid int, op constants.OprPermission) bool {
return isAdmin(ctx) || reflect.ValueOf(repository.PermissionRepository.GetPermission(getUserName(ctx), uuid)).FieldByName(string(op)).Bool()
}
func getQueryInt(ctx *gin.Context, query string) (i int) {
i, err := strconv.Atoi(ctx.Query(query))
errCheck(ctx, err != nil, "Invalid parameters!")
return
}
func getQueryString(ctx *gin.Context, query string) (s string) {
s = ctx.Query(query)
errCheck(ctx, s == "", "Invalid parameters!")
return
}
func bind[T any](ctx *gin.Context) T {
var data T
errCheck(ctx, ctx.ShouldBind(&data) != nil, "Invalid parameters!")
return data
}

View File

@@ -1,6 +1,8 @@
package api
import (
"errors"
"github.com/lzh-1625/go_process_manager/internal/app/logic"
"github.com/gin-gonic/gin"
@@ -10,18 +12,26 @@ type configApi struct{}
var ConfigApi = new(configApi)
func (c *configApi) GetSystemConfiguration(ctx *gin.Context) {
func (c *configApi) GetSystemConfiguration(ctx *gin.Context, _ any) error {
result := logic.ConfigLogic.GetSystemConfiguration()
rOk(ctx, "Operation successful!", result)
return nil
}
func (c *configApi) SetSystemConfiguration(ctx *gin.Context) {
req := bind[map[string]string](ctx)
errCheck(ctx, logic.ConfigLogic.SetSystemConfiguration(req) != nil, "Set config fail!")
rOk(ctx, "Operation successful!", nil)
func (c *configApi) SetSystemConfiguration(ctx *gin.Context, _ any) (err error) {
req := map[string]string{}
if err = ctx.BindJSON(&req); err != nil {
return
}
if err = logic.ConfigLogic.SetSystemConfiguration(req); err != nil {
return
}
return
}
func (c *configApi) EsConfigReload(ctx *gin.Context) {
errCheck(ctx, !logic.EsLogic.InitEs(), "Incorrect username or password!")
rOk(ctx, "Operation successful!", nil)
func (c *configApi) EsConfigReload(ctx *gin.Context, _ any) (err error) {
if !logic.EsLogic.InitEs() {
return errors.New("es init fail")
}
return
}

View File

@@ -2,6 +2,7 @@ package api
import (
"github.com/lzh-1625/go_process_manager/internal/app/logic"
"github.com/lzh-1625/go_process_manager/internal/app/model"
"github.com/gin-gonic/gin"
)
@@ -10,24 +11,27 @@ type file struct{}
var FileApi = new(file)
func (f *file) FilePathHandler(ctx *gin.Context) {
path := getQueryString(ctx, "path")
rOk(ctx, "Operation successful!", logic.FileLogic.GetFileAndDirByPath(path))
func (f *file) FilePathHandler(ctx *gin.Context, req model.FilePathHandlerReq) (err error) {
rOk(ctx, "Operation successful!", logic.FileLogic.GetFileAndDirByPath(req.Path))
return
}
func (f *file) FileWriteHandler(ctx *gin.Context) {
func (f *file) FileWriteHandler(ctx *gin.Context, _ any) (err error) {
path := ctx.PostForm("filePath")
fi, err := ctx.FormFile("data")
errCheck(ctx, err != nil, "Read file data failed!")
if err != nil {
return
}
fiReader, _ := fi.Open()
err = logic.FileLogic.UpdateFileData(path, fiReader, fi.Size)
errCheck(ctx, err != nil, "Update file data operation failed!")
rOk(ctx, "Operation successful!", nil)
return
}
func (f *file) FileReadHandler(ctx *gin.Context) {
path := getQueryString(ctx, "filePath")
bytes, err := logic.FileLogic.ReadFileFromPath(path)
errCheck(ctx, err != nil, "Operation failed!")
func (f *file) FileReadHandler(ctx *gin.Context, req model.FileReadHandlerReq) (err error) {
bytes, err := logic.FileLogic.ReadFileFromPath(req.FilePath)
if err != nil {
return
}
rOk(ctx, "Operation successful!", string(bytes))
return
}

View File

@@ -1,6 +1,7 @@
package api
import (
"errors"
"slices"
"github.com/lzh-1625/go_process_manager/internal/app/constants"
@@ -15,8 +16,7 @@ type logApi struct{}
var LogApi = new(logApi)
func (a *logApi) GetLog(ctx *gin.Context) {
req := bind[model.GetLogReq](ctx)
func (a *logApi) GetLog(ctx *gin.Context, req model.GetLogReq) (err error) {
if isAdmin(ctx) {
rOk(ctx, "Query successful!", logic.LogLogicImpl.Search(req, req.FilterName...))
} else {
@@ -27,11 +27,15 @@ func (a *logApi) GetLog(ctx *gin.Context) {
if len(filterName) == 0 {
filterName = processNameList
}
errCheck(ctx, len(filterName) == 0, "No information found!")
if len(filterName) == 0 {
return errors.New("no information found")
}
rOk(ctx, "Query successful!", logic.LogLogicImpl.Search(req, filterName...))
}
return
}
func (a *logApi) GetRunningLog(ctx *gin.Context) {
func (a *logApi) GetRunningLog(ctx *gin.Context, _ any) error {
rOk(ctx, "Query successful!", logic.Loghandler.GetRunning())
return nil
}

View File

@@ -11,14 +11,12 @@ var PermissionApi = new(permissionApi)
type permissionApi struct{}
func (p *permissionApi) EditPermssion(ctx *gin.Context) {
req := bind[model.Permission](ctx)
err := repository.PermissionRepository.EditPermssion(req)
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
func (p *permissionApi) EditPermssion(ctx *gin.Context, req model.Permission) (err error) {
return repository.PermissionRepository.EditPermssion(req)
}
func (p *permissionApi) GetPermissionList(ctx *gin.Context) {
result := repository.PermissionRepository.GetPermssionList(getQueryString(ctx, "account"))
func (p *permissionApi) GetPermissionList(ctx *gin.Context, req model.GetPermissionListReq) (err error) {
result := repository.PermissionRepository.GetPermssionList(req.Account)
rOk(ctx, "Query successful!", result)
return
}

View File

@@ -1,6 +1,7 @@
package api
import (
"errors"
"time"
"github.com/google/uuid"
@@ -16,114 +17,117 @@ type procApi struct{}
var ProcApi = new(procApi)
func (p *procApi) CreateNewProcess(ctx *gin.Context) {
req := bind[model.Process](ctx)
func (p *procApi) CreateNewProcess(ctx *gin.Context, req model.Process) (err error) {
index, err := repository.ProcessRepository.AddProcessConfig(req)
errCheck(ctx, err != nil, err)
if err != nil {
return
}
req.Uuid = index
proc, err := logic.ProcessCtlLogic.NewProcess(req)
errCheck(ctx, err != nil, err)
if err != nil {
return
}
logic.ProcessCtlLogic.AddProcess(req.Uuid, proc)
rOk(ctx, "Operation successful!", gin.H{
"id": req.Uuid,
})
}
func (p *procApi) DeleteNewProcess(ctx *gin.Context) {
uuid := getQueryInt(ctx, "uuid")
logic.ProcessCtlLogic.KillProcess(uuid)
logic.ProcessCtlLogic.DeleteProcess(uuid)
err := repository.ProcessRepository.DeleteProcessConfig(uuid)
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
}
func (p *procApi) KillProcess(ctx *gin.Context) {
uuid := getQueryInt(ctx, "uuid")
err := logic.ProcessCtlLogic.KillProcess(uuid)
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
}
func (p *procApi) StartProcess(ctx *gin.Context) {
uuid := getQueryInt(ctx, "uuid")
prod, err := logic.ProcessCtlLogic.GetProcess(uuid)
if err != nil { // 进程不存在则创建
proc, err := logic.ProcessCtlLogic.RunNewProcess(repository.ProcessRepository.GetProcessConfigById(uuid))
errCheck(ctx, err != nil, err)
logic.ProcessCtlLogic.AddProcess(uuid, proc)
rOk(ctx, "Operation successful!", nil)
return
}
func (p *procApi) DeleteNewProcess(ctx *gin.Context, req model.ProcessUuidReq) (err error) {
logic.ProcessCtlLogic.KillProcess(req.Uuid)
logic.ProcessCtlLogic.DeleteProcess(req.Uuid)
return repository.ProcessRepository.DeleteProcessConfig(req.Uuid)
}
func (p *procApi) KillProcess(ctx *gin.Context, req model.ProcessUuidReq) (err error) {
return logic.ProcessCtlLogic.KillProcess(req.Uuid)
}
func (p *procApi) StartProcess(ctx *gin.Context, req model.ProcessUuidReq) (err error) {
prod, err := logic.ProcessCtlLogic.GetProcess(req.Uuid)
if err != nil { // 进程不存在则创建
proc, err1 := logic.ProcessCtlLogic.RunNewProcess(repository.ProcessRepository.GetProcessConfigById(req.Uuid))
if err1 != nil {
return err1
}
logic.ProcessCtlLogic.AddProcess(req.Uuid, proc)
rOk(ctx, "Operation successful!", nil)
return nil
}
if prod.State.State == 1 {
return errors.New("process is currently running")
}
errCheck(ctx, prod.State.State == 1, "The process is currently running.")
prod.ResetRestartTimes()
err = prod.Start()
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
return
}
func (p *procApi) StartAllProcess(ctx *gin.Context) {
func (p *procApi) StartAllProcess(ctx *gin.Context, _ any) (err error) {
if isAdmin(ctx) {
logic.ProcessCtlLogic.ProcessStartAll()
} else {
logic.ProcessCtlLogic.ProcesStartAllByUsername(getUserName(ctx))
}
rOk(ctx, "Operation successful!", nil)
return
}
func (p *procApi) KillAllProcess(ctx *gin.Context) {
func (p *procApi) KillAllProcess(ctx *gin.Context, _ any) (err error) {
if isAdmin(ctx) {
logic.ProcessCtlLogic.KillAllProcess()
} else {
logic.ProcessCtlLogic.KillAllProcessByUserName(getUserName(ctx))
}
rOk(ctx, "Operation successful!", nil)
return
}
func (p *procApi) GetProcessList(ctx *gin.Context) {
func (p *procApi) GetProcessList(ctx *gin.Context, _ any) (err error) {
if isAdmin(ctx) {
rOk(ctx, "Query successful!", logic.ProcessCtlLogic.GetProcessList())
} else {
rOk(ctx, "Query successful!", logic.ProcessCtlLogic.GetProcessListByUser(getUserName(ctx)))
}
return
}
func (p *procApi) UpdateProcessConfig(ctx *gin.Context) {
req := bind[model.Process](ctx)
func (p *procApi) UpdateProcessConfig(ctx *gin.Context, req model.Process) (err error) {
logic.ProcessCtlLogic.UpdateProcessConfig(req)
err := repository.ProcessRepository.UpdateProcessConfig(req)
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
err = repository.ProcessRepository.UpdateProcessConfig(req)
return
}
func (p *procApi) GetProcessConfig(ctx *gin.Context) {
uuid := getQueryInt(ctx, "uuid")
data := repository.ProcessRepository.GetProcessConfigById(uuid)
errCheck(ctx, data.Uuid == 0, "No information found!")
rOk(ctx, "Query successful!", data)
func (p *procApi) GetProcessConfig(ctx *gin.Context, req model.ProcessUuidReq) (err error) {
data := repository.ProcessRepository.GetProcessConfigById(req.Uuid)
if data.Uuid == 0 {
return errors.New("no information found")
}
return
}
func (p *procApi) ProcessControl(ctx *gin.Context) {
func (p *procApi) ProcessControl(ctx *gin.Context, req model.ProcessUuidReq) (err error) {
user := getUserName(ctx)
uuid := getQueryInt(ctx, "uuid")
proc, err := logic.ProcessCtlLogic.GetProcess(uuid)
errCheck(ctx, err != nil, err)
proc, err := logic.ProcessCtlLogic.GetProcess(req.Uuid)
if err != nil {
return
}
proc.ProcessControl(user)
rOk(ctx, "Operation successful!", nil)
return
}
func (p *procApi) ProcessCreateShare(ctx *gin.Context) {
req := bind[model.ProcessShare](ctx)
func (p *procApi) ProcessCreateShare(ctx *gin.Context, req model.ProcessShare) (err error) {
token := utils.UnwarpIgnore(uuid.NewRandom()).String()
err := repository.WsShare.AddShareData(model.WsShare{
if err = repository.WsShare.AddShareData(model.WsShare{
ExpireTime: time.Now().Add(time.Minute * time.Duration(req.Minutes)),
Write: req.Write,
Token: token,
Pid: req.Pid,
CreateBy: getUserName(ctx),
})
errCheck(ctx, err != nil, err)
}); err != nil {
return
}
rOk(ctx, "Operation successful!", gin.H{
"token": token,
})
return
}

View File

@@ -11,32 +11,27 @@ type pushApi struct{}
var PushApi = new(pushApi)
func (p *pushApi) GetPushList(ctx *gin.Context) {
func (p *pushApi) GetPushList(ctx *gin.Context, __ any) (err error) {
rOk(ctx, "Query successful!", repository.PushRepository.GetPushList())
return
}
func (p *pushApi) GetPushById(ctx *gin.Context) {
id := getQueryInt(ctx, "id")
rOk(ctx, "Query successful!", repository.PushRepository.GetPushConfigById(id))
func (p *pushApi) GetPushById(ctx *gin.Context, req model.PushIdReq) (err error) {
rOk(ctx, "Query successful!", repository.PushRepository.GetPushConfigById(req.Id))
return
}
func (p *pushApi) AddPushConfig(ctx *gin.Context) {
req := bind[model.Push](ctx)
err := repository.PushRepository.AddPushConfig(req)
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
func (p *pushApi) AddPushConfig(ctx *gin.Context, req model.Push) (err error) {
err = repository.PushRepository.AddPushConfig(req)
return
}
func (p *pushApi) UpdatePushConfig(ctx *gin.Context) {
req := bind[model.Push](ctx)
err := repository.PushRepository.UpdatePushConfig(req)
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
func (p *pushApi) UpdatePushConfig(ctx *gin.Context, req model.Push) (err error) {
err = repository.PushRepository.UpdatePushConfig(req)
return
}
func (p *pushApi) DeletePushConfig(ctx *gin.Context) {
id := getQueryInt(ctx, "id")
err := repository.PushRepository.DeletePushConfig(id)
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
func (p *pushApi) DeletePushConfig(ctx *gin.Context, req model.PushIdReq) (err error) {
err = repository.PushRepository.DeletePushConfig(req.Id)
return
}

View File

@@ -1,6 +1,8 @@
package api
import (
"errors"
"github.com/lzh-1625/go_process_manager/internal/app/logic"
"github.com/lzh-1625/go_process_manager/internal/app/model"
"github.com/lzh-1625/go_process_manager/internal/app/repository"
@@ -12,62 +14,55 @@ type taskApi struct{}
var TaskApi = new(taskApi)
func (t *taskApi) CreateTask(ctx *gin.Context) {
req := bind[model.Task](ctx)
err := logic.TaskLogic.CreateTask(req)
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
func (t *taskApi) CreateTask(ctx *gin.Context, req model.Task) (err error) {
return logic.TaskLogic.CreateTask(req)
}
func (t *taskApi) GetTaskById(ctx *gin.Context) {
result, err := repository.TaskRepository.GetTaskById(getQueryInt(ctx, "id"))
errCheck(ctx, err != nil, "Query failed!")
func (t *taskApi) GetTaskById(ctx *gin.Context, req model.TaskIdReq) (err error) {
result, err := repository.TaskRepository.GetTaskById(req.Id)
if err != nil {
return
}
rOk(ctx, "Operation successful!", result)
return
}
func (t *taskApi) GetTaskList(ctx *gin.Context) {
func (t *taskApi) GetTaskList(ctx *gin.Context, _ any) (err error) {
result := logic.TaskLogic.GetAllTaskJob()
rOk(ctx, "Operation successful!", result)
return
}
func (t *taskApi) DeleteTaskById(ctx *gin.Context) {
err := logic.TaskLogic.DeleteTask(getQueryInt(ctx, "id"))
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
func (t *taskApi) DeleteTaskById(ctx *gin.Context, req model.TaskIdReq) (err error) {
return logic.TaskLogic.DeleteTask(req.Id)
}
func (t *taskApi) StartTask(ctx *gin.Context) {
go logic.TaskLogic.RunTaskById(getQueryInt(ctx, "id"))
rOk(ctx, "Operation successful!", nil)
func (t *taskApi) StartTask(ctx *gin.Context, req model.TaskIdReq) (err error) {
go logic.TaskLogic.RunTaskById(req.Id)
return
}
func (t *taskApi) StopTask(ctx *gin.Context) {
errCheck(ctx, logic.TaskLogic.StopTaskJob(getQueryInt(ctx, "id")) != nil, "Operation failed!")
rOk(ctx, "Operation successful!", nil)
func (t *taskApi) StopTask(ctx *gin.Context, req model.TaskIdReq) (err error) {
if logic.TaskLogic.StopTaskJob(req.Id) != nil {
return errors.New("operation failed")
}
return
}
func (t *taskApi) EditTask(ctx *gin.Context) {
req := bind[model.Task](ctx)
err := logic.TaskLogic.EditTask(req)
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
func (t *taskApi) EditTask(ctx *gin.Context, req model.Task) (err error) {
return logic.TaskLogic.EditTask(req)
}
func (t *taskApi) EditTaskEnable(ctx *gin.Context) {
req := bind[model.Task](ctx)
err := logic.TaskLogic.EditTaskEnable(req.Id, req.Enable)
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
func (t *taskApi) EditTaskEnable(ctx *gin.Context, req model.Task) (err error) {
return logic.TaskLogic.EditTaskEnable(req.Id, req.Enable)
}
func (t *taskApi) RunTaskByKey(ctx *gin.Context) {
err := logic.TaskLogic.RunTaskByKey(ctx.Param("key"))
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
func (t *taskApi) RunTaskByKey(ctx *gin.Context, _ any) (err error) {
return logic.TaskLogic.RunTaskByKey(ctx.Param("key"))
}
func (t *taskApi) CreateTaskApiKey(ctx *gin.Context) {
err := logic.TaskLogic.CreateApiKey(getQueryInt(ctx, "id"))
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
func (t *taskApi) CreateTaskApiKey(ctx *gin.Context, req model.TaskIdReq) (err error) {
return logic.TaskLogic.CreateApiKey(req.Id)
}

View File

@@ -1,6 +1,8 @@
package api
import (
"errors"
"github.com/lzh-1625/go_process_manager/config"
"github.com/lzh-1625/go_process_manager/internal/app/constants"
"github.com/lzh-1625/go_process_manager/internal/app/model"
@@ -16,57 +18,65 @@ var UserApi = new(userApi)
const DEFAULT_ROOT_PASSWORD = "root"
func (u *userApi) LoginHandler(ctx *gin.Context) {
req := bind[map[string]string](ctx)
account := req["account"]
password := req["password"]
errCheck(ctx, !u.checkLoginInfo(account, password), "Incorrect username or password!")
token, err := utils.GenToken(account)
errCheck(ctx, err != nil, err)
func (u *userApi) LoginHandler(ctx *gin.Context, req model.LoginHandlerReq) (err error) {
if !u.checkLoginInfo(req.Account, req.Password) {
return errors.New("incorrect username or password")
}
token, err := utils.GenToken(req.Account)
if err != nil {
return
}
rOk(ctx, "Operation successful!", gin.H{
"token": token,
"username": account,
"role": repository.UserRepository.GetUserByName(account).Role,
"username": req.Account,
"role": repository.UserRepository.GetUserByName(req.Account).Role,
})
return
}
func (u *userApi) CreateUser(ctx *gin.Context) {
req := bind[model.User](ctx)
errCheck(ctx, req.Role == constants.ROLE_ROOT, "Creation of root accounts is forbidden!")
errCheck(ctx, req.Account == constants.CONSOLE, "Operation failed!")
errCheck(ctx, len(req.Password) < config.CF.UserPassWordMinLength, "Password is too short")
err := repository.UserRepository.CreateUser(req)
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
func (u *userApi) CreateUser(ctx *gin.Context, req model.User) (err error) {
if req.Role == constants.ROLE_ROOT {
return errors.New("creation of root accounts is forbidden")
}
if req.Account == constants.CONSOLE {
return errors.New("operation failed")
}
if len(req.Password) < config.CF.UserPassWordMinLength {
return errors.New("password is too short")
}
err = repository.UserRepository.CreateUser(req)
return
}
func (u *userApi) ChangePassword(ctx *gin.Context) {
req := bind[model.User](ctx)
func (u *userApi) ChangePassword(ctx *gin.Context, req model.User) (err error) {
reqUser := getUserName(ctx)
errCheck(ctx, getRole(ctx) != constants.ROLE_ROOT && req.Account != "", "Invalid parameters!")
if getRole(ctx) != constants.ROLE_ROOT && req.Account != "" {
return errors.New("invalid parameters")
}
var userName string
if req.Account != "" {
userName = req.Account
} else {
userName = reqUser
}
errCheck(ctx, len(req.Password) < config.CF.UserPassWordMinLength, "Password is too short")
err := repository.UserRepository.UpdatePassword(userName, req.Password)
errCheck(ctx, err != nil, err)
rOk(ctx, "Operation successful!", nil)
if len(req.Password) < config.CF.UserPassWordMinLength {
return errors.New("password is too short")
}
err = repository.UserRepository.UpdatePassword(userName, req.Password)
return
}
func (u *userApi) DeleteUser(ctx *gin.Context) {
account := getQueryString(ctx, "account")
errCheck(ctx, account == "root", "Deletion of root accounts is forbidden!")
err := repository.UserRepository.DeleteUser(account)
errCheck(ctx, err != nil, "Deletion of root accounts failed!")
rOk(ctx, "Operation successful!", nil)
func (u *userApi) DeleteUser(ctx *gin.Context, req model.User) (err error) {
if req.Account == "root" {
return errors.New("deletion of root accounts is forbidden")
}
err = repository.UserRepository.DeleteUser(req.Account)
return
}
func (u *userApi) GetUserList(ctx *gin.Context) {
func (u *userApi) GetUserList(ctx *gin.Context, _ any) error {
rOk(ctx, "Query successful!", repository.UserRepository.GetUserList())
return nil
}
func (u *userApi) checkLoginInfo(account, password string) bool {

View File

@@ -2,6 +2,7 @@ package api
import (
"context"
"errors"
"strconv"
"sync"
"time"
@@ -9,6 +10,7 @@ import (
"github.com/lzh-1625/go_process_manager/config"
"github.com/lzh-1625/go_process_manager/internal/app/constants"
"github.com/lzh-1625/go_process_manager/internal/app/logic"
"github.com/lzh-1625/go_process_manager/internal/app/model"
"github.com/lzh-1625/go_process_manager/internal/app/repository"
"github.com/lzh-1625/go_process_manager/log"
"github.com/lzh-1625/go_process_manager/utils"
@@ -47,19 +49,22 @@ var upgrader = websocket.Upgrader{
WriteBufferSize: 1024,
}
func (w *wsApi) WebsocketHandle(ctx *gin.Context) {
func (w *wsApi) WebsocketHandle(ctx *gin.Context, req model.WebsocketHandleReq) (err error) {
reqUser := getUserName(ctx)
uuid := getQueryInt(ctx, "uuid")
proc, err := logic.ProcessCtlLogic.GetProcess(uuid)
errCheck(ctx, err != nil, "Operation failed!")
errCheck(ctx, proc.HasWsConn(reqUser), "A connection already exists; unable to establish a new one!")
errCheck(ctx, proc.Control.Controller != reqUser && !proc.VerifyControl(), "Insufficient permissions; please check your access rights!")
proc, err := logic.ProcessCtlLogic.GetProcess(req.Uuid)
if err != nil {
return
}
if !proc.HasWsConn(reqUser) {
return errors.New("connection already exists; unable to establish a new one")
}
if proc.Control.Controller == reqUser || proc.VerifyControl() {
return errors.New("insufficient permissions; please check your access rights")
}
conn, err := upgrader.Upgrade(ctx.Writer, ctx.Request, nil)
errCheck(ctx, err != nil, "WebSocket connection upgrade failed!")
log.Logger.AddAdditionalInfo("processName", proc.Name)
log.Logger.AddAdditionalInfo("userName", reqUser)
defer log.Logger.DeleteAdditionalInfo(2)
if err != nil {
return
}
log.Logger.Infow("ws连接成功")
@@ -72,7 +77,7 @@ func (w *wsApi) WebsocketHandle(ctx *gin.Context) {
proc.ReadCache(wci)
if proc.State.State == 1 {
proc.SetTerminalSize(utils.GetIntByString(ctx.Query("cols")), utils.GetIntByString(ctx.Query("rows")))
w.startWsConnect(wci, cancel, proc, hasOprPermission(ctx, uuid, constants.OPERATION_TERMINAL_WRITE))
w.startWsConnect(wci, cancel, proc, hasOprPermission(ctx, req.Uuid, constants.OPERATION_TERMINAL_WRITE))
proc.AddConn(reqUser, wci)
defer proc.DeleteConn(reqUser)
}
@@ -89,21 +94,35 @@ func (w *wsApi) WebsocketHandle(ctx *gin.Context) {
log.Logger.Infow("ws连接断开", "操作类型", "tcp连接建立已被关闭")
}
conn.Close()
return
}
func (w *wsApi) WebsocketShareHandle(ctx *gin.Context) {
token := getQueryString(ctx, "token")
data, err := repository.WsShare.GetWsShareDataByToken(token)
errCheck(ctx, err != nil, "Operation failed!")
errCheck(ctx, data.ExpireTime.Unix() <= time.Now().Unix(), "Share expired!")
func (w *wsApi) WebsocketShareHandle(ctx *gin.Context, req model.WebsocketHandleReq) (err error) {
data, err := repository.WsShare.GetWsShareDataByToken(req.Token)
if err != nil {
return
}
if data.ExpireTime.Unix() <= time.Now().Unix() {
return errors.New("share expired")
}
proc, err := logic.ProcessCtlLogic.GetProcess(data.Pid)
errCheck(ctx, err != nil, err)
if err != nil {
return
}
guestName := "guest-" + strconv.Itoa(int(data.ID)) // 构造访客用户名
errCheck(ctx, proc.HasWsConn(guestName), "A connection already exists; unable to establish a new one!")
errCheck(ctx, proc.State.State != 1, "The process is currently running.")
errCheck(ctx, !proc.VerifyControl(), "Insufficient permissions; please check your access rights!")
if proc.HasWsConn(guestName) {
return errors.New("connection already exists; unable to establish a new one")
}
if proc.State.State != 1 {
return errors.New("process is currently running")
}
if !proc.VerifyControl() {
return errors.New("insufficient permissions; please check your access rights")
}
conn, err := upgrader.Upgrade(ctx.Writer, ctx.Request, nil)
errCheck(ctx, err != nil, "WebSocket connection upgrade failed!")
if err != nil {
return
}
log.Logger.Infow("ws连接成功")
data.UpdatedAt = time.Now()
@@ -135,6 +154,7 @@ func (w *wsApi) WebsocketShareHandle(ctx *gin.Context) {
log.Logger.Infow("ws连接断开", "操作类型", "分享时间已结束")
}
conn.Close()
return
}
func (w *wsApi) startWsConnect(wci *WsConnetInstance, cancel context.CancelFunc, proc logic.Process, write bool) {
@@ -183,7 +203,8 @@ func GetWsShareList(ctx *gin.Context) {
}
func DeleteWsShareById(ctx *gin.Context) {
err := logic.WsSahreLogic.DeleteById(ctx.GetInt("id"))
errCheck(ctx, err != nil, err)
if err := logic.WsSahreLogic.DeleteById(ctx.GetInt("id")); err != nil {
return
}
rOk(ctx, "Operation successful!", nil)
}

View File

@@ -1,8 +0,0 @@
package constants
const (
BIND_NONE = 0
BIND_OPTION_HEADER = 1 << iota
BIND_OPTION_BODY
BIND_OPTION_QUERY
)

View File

@@ -4,3 +4,11 @@ type FileStruct struct {
Name string `json:"name"`
IsDir bool `json:"isDir"`
}
type FilePathHandlerReq struct {
Path string `form:"path"`
}
type FileReadHandlerReq struct {
FilePath string `form:"filePath"`
}

View File

@@ -29,3 +29,7 @@ type PermissionPo struct {
Write bool `gorm:"column:write;NOT NULL" json:"write"`
Log bool `gorm:"column:log;NOT NULL" json:"log"`
}
type GetPermissionListReq struct {
Account string `form:"account"`
}

View File

@@ -26,3 +26,7 @@ type ProcessShare struct {
Pid int `json:"pid"`
Write bool `json:"write"`
}
type ProcessUuidReq struct {
Uuid int `form:"uuid"`
}

View File

@@ -12,3 +12,7 @@ type Push struct {
func (*Push) TableName() string {
return "push"
}
type PushIdReq struct {
Id int `form:"id"`
}

View File

@@ -45,3 +45,7 @@ type TaskVo struct {
StartTime time.Time `json:"startTime"`
Running bool `json:"running"`
}
type TaskIdReq struct {
Id int `form:"id"`
}

View File

@@ -17,3 +17,12 @@ type User struct {
func (*User) TableName() string {
return "users"
}
type LoginHandlerReq struct {
Account string `form:"account"`
Password string `form:"password"`
}
type DeleteUserReq struct {
Account string `form:"account"`
}

View File

@@ -14,3 +14,14 @@ type WsShare struct {
CreateBy string `gorm:"column:create_by" json:"createBy"`
Token string `gorm:"column:token" json:"token"`
}
func (WsShare) TableName() string {
return "ws_share"
}
type WebsocketHandleReq struct {
Uuid int `json:"uuid"`
Cols int `json:"cols"`
Rows int `json:"rows"`
Token string `json:"token"`
}

View File

@@ -51,6 +51,7 @@ func pprofInit(r *gin.Engine) {
}
func routePathInit(r *gin.Engine) {
apiGroup := r.Group("/api")
apiGroup.Use(middle.CheckToken())
apiGroup.Use(middle.PanicMiddle())
@@ -58,107 +59,114 @@ func routePathInit(r *gin.Engine) {
{
wsGroup := apiGroup.Group("/ws")
{
wsGroup.GET("", middle.OprPermission(constants.OPERATION_TERMINAL), api.WsApi.WebsocketHandle)
wsGroup.GET("/share", api.WsApi.WebsocketShareHandle)
wsGroup.GET("", middle.OprPermission(constants.OPERATION_TERMINAL), bind(api.WsApi.WebsocketHandle, Query))
wsGroup.GET("/share", bind(api.WsApi.WebsocketShareHandle, Query))
}
processGroup := apiGroup.Group("/process")
{
processGroup.DELETE("", middle.OprPermission(constants.OPERATION_STOP), api.ProcApi.KillProcess)
processGroup.GET("", api.ProcApi.GetProcessList)
processGroup.GET("/wait", middle.ProcessWaitCond.WaitGetMiddel, api.ProcApi.GetProcessList)
processGroup.PUT("", middle.OprPermission(constants.OPERATION_START), api.ProcApi.StartProcess)
processGroup.PUT("/all", api.ProcApi.StartAllProcess)
processGroup.DELETE("/all", api.ProcApi.KillAllProcess)
processGroup.POST("/share", middle.RolePermission(constants.ROLE_ADMIN), api.ProcApi.ProcessCreateShare)
processGroup.GET("/control", middle.RolePermission(constants.ROLE_ROOT), middle.ProcessWaitCond.WaitTriggerMiddel, api.ProcApi.ProcessControl)
processGroup.DELETE("", middle.OprPermission(constants.OPERATION_STOP), bind(api.ProcApi.KillProcess, Query))
processGroup.GET("", bind(api.ProcApi.GetProcessList, None))
processGroup.GET("/wait", middle.ProcessWaitCond.WaitGetMiddel, bind(api.ProcApi.GetProcessList, None))
processGroup.PUT("", middle.OprPermission(constants.OPERATION_START), bind(api.ProcApi.StartProcess, Body))
processGroup.PUT("/all", bind(api.ProcApi.StartAllProcess, None))
processGroup.DELETE("/all", bind(api.ProcApi.KillAllProcess, None))
processGroup.POST("/share", middle.RolePermission(constants.ROLE_ADMIN), bind(api.ProcApi.ProcessCreateShare, Body))
processGroup.GET("/control", middle.RolePermission(constants.ROLE_ROOT), middle.ProcessWaitCond.WaitTriggerMiddel, bind(api.ProcApi.ProcessControl, Query))
proConfigGroup := processGroup.Group("/config")
{
proConfigGroup.POST("", middle.RolePermission(constants.ROLE_ROOT), middle.ProcessWaitCond.WaitTriggerMiddel, api.ProcApi.CreateNewProcess)
proConfigGroup.DELETE("", middle.RolePermission(constants.ROLE_ROOT), middle.ProcessWaitCond.WaitTriggerMiddel, api.ProcApi.DeleteNewProcess)
proConfigGroup.PUT("", middle.RolePermission(constants.ROLE_ROOT), api.ProcApi.UpdateProcessConfig)
proConfigGroup.GET("", middle.RolePermission(constants.ROLE_ADMIN), api.ProcApi.GetProcessConfig)
proConfigGroup.POST("", middle.RolePermission(constants.ROLE_ROOT), middle.ProcessWaitCond.WaitTriggerMiddel, bind(api.ProcApi.CreateNewProcess, Body))
proConfigGroup.DELETE("", middle.RolePermission(constants.ROLE_ROOT), middle.ProcessWaitCond.WaitTriggerMiddel, bind(api.ProcApi.DeleteNewProcess, Query))
proConfigGroup.PUT("", middle.RolePermission(constants.ROLE_ROOT), bind(api.ProcApi.UpdateProcessConfig, Body))
proConfigGroup.GET("", middle.RolePermission(constants.ROLE_ADMIN), bind(api.ProcApi.GetProcessConfig, Query))
}
}
taskGroup := apiGroup.Group("/task")
{
taskGroup.GET("", middle.RolePermission(constants.ROLE_ADMIN), api.TaskApi.GetTaskById)
taskGroup.GET("/all", middle.RolePermission(constants.ROLE_ADMIN), api.TaskApi.GetTaskList)
taskGroup.GET("/all/wait", middle.RolePermission(constants.ROLE_ADMIN), middle.TaskWaitCond.WaitGetMiddel, api.TaskApi.GetTaskList)
taskGroup.POST("", middle.RolePermission(constants.ROLE_ADMIN), middle.TaskWaitCond.WaitTriggerMiddel, api.TaskApi.CreateTask)
taskGroup.DELETE("", middle.RolePermission(constants.ROLE_ADMIN), middle.TaskWaitCond.WaitTriggerMiddel, api.TaskApi.DeleteTaskById)
taskGroup.PUT("", middle.RolePermission(constants.ROLE_ADMIN), middle.TaskWaitCond.WaitTriggerMiddel, api.TaskApi.EditTask)
taskGroup.PUT("/enable", middle.RolePermission(constants.ROLE_ADMIN), middle.TaskWaitCond.WaitTriggerMiddel, api.TaskApi.EditTaskEnable)
taskGroup.GET("/start", middle.RolePermission(constants.ROLE_ADMIN), api.TaskApi.StartTask)
taskGroup.GET("/stop", middle.RolePermission(constants.ROLE_ADMIN), api.TaskApi.StopTask)
taskGroup.POST("/key", middle.RolePermission(constants.ROLE_ADMIN), api.TaskApi.CreateTaskApiKey)
taskGroup.GET("/api-key/:key", api.TaskApi.RunTaskByKey)
taskGroup.GET("", middle.RolePermission(constants.ROLE_ADMIN), bind(api.TaskApi.GetTaskById, Query))
taskGroup.GET("/all", middle.RolePermission(constants.ROLE_ADMIN), bind(api.TaskApi.GetTaskList, None))
taskGroup.GET("/all/wait", middle.RolePermission(constants.ROLE_ADMIN), middle.TaskWaitCond.WaitGetMiddel, bind(api.TaskApi.GetTaskList, None))
taskGroup.POST("", middle.RolePermission(constants.ROLE_ADMIN), middle.TaskWaitCond.WaitTriggerMiddel, bind(api.TaskApi.CreateTask, Body))
taskGroup.DELETE("", middle.RolePermission(constants.ROLE_ADMIN), middle.TaskWaitCond.WaitTriggerMiddel, bind(api.TaskApi.DeleteTaskById, Query))
taskGroup.PUT("", middle.RolePermission(constants.ROLE_ADMIN), middle.TaskWaitCond.WaitTriggerMiddel, bind(api.TaskApi.EditTask, Body))
taskGroup.PUT("/enable", middle.RolePermission(constants.ROLE_ADMIN), middle.TaskWaitCond.WaitTriggerMiddel, bind(api.TaskApi.EditTaskEnable, Body))
taskGroup.GET("/start", middle.RolePermission(constants.ROLE_ADMIN), bind(api.TaskApi.StartTask, Query))
taskGroup.GET("/stop", middle.RolePermission(constants.ROLE_ADMIN), bind(api.TaskApi.StopTask, Query))
taskGroup.POST("/key", middle.RolePermission(constants.ROLE_ADMIN), bind(api.TaskApi.CreateTaskApiKey, Body))
taskGroup.GET("/api-key/:key", bind(api.TaskApi.RunTaskByKey, None))
}
userGroup := apiGroup.Group("/user")
{
userGroup.POST("/login", api.UserApi.LoginHandler)
userGroup.POST("", middle.RolePermission(constants.ROLE_ROOT), api.UserApi.CreateUser)
userGroup.PUT("/password", middle.RolePermission(constants.ROLE_USER), api.UserApi.ChangePassword)
userGroup.DELETE("", middle.RolePermission(constants.ROLE_ROOT), api.UserApi.DeleteUser)
userGroup.GET("", middle.RolePermission(constants.ROLE_ROOT), api.UserApi.GetUserList)
userGroup.POST("/login", bind(api.UserApi.LoginHandler, Body))
userGroup.POST("", middle.RolePermission(constants.ROLE_ROOT), bind(api.UserApi.CreateUser, Body))
userGroup.PUT("/password", middle.RolePermission(constants.ROLE_USER), bind(api.UserApi.ChangePassword, Body))
userGroup.DELETE("", middle.RolePermission(constants.ROLE_ROOT), bind(api.UserApi.DeleteUser, Query))
userGroup.GET("", middle.RolePermission(constants.ROLE_ROOT), bind(api.UserApi.GetUserList, None))
}
pushGroup := apiGroup.Group("/push").Use(middle.RolePermission(constants.ROLE_ADMIN))
{
pushGroup.GET("/list", api.PushApi.GetPushList)
pushGroup.GET("", api.PushApi.GetPushById)
pushGroup.POST("", api.PushApi.AddPushConfig)
pushGroup.PUT("", api.PushApi.UpdatePushConfig)
pushGroup.DELETE("", api.PushApi.DeletePushConfig)
pushGroup.GET("/list", bind(api.PushApi.GetPushList, None))
pushGroup.GET("", bind(api.PushApi.GetPushById, Query))
pushGroup.POST("", bind(api.PushApi.AddPushConfig, Body))
pushGroup.PUT("", bind(api.PushApi.UpdatePushConfig, Body))
pushGroup.DELETE("", bind(api.PushApi.DeletePushConfig, Query))
}
fileGroup := apiGroup.Group("/file").Use(middle.RolePermission(constants.ROLE_ADMIN))
{
fileGroup.GET("/list", api.FileApi.FilePathHandler)
fileGroup.PUT("", api.FileApi.FileWriteHandler)
fileGroup.GET("", api.FileApi.FileReadHandler)
fileGroup.GET("/list", bind(api.FileApi.FilePathHandler, Query))
fileGroup.PUT("", bind(api.FileApi.FileWriteHandler, None))
fileGroup.GET("", bind(api.FileApi.FileReadHandler, Query))
}
permissionGroup := apiGroup.Group("/permission").Use(middle.RolePermission(constants.ROLE_ROOT))
{
permissionGroup.GET("/list", api.PermissionApi.GetPermissionList)
permissionGroup.PUT("", middle.ProcessWaitCond.WaitTriggerMiddel, api.PermissionApi.EditPermssion)
permissionGroup.GET("/list", bind(api.PermissionApi.GetPermissionList, Query))
permissionGroup.PUT("", middle.ProcessWaitCond.WaitTriggerMiddel, bind(api.PermissionApi.EditPermssion, Body))
}
logGroup := apiGroup.Group("/log").Use(middle.RolePermission(constants.ROLE_USER))
{
logGroup.POST("", api.LogApi.GetLog)
logGroup.GET("/running", api.LogApi.GetRunningLog)
logGroup.POST("", bind(api.LogApi.GetLog, Body))
logGroup.GET("/running", bind(api.LogApi.GetRunningLog, None))
}
configGroup := apiGroup.Group("/config").Use(middle.RolePermission(constants.ROLE_ROOT))
{
configGroup.GET("", api.ConfigApi.GetSystemConfiguration)
configGroup.PUT("", api.ConfigApi.SetSystemConfiguration)
configGroup.PUT("/es", api.ConfigApi.EsConfigReload)
configGroup.GET("", bind(api.ConfigApi.GetSystemConfiguration, None))
configGroup.PUT("", bind(api.ConfigApi.SetSystemConfiguration, None))
configGroup.PUT("/es", bind(api.ConfigApi.EsConfigReload, None))
}
}
}
func bind[T any](fn func(*gin.Context, *T) error, bindOption int) func(*gin.Context) {
const (
None = 0
Header = 1 << iota
Body
Query
)
func bind[T any](fn func(*gin.Context, T) error, bindOption int) func(*gin.Context) {
return func(ctx *gin.Context) {
var req *T
if bindOption&constants.BIND_OPTION_BODY != 0 {
var req T
if bindOption&Body != 0 {
if err := ctx.BindJSON(req); err != nil {
rErr(ctx, err)
return
}
}
if bindOption&constants.BIND_OPTION_HEADER != 0 {
if bindOption&Header != 0 {
if err := ctx.BindHeader(req); err != nil {
rErr(ctx, err)
return
}
}
if bindOption&constants.BIND_OPTION_QUERY != 0 {
if bindOption&Query != 0 {
if err := ctx.BindQuery(req); err != nil {
rErr(ctx, err)
return
@@ -167,9 +175,15 @@ func bind[T any](fn func(*gin.Context, *T) error, bindOption int) func(*gin.Cont
err := fn(ctx, req)
if err != nil {
rErr(ctx, err)
return
}
if ctx.Writer.Status() == 0 {
ctx.JSON(200, gin.H{
"code": 0,
"message": "success",
})
}
}
}
func rErr(ctx *gin.Context, err error) {