Files
oneterm/backend/internal/api/controller/asset.go
2025-05-05 21:08:45 +08:00

156 lines
4.6 KiB
Go

package controller
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/spf13/cast"
"go.uber.org/zap"
"github.com/veops/oneterm/internal/acl"
"github.com/veops/oneterm/internal/model"
"github.com/veops/oneterm/internal/service"
"github.com/veops/oneterm/pkg/config"
"github.com/veops/oneterm/pkg/errors"
"github.com/veops/oneterm/pkg/logger"
)
const (
kFmtAssetIds = "assetIds-%d"
kAuthorizationIds = "authorizationIds"
kNodeIds = "nodeIds"
kAccountIds = "accountIds"
)
var (
assetService = service.NewAssetService()
assetPreHooks = []preHook[*model.Asset]{
// Preprocess asset data
func(ctx *gin.Context, data *model.Asset) {
assetService.PreprocessAssetData(data)
},
}
assetPostHooks = []postHook[*model.Asset]{
// Attach node chain
func(ctx *gin.Context, data []*model.Asset) {
if err := assetService.AttachNodeChain(ctx, data); err != nil {
logger.L().Error("attach node chain failed", zap.Error(err))
return
}
},
// Apply authorization filters
func(ctx *gin.Context, data []*model.Asset) {
currentUser, _ := acl.GetSessionFromCtx(ctx)
if acl.IsAdmin(currentUser) {
return
}
authorizationIds, _ := ctx.Value(kAuthorizationIds).([]*model.AuthorizationIds)
nodeIds, _ := ctx.Value(kNodeIds).([]int)
accountIds, _ := ctx.Value(kAccountIds).([]int)
assetService.ApplyAuthorizationFilters(ctx, data, authorizationIds, nodeIds, accountIds)
},
}
)
// CreateAsset godoc
//
// @Tags asset
// @Param asset body model.Asset true "asset"
// @Success 200 {object} HttpResponse
// @Router /asset [post]
func (c *Controller) CreateAsset(ctx *gin.Context) {
asset := &model.Asset{}
doCreate(ctx, true, asset, config.RESOURCE_ASSET, assetPreHooks...)
assetService.UpdateConnectables(asset.Id)
}
// DeleteAsset godoc
//
// @Tags asset
// @Param id path int true "asset id"
// @Success 200 {object} HttpResponse
// @Router /asset/:id [delete]
func (c *Controller) DeleteAsset(ctx *gin.Context) {
doDelete(ctx, true, &model.Asset{}, config.RESOURCE_ASSET)
}
// UpdateAsset godoc
//
// @Tags asset
// @Param id path int true "asset id"
// @Param asset body model.Asset true "asset"
// @Success 200 {object} HttpResponse
// @Router /asset/:id [put]
func (c *Controller) UpdateAsset(ctx *gin.Context) {
doUpdate(ctx, true, &model.Asset{}, config.RESOURCE_ASSET, assetPreHooks...)
assetService.UpdateConnectables(cast.ToInt(ctx.Param("id")))
}
// GetAssets godoc
//
// @Tags asset
// @Param page_index query int true "page_index"
// @Param page_size query int true "page_size"
// @Param search query string false "name or ip"
// @Param id query int false "asset id"
// @Param ids query string false "asset ids"
// @Param parent_id query int false "asset's parent id"
// @Param name query string false "asset name"
// @Param ip query string false "asset ip"
// @Param info query bool false "is info mode"
// @Success 200 {object} HttpResponse{data=ListData{list=[]model.Asset}}
// @Router /asset [get]
func (c *Controller) GetAssets(ctx *gin.Context) {
currentUser, _ := acl.GetSessionFromCtx(ctx)
info := cast.ToBool(ctx.Query("info"))
// Build base query using service layer
db, err := assetService.BuildQuery(ctx)
if err != nil {
ctx.AbortWithError(http.StatusInternalServerError, &errors.ApiError{Code: errors.ErrInternal, Data: map[string]any{"err": err}})
return
}
// Apply parent_id filter if needed
if q, ok := ctx.GetQuery("parent_id"); ok {
db, err = assetService.FilterByParentId(db, cast.ToInt(q))
if err != nil {
logger.L().Error("parent id filtering failed", zap.Error(err))
ctx.AbortWithError(http.StatusInternalServerError, &errors.ApiError{Code: errors.ErrInternal, Data: map[string]any{"err": err}})
return
}
}
// Apply info mode settings
if info {
db = db.Select("id", "parent_id", "name", "ip", "protocols", "connectable", "authorization")
// Apply authorization filter if needed
if !acl.IsAdmin(currentUser) {
ids, err := GetAssetIdsByAuthorization(ctx)
if err != nil {
ctx.AbortWithError(http.StatusInternalServerError, &errors.ApiError{Code: errors.ErrInternal, Data: map[string]any{"err": err}})
return
}
db = db.Where("id IN ?", ids)
}
}
doGet(ctx, !info, db, config.RESOURCE_ASSET, assetPostHooks...)
}
// GetAssetIdsByAuthorization gets asset IDs by authorization
func GetAssetIdsByAuthorization(ctx *gin.Context) ([]int, error) {
authIds, err := getAuthorizationIds(ctx)
if err != nil {
return nil, err
}
_, assetIds, _, err := assetService.GetAssetIdsByAuthorization(ctx, authIds)
return assetIds, err
}