Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
765 lines
15 KiB
Go
765 lines
15 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
composeTypes "github.com/cortezaproject/corteza/server/compose/types"
|
|
"github.com/cortezaproject/corteza/server/pkg/envoy"
|
|
"github.com/cortezaproject/corteza/server/pkg/envoy/resource"
|
|
pkgid "github.com/cortezaproject/corteza/server/pkg/id"
|
|
"github.com/cortezaproject/corteza/server/pkg/rbac"
|
|
"github.com/cortezaproject/corteza/server/store"
|
|
"github.com/cortezaproject/corteza/server/system/types"
|
|
"github.com/spf13/cast"
|
|
)
|
|
|
|
type (
|
|
roleFilter types.RoleFilter
|
|
userFilter types.UserFilter
|
|
templateFilter types.TemplateFilter
|
|
applicationFilter types.ApplicationFilter
|
|
apiGwRouteFilter types.ApigwRouteFilter
|
|
reportFilter types.ReportFilter
|
|
settingFilter types.SettingsFilter
|
|
rbacFilter struct {
|
|
rbac.RuleFilter
|
|
// This will help us determine what rules for what resources we are able to export
|
|
resourceID map[uint64]bool
|
|
strict bool
|
|
}
|
|
resourceTranslationFilter types.ResourceTranslationFilter
|
|
|
|
systemDecoder struct {
|
|
resourceID []uint64
|
|
ux *userIndex
|
|
}
|
|
)
|
|
|
|
func newSystemDecoder(ux *userIndex) *systemDecoder {
|
|
return &systemDecoder{
|
|
resourceID: make([]uint64, 0, 200),
|
|
ux: ux,
|
|
}
|
|
}
|
|
|
|
func (d *systemDecoder) decodeRoles(ctx context.Context, s store.Storer, ff []*roleFilter) *auxRsp {
|
|
mm := make([]envoy.Marshaller, 0, 100)
|
|
if ff == nil {
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
var nn types.RoleSet
|
|
var fn types.RoleFilter
|
|
var err error
|
|
|
|
for _, f := range ff {
|
|
aux := *f
|
|
|
|
if aux.Limit == 0 {
|
|
aux.Limit = 1000
|
|
}
|
|
|
|
for {
|
|
nn, fn, err = s.SearchRoles(ctx, types.RoleFilter(aux))
|
|
if err != nil {
|
|
return &auxRsp{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
for _, n := range nn {
|
|
mm = append(mm, newRole(n))
|
|
d.resourceID = append(d.resourceID, n.ID)
|
|
}
|
|
|
|
if fn.NextPage != nil {
|
|
aux.PageCursor = fn.NextPage
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
func (d *systemDecoder) decodeUsers(ctx context.Context, s store.Storer, ff []*userFilter) *auxRsp {
|
|
mm := make([]envoy.Marshaller, 0, 100)
|
|
if ff == nil {
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
var nn types.UserSet
|
|
var fn types.UserFilter
|
|
var err error
|
|
|
|
for _, f := range ff {
|
|
aux := *f
|
|
|
|
if aux.Limit == 0 {
|
|
aux.Limit = 1000
|
|
}
|
|
|
|
for {
|
|
nn, fn, err = s.SearchUsers(ctx, types.UserFilter(aux))
|
|
if err != nil {
|
|
return &auxRsp{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
for _, n := range nn {
|
|
mm = append(mm, newUser(n))
|
|
d.resourceID = append(d.resourceID, n.ID)
|
|
}
|
|
|
|
if fn.NextPage != nil {
|
|
aux.PageCursor = fn.NextPage
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
func (d *systemDecoder) decodeTemplates(ctx context.Context, s store.Storer, ff []*templateFilter) *auxRsp {
|
|
mm := make([]envoy.Marshaller, 0, 100)
|
|
if ff == nil {
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
var nn types.TemplateSet
|
|
var fn types.TemplateFilter
|
|
var err error
|
|
|
|
for _, f := range ff {
|
|
aux := *f
|
|
|
|
if aux.Limit == 0 {
|
|
aux.Limit = 1000
|
|
}
|
|
|
|
for {
|
|
nn, fn, err = s.SearchTemplates(ctx, types.TemplateFilter(aux))
|
|
if err != nil {
|
|
return &auxRsp{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
for _, n := range nn {
|
|
mm = append(mm, newTemplate(n))
|
|
d.resourceID = append(d.resourceID, n.ID)
|
|
}
|
|
|
|
if fn.NextPage != nil {
|
|
aux.PageCursor = fn.NextPage
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
func (d *systemDecoder) decodeAPIGWRoutes(ctx context.Context, s store.Storer, ff []*apiGwRouteFilter) *auxRsp {
|
|
mm := make([]envoy.Marshaller, 0, 100)
|
|
if ff == nil {
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
var nn types.ApigwRouteSet
|
|
var fn types.ApigwRouteFilter
|
|
var err error
|
|
|
|
for _, f := range ff {
|
|
aux := *f
|
|
|
|
if aux.Limit == 0 {
|
|
aux.Limit = 1000
|
|
}
|
|
|
|
for {
|
|
nn, fn, err = s.SearchApigwRoutes(ctx, types.ApigwRouteFilter(aux))
|
|
if err != nil {
|
|
return &auxRsp{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
// filters
|
|
for _, n := range nn {
|
|
gwf, _, err := s.SearchApigwFilters(ctx, types.ApigwFilterFilter{RouteID: n.ID})
|
|
if err != nil {
|
|
return &auxRsp{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
mm = append(mm, newAPIGateway(n, gwf, d.ux))
|
|
d.resourceID = append(d.resourceID, n.ID)
|
|
}
|
|
|
|
if fn.NextPage != nil {
|
|
aux.PageCursor = fn.NextPage
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
func (d *systemDecoder) decodeReports(ctx context.Context, s store.Storer, ff []*reportFilter) *auxRsp {
|
|
mm := make([]envoy.Marshaller, 0, 100)
|
|
if ff == nil {
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
var nn types.ReportSet
|
|
var fn types.ReportFilter
|
|
var err error
|
|
|
|
for _, f := range ff {
|
|
aux := *f
|
|
|
|
if aux.Limit == 0 {
|
|
aux.Limit = 1000
|
|
}
|
|
|
|
for {
|
|
nn, fn, err = s.SearchReports(ctx, types.ReportFilter(aux))
|
|
if err != nil {
|
|
return &auxRsp{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
for _, n := range nn {
|
|
mm = append(mm, newReport(n, d.ux))
|
|
d.resourceID = append(d.resourceID, n.ID)
|
|
}
|
|
|
|
if fn.NextPage != nil {
|
|
aux.PageCursor = fn.NextPage
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
func (d *systemDecoder) decodeApplications(ctx context.Context, s store.Storer, ff []*applicationFilter) *auxRsp {
|
|
mm := make([]envoy.Marshaller, 0, 100)
|
|
if ff == nil {
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
var nn types.ApplicationSet
|
|
var fn types.ApplicationFilter
|
|
var err error
|
|
|
|
for _, f := range ff {
|
|
aux := *f
|
|
|
|
if aux.Limit == 0 {
|
|
aux.Limit = 1000
|
|
}
|
|
|
|
for {
|
|
nn, fn, err = s.SearchApplications(ctx, types.ApplicationFilter(aux))
|
|
if err != nil {
|
|
return &auxRsp{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
for _, n := range nn {
|
|
// Index users
|
|
err = d.ux.add(
|
|
ctx,
|
|
n.OwnerID,
|
|
)
|
|
|
|
mm = append(mm, newApplication(n, d.ux))
|
|
d.resourceID = append(d.resourceID, n.ID)
|
|
}
|
|
|
|
if fn.NextPage != nil {
|
|
aux.PageCursor = fn.NextPage
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
func (d *systemDecoder) decodeSettings(ctx context.Context, s store.Storer, ff []*settingFilter) *auxRsp {
|
|
mm := make([]envoy.Marshaller, 0, 100)
|
|
if ff == nil {
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
var nn types.SettingValueSet
|
|
var err error
|
|
|
|
for _, f := range ff {
|
|
aux := *f
|
|
|
|
for {
|
|
nn, _, err = store.SearchSettingValues(ctx, s, types.SettingsFilter(aux))
|
|
if err != nil {
|
|
return &auxRsp{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
for _, n := range nn {
|
|
// Index users
|
|
err = d.ux.add(
|
|
ctx,
|
|
n.OwnedBy,
|
|
n.UpdatedBy,
|
|
)
|
|
|
|
mm = append(mm, newSetting(n, d.ux))
|
|
}
|
|
// mm = append(mm, NewSettings(nn))
|
|
|
|
break
|
|
}
|
|
}
|
|
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
func (d *systemDecoder) decodeRbac(ctx context.Context, s store.Storer, ff []*rbacFilter) *auxRsp {
|
|
mm := make([]envoy.Marshaller, 0, 100)
|
|
if ff == nil {
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
var nn rbac.RuleSet
|
|
var err error
|
|
|
|
c := func(r *resource.Ref, f *rbacFilter, path ...*resource.Ref) (bool, error) {
|
|
if r == nil {
|
|
return true, nil
|
|
}
|
|
|
|
// the first identifier is the most specific .. the ID
|
|
id, err := cast.ToUint64E(r.Identifiers.First())
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if r.ResourceType == composeTypes.ModuleFieldResourceType {
|
|
id, err = cast.ToUint64E(path[1].Identifiers.First())
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
}
|
|
|
|
return f.resourceID[id], nil
|
|
}
|
|
|
|
for _, f := range ff {
|
|
aux := *f
|
|
|
|
for {
|
|
nn, _, err = s.SearchRbacRules(ctx, rbac.RuleFilter(aux.RuleFilter))
|
|
if err != nil {
|
|
return &auxRsp{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
for _, n := range nn {
|
|
r, err := newRbacRule(n)
|
|
rt := strings.Split(r.refRbacResource, "/")[0]
|
|
if err != nil {
|
|
return &auxRsp{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
// somesort of a generic rule; no specifc resource
|
|
// @todo check for pp inclusion!!
|
|
if r.refRbacRes == nil && len(r.refPathRes) == 0 {
|
|
mm = append(mm, r)
|
|
} else {
|
|
// Check the resource ref and the path refs for validity.
|
|
// ComposeRecords are fetched in chunks so this check is not valid here.
|
|
if rt != composeTypes.RecordResourceType {
|
|
if ok, err := c(r.refRbacRes, f, r.refPathRes...); err != nil {
|
|
return &auxRsp{
|
|
err: err,
|
|
}
|
|
} else if !ok {
|
|
continue
|
|
}
|
|
}
|
|
|
|
for _, p := range r.refPathRes {
|
|
if ok, err := c(p, f); err != nil {
|
|
return &auxRsp{
|
|
err: err,
|
|
}
|
|
} else if !ok {
|
|
continue
|
|
}
|
|
}
|
|
|
|
mm = append(mm, r)
|
|
}
|
|
}
|
|
|
|
break
|
|
}
|
|
}
|
|
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
func (d *systemDecoder) decodeResourceTranslation(ctx context.Context, s store.Storer, ff []*resourceTranslationFilter) *auxRsp {
|
|
mm := make([]envoy.Marshaller, 0, 100)
|
|
if ff == nil {
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
var (
|
|
resMap = make(map[string]*resourceTranslation)
|
|
|
|
nn types.ResourceTranslationSet
|
|
fn types.ResourceTranslationFilter
|
|
err error
|
|
)
|
|
|
|
for _, f := range ff {
|
|
aux := *f
|
|
|
|
if aux.Limit == 0 {
|
|
aux.Limit = 1000
|
|
}
|
|
|
|
for {
|
|
nn, fn, err = s.SearchResourceTranslations(ctx, types.ResourceTranslationFilter(aux))
|
|
if err != nil {
|
|
return &auxRsp{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
for _, n := range nn {
|
|
if _, ok := resMap[n.Resource]; !ok {
|
|
resMap[n.Resource], err = newResourceTranslation(types.ResourceTranslationSet{n})
|
|
if err != nil {
|
|
return &auxRsp{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
// parse the resource wo we can define relations/check if we can unmarshal it
|
|
_, ref, pp, err := resource.ParseResourceTranslation(n.Resource)
|
|
resMap[n.Resource].refLocaleRes = ref
|
|
resMap[n.Resource].refPathRes = pp
|
|
if err != nil {
|
|
return &auxRsp{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
continue
|
|
}
|
|
|
|
resMap[n.Resource].locales = append(resMap[n.Resource].locales, n)
|
|
}
|
|
|
|
if fn.NextPage != nil {
|
|
aux.PageCursor = fn.NextPage
|
|
} else {
|
|
break
|
|
}
|
|
|
|
break
|
|
}
|
|
}
|
|
|
|
for _, lr := range resMap {
|
|
mm = append(mm, lr)
|
|
}
|
|
|
|
return &auxRsp{
|
|
mm: mm,
|
|
}
|
|
}
|
|
|
|
func (df *DecodeFilter) systemFromResource(rr ...string) *DecodeFilter {
|
|
for _, r := range rr {
|
|
if !strings.HasPrefix(r, "system") {
|
|
continue
|
|
}
|
|
|
|
id := ""
|
|
if strings.Count(r, ":") == 2 && !strings.HasSuffix(r, "*") {
|
|
// There is an identifier
|
|
aux := strings.Split(r, ":")
|
|
|
|
id = aux[len(aux)-1]
|
|
r = strings.Join(aux[:len(aux)-1], ":")
|
|
}
|
|
|
|
switch strings.ToLower(r) {
|
|
case "system:role":
|
|
df = df.Roles(&types.RoleFilter{
|
|
Query: id,
|
|
})
|
|
case "system:user":
|
|
df = df.Users(&types.UserFilter{
|
|
Query: id,
|
|
AllKinds: true,
|
|
})
|
|
case "system:template":
|
|
df = df.Templates(&types.TemplateFilter{
|
|
Handle: id,
|
|
})
|
|
templateID, err := cast.ToUint64E(id)
|
|
if err == nil && templateID > 0 {
|
|
df = df.Templates(&types.TemplateFilter{
|
|
TemplateID: pkgid.Strings(templateID),
|
|
})
|
|
}
|
|
case "system:apigw-route":
|
|
df = df.APIGWRoutes(&types.ApigwRouteFilter{
|
|
Route: id,
|
|
})
|
|
case "system:report":
|
|
df = df.Reports(&types.ReportFilter{
|
|
Handle: id,
|
|
})
|
|
reportID, err := cast.ToUint64E(id)
|
|
if err == nil && reportID > 0 {
|
|
df = df.Reports(&types.ReportFilter{
|
|
ReportID: pkgid.Strings(reportID),
|
|
})
|
|
}
|
|
|
|
case "system:application":
|
|
df = df.Applications(&types.ApplicationFilter{
|
|
Query: id,
|
|
})
|
|
case "system:setting":
|
|
df = df.Settings(&types.SettingsFilter{})
|
|
case "system:rbac":
|
|
df = df.Rbac(&rbac.RuleFilter{})
|
|
case "system:resource-translation":
|
|
df = df.Rbac(&rbac.RuleFilter{})
|
|
}
|
|
}
|
|
|
|
return df
|
|
}
|
|
|
|
func (df *DecodeFilter) systemFromRef(rr ...*resource.Ref) *DecodeFilter {
|
|
for _, r := range rr {
|
|
if strings.Index(r.ResourceType, "system") < 0 {
|
|
continue
|
|
}
|
|
|
|
switch r.ResourceType {
|
|
case types.RoleResourceType:
|
|
for _, i := range r.Identifiers.StringSlice() {
|
|
df = df.Roles(&types.RoleFilter{
|
|
Query: i,
|
|
})
|
|
}
|
|
case types.UserResourceType:
|
|
for _, i := range r.Identifiers.StringSlice() {
|
|
df = df.Users(&types.UserFilter{
|
|
Query: i,
|
|
AllKinds: true,
|
|
})
|
|
}
|
|
case types.TemplateResourceType:
|
|
for _, i := range r.Identifiers.StringSlice() {
|
|
df = df.Templates(&types.TemplateFilter{
|
|
Handle: i,
|
|
})
|
|
templateID, err := cast.ToUint64E(i)
|
|
if err == nil && templateID > 0 {
|
|
df = df.Templates(&types.TemplateFilter{
|
|
TemplateID: pkgid.Strings(templateID),
|
|
})
|
|
}
|
|
}
|
|
case types.ApplicationResourceType:
|
|
for _, i := range r.Identifiers.StringSlice() {
|
|
df = df.Applications(&types.ApplicationFilter{
|
|
Query: i,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
return df
|
|
}
|
|
|
|
// Roles adds a new RoleFilter
|
|
func (df *DecodeFilter) Roles(f *types.RoleFilter) *DecodeFilter {
|
|
if df.roles == nil {
|
|
df.roles = make([]*roleFilter, 0, 1)
|
|
}
|
|
df.roles = append(df.roles, (*roleFilter)(f))
|
|
return df
|
|
}
|
|
|
|
// Users adds a new UserFilter
|
|
func (df *DecodeFilter) Users(f *types.UserFilter) *DecodeFilter {
|
|
if df.users == nil {
|
|
df.users = make([]*userFilter, 0, 1)
|
|
}
|
|
df.users = append(df.users, (*userFilter)(f))
|
|
return df
|
|
}
|
|
|
|
// Templates adds a new TemplateFilter
|
|
func (df *DecodeFilter) Templates(f *types.TemplateFilter) *DecodeFilter {
|
|
if df.templates == nil {
|
|
df.templates = make([]*templateFilter, 0, 1)
|
|
}
|
|
df.templates = append(df.templates, (*templateFilter)(f))
|
|
return df
|
|
}
|
|
|
|
func (df *DecodeFilter) APIGWRoutes(f *types.ApigwRouteFilter) *DecodeFilter {
|
|
if df.apiGwRoutes == nil {
|
|
df.apiGwRoutes = make([]*apiGwRouteFilter, 0, 1)
|
|
}
|
|
df.apiGwRoutes = append(df.apiGwRoutes, (*apiGwRouteFilter)(f))
|
|
return df
|
|
}
|
|
|
|
func (df *DecodeFilter) Reports(f *types.ReportFilter) *DecodeFilter {
|
|
if df.reports == nil {
|
|
df.reports = make([]*reportFilter, 0, 1)
|
|
}
|
|
df.reports = append(df.reports, (*reportFilter)(f))
|
|
return df
|
|
}
|
|
|
|
// Applications adds a new ApplicationFilter
|
|
func (df *DecodeFilter) Applications(f *types.ApplicationFilter) *DecodeFilter {
|
|
if df.applications == nil {
|
|
df.applications = make([]*applicationFilter, 0, 1)
|
|
}
|
|
df.applications = append(df.applications, (*applicationFilter)(f))
|
|
return df
|
|
}
|
|
|
|
// Settings adds a new SettingsFilter
|
|
func (df *DecodeFilter) Settings(f *types.SettingsFilter) *DecodeFilter {
|
|
if df.settings == nil {
|
|
df.settings = make([]*settingFilter, 0, 1)
|
|
}
|
|
df.settings = append(df.settings, (*settingFilter)(f))
|
|
return df
|
|
}
|
|
|
|
// Rbac adds a new RuleFilter
|
|
func (df *DecodeFilter) Rbac(f *rbac.RuleFilter) *DecodeFilter {
|
|
if df.rbac == nil {
|
|
df.rbac = make([]*rbacFilter, 0, 1)
|
|
} else {
|
|
// There can only be a single rbac filter
|
|
// since it makes no sense to have multiple of
|
|
return df
|
|
}
|
|
|
|
df.rbac = append(df.rbac, &rbacFilter{RuleFilter: *f})
|
|
return df
|
|
}
|
|
|
|
// ResourceTranslation adds a new ResourceTranslationFilter
|
|
func (df *DecodeFilter) ResourceTranslation(f *types.ResourceTranslationFilter) *DecodeFilter {
|
|
if df.resourceTranslations == nil {
|
|
df.resourceTranslations = make([]*resourceTranslationFilter, 0, 1)
|
|
} else {
|
|
// There can only be a single resourceTranslations filter
|
|
// since it makes no sense to have multiple of
|
|
return df
|
|
}
|
|
|
|
df.resourceTranslations = append(df.resourceTranslations, (*resourceTranslationFilter)(f))
|
|
return df
|
|
}
|
|
|
|
func (df *DecodeFilter) RbacStrict(f *rbac.RuleFilter) *DecodeFilter {
|
|
if df.rbac == nil {
|
|
df.rbac = make([]*rbacFilter, 0, 1)
|
|
} else {
|
|
// There can only be a single rbac filter
|
|
// since it makes no sense to have multiple of
|
|
return df
|
|
}
|
|
|
|
df.rbac = append(df.rbac, &rbacFilter{RuleFilter: *f})
|
|
return df
|
|
}
|
|
|
|
// allowRbacResource adds a new resource identifier to supported resource rules
|
|
func (df *DecodeFilter) allowRbacResource(id ...uint64) {
|
|
if df.rbac == nil || len(df.rbac) == 0 {
|
|
return
|
|
}
|
|
rf := df.rbac[0]
|
|
|
|
if rf.resourceID == nil {
|
|
rf.resourceID = make(map[uint64]bool)
|
|
}
|
|
for _, i := range id {
|
|
rf.resourceID[i] = true
|
|
}
|
|
}
|