mirror of
https://github.com/veops/oneterm.git
synced 2025-10-05 15:27:01 +08:00
690 lines
18 KiB
Go
690 lines
18 KiB
Go
package controller
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"reflect"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/samber/lo"
|
|
"github.com/spf13/cast"
|
|
"golang.org/x/sync/errgroup"
|
|
"gorm.io/gorm"
|
|
|
|
"github.com/veops/oneterm/internal/acl"
|
|
"github.com/veops/oneterm/internal/model"
|
|
"github.com/veops/oneterm/internal/repository"
|
|
"github.com/veops/oneterm/pkg/config"
|
|
dbpkg "github.com/veops/oneterm/pkg/db"
|
|
"github.com/veops/oneterm/pkg/remote"
|
|
)
|
|
|
|
var (
|
|
defaultHttpResponse = &HttpResponse{
|
|
Code: 0,
|
|
Message: "ok",
|
|
Data: nil,
|
|
}
|
|
)
|
|
|
|
type preHook[T any] func(*gin.Context, T)
|
|
type postHook[T any] func(*gin.Context, []T)
|
|
type deleteCheck func(*gin.Context, int)
|
|
|
|
type Controller struct{}
|
|
|
|
func NewController() *Controller {
|
|
return &Controller{}
|
|
}
|
|
|
|
type HttpResponse struct {
|
|
Code int `json:"code"`
|
|
Message string `json:"message"`
|
|
Data any `json:"data"`
|
|
}
|
|
|
|
type ListData struct {
|
|
Count int64 `json:"count"`
|
|
List []any `json:"list"`
|
|
}
|
|
|
|
func NewHttpResponseWithData(data any) *HttpResponse {
|
|
return &HttpResponse{
|
|
Code: 0,
|
|
Message: "ok",
|
|
Data: data,
|
|
}
|
|
}
|
|
|
|
func doCreate[T model.Model](ctx *gin.Context, needAcl bool, md T, resourceType string, preHooks ...preHook[T]) (err error) {
|
|
defer repository.DeleteAllFromCacheDb(ctx, md)
|
|
|
|
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
|
|
|
if err = ctx.ShouldBindBodyWithJSON(md); err != nil {
|
|
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrInvalidArgument, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
|
|
for _, hook := range preHooks {
|
|
if hook == nil {
|
|
continue
|
|
}
|
|
hook(ctx, md)
|
|
if ctx.IsAborted() {
|
|
return
|
|
}
|
|
}
|
|
|
|
resourceId := 0
|
|
if needAcl {
|
|
_, ok := any(md).(*model.Node)
|
|
resourceId, err = acl.CreateGrantAcl(ctx, currentUser, resourceType, md.GetName()+lo.Ternary(ok, time.Now().Format(time.RFC3339), ""))
|
|
if err != nil {
|
|
handleRemoteErr(ctx, err)
|
|
return
|
|
}
|
|
md.SetResourceId(resourceId)
|
|
}
|
|
|
|
md.SetCreatorId(currentUser.Uid)
|
|
md.SetUpdaterId(currentUser.Uid)
|
|
|
|
if err = dbpkg.DB.Transaction(func(tx *gorm.DB) (err error) {
|
|
if err = tx.Model(md).Create(md).Error; err != nil {
|
|
return
|
|
}
|
|
|
|
switch t := any(md).(type) {
|
|
case *model.Asset:
|
|
if err = handleAuthorization(ctx, tx, model.ACTION_CREATE, t, nil); err != nil {
|
|
handleRemoteErr(ctx, err)
|
|
return
|
|
}
|
|
case *model.Node:
|
|
if err = acl.UpdateResource(ctx, currentUser.GetUid(), resourceId, map[string]string{"name": cast.ToString(md.GetId())}); err != nil {
|
|
handleRemoteErr(ctx, err)
|
|
return
|
|
}
|
|
}
|
|
|
|
if err = tx.Create(&model.History{
|
|
RemoteIp: ctx.ClientIP(),
|
|
Type: md.TableName(),
|
|
TargetId: md.GetId(),
|
|
ActionType: model.ACTION_CREATE,
|
|
Old: nil,
|
|
New: toMap(md),
|
|
CreatorId: currentUser.Uid,
|
|
CreatedAt: time.Now(),
|
|
}).Error; err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}); err != nil {
|
|
if errors.Is(err, gorm.ErrDuplicatedKey) {
|
|
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrDuplicateName, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, HttpResponse{
|
|
Data: map[string]any{
|
|
"id": md.GetId(),
|
|
},
|
|
})
|
|
|
|
return
|
|
}
|
|
|
|
func doDelete[T model.Model](ctx *gin.Context, needAcl bool, md T, resourceType string, dcs ...deleteCheck) (err error) {
|
|
defer repository.DeleteAllFromCacheDb(ctx, md)
|
|
|
|
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
|
|
|
id, err := cast.ToIntE(ctx.Param("id"))
|
|
if err != nil {
|
|
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrInvalidArgument, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
|
|
if err = dbpkg.DB.Model(md).Where("id = ?", id).First(md).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
ctx.JSON(http.StatusOK, HttpResponse{
|
|
Data: map[string]any{
|
|
"id": md.GetId(),
|
|
},
|
|
})
|
|
return
|
|
}
|
|
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
if needAcl && !hasPerm(ctx, md, resourceType, acl.DELETE) {
|
|
ctx.AbortWithError(http.StatusForbidden, &ApiError{Code: ErrNoPerm, Data: map[string]any{"perm": acl.DELETE}})
|
|
return
|
|
}
|
|
for _, dc := range dcs {
|
|
if dc == nil {
|
|
continue
|
|
}
|
|
dc(ctx, id)
|
|
if ctx.IsAborted() {
|
|
return
|
|
}
|
|
}
|
|
if needAcl {
|
|
if err = acl.DeleteResource(ctx, currentUser.GetUid(), md.GetResourceId()); err != nil {
|
|
handleRemoteErr(ctx, err)
|
|
return
|
|
}
|
|
}
|
|
|
|
if err = dbpkg.DB.Transaction(func(tx *gorm.DB) (err error) {
|
|
switch t := any(md).(type) {
|
|
case *model.Asset:
|
|
if err = handleAuthorization(ctx, tx, model.ACTION_DELETE, t, nil, nil); err != nil {
|
|
handleRemoteErr(ctx, err)
|
|
return
|
|
}
|
|
}
|
|
|
|
if err = tx.Delete(md, id).Error; err != nil {
|
|
return
|
|
}
|
|
err = tx.Create(&model.History{
|
|
RemoteIp: ctx.ClientIP(),
|
|
Type: md.TableName(),
|
|
TargetId: md.GetId(),
|
|
ActionType: model.ACTION_DELETE,
|
|
Old: toMap(md),
|
|
New: nil,
|
|
CreatorId: currentUser.Uid,
|
|
CreatedAt: time.Now(),
|
|
}).Error
|
|
return
|
|
}); err != nil {
|
|
if errors.Is(err, gorm.ErrDuplicatedKey) {
|
|
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrDuplicateName, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, HttpResponse{
|
|
Data: map[string]any{
|
|
"id": md.GetId(),
|
|
},
|
|
})
|
|
|
|
return
|
|
}
|
|
|
|
func doUpdate[T model.Model](ctx *gin.Context, needAcl bool, md T, resourceType string, preHooks ...preHook[T]) (err error) {
|
|
defer repository.DeleteAllFromCacheDb(ctx, md)
|
|
|
|
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
|
|
|
id, err := cast.ToIntE(ctx.Param("id"))
|
|
if err != nil {
|
|
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrInvalidArgument, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
|
|
if err = ctx.ShouldBindBodyWithJSON(md); err != nil {
|
|
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrInvalidArgument, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
md.SetUpdaterId(currentUser.Uid)
|
|
|
|
for _, hook := range preHooks {
|
|
if hook == nil {
|
|
continue
|
|
}
|
|
hook(ctx, md)
|
|
if ctx.IsAborted() {
|
|
return
|
|
}
|
|
}
|
|
|
|
old := getEmpty(md)
|
|
if err = dbpkg.DB.Model(md).Where("id = ?", id).First(old).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
ctx.JSON(http.StatusOK, defaultHttpResponse)
|
|
return
|
|
}
|
|
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
if needAcl {
|
|
md.SetResourceId(old.GetResourceId())
|
|
// fmt.Printf("%+v\n", old)
|
|
// fmt.Printf("%+v\n", md)
|
|
if !hasPerm(ctx, md, resourceType, acl.WRITE) {
|
|
ctx.AbortWithError(http.StatusForbidden, &ApiError{Code: ErrNoPerm, Data: map[string]any{"perm": acl.WRITE}})
|
|
return
|
|
}
|
|
|
|
_, ok := any(md).(*model.Node)
|
|
if err = acl.UpdateResource(ctx, currentUser.GetUid(), old.GetResourceId(),
|
|
map[string]string{"name": lo.Ternary(ok, cast.ToString(md.GetId()), md.GetName())}); err != nil {
|
|
handleRemoteErr(ctx, err)
|
|
return
|
|
}
|
|
}
|
|
md.SetId(id)
|
|
|
|
if err = dbpkg.DB.Transaction(func(tx *gorm.DB) (err error) {
|
|
omits := []string{"resource_id", "created_at", "deleted_at"}
|
|
selects := []string{"*"}
|
|
switch t := any(md).(type) {
|
|
case *model.Asset:
|
|
if err = handleAuthorization(ctx, tx, model.ACTION_UPDATE, t, nil); err != nil {
|
|
handleRemoteErr(ctx, err)
|
|
return
|
|
}
|
|
if cast.ToBool(ctx.Value("isAuthWithKey")) {
|
|
selects = []string{"ip", "protocols", "authorization"}
|
|
}
|
|
case *model.Account:
|
|
if cast.ToBool(ctx.Value("isAuthWithKey")) {
|
|
selects = []string{"account", "password", "phrase", "pk", "account_type"}
|
|
}
|
|
}
|
|
|
|
if err = dbpkg.DB.Select(selects).Omit(omits...).Save(md).Error; err != nil {
|
|
return
|
|
}
|
|
err = dbpkg.DB.Create(&model.History{
|
|
RemoteIp: ctx.ClientIP(),
|
|
Type: md.TableName(),
|
|
TargetId: md.GetId(),
|
|
ActionType: model.ACTION_UPDATE,
|
|
Old: toMap(old),
|
|
New: toMap(md),
|
|
CreatorId: currentUser.Uid,
|
|
CreatedAt: time.Now(),
|
|
}).Error
|
|
return
|
|
}); err != nil {
|
|
if errors.Is(err, gorm.ErrDuplicatedKey) {
|
|
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrDuplicateName, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, HttpResponse{
|
|
Data: map[string]any{
|
|
"id": md.GetId(),
|
|
},
|
|
})
|
|
|
|
return
|
|
}
|
|
|
|
func doGet[T any](ctx *gin.Context, needAcl bool, dbFind *gorm.DB, resourceType string, postHooks ...postHook[T]) (err error) {
|
|
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
|
|
|
if needAcl && !acl.IsAdmin(currentUser) {
|
|
if dbFind, err = handleAcl[T](ctx, dbFind, resourceType); err != nil {
|
|
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
}
|
|
|
|
dbCount := dbFind.Session(&gorm.Session{})
|
|
dbFind = dbFind.Session(&gorm.Session{})
|
|
|
|
count, list := int64(0), make([]T, 0)
|
|
eg := &errgroup.Group{}
|
|
eg.Go(func() error {
|
|
return dbCount.Count(&count).
|
|
Error
|
|
})
|
|
eg.Go(func() error {
|
|
pi, ps := cast.ToInt(ctx.Query("page_index")), cast.ToInt(ctx.Query("page_size"))
|
|
if _, ok := ctx.GetQuery("page_index"); ok {
|
|
dbFind = dbFind.Offset((pi - 1) * ps)
|
|
}
|
|
if _, ok := ctx.GetQuery("page_size"); ok && ps != -1 {
|
|
dbFind = dbFind.Limit(lo.Ternary(ps == 0, 20, ps))
|
|
}
|
|
return dbFind.
|
|
Order("id DESC").
|
|
Find(&list).
|
|
Error
|
|
})
|
|
if err = eg.Wait(); err != nil {
|
|
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
|
|
// switch t := any(list).(type) {
|
|
// case []*model.Node:
|
|
// if t, err = nodePostHookParent(ctx, t); err != nil {
|
|
// return
|
|
// }
|
|
// list = lo.Map(t, func(n *model.Node, _ int) T { return any(n).(T) })
|
|
// }
|
|
for _, hook := range postHooks {
|
|
if hook == nil {
|
|
continue
|
|
}
|
|
hook(ctx, list)
|
|
if ctx.IsAborted() {
|
|
return
|
|
}
|
|
}
|
|
|
|
if err = handlePermissions(ctx, list, resourceType); err != nil {
|
|
return
|
|
}
|
|
|
|
res := &ListData{
|
|
Count: count,
|
|
List: lo.Map(list, func(t T, _ int) any { return t }),
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, NewHttpResponseWithData(res))
|
|
|
|
return
|
|
}
|
|
|
|
func handleRemoteErr(ctx *gin.Context, err error) {
|
|
switch e := err.(type) {
|
|
case *remote.RemoteError:
|
|
if e.HttpCode == http.StatusBadRequest {
|
|
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrRemoteClient, Data: e.Resp})
|
|
return
|
|
}
|
|
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrRemoteServer, Data: e.Resp})
|
|
default:
|
|
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
|
}
|
|
}
|
|
|
|
func filterSearch(ctx *gin.Context, db *gorm.DB, fields ...string) *gorm.DB {
|
|
q, ok := ctx.GetQuery("search")
|
|
if !ok || len(fields) <= 0 {
|
|
return db
|
|
}
|
|
|
|
d := dbpkg.DB
|
|
for _, f := range fields {
|
|
d = d.Or(fmt.Sprintf("%s LIKE ?", f), fmt.Sprintf("%%%s%%", q))
|
|
}
|
|
|
|
db = db.Where(d)
|
|
|
|
return db
|
|
}
|
|
func filterStartEnd(ctx *gin.Context, db *gorm.DB) (*gorm.DB, error) {
|
|
if q, ok := ctx.GetQuery("start"); ok {
|
|
t, err := time.Parse(time.RFC3339, q)
|
|
if err != nil {
|
|
ctx.AbortWithError(http.StatusBadRequest, err)
|
|
return db, err
|
|
}
|
|
db = db.Where("created_at >= ?", t)
|
|
}
|
|
if q, ok := ctx.GetQuery("end"); ok {
|
|
t, err := time.Parse(time.RFC3339, q)
|
|
if err != nil {
|
|
ctx.AbortWithError(http.StatusBadRequest, err)
|
|
return db, err
|
|
}
|
|
db = db.Where("created_at <= ?", t)
|
|
}
|
|
|
|
return db, nil
|
|
}
|
|
func filterEqual(ctx *gin.Context, db *gorm.DB, fields ...string) *gorm.DB {
|
|
for _, f := range fields {
|
|
if q, ok := ctx.GetQuery(f); ok {
|
|
db = db.Where(fmt.Sprintf("%s = ?", f), q)
|
|
}
|
|
}
|
|
|
|
return db
|
|
}
|
|
func filterLike(ctx *gin.Context, db *gorm.DB, fields ...string) *gorm.DB {
|
|
likes := false
|
|
d := dbpkg.DB
|
|
for _, f := range fields {
|
|
if q, ok := ctx.GetQuery(f); ok && q != "" {
|
|
d = d.Or(fmt.Sprintf("%s LIKE ?", f), fmt.Sprintf("%%%s%%", q))
|
|
likes = true
|
|
}
|
|
}
|
|
if !likes {
|
|
return db
|
|
}
|
|
db = db.Where(d)
|
|
|
|
return db
|
|
}
|
|
|
|
func toMap(data any) model.Map[string, any] {
|
|
bs, _ := json.Marshal(data)
|
|
res := make(map[string]any)
|
|
json.Unmarshal(bs, &res)
|
|
return res
|
|
}
|
|
|
|
func getEmpty[T model.Model](data T) T {
|
|
t := reflect.TypeOf(data).Elem()
|
|
v := reflect.New(t)
|
|
return v.Interface().(T)
|
|
}
|
|
|
|
func hasPerm[T model.Model](ctx context.Context, md T, resourceTypeName, action string) bool {
|
|
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
|
|
|
if acl.IsAdmin(currentUser) {
|
|
return true
|
|
}
|
|
|
|
if ok, _ := acl.HasPermission(ctx, currentUser.GetRid(), resourceTypeName, md.GetResourceId(), action); ok {
|
|
return true
|
|
}
|
|
|
|
pids := make([]int, 0)
|
|
switch t := any(md).(type) {
|
|
case *model.Asset:
|
|
pids, _ = repository.HandleSelfParent(ctx, t.ParentId)
|
|
case *model.Node:
|
|
pids, _ = repository.HandleSelfParent(ctx, t.Id)
|
|
}
|
|
|
|
if len(pids) > 0 {
|
|
res, _ := acl.GetRoleResources(ctx, currentUser.GetRid(), config.RESOURCE_NODE)
|
|
resId2perms := lo.SliceToMap(res, func(r *acl.Resource) (int, []string) { return r.ResourceId, r.Permissions })
|
|
resId2perms, _ = handleSelfChildPerms(ctx, resId2perms)
|
|
nodes, _ := repository.GetAllFromCacheDb(ctx, model.DefaultNode)
|
|
id2resId := lo.SliceToMap(nodes, func(n *model.Node) (int, int) { return n.Id, n.ResourceId })
|
|
if lo.ContainsBy(pids, func(pid int) bool { return lo.Contains(resId2perms[id2resId[pid]], action) }) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func handlePermissions[T any](ctx *gin.Context, data []T, resourceTypeName string) (err error) {
|
|
if info := cast.ToBool(ctx.Query("info")); info {
|
|
return
|
|
}
|
|
|
|
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
|
|
|
if !lo.Contains(config.PermResource, resourceTypeName) {
|
|
return
|
|
}
|
|
|
|
res, err := acl.GetRoleResources(ctx, currentUser.GetRid(), resourceTypeName)
|
|
if err != nil {
|
|
handleRemoteErr(ctx, err)
|
|
return
|
|
}
|
|
resId2perms := lo.SliceToMap(res, func(r *acl.Resource) (int, []string) { return r.ResourceId, r.Permissions })
|
|
|
|
switch ds := any(data).(type) {
|
|
case []*model.Node:
|
|
resId2perms, err = handleSelfChildPerms(ctx, resId2perms)
|
|
if err != nil {
|
|
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
case []*model.Asset:
|
|
res, err = acl.GetRoleResources(ctx, currentUser.GetRid(), config.RESOURCE_NODE)
|
|
if err != nil {
|
|
handleRemoteErr(ctx, err)
|
|
return
|
|
}
|
|
nodeResId2perms := lo.SliceToMap(res, func(r *acl.Resource) (int, []string) { return r.ResourceId, r.Permissions })
|
|
if nodeResId2perms, err = handleSelfChildPerms(ctx, nodeResId2perms); err != nil {
|
|
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
var nodeId2ResId map[int]int
|
|
nodeId2ResId, err = getNodeId2ResId(ctx)
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, d := range ds {
|
|
resId2perms[d.GetResourceId()] = append(
|
|
resId2perms[d.GetResourceId()],
|
|
nodeResId2perms[nodeId2ResId[d.ParentId]]...,
|
|
)
|
|
}
|
|
}
|
|
|
|
ds := lo.Map(data, func(d T, _ int) model.Model {
|
|
x, _ := any(d).(model.Model)
|
|
return x
|
|
})
|
|
b := acl.IsAdmin(currentUser)
|
|
for _, d := range ds {
|
|
if b {
|
|
d.SetPerms(acl.AllPermissions)
|
|
continue
|
|
}
|
|
d.SetPerms(resId2perms[d.GetResourceId()])
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func handleAcl[T any](ctx *gin.Context, dbFind *gorm.DB, resourceType string) (db *gorm.DB, err error) {
|
|
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
|
|
|
resIds, err := acl.GetRoleResourceIds(ctx, currentUser.Acl.Rid, resourceType)
|
|
if err != nil {
|
|
return
|
|
}
|
|
switch any(*new(T)).(type) {
|
|
case *model.Node:
|
|
db, err = handleNodeIds(ctx, dbFind, resIds)
|
|
case *model.Asset:
|
|
db, err = handleAssetIds(ctx, dbFind, resIds)
|
|
case *model.Account:
|
|
db, err = handleAccountIds(ctx, dbFind, resIds)
|
|
case *model.Gateway:
|
|
db = dbFind
|
|
case *model.Command:
|
|
db = dbFind
|
|
default:
|
|
db = dbFind.Where("resource_id IN ?", resIds)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func handleNodeIds(ctx *gin.Context, dbFind *gorm.DB, resIds []int) (db *gorm.DB, err error) {
|
|
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
|
|
|
nodes, err := repository.GetAllFromCacheDb(ctx, model.DefaultNode)
|
|
if err != nil {
|
|
return
|
|
}
|
|
nodes = lo.Filter(nodes, func(n *model.Node, _ int) bool { return lo.Contains(resIds, n.ResourceId) })
|
|
ids := lo.Map(nodes, func(n *model.Node, _ int) int { return n.Id })
|
|
if ids, err = repository.HandleSelfChild(ctx, ids...); err != nil {
|
|
return
|
|
}
|
|
|
|
assetResIds, err := acl.GetRoleResourceIds(ctx, currentUser.GetRid(), config.RESOURCE_ASSET)
|
|
if err != nil {
|
|
return
|
|
}
|
|
assets := make([]*model.AssetIdPid, 0)
|
|
if err = dbpkg.DB.Model(assets).Where("resource_id IN ?", assetResIds).Find(&assets).Error; err != nil {
|
|
return
|
|
}
|
|
ids = append(ids, lo.Map(assets, func(a *model.AssetIdPid, _ int) int { return a.ParentId })...)
|
|
|
|
ids, err = repository.HandleSelfParent(ctx, ids...)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
db = dbFind.Where("id IN ?", ids)
|
|
|
|
return
|
|
}
|
|
|
|
func handleAssetIds(ctx *gin.Context, dbFind *gorm.DB, resIds []int) (db *gorm.DB, err error) {
|
|
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
|
|
|
nodes, err := repository.GetAllFromCacheDb(ctx, model.DefaultNode)
|
|
if err != nil {
|
|
return
|
|
}
|
|
nodeResIds, err := acl.GetRoleResourceIds(ctx, currentUser.GetRid(), config.RESOURCE_NODE)
|
|
if err != nil {
|
|
return
|
|
}
|
|
nodes = lo.Filter(nodes, func(n *model.Node, _ int) bool { return lo.Contains(nodeResIds, n.ResourceId) })
|
|
nodeIds := lo.Map(nodes, func(n *model.Node, _ int) int { return n.Id })
|
|
if nodeIds, err = repository.HandleSelfChild(ctx, nodeIds...); err != nil {
|
|
return
|
|
}
|
|
|
|
d := dbpkg.DB.Where("resource_id IN ?", resIds).Or("parent_id IN?", nodeIds)
|
|
|
|
db = dbFind.Where(d)
|
|
|
|
return
|
|
}
|
|
|
|
func handleAccountIds(ctx *gin.Context, dbFind *gorm.DB, resIds []int) (db *gorm.DB, err error) {
|
|
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
|
|
|
assetResIds, err := acl.GetRoleResourceIds(ctx, currentUser.GetRid(), config.RESOURCE_ASSET)
|
|
if err != nil {
|
|
return
|
|
}
|
|
t, _ := handleAssetIds(ctx, dbpkg.DB.Model(model.DefaultAsset), assetResIds)
|
|
ss := make([]model.Slice[string], 0)
|
|
if err = t.Pluck("JSON_KEYS(authorization)", &ss).Error; err != nil {
|
|
return
|
|
}
|
|
ids := lo.Uniq(lo.Map(lo.Flatten(ss), func(s string, _ int) int { return cast.ToInt(s) }))
|
|
|
|
d := dbpkg.DB.Where("resource_id IN ?", resIds).Or("id IN ?", ids)
|
|
|
|
db = dbFind.Where(d)
|
|
|
|
return
|
|
}
|