mirror of
https://github.com/veops/oneterm.git
synced 2025-10-09 01:00:09 +08:00
feat(api): permission
This commit is contained in:
@@ -134,15 +134,14 @@ func RunApi() error {
|
||||
share.POST("", authAdmin(), c.CreateShare)
|
||||
share.DELETE("/:id", authAdmin(), c.DeleteShare)
|
||||
share.GET("", authAdmin(), c.GetShare)
|
||||
share.GET("/connect/:uuid", c.ConnectShare)
|
||||
}
|
||||
// r.GET("/api/oneterm/v1/share/connect/:uuid", Error2Resp(), c.ConnectShare)
|
||||
r.GET("/api/oneterm/v1/share/connect/:uuid", Error2Resp(), c.ConnectShare)
|
||||
|
||||
authorization := v1.Group("/authorization")
|
||||
authorization := v1.Group("/authorization", authAdmin())
|
||||
{
|
||||
authorization.POST("", c.CreateAuthorization)
|
||||
authorization.POST("", c.UpsertAuthorization)
|
||||
authorization.DELETE("/:id", c.DeleteAccount)
|
||||
authorization.PUT("/:id", c.UpdateAuthorization)
|
||||
authorization.GET("", c.GetAuthorizations)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -2,8 +2,10 @@ package controller
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/samber/lo"
|
||||
@@ -12,12 +14,17 @@ import (
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/veops/oneterm/acl"
|
||||
redis "github.com/veops/oneterm/cache"
|
||||
"github.com/veops/oneterm/conf"
|
||||
mysql "github.com/veops/oneterm/db"
|
||||
"github.com/veops/oneterm/model"
|
||||
"github.com/veops/oneterm/util"
|
||||
)
|
||||
|
||||
const (
|
||||
kFmtAccountIds = "accountIds-%d"
|
||||
)
|
||||
|
||||
var (
|
||||
accountPreHooks = []preHook[*model.Account]{
|
||||
func(ctx *gin.Context, data *model.Account) {
|
||||
@@ -145,7 +152,7 @@ func (c *Controller) GetAccounts(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
if info && !acl.IsAdmin(currentUser) {
|
||||
ids, err := getAccountIdsByAuthorization(ctx)
|
||||
ids, err := GetAccountIdsByAuthorization(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -157,29 +164,29 @@ func (c *Controller) GetAccounts(ctx *gin.Context) {
|
||||
doGet[*model.Account](ctx, !info, db, acl.GetResourceTypeName(conf.RESOURCE_ACCOUNT), accountPostHooks...)
|
||||
}
|
||||
|
||||
func getAccountIdsByAuthorization(ctx *gin.Context) (ids []int, err error) {
|
||||
assetIds, err := getAssertIdsByAuthorization(ctx)
|
||||
func GetAccountIdsByAuthorization(ctx *gin.Context) (ids []int, err error) {
|
||||
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
||||
|
||||
k := fmt.Sprintf(kFmtAccountIds, currentUser.GetUid())
|
||||
if err = redis.Get(ctx, k, &ids); err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
assetIds, err := GetAssetIdsByAuthorization(ctx)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
||||
return
|
||||
}
|
||||
assets := make([]*model.Asset, 0)
|
||||
if err = mysql.DB.Model(&model.Asset{}).Where("id IN ?", assetIds).Find(&assets).Error; err != nil {
|
||||
ss := make([][]int, 0)
|
||||
if err = mysql.DB.Model(&model.Asset{}).Where("id IN ?", assetIds).Pluck("JSON_KEYS(authorization)", &ss).Error; err != nil {
|
||||
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
||||
return
|
||||
}
|
||||
authorizationIds, _ := ctx.Value("authorizationIds").([]*model.AuthorizationIds)
|
||||
parentNodeIds, _ := ctx.Value("parentNodeIds").([]int)
|
||||
for _, a := range assets {
|
||||
if lo.Contains(parentNodeIds, a.Id) {
|
||||
ids = append(ids, lo.Keys(a.Authorization)...)
|
||||
}
|
||||
accountIds := lo.Uniq(
|
||||
lo.Map(lo.Filter(authorizationIds, func(item *model.AuthorizationIds, _ int) bool {
|
||||
return item.AssetId != nil && *item.AssetId == a.Id && item.AccountId != nil
|
||||
}),
|
||||
func(item *model.AuthorizationIds, _ int) int { return *item.AccountId }))
|
||||
ids = append(ids, accountIds...)
|
||||
}
|
||||
ids = lo.Uniq(lo.Flatten(ss))
|
||||
_, _, accountIds := getIdsByAuthorizationIds(ctx)
|
||||
ids = lo.Uniq(append(ids, accountIds...))
|
||||
|
||||
redis.SetEx(ctx, k, ids, time.Minute)
|
||||
|
||||
return
|
||||
}
|
||||
|
@@ -1,9 +1,10 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/samber/lo"
|
||||
@@ -11,6 +12,7 @@ import (
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/veops/oneterm/acl"
|
||||
redis "github.com/veops/oneterm/cache"
|
||||
"github.com/veops/oneterm/conf"
|
||||
mysql "github.com/veops/oneterm/db"
|
||||
"github.com/veops/oneterm/logger"
|
||||
@@ -18,6 +20,13 @@ import (
|
||||
"github.com/veops/oneterm/schedule"
|
||||
)
|
||||
|
||||
const (
|
||||
kFmtAssetIds = "assetIds-%d"
|
||||
kAuthorizationIds = "authorizationIds"
|
||||
kParentNodeIds = "parentNodeIds"
|
||||
kAccountIds = "accountIds"
|
||||
)
|
||||
|
||||
var (
|
||||
assetPreHooks = []preHook[*model.Asset]{
|
||||
func(ctx *gin.Context, data *model.Asset) {
|
||||
@@ -92,7 +101,7 @@ func (c *Controller) GetAssets(ctx *gin.Context) {
|
||||
db = db.Where("id IN ?", lo.Map(strings.Split(q, ","), func(s string, _ int) int { return cast.ToInt(s) }))
|
||||
}
|
||||
if q, ok := ctx.GetQuery("parent_id"); ok {
|
||||
parentIds, err := handleParentId(cast.ToInt(q))
|
||||
parentIds, err := handleParentId(ctx, cast.ToInt(q))
|
||||
if err != nil {
|
||||
logger.L().Error("parent id found failed", zap.Error(err))
|
||||
return
|
||||
@@ -101,7 +110,7 @@ func (c *Controller) GetAssets(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
if info && !acl.IsAdmin(currentUser) {
|
||||
ids, err := getAssertIdsByAuthorization(ctx)
|
||||
ids, err := GetAssetIdsByAuthorization(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -147,29 +156,33 @@ func assetPostHookAuth(ctx *gin.Context, data []*model.Asset) {
|
||||
return
|
||||
}
|
||||
authorizationIds, _ := ctx.Value("authorizationIds").([]*model.AuthorizationIds)
|
||||
parentNodeIds, _ := ctx.Value("parentNodeIds").([]int)
|
||||
parentNodeIds, _, accountIds := getIdsByAuthorizationIds(ctx)
|
||||
for _, a := range data {
|
||||
if lo.Contains(parentNodeIds, a.Id) {
|
||||
continue
|
||||
}
|
||||
accountIds := lo.Uniq(
|
||||
ids := lo.Uniq(
|
||||
lo.Map(lo.Filter(authorizationIds, func(item *model.AuthorizationIds, _ int) bool {
|
||||
return item.AssetId != nil && *item.AssetId == a.Id && item.AccountId != nil
|
||||
}),
|
||||
func(item *model.AuthorizationIds, _ int) int { return *item.AccountId }))
|
||||
|
||||
for k := range a.Authorization {
|
||||
if !lo.Contains(accountIds, k) {
|
||||
if !lo.Contains(ids, k) && !lo.Contains(accountIds, k) {
|
||||
delete(a.Authorization, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleParentId(parentId int) (pids []int, err error) {
|
||||
func handleParentId(ctx context.Context, parentId int) (pids []int, err error) {
|
||||
nodes := make([]*model.NodeIdPid, 0)
|
||||
if err = redis.Get(ctx, kFmtAllNodes, &nodes); err != nil {
|
||||
if err = mysql.DB.Model(&model.Node{}).Find(&nodes).Error; err != nil {
|
||||
return
|
||||
}
|
||||
redis.SetEx(ctx, kFmtAllNodes, nodes, time.Hour)
|
||||
}
|
||||
g := make(map[int][]int)
|
||||
for _, n := range nodes {
|
||||
g[n.ParentId] = append(g[n.ParentId], n.Id)
|
||||
@@ -186,33 +199,69 @@ func handleParentId(parentId int) (pids []int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func getAssertIdsByAuthorization(ctx *gin.Context) (ids []int, err error) {
|
||||
authorizationResourceIds, err := getAutorizationResourceIds(ctx)
|
||||
func GetAssetIdsByAuthorization(ctx *gin.Context) (ids []int, err error) {
|
||||
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
||||
|
||||
authIds, err := getAuthorizationIds(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ctx.Set(kAuthorizationIds, authIds)
|
||||
|
||||
k := fmt.Sprintf(kFmtAssetIds, currentUser.GetUid())
|
||||
if err = redis.Get(ctx, k, &ids); err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
parentNodeIds, ids, accountIds := getIdsByAuthorizationIds(ctx)
|
||||
|
||||
tmp, err := handleSelfChild(ctx, parentNodeIds)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
parentNodeIds = append(parentNodeIds, tmp...)
|
||||
ctx.Set(kParentNodeIds, parentNodeIds)
|
||||
ctx.Set(kAccountIds, accountIds)
|
||||
tmp, err = getAssetIdsByNodeAccount(ctx, parentNodeIds, accountIds)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ids = lo.Uniq(append(ids, tmp...))
|
||||
|
||||
redis.SetEx(ctx, k, ids, time.Minute)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getIdsByAuthorizationIds(ctx context.Context) (parentNodeIds, assetIds, accountIds []int) {
|
||||
authIds, _ := ctx.Value(kAuthorizationIds).([]*model.AuthorizationIds)
|
||||
|
||||
for _, a := range authIds {
|
||||
if a.NodeId != nil && a.AssetId == nil && a.AccountId == nil {
|
||||
parentNodeIds = append(parentNodeIds, *a.NodeId)
|
||||
}
|
||||
if a.AssetId != nil && a.NodeId == nil && a.AccountId == nil {
|
||||
assetIds = append(assetIds, *a.AssetId)
|
||||
}
|
||||
if a.AccountId != nil && a.AssetId == nil && a.NodeId == nil {
|
||||
accountIds = append(accountIds, *a.AccountId)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getAuthorizationIds(ctx *gin.Context) (authIds []*model.AuthorizationIds, err error) {
|
||||
resourceIds, err := getAutorizationResourceIds(ctx)
|
||||
if err != nil {
|
||||
handleRemoteErr(ctx, err)
|
||||
return
|
||||
}
|
||||
authIds := make([]*model.AuthorizationIds, 0)
|
||||
if err = mysql.DB.Model(authIds).Where("resource_id IN ?", authorizationResourceIds).Find(&ids).Error; err != nil {
|
||||
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
||||
return
|
||||
}
|
||||
ctx.Set("authorizationIds", authIds)
|
||||
|
||||
parentNodeIds := make([]int, 0)
|
||||
for _, a := range authIds {
|
||||
if a.NodeId != nil {
|
||||
parentNodeIds = append(parentNodeIds, *a.NodeId)
|
||||
} else if a.AssetId != nil {
|
||||
ids = append(ids, *a.AssetId)
|
||||
}
|
||||
}
|
||||
ctx.Set("parentNodeIds", parentNodeIds)
|
||||
tmp := make([]int, 0)
|
||||
if err = mysql.DB.Model(&model.Asset{}).Where("parent_id IN?", parentNodeIds).Pluck("id", &tmp).Error; err != nil {
|
||||
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
||||
return
|
||||
}
|
||||
ids = append(ids, tmp...)
|
||||
err = mysql.DB.Model(authIds).Where("resource_id IN ?", resourceIds).Find(&authIds).Error
|
||||
return
|
||||
}
|
||||
|
||||
func getAssetIdsByNodeAccount(ctx context.Context, parentNodeIds, accountIds []int) (assetIds []int, err error) {
|
||||
err = mysql.DB.Model(&model.Asset{}).Where("parent_id IN?", parentNodeIds).Or("JSON_KEYS(authorization) IN ?", accountIds).Pluck("id", &assetIds).Error
|
||||
return
|
||||
}
|
||||
|
@@ -1,9 +1,11 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/samber/lo"
|
||||
@@ -13,12 +15,104 @@ import (
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/veops/oneterm/acl"
|
||||
redis "github.com/veops/oneterm/cache"
|
||||
"github.com/veops/oneterm/conf"
|
||||
mysql "github.com/veops/oneterm/db"
|
||||
"github.com/veops/oneterm/logger"
|
||||
"github.com/veops/oneterm/model"
|
||||
gsession "github.com/veops/oneterm/session"
|
||||
)
|
||||
|
||||
const (
|
||||
kFmtAuthorizationIds = "AuthorizationIds-%d"
|
||||
kFmtHasAuthorization = "HasAuthorization-%d-%d-%d"
|
||||
)
|
||||
|
||||
// UpsertAuthorization godoc
|
||||
//
|
||||
// @Tags authorization
|
||||
// @Param authorization body model.Authorization true "authorization"
|
||||
// @Success 200 {object} HttpResponse
|
||||
// @Router /authorization [post]
|
||||
func (c *Controller) UpsertAuthorization(ctx *gin.Context) {
|
||||
auth := &model.Authorization{}
|
||||
err := ctx.ShouldBindBodyWithJSON(auth)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrInvalidArgument, Data: map[string]any{"err": err}})
|
||||
return
|
||||
}
|
||||
if err := mysql.DB.Transaction(func(tx *gorm.DB) error {
|
||||
auth := &model.Authorization{}
|
||||
if err = tx.Model(auth).
|
||||
Where(fmt.Sprintf("node_id %s AND asset_id %s AND account_id %s",
|
||||
lo.Ternary(auth.NodeId == nil, "IS NULL", fmt.Sprintf("=%d", auth.NodeId)),
|
||||
lo.Ternary(auth.AssetId == nil, "IS NULL", fmt.Sprintf("=%d", auth.AssetId)),
|
||||
lo.Ternary(auth.AccountId == nil, "IS NULL", fmt.Sprintf("=%d", auth.AccountId)),
|
||||
)).
|
||||
FirstOrCreate(auth).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
action := lo.Ternary(auth.Id > 0, model.ACTION_UPDATE, model.ACTION_CREATE)
|
||||
return handleAuthorization(ctx, tx, action, nil, auth)
|
||||
}); err != nil {
|
||||
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, HttpResponse{
|
||||
Data: map[string]any{
|
||||
"id": auth.GetId(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteAccount godoc
|
||||
//
|
||||
// @Tags authorization
|
||||
// @Param id path int true "authorization id"
|
||||
// @Success 200 {object} HttpResponse
|
||||
// @Router /authorization/:id [delete]
|
||||
func (c *Controller) DeleteAuthorization(ctx *gin.Context) {
|
||||
auth := &model.Authorization{
|
||||
Id: cast.ToInt(ctx.Param("id")),
|
||||
}
|
||||
if err := handleAuthorization(ctx, mysql.DB, model.ACTION_DELETE, nil, auth); err != nil {
|
||||
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusOK, HttpResponse{
|
||||
Data: map[string]any{
|
||||
"id": auth.GetId(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// GetAuthorizations godoc
|
||||
//
|
||||
// @Tags authorization
|
||||
// @Param page_index query int true "page_index"
|
||||
// @Param page_size query int true "page_size"
|
||||
// @Param node_id query int false "node id"
|
||||
// @Param asset_id query int false "asset id"
|
||||
// @Param account_id query int false "account id"
|
||||
// @Success 200 {object} HttpResponse{data=ListData{list=[]model.Account}}
|
||||
// @Router /authorization [get]
|
||||
func (c *Controller) GetAuthorizations(ctx *gin.Context) {
|
||||
db := mysql.DB.Model(&model.Authorization{})
|
||||
for _, k := range []string{"node_id", "asset_id", "account_id"} {
|
||||
q, ok := ctx.GetQuery(k)
|
||||
if ok {
|
||||
db = db.Where(fmt.Sprintf("%s IN ?", k), lo.Map(strings.Split(q, ","), func(s string, _ int) int { return cast.ToInt(s) }))
|
||||
} else {
|
||||
db = db.Where(fmt.Sprintf("%s IS NULL", k))
|
||||
}
|
||||
}
|
||||
|
||||
doGet[*model.Authorization](ctx, false, db, acl.GetResourceTypeName(conf.RESOURCE_AUTHORIZATION))
|
||||
}
|
||||
|
||||
func getAuthsByAsset(t *model.Asset) (data []*model.Authorization, err error) {
|
||||
db := mysql.DB.Model(data)
|
||||
for accountId := range t.Authorization {
|
||||
@@ -57,7 +151,8 @@ func handleAuthorization(ctx *gin.Context, tx *gorm.DB, action int, asset *model
|
||||
}
|
||||
}
|
||||
|
||||
for _, auth := range lo.Filter(auths, func(item *model.Authorization, _ int) bool { return item != nil }) {
|
||||
for _, a := range lo.Filter(auths, func(item *model.Authorization, _ int) bool { return item != nil }) {
|
||||
auth := a
|
||||
switch action {
|
||||
case model.ACTION_CREATE:
|
||||
eg.Go(func() (err error) {
|
||||
@@ -103,29 +198,14 @@ func handleAuthorization(ctx *gin.Context, tx *gorm.DB, action int, asset *model
|
||||
return
|
||||
}
|
||||
|
||||
func sameAuthorization(old, new model.Map[int, model.Slice[int]]) bool {
|
||||
if len(old) != len(new) {
|
||||
return false
|
||||
}
|
||||
ks := lo.Uniq(append(lo.Keys(old), lo.Keys(new)...))
|
||||
for _, k := range ks {
|
||||
if len(old[k]) != len(new[k]) {
|
||||
return false
|
||||
}
|
||||
o, n := make([]int, 0, len(old[k])), make([]int, 0, len(new[k]))
|
||||
copy(o, old[k])
|
||||
copy(n, new[k])
|
||||
sort.Ints(o)
|
||||
sort.Ints(n)
|
||||
if !reflect.DeepEqual(o, n) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func getAutorizationResourceIds(ctx *gin.Context) (resourceIds []int, err error) {
|
||||
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
||||
|
||||
k := fmt.Sprintf(kFmtAuthorizationIds, currentUser.GetUid())
|
||||
if err = redis.Get(ctx, k, &resourceIds); err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var rs []*acl.Resource
|
||||
rs, err = acl.GetRoleResources(ctx, currentUser.Acl.Rid, conf.RESOURCE_AUTHORIZATION)
|
||||
if err != nil {
|
||||
@@ -133,97 +213,63 @@ func getAutorizationResourceIds(ctx *gin.Context) (resourceIds []int, err error)
|
||||
}
|
||||
resourceIds = lo.Map(rs, func(r *acl.Resource, _ int) int { return r.ResourceId })
|
||||
|
||||
redis.SetEx(ctx, k, resourceIds, time.Minute)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func hasAuthorization(ctx *gin.Context, assetId, accountId int) (ok bool) {
|
||||
if cast.ToString(ctx.Value("shareId")) != "" {
|
||||
func hasAuthorization(ctx *gin.Context, sess *gsession.Session) (ok bool) {
|
||||
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
||||
|
||||
if sess.ShareId != 0 {
|
||||
return true
|
||||
}
|
||||
ids, err := getAutorizationResourceIds(ctx)
|
||||
|
||||
k := fmt.Sprintf(kFmtHasAuthorization, currentUser.GetUid(), sess.AccountId, sess.AssetId)
|
||||
if err := redis.Get(ctx, k, &ok); err == nil {
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
redis.SetEx(ctx, k, ok, time.Minute)
|
||||
}()
|
||||
|
||||
if ok = acl.IsAdmin(currentUser); ok {
|
||||
return
|
||||
}
|
||||
|
||||
if sess.Session.Asset == nil {
|
||||
if err := mysql.DB.Model(sess.Session.Asset).First(&sess.Session.Asset, sess.AssetId).Error; err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
authIds, err := getAuthorizationIds(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, ok = lo.Find(authIds, func(item *model.AuthorizationIds) bool {
|
||||
return item.NodeId == nil && item.AssetId != nil && *item.AssetId == sess.AssetId && item.AccountId != nil && *item.AccountId == sess.AccountId
|
||||
}); ok {
|
||||
return
|
||||
}
|
||||
ctx.Set(kAuthorizationIds, authIds)
|
||||
|
||||
parentNodeIds, assetIds, accountIds := getIdsByAuthorizationIds(ctx)
|
||||
tmp, err := handleSelfChild(ctx, parentNodeIds)
|
||||
if err != nil {
|
||||
logger.L().Error("", zap.Error(err))
|
||||
return
|
||||
}
|
||||
cnt := int64(0)
|
||||
err = mysql.DB.Model(&model.Authorization{}).
|
||||
Where("asset_id =? AND account_id =? AND resource_id IN (?)", assetId, accountId, ids).
|
||||
Count(&cnt).Error
|
||||
parentNodeIds = append(parentNodeIds, tmp...)
|
||||
if ok = lo.Contains(parentNodeIds, sess.Session.Asset.ParentId) || lo.Contains(assetIds, sess.AssetId) || lo.Contains(accountIds, sess.AccountId); ok {
|
||||
return
|
||||
}
|
||||
|
||||
ids, err := getAssetIdsByNodeAccount(ctx, parentNodeIds, accountIds)
|
||||
if err != nil {
|
||||
logger.L().Error("", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
return cnt > 0
|
||||
}
|
||||
|
||||
// CreateAccount godoc
|
||||
//
|
||||
// @Tags authorization
|
||||
// @Param authorization body model.Authorization true "authorization"
|
||||
// @Success 200 {object} HttpResponse
|
||||
// @Router /authorization [post]
|
||||
func (c *Controller) CreateAuthorization(ctx *gin.Context) {
|
||||
auth := &model.Authorization{}
|
||||
err := ctx.ShouldBindBodyWithJSON(auth)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrInvalidArgument, Data: map[string]any{"err": err}})
|
||||
return
|
||||
}
|
||||
if err := handleAuthorization(ctx, mysql.DB, model.ACTION_CREATE, nil, auth); err != nil {
|
||||
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusOK, HttpResponse{
|
||||
Data: map[string]any{
|
||||
"id": auth.GetId(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteAccount godoc
|
||||
//
|
||||
// @Tags authorization
|
||||
// @Param id path int true "authorization id"
|
||||
// @Success 200 {object} HttpResponse
|
||||
// @Router /authorization/:id [delete]
|
||||
func (c *Controller) DeleteAuthorization(ctx *gin.Context) {
|
||||
auth := &model.Authorization{
|
||||
Id: cast.ToInt(ctx.Param("id")),
|
||||
}
|
||||
if err := handleAuthorization(ctx, mysql.DB, model.ACTION_DELETE, nil, auth); err != nil {
|
||||
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusOK, HttpResponse{
|
||||
Data: map[string]any{
|
||||
"id": auth.GetId(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateAccount godoc
|
||||
//
|
||||
// @Tags authorization
|
||||
// @Param id path int true "authorization id"
|
||||
// @Param authorization body model.Authorization true "authorization"
|
||||
// @Success 200 {object} HttpResponse
|
||||
// @Router /authorization/:id [put]
|
||||
func (c *Controller) UpdateAuthorization(ctx *gin.Context) {
|
||||
auth := &model.Authorization{}
|
||||
err := ctx.ShouldBindBodyWithJSON(auth)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(http.StatusBadRequest, &ApiError{Code: ErrInvalidArgument, Data: map[string]any{"err": err}})
|
||||
return
|
||||
}
|
||||
auth.Id = cast.ToInt(ctx.Param("id"))
|
||||
if err := handleAuthorization(ctx, mysql.DB, model.ACTION_UPDATE, nil, auth); err != nil {
|
||||
ctx.AbortWithError(http.StatusInternalServerError, &ApiError{Code: ErrInternal, Data: map[string]any{"err": err}})
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusOK, HttpResponse{
|
||||
Data: map[string]any{
|
||||
"id": auth.GetId(),
|
||||
},
|
||||
})
|
||||
return lo.Contains(ids, sess.AssetId)
|
||||
}
|
||||
|
@@ -269,6 +269,7 @@ func DoConnect(ctx *gin.Context, ws *websocket.Conn) (sess *gsession.Session, er
|
||||
Uid: currentUser.GetUid(),
|
||||
UserName: currentUser.GetUserName(),
|
||||
AssetId: assetId,
|
||||
Asset: asset,
|
||||
AssetInfo: fmt.Sprintf("%s(%s)", asset.Name, asset.Ip),
|
||||
AccountId: accountId,
|
||||
AccountInfo: fmt.Sprintf("%s(%s)", account.Name, account.Account),
|
||||
@@ -305,7 +306,7 @@ func DoConnect(ctx *gin.Context, ws *websocket.Conn) (sess *gsession.Session, er
|
||||
ctx.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
if !acl.IsAdmin(currentUser) && !hasAuthorization(ctx, assetId, accountId) {
|
||||
if !hasAuthorization(ctx, sess) {
|
||||
err = &ApiError{Code: ErrUnauthorized}
|
||||
ctx.AbortWithError(http.StatusForbidden, err)
|
||||
return
|
||||
|
@@ -18,6 +18,7 @@ import (
|
||||
mysql "github.com/veops/oneterm/db"
|
||||
"github.com/veops/oneterm/logger"
|
||||
"github.com/veops/oneterm/model"
|
||||
gsession "github.com/veops/oneterm/session"
|
||||
)
|
||||
|
||||
// GetFileHistory godoc
|
||||
@@ -60,8 +61,14 @@ func (c *Controller) GetFileHistory(ctx *gin.Context) {
|
||||
// @Success 200 {object} HttpResponse
|
||||
// @Router /file/ls/:asset_id/:account_id [post]
|
||||
func (c *Controller) FileLS(ctx *gin.Context) {
|
||||
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
||||
if !acl.IsAdmin(currentUser) && !hasAuthorization(ctx, cast.ToInt(ctx.Param("account_id")), cast.ToInt(ctx.Param("account_id"))) {
|
||||
sess := &gsession.Session{
|
||||
Session: &model.Session{
|
||||
AssetId: cast.ToInt(ctx.Param("asset_id")),
|
||||
AccountId: cast.ToInt(ctx.Param("account_id")),
|
||||
},
|
||||
}
|
||||
|
||||
if !hasAuthorization(ctx, sess) {
|
||||
ctx.AbortWithError(http.StatusForbidden, &ApiError{Code: ErrNoPerm, Data: map[string]any{}})
|
||||
return
|
||||
}
|
||||
@@ -101,7 +108,15 @@ func (c *Controller) FileLS(ctx *gin.Context) {
|
||||
// @Router /file/mkdir/:asset_id/:account_id [post]
|
||||
func (c *Controller) FileMkdir(ctx *gin.Context) {
|
||||
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
||||
if !acl.IsAdmin(currentUser) && !hasAuthorization(ctx, cast.ToInt(ctx.Param("account_id")), cast.ToInt(ctx.Param("account_id"))) {
|
||||
|
||||
sess := &gsession.Session{
|
||||
Session: &model.Session{
|
||||
AssetId: cast.ToInt(ctx.Param("asset_id")),
|
||||
AccountId: cast.ToInt(ctx.Param("account_id")),
|
||||
},
|
||||
}
|
||||
|
||||
if !hasAuthorization(ctx, sess) {
|
||||
ctx.AbortWithError(http.StatusForbidden, &ApiError{Code: ErrNoPerm, Data: map[string]any{}})
|
||||
return
|
||||
}
|
||||
@@ -141,7 +156,15 @@ func (c *Controller) FileMkdir(ctx *gin.Context) {
|
||||
// @Router /file/upload/:asset_id/:account_id [post]
|
||||
func (c *Controller) FileUpload(ctx *gin.Context) {
|
||||
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
||||
if !acl.IsAdmin(currentUser) && !hasAuthorization(ctx, cast.ToInt(ctx.Param("account_id")), cast.ToInt(ctx.Param("account_id"))) {
|
||||
|
||||
sess := &gsession.Session{
|
||||
Session: &model.Session{
|
||||
AssetId: cast.ToInt(ctx.Param("asset_id")),
|
||||
AccountId: cast.ToInt(ctx.Param("account_id")),
|
||||
},
|
||||
}
|
||||
|
||||
if !hasAuthorization(ctx, sess) {
|
||||
ctx.AbortWithError(http.StatusForbidden, &ApiError{Code: ErrNoPerm, Data: map[string]any{}})
|
||||
return
|
||||
}
|
||||
@@ -202,7 +225,15 @@ func (c *Controller) FileUpload(ctx *gin.Context) {
|
||||
// @Router /file/download/:asset_id/:account_id [get]
|
||||
func (c *Controller) FileDownload(ctx *gin.Context) {
|
||||
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
||||
if !acl.IsAdmin(currentUser) && !hasAuthorization(ctx, cast.ToInt(ctx.Param("account_id")), cast.ToInt(ctx.Param("account_id"))) {
|
||||
|
||||
sess := &gsession.Session{
|
||||
Session: &model.Session{
|
||||
AssetId: cast.ToInt(ctx.Param("asset_id")),
|
||||
AccountId: cast.ToInt(ctx.Param("account_id")),
|
||||
},
|
||||
}
|
||||
|
||||
if !hasAuthorization(ctx, sess) {
|
||||
ctx.AbortWithError(http.StatusForbidden, &ApiError{Code: ErrNoPerm, Data: map[string]any{}})
|
||||
return
|
||||
}
|
||||
|
@@ -1,9 +1,11 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/samber/lo"
|
||||
@@ -12,11 +14,16 @@ import (
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/veops/oneterm/acl"
|
||||
redis "github.com/veops/oneterm/cache"
|
||||
mysql "github.com/veops/oneterm/db"
|
||||
"github.com/veops/oneterm/logger"
|
||||
"github.com/veops/oneterm/model"
|
||||
)
|
||||
|
||||
const (
|
||||
kFmtAllNodes = "allNodes"
|
||||
)
|
||||
|
||||
var (
|
||||
nodePreHooks = []preHook[*model.Node]{nodePreHookCheckCycle}
|
||||
nodePostHooks = []postHook[*model.Node]{nodePostHookCountAsset, nodePostHookHasChild}
|
||||
@@ -30,6 +37,7 @@ var (
|
||||
// @Success 200 {object} HttpResponse
|
||||
// @Router /node [post]
|
||||
func (c *Controller) CreateNode(ctx *gin.Context) {
|
||||
redis.RC.Del(ctx, kFmtAllNodes)
|
||||
doCreate(ctx, false, &model.Node{}, "")
|
||||
}
|
||||
|
||||
@@ -40,6 +48,7 @@ func (c *Controller) CreateNode(ctx *gin.Context) {
|
||||
// @Success 200 {object} HttpResponse
|
||||
// @Router /node/:id [delete]
|
||||
func (c *Controller) DeleteNode(ctx *gin.Context) {
|
||||
redis.RC.Del(ctx, kFmtAllNodes)
|
||||
doDelete(ctx, false, &model.Node{}, nodeDcs...)
|
||||
}
|
||||
|
||||
@@ -51,6 +60,7 @@ func (c *Controller) DeleteNode(ctx *gin.Context) {
|
||||
// @Success 200 {object} HttpResponse
|
||||
// @Router /node/:id [put]
|
||||
func (c *Controller) UpdateNode(ctx *gin.Context) {
|
||||
redis.RC.Del(ctx, kFmtAllNodes)
|
||||
doUpdate(ctx, false, &model.Node{}, nodePreHooks...)
|
||||
}
|
||||
|
||||
@@ -77,7 +87,7 @@ func (c *Controller) GetNodes(ctx *gin.Context) {
|
||||
db = db.Where("id IN ?", lo.Map(strings.Split(q, ","), func(s string, _ int) int { return cast.ToInt(s) }))
|
||||
}
|
||||
if id, ok := ctx.GetQuery("no_self_child"); ok {
|
||||
ids, err := handleNoSelfChild(cast.ToInt(id))
|
||||
ids, err := handleNoSelfChild(ctx, cast.ToInt(id))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -85,7 +95,7 @@ func (c *Controller) GetNodes(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
if id, ok := ctx.GetQuery("self_parent"); ok {
|
||||
ids, err := handleSelfParent(cast.ToInt(id))
|
||||
ids, err := handleSelfParent(ctx, cast.ToInt(id))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -200,11 +210,14 @@ func nodeDelHook(ctx *gin.Context, id int) {
|
||||
ctx.AbortWithError(http.StatusBadRequest, err)
|
||||
}
|
||||
|
||||
func handleNoSelfChild(id int) (ids []int, err error) {
|
||||
func handleNoSelfChild(ctx context.Context, id int) (ids []int, err error) {
|
||||
nodes := make([]*model.NodeIdPid, 0)
|
||||
if err = redis.Get(ctx, kFmtAllNodes, &nodes); err != nil {
|
||||
if err = mysql.DB.Model(&model.Node{}).Find(&nodes).Error; err != nil {
|
||||
return
|
||||
}
|
||||
redis.SetEx(ctx, kFmtAllNodes, nodes, time.Hour)
|
||||
}
|
||||
g := make(map[int][]int)
|
||||
for _, n := range nodes {
|
||||
g[n.ParentId] = append(g[n.ParentId], n.Id)
|
||||
@@ -221,11 +234,14 @@ func handleNoSelfChild(id int) (ids []int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func handleSelfParent(id int) (ids []int, err error) {
|
||||
func handleSelfParent(ctx context.Context, id int) (ids []int, err error) {
|
||||
nodes := make([]*model.NodeIdPid, 0)
|
||||
if err = redis.Get(ctx, kFmtAllNodes, &nodes); err != nil {
|
||||
if err = mysql.DB.Model(&model.Node{}).Find(&nodes).Error; err != nil {
|
||||
return
|
||||
}
|
||||
redis.SetEx(ctx, kFmtAllNodes, nodes, time.Hour)
|
||||
}
|
||||
g := make(map[int][]int)
|
||||
for _, n := range nodes {
|
||||
g[n.ParentId] = append(g[n.ParentId], n.Id)
|
||||
@@ -244,11 +260,15 @@ func handleSelfParent(id int) (ids []int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func handleSelfChild(ins []int) (ids []int, err error) {
|
||||
func handleSelfChild(ctx context.Context, parentIds []int) (ids []int, err error) {
|
||||
// TODO: cache
|
||||
nodes := make([]*model.NodeIdPid, 0)
|
||||
if err = redis.Get(ctx, kFmtAllNodes, &nodes); err != nil {
|
||||
if err = mysql.DB.Model(&model.Node{}).Find(&nodes).Error; err != nil {
|
||||
return
|
||||
}
|
||||
redis.SetEx(ctx, kFmtAllNodes, nodes, time.Hour)
|
||||
}
|
||||
g := make(map[int][]int)
|
||||
for _, n := range nodes {
|
||||
g[n.ParentId] = append(g[n.ParentId], n.Id)
|
||||
@@ -259,7 +279,7 @@ func handleSelfChild(ins []int) (ids []int, err error) {
|
||||
ids = append(ids, x)
|
||||
}
|
||||
for _, y := range g[x] {
|
||||
dfs(y, b || lo.Contains(ins, x))
|
||||
dfs(y, b || lo.Contains(parentIds, x))
|
||||
}
|
||||
}
|
||||
dfs(0, false)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Package docs Code generated by swaggo/swag at 2024-09-19 17:52:48.7357174 +0800 CST m=+7.810953701. DO NOT EDIT
|
||||
// Package docs Code generated by swaggo/swag at 2024-09-20 17:24:49.219072 +0800 CST m=+7.114523601. DO NOT EDIT
|
||||
package docs
|
||||
|
||||
import "github.com/swaggo/swag"
|
||||
@@ -368,6 +368,80 @@ const docTemplate = `{
|
||||
}
|
||||
},
|
||||
"/authorization": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"authorization"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "page_index",
|
||||
"name": "page_index",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "page_size",
|
||||
"name": "page_size",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "node id",
|
||||
"name": "node_id",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "asset id",
|
||||
"name": "asset_id",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "account id",
|
||||
"name": "account_id",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/controller.HttpResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/controller.ListData"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"list": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/model.Account"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"tags": [
|
||||
"authorization"
|
||||
@@ -394,37 +468,6 @@ const docTemplate = `{
|
||||
}
|
||||
},
|
||||
"/authorization/:id": {
|
||||
"put": {
|
||||
"tags": [
|
||||
"authorization"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "authorization id",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "authorization",
|
||||
"name": "authorization",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Authorization"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controller.HttpResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"tags": [
|
||||
"authorization"
|
||||
|
@@ -357,6 +357,80 @@
|
||||
}
|
||||
},
|
||||
"/authorization": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"authorization"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "page_index",
|
||||
"name": "page_index",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "page_size",
|
||||
"name": "page_size",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "node id",
|
||||
"name": "node_id",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "asset id",
|
||||
"name": "asset_id",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "account id",
|
||||
"name": "account_id",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/controller.HttpResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/controller.ListData"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"list": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/model.Account"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"tags": [
|
||||
"authorization"
|
||||
@@ -383,37 +457,6 @@
|
||||
}
|
||||
},
|
||||
"/authorization/:id": {
|
||||
"put": {
|
||||
"tags": [
|
||||
"authorization"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "authorization id",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "authorization",
|
||||
"name": "authorization",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Authorization"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controller.HttpResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"tags": [
|
||||
"authorization"
|
||||
|
@@ -688,6 +688,49 @@ paths:
|
||||
tags:
|
||||
- asset
|
||||
/authorization:
|
||||
get:
|
||||
parameters:
|
||||
- description: page_index
|
||||
in: query
|
||||
name: page_index
|
||||
required: true
|
||||
type: integer
|
||||
- description: page_size
|
||||
in: query
|
||||
name: page_size
|
||||
required: true
|
||||
type: integer
|
||||
- description: node id
|
||||
in: query
|
||||
name: node_id
|
||||
type: integer
|
||||
- description: asset id
|
||||
in: query
|
||||
name: asset_id
|
||||
type: integer
|
||||
- description: account id
|
||||
in: query
|
||||
name: account_id
|
||||
type: integer
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/controller.HttpResponse'
|
||||
- properties:
|
||||
data:
|
||||
allOf:
|
||||
- $ref: '#/definitions/controller.ListData'
|
||||
- properties:
|
||||
list:
|
||||
items:
|
||||
$ref: '#/definitions/model.Account'
|
||||
type: array
|
||||
type: object
|
||||
type: object
|
||||
tags:
|
||||
- authorization
|
||||
post:
|
||||
parameters:
|
||||
- description: authorization
|
||||
@@ -718,26 +761,6 @@ paths:
|
||||
$ref: '#/definitions/controller.HttpResponse'
|
||||
tags:
|
||||
- authorization
|
||||
put:
|
||||
parameters:
|
||||
- description: authorization id
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
- description: authorization
|
||||
in: body
|
||||
name: authorization
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/model.Authorization'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controller.HttpResponse'
|
||||
tags:
|
||||
- authorization
|
||||
/command:
|
||||
get:
|
||||
parameters:
|
||||
|
@@ -16,9 +16,9 @@ type Asset struct {
|
||||
Comment string `json:"comment" gorm:"column:comment"`
|
||||
ParentId int `json:"parent_id" gorm:"column:parent_id"`
|
||||
Ip string `json:"ip" gorm:"column:ip"`
|
||||
Protocols Slice[string] `json:"protocols" gorm:"column:protocols"`
|
||||
Protocols Slice[string] `json:"protocols" gorm:"column:protocols;type:text"`
|
||||
GatewayId int `json:"gateway_id" gorm:"column:gateway_id"`
|
||||
Authorization Map[int, Slice[int]] `json:"authorization" gorm:"column:authorization"`
|
||||
Authorization Map[int, Slice[int]] `json:"authorization" gorm:"column:authorization;type:text"`
|
||||
AccessAuth AccessAuth `json:"access_auth" gorm:"embedded;column:access_auth"`
|
||||
Connectable bool `json:"connectable" gorm:"column:connectable"`
|
||||
NodeChain string `json:"node_chain" gorm:"-"`
|
||||
@@ -34,8 +34,8 @@ type Asset struct {
|
||||
type AccessAuth struct {
|
||||
Start *time.Time `json:"start,omitempty" gorm:"column:start"`
|
||||
End *time.Time `json:"end,omitempty" gorm:"column:end"`
|
||||
CmdIds Slice[int] `json:"cmd_ids" gorm:"column:cmd_ids"`
|
||||
Ranges Slice[Range] `json:"ranges" gorm:"column:ranges"`
|
||||
CmdIds Slice[int] `json:"cmd_ids" gorm:"column:cmd_ids;type:text"`
|
||||
Ranges Slice[Range] `json:"ranges" gorm:"column:ranges;type:text"`
|
||||
Allow bool `json:"allow" gorm:"column:allow"`
|
||||
}
|
||||
|
||||
|
@@ -15,9 +15,9 @@ type Node struct {
|
||||
Name string `json:"name" gorm:"column:name"`
|
||||
Comment string `json:"comment" gorm:"column:comment"`
|
||||
ParentId int `json:"parent_id" gorm:"column:parent_id"`
|
||||
Authorization Map[int, Slice[int]] `json:"authorization" gorm:"column:authorization"`
|
||||
Authorization Map[int, Slice[int]] `json:"authorization" gorm:"column:authorization;type:text"`
|
||||
AccessAuth AccessAuth `json:"access_auth" gorm:"embedded;column:access_auth"`
|
||||
Protocols Slice[string] `json:"protocols" gorm:"column:protocols"`
|
||||
Protocols Slice[string] `json:"protocols" gorm:"column:protocols;type:text"`
|
||||
GatewayId int `json:"gateway_id" gorm:"column:gateway_id"`
|
||||
|
||||
// ResourceId int `json:"resource_id"`
|
||||
|
@@ -28,6 +28,7 @@ type Session struct {
|
||||
Uid int `json:"uid" gorm:"column:uid"`
|
||||
UserName string `json:"user_name" gorm:"column:user_name"`
|
||||
AssetId int `json:"asset_id" gorm:"column:asset_id"`
|
||||
Asset *Asset `json:"-" gorm:"-"`
|
||||
AssetInfo string `json:"asset_info" gorm:"column:asset_info"`
|
||||
AccountId int `json:"account_id" gorm:"column:account_id"`
|
||||
AccountInfo string `json:"account_info" gorm:"column:account_info"`
|
||||
|
@@ -30,7 +30,7 @@ func UpdateConnectables(ids ...int) (err error) {
|
||||
if len(ids) > 0 {
|
||||
db = db.Where("id IN ?", ids)
|
||||
} else {
|
||||
db = db.Where("updated_at <= ?", time.Now().Add(time.Hour).Unix())
|
||||
db = db.Where("updated_at <= ?", time.Now().Add(-time.Hour))
|
||||
}
|
||||
if err = db.
|
||||
Find(&assets).Error; err != nil {
|
||||
|
@@ -23,7 +23,6 @@ import (
|
||||
"github.com/veops/oneterm/acl"
|
||||
"github.com/veops/oneterm/api/controller"
|
||||
redis "github.com/veops/oneterm/cache"
|
||||
"github.com/veops/oneterm/conf"
|
||||
mysql "github.com/veops/oneterm/db"
|
||||
"github.com/veops/oneterm/logger"
|
||||
"github.com/veops/oneterm/model"
|
||||
@@ -226,24 +225,22 @@ func (m *view) refresh() {
|
||||
auths := make([]*model.Authorization, 0)
|
||||
assets := make([]*model.Asset, 0)
|
||||
accounts := make([]*model.Account, 0)
|
||||
dbAuth := mysql.DB.Model(auths)
|
||||
dbAsset := mysql.DB.Model(assets)
|
||||
dbAccount := mysql.DB.Model(accounts)
|
||||
|
||||
if !acl.IsAdmin(m.currentUser) {
|
||||
rs, err := acl.GetRoleResources(ctx, m.currentUser.Acl.Rid, conf.GetResourceTypeName(conf.RESOURCE_AUTHORIZATION))
|
||||
assetIds, err := controller.GetAssetIdsByAuthorization(m.Ctx)
|
||||
if err != nil {
|
||||
logger.L().Error("auths", zap.Error(err))
|
||||
return
|
||||
}
|
||||
dbAuth = dbAuth.Where("resource_id IN ?", lo.Map(rs, func(r *acl.Resource, _ int) int { return r.ResourceId }))
|
||||
}
|
||||
if err := dbAuth.Find(&auths).Error; err != nil {
|
||||
logger.L().Error("auths", zap.Error(err))
|
||||
dbAccount = dbAccount.Where("id IN ?", assetIds)
|
||||
|
||||
accountIds, err := controller.GetAccountIdsByAuthorization(m.Ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
dbAccount = dbAccount.Where("id IN ?", lo.Map(auths, func(a *model.Authorization, _ int) int { return *a.AccountId }))
|
||||
dbAsset = dbAsset.Where("id IN ?", lo.Map(auths, func(a *model.Authorization, _ int) int { return *a.AssetId }))
|
||||
dbAsset = dbAsset.Where("id IN ?", accountIds)
|
||||
}
|
||||
|
||||
eg := &errgroup.Group{}
|
||||
eg.Go(func() error {
|
||||
|
Reference in New Issue
Block a user