Skip to content

Commit

Permalink
feat(api): permission
Browse files Browse the repository at this point in the history
  • Loading branch information
ttktatakai committed Sep 23, 2024
1 parent 03eec7a commit 78199b7
Show file tree
Hide file tree
Showing 20 changed files with 494 additions and 143 deletions.
18 changes: 1 addition & 17 deletions backend/acl/perm.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,17 @@ import (
"context"
"fmt"

"github.com/gin-gonic/gin"
"github.com/samber/lo"

"github.com/veops/oneterm/conf"
)

func GetSessionFromCtx(ctx *gin.Context) (res *Session, err error) {
func GetSessionFromCtx(ctx context.Context) (res *Session, err error) {
res, ok := ctx.Value("session").(*Session)
if !ok || res == nil {
err = fmt.Errorf("empty session")
}
return
}

func HasPerm(resourceId int, rid int, action string) bool {
mapping, err := GetResourcePermissions(context.Background(), resourceId)
if err != nil {
return false
}
for _, v := range mapping {
if lo.ContainsBy(v.Perms, func(p *Perm) bool { return p.Rid == rid && p.Name == action }) {
return true
}
}
return false
}

func IsAdmin(session *Session) bool {
for _, pr := range session.Acl.ParentRoles {
if pr == "admin" || pr == "acl_admin" || pr == "oneterm_admin" {
Expand Down
93 changes: 93 additions & 0 deletions backend/acl/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,105 @@ import (
"fmt"

"github.com/gin-gonic/gin"
"github.com/samber/lo"
"github.com/spf13/cast"
"go.uber.org/zap"
"golang.org/x/sync/errgroup"

"github.com/veops/oneterm/conf"
mysql "github.com/veops/oneterm/db"
"github.com/veops/oneterm/logger"
"github.com/veops/oneterm/model"
"github.com/veops/oneterm/remote"
)

func init() {
migrateNode()
}

type ResourceType struct {
AppId string `json:"app_id"`
Name string `json:"name"`
}

func migrateNode() {
ctx := context.Background()

rts, err := GetResourceTypes(ctx)
if err != nil {
logger.L().Fatal("get resource type failed", zap.Error(err))
}

if _, ok := lo.Find(rts, func(rt *ResourceType) bool { return rt.AppId == "oneterm" && rt.Name == "node" }); !ok {
if err = AddResourceTypes(ctx, &ResourceType{AppId: "oneterm", Name: "node"}); err != nil {
logger.L().Fatal("add resource type failed", zap.Error(err))
}
}

nodes := make([]*model.Node, 0)
if err = mysql.DB.Model(&nodes).Where("resource_id=?", 0).Find(&nodes).Error; err != nil {
logger.L().Fatal("get nodes failed", zap.Error(err))
}
eg := errgroup.Group{}
for _, n := range nodes {
nd := n
eg.Go(func() error {
r, err := AddResource(ctx, 0, "node", cast.ToString(nd.Id))
if err != nil {
return err
}
if err := mysql.DB.Model(&nd).Where("id=?", nd.Id).Update("resource_id", r.ResourceId).Error; err != nil {
return err
}
return nil
})
}
if err = eg.Wait(); err != nil {
logger.L().Fatal("add resource failed", zap.Error(err))
}
}

func GetResourceTypes(ctx context.Context) (rt []*ResourceType, err error) {
token, err := remote.GetAclToken(ctx)
if err != nil {
return
}

rt = make([]*ResourceType, 0)
url := fmt.Sprintf("%s/acl/resource_types", conf.Cfg.Auth.Acl.Url)
resp, err := remote.RC.R().
SetHeaders(map[string]string{
"App-Access-Token": token,
}).
SetQueryParams(map[string]string{
"app_id": "oneterm",
"page_size": "100",
}).
SetResult(&rt).
Post(url)
err = remote.HandleErr(err, resp, func(dt map[string]any) bool { return true })

return
}

func AddResourceTypes(ctx context.Context, rt *ResourceType) (err error) {
token, err := remote.GetAclToken(ctx)
if err != nil {
return
}

url := fmt.Sprintf("%s/acl/resource_types", conf.Cfg.Auth.Acl.Url)
resp, err := remote.RC.R().
SetHeaders(map[string]string{
"App-Access-Token": token,
}).
SetBody(rt).
Post(url)
err = remote.HandleErr(err, resp, func(dt map[string]any) bool { return true })

return
}

func AddResource(ctx context.Context, uid int, resourceTypeId string, name string) (res *Resource, err error) {
token, err := remote.GetAclToken(ctx)
if err != nil {
Expand Down
17 changes: 15 additions & 2 deletions backend/acl/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,26 @@ package acl
import (
"context"
"fmt"
"time"

"github.com/spf13/cast"
"golang.org/x/sync/errgroup"

redis "github.com/veops/oneterm/cache"
"github.com/veops/oneterm/conf"
"github.com/veops/oneterm/remote"
)

const (
kFmtResources = "resource-%s-%d"
)

func GetRoleResources(ctx context.Context, rid int, resourceTypeId string) (res []*Resource, err error) {
k := fmt.Sprintf(kFmtResources, resourceTypeId, rid)
if err = redis.Get(ctx, k, &res); err == nil {
return
}

token, err := remote.GetAclToken(ctx)
if err != nil {
return
Expand All @@ -34,10 +45,12 @@ func GetRoleResources(ctx context.Context, rid int, resourceTypeId string) (res

res = data.Resources

redis.SetEx(ctx, k, res, time.Minute)

return
}

func HasPermission(ctx context.Context, rid int, resourceName, resourceTypeName, permission string) (res bool, err error) {
func HasPermission(ctx context.Context, rid int, resourceTypeName string, resourceId int, permission string) (res bool, err error) {
token, err := remote.GetAclToken(ctx)
if err != nil {
return false, err
Expand All @@ -49,7 +62,7 @@ func HasPermission(ctx context.Context, rid int, resourceName, resourceTypeName,
SetHeader("App-Access-Token", token).
SetQueryParams(map[string]string{
"rid": cast.ToString(rid),
"resource_name": resourceName,
"resource_id": cast.ToString(resourceId),
"resource_type_name": resourceTypeName,
"perm": permission,
}).
Expand Down
8 changes: 4 additions & 4 deletions backend/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,13 @@ func RunApi() error {

share := v1.Group("/share")
{
share.POST("", authAdmin(), c.CreateShare)
share.DELETE("/:id", authAdmin(), c.DeleteShare)
share.GET("", authAdmin(), c.GetShare)
share.POST("", c.CreateShare)
share.DELETE("/:id", c.DeleteShare)
share.GET("", c.GetShare)
}
r.GET("/api/oneterm/v1/share/connect/:uuid", Error2Resp(), c.ConnectShare)

authorization := v1.Group("/authorization", authAdmin())
authorization := v1.Group("/authorization")
{
authorization.POST("", c.UpsertAuthorization)
authorization.DELETE("/:id", c.DeleteAccount)
Expand Down
6 changes: 3 additions & 3 deletions backend/api/controller/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func (c *Controller) CreateAccount(ctx *gin.Context) {
// @Success 200 {object} HttpResponse
// @Router /account/:id [delete]
func (c *Controller) DeleteAccount(ctx *gin.Context) {
doDelete(ctx, true, &model.Account{}, accountDcs...)
doDelete(ctx, true, &model.Account{}, conf.RESOURCE_ACCOUNT,accountDcs...)
}

// UpdateAccount godoc
Expand All @@ -123,7 +123,7 @@ func (c *Controller) DeleteAccount(ctx *gin.Context) {
// @Success 200 {object} HttpResponse
// @Router /account/:id [put]
func (c *Controller) UpdateAccount(ctx *gin.Context) {
doUpdate(ctx, true, &model.Account{}, accountPreHooks...)
doUpdate(ctx, true, &model.Account{},conf.RESOURCE_ACCOUNT, accountPreHooks...)
}

// GetAccounts godoc
Expand Down Expand Up @@ -161,7 +161,7 @@ func (c *Controller) GetAccounts(ctx *gin.Context) {

db = db.Order("name")

doGet[*model.Account](ctx, !info, db, acl.GetResourceTypeName(conf.RESOURCE_ACCOUNT), accountPostHooks...)
doGet(ctx, !info, db, acl.GetResourceTypeName(conf.RESOURCE_ACCOUNT), accountPostHooks...)
}

func GetAccountIdsByAuthorization(ctx *gin.Context) (ids []int, err error) {
Expand Down
36 changes: 10 additions & 26 deletions backend/api/controller/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (c *Controller) CreateAsset(ctx *gin.Context) {
// @Success 200 {object} HttpResponse
// @Router /asset/:id [delete]
func (c *Controller) DeleteAsset(ctx *gin.Context) {
doDelete(ctx, true, &model.Asset{})
doDelete(ctx, true, &model.Asset{}, conf.RESOURCE_ASSET)
}

// UpdateAsset godoc
Expand All @@ -71,7 +71,7 @@ func (c *Controller) DeleteAsset(ctx *gin.Context) {
// @Success 200 {object} HttpResponse
// @Router /asset/:id [put]
func (c *Controller) UpdateAsset(ctx *gin.Context) {
doUpdate(ctx, true, &model.Asset{})
doUpdate(ctx, true, &model.Asset{}, conf.RESOURCE_ASSET)
schedule.UpdateConnectables(cast.ToInt(ctx.Param("id")))
}

Expand Down Expand Up @@ -123,14 +123,11 @@ func (c *Controller) GetAssets(ctx *gin.Context) {
}

func assetPostHookCount(ctx *gin.Context, data []*model.Asset) {
nodes := make([]*model.NodeIdPidName, 0)
if err := mysql.DB.
Model(nodes).
Find(&nodes).
Error; err != nil {
logger.L().Error("asset posthookfailed", zap.Error(err))
nodes, err := getAllNodes(ctx)
if err != nil {
return
}

g := make(map[int][]model.Pair[int, string])
for _, n := range nodes {
g[n.ParentId] = append(g[n.ParentId], model.Pair[int, string]{First: n.Id, Second: n.Name})
Expand Down Expand Up @@ -176,13 +173,11 @@ func assetPostHookAuth(ctx *gin.Context, data []*model.Asset) {
}

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)
nodes, err := getAllNodes(ctx)
if err != nil {
return
}

g := make(map[int][]int)
for _, n := range nodes {
g[n.ParentId] = append(g[n.ParentId], n.Id)
Expand Down Expand Up @@ -250,18 +245,7 @@ func getIdsByAuthorizationIds(ctx context.Context) (parentNodeIds, assetIds, acc
return
}

func getAuthorizationIds(ctx *gin.Context) (authIds []*model.AuthorizationIds, err error) {
resourceIds, err := getAutorizationResourceIds(ctx)
if err != nil {
handleRemoteErr(ctx, err)
return
}

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
err = mysql.DB.WithContext(ctx).Model(&model.Asset{}).Where("parent_id IN?", parentNodeIds).Or("JSON_KEYS(authorization) IN ?", accountIds).Pluck("id", &assetIds).Error
return
}
Loading

0 comments on commit 78199b7

Please sign in to comment.