Files
oneterm/backend/internal/api/controller/command.go

142 lines
4.1 KiB
Go

package controller
import (
"errors"
"fmt"
"net/http"
"regexp"
"strings"
"github.com/gin-gonic/gin"
"github.com/samber/lo"
"github.com/spf13/cast"
"gorm.io/gorm"
"github.com/veops/oneterm/internal/acl"
"github.com/veops/oneterm/internal/model"
"github.com/veops/oneterm/pkg/config"
dbpkg "github.com/veops/oneterm/pkg/db"
)
var (
commandPreHooks = []preHook[*model.Command]{
func(ctx *gin.Context, data *model.Command) {
if !data.IsRe {
return
}
_, err := regexp.Compile(data.Cmd)
if err != nil {
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrBadRequest, Data: map[string]any{"err": err}})
}
},
}
commandDcs = []deleteCheck{
func(ctx *gin.Context, id int) {
assetName := ""
err := dbpkg.DB.
Model(model.DefaultAsset).
Select("name").
Where(fmt.Sprintf("JSON_CONTAINS(cmd_ids, '%d')", id)).
First(&assetName).
Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return
}
code := lo.Ternary(err == nil, http.StatusBadRequest, http.StatusInternalServerError)
err = lo.Ternary[error](err == nil, &ApiError{Code: ErrHasDepency, Data: map[string]any{"name": assetName}}, err)
ctx.AbortWithError(code, err)
},
}
)
// CreateCommand godoc
//
// @Tags command
// @Param command body model.Command true "command"
// @Success 200 {object} HttpResponse
// @Router /command [post]
func (c *Controller) CreateCommand(ctx *gin.Context) {
doCreate(ctx, true, &model.Command{}, config.RESOURCE_COMMAND, commandPreHooks...)
}
// DeleteCommand godoc
//
// @Tags command
// @Param id path int true "command id"
// @Success 200 {object} HttpResponse
// @Router /command/:id [delete]
func (c *Controller) DeleteCommand(ctx *gin.Context) {
doDelete(ctx, true, &model.Command{}, config.RESOURCE_COMMAND, commandDcs...)
}
// UpdateCommand godoc
//
// @Tags command
// @Param id path int true "command id"
// @Param command body model.Command true "command"
// @Success 200 {object} HttpResponse
// @Router /command/:id [put]
func (c *Controller) UpdateCommand(ctx *gin.Context) {
doUpdate(ctx, true, &model.Command{}, config.RESOURCE_COMMAND, commandPreHooks...)
}
// GetCommands godoc
//
// @Tags command
// @Param page_index query int true "command id"
// @Param page_size query int true "command id"
// @Param search query string false "name or cmd"
// @Param id query int false "command id"
// @Param ids query string false "command ids"
// @Param name query string false "command name"
// @Param enable query int false "command enable"
// @Param info query bool false "is info mode"
// @Param search query string false "name or cmd"
// @Success 200 {object} HttpResponse{data=ListData{list=[]model.Command}}
// @Router /command [get]
func (c *Controller) GetCommands(ctx *gin.Context) {
currentUser, _ := acl.GetSessionFromCtx(ctx)
info := cast.ToBool(ctx.Query("info"))
db := dbpkg.DB.Model(&model.Command{})
db = filterEqual(ctx, db, "id", "enable")
db = filterLike(ctx, db, "name")
db = filterSearch(ctx, db, "name", "cmd")
if q, ok := ctx.GetQuery("ids"); ok {
db = db.Where("id IN ?", lo.Map(strings.Split(q, ","), func(s string, _ int) int { return cast.ToInt(s) }))
}
if info && !acl.IsAdmin(currentUser) {
//rs := make([]*acl.Resource, 0)
rs, err := acl.GetRoleResources(ctx, currentUser.Acl.Rid, config.RESOURCE_AUTHORIZATION)
if err != nil {
handleRemoteErr(ctx, err)
return
}
sub := dbpkg.DB.
Model(&model.Authorization{}).
Select("DISTINCT asset_id").
Where("resource_id IN ?", lo.Map(rs, func(r *acl.Resource, _ int) int { return r.ResourceId }))
cmdIds := make([]model.Slice[int], 0)
if err = dbpkg.DB.
Model(model.DefaultAsset).
Select("cmd_ids").
Where("id IN (?)", sub).
Find(&cmdIds).
Error; err != nil {
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
}
ids := make([]int, 0)
for _, s := range cmdIds {
ids = append(ids, s...)
}
db = db.Where("id IN ?", lo.Uniq(ids))
}
db = db.Order("name")
doGet[*model.Command](ctx, !info, db, config.RESOURCE_COMMAND)
}