3
0

Improve resource referencing

* Use Ref structs to allow for more context
* Assure constraints
This commit is contained in:
Tomaž Jerman
2022-04-27 13:11:58 +02:00
committed by Denis Arh
parent f5a4bd9a30
commit a790c12064
17 changed files with 191 additions and 85 deletions

View File

@@ -22,6 +22,7 @@ type (
)
func NewAPIGateway(res *types.ApigwRoute) *APIGateway {
// @todo we could use method + path combo to uniquely identify them also
r := &APIGateway{
base: &base{},
}

View File

@@ -19,7 +19,7 @@ type (
}
)
func NewComposeChart(res *types.Chart, nsRef string, mmRef []string) *ComposeChart {
func NewComposeChart(res *types.Chart, nsRef *Ref, mmRef RefSet) *ComposeChart {
r := &ComposeChart{
base: &base{},
RefMods: make(RefSet, len(mmRef)),
@@ -29,9 +29,9 @@ func NewComposeChart(res *types.Chart, nsRef string, mmRef []string) *ComposeCha
r.AddIdentifier(identifiers(res.Handle, res.Name, res.ID)...)
r.RefNs = r.AddRef(types.NamespaceResourceType, nsRef)
r.RefNs = r.addRef(nsRef)
for i, mRef := range mmRef {
r.RefMods[i] = r.AddRef(types.ModuleResourceType, mRef).Constraint(r.RefNs)
r.RefMods[i] = r.addRef(mRef).Constraint(r.RefNs)
}
// Initial timestamps

View File

@@ -31,7 +31,7 @@ type (
}
)
func NewComposeModule(res *types.Module, nsRef string) *ComposeModule {
func NewComposeModule(res *types.Module, nsRef *Ref) *ComposeModule {
r := &ComposeModule{
base: &base{},
RefMods: make(RefSet, 0, len(res.Fields)),
@@ -41,7 +41,7 @@ func NewComposeModule(res *types.Module, nsRef string) *ComposeModule {
r.AddIdentifier(identifiers(res.Handle, res.Name, res.ID)...)
r.RefNs = r.AddRef(types.NamespaceResourceType, nsRef)
r.RefNs = r.addRef(nsRef)
// Field deps
for _, f := range res.Fields {
@@ -101,20 +101,20 @@ func (r *ComposeModule) SysID() uint64 {
return r.Res.ID
}
func (r *ComposeModule) RBACParts() (resource string, ref *Ref, path []*Ref) {
ref = r.Ref()
func (r *ComposeModule) resourceParts(tpl string) (resource string, ref *Ref, path []*Ref) {
ref = r.Ref().Constraint(r.RefNs)
path = []*Ref{r.RefNs}
resource = fmt.Sprintf(types.ModuleRbacResourceTpl(), types.ModuleResourceType, r.RefNs.Identifiers.First(), firstOkString(strconv.FormatUint(r.Res.ID, 10), r.Res.Handle))
resource = fmt.Sprintf(tpl, types.ModuleResourceType, r.RefNs.Identifiers.First(), firstOkString(strconv.FormatUint(r.Res.ID, 10), r.Res.Handle))
return
}
func (r *ComposeModule) ResourceTranslationParts() (resource string, ref *Ref, path []*Ref) {
ref = r.Ref()
path = []*Ref{r.RefNs}
resource = fmt.Sprintf(types.ModuleResourceTranslationTpl(), types.ModuleResourceTranslationType, r.RefNs.Identifiers.First(), firstOkString(strconv.FormatUint(r.Res.ID, 10), r.Res.Handle))
func (r *ComposeModule) RBACParts() (resource string, ref *Ref, path []*Ref) {
return r.resourceParts(types.ModuleRbacResourceTpl())
}
return
func (r *ComposeModule) ResourceTranslationParts() (resource string, ref *Ref, path []*Ref) {
return r.resourceParts(types.ModuleResourceTranslationTpl())
}
func (r *ComposeModule) encodeTranslations() ([]*ResourceTranslation, error) {
@@ -186,14 +186,22 @@ func FindComposeModuleField(rr InterfaceSet, mod, ii Identifiers) (field *types.
return nil
}
func (r *ComposeModuleField) ResourceTranslationParts() (resource string, ref *Ref, path []*Ref) {
ref = r.Ref()
func (r *ComposeModuleField) resourceParts(tpl string) (resource string, ref *Ref, path []*Ref) {
ref = r.Ref().Constraint(r.RefNs).Constraint(r.RefMod)
path = []*Ref{r.RefNs, r.RefMod}
resource = fmt.Sprintf(types.ModuleFieldResourceTranslationTpl(), types.ModuleFieldResourceTranslationType, r.RefNs.Identifiers.First(), r.RefMod.Identifiers.First(), firstOkString(strconv.FormatUint(r.Res.ID, 10), r.Res.Name))
return
}
func (r *ComposeModuleField) RBACParts() (resource string, ref *Ref, path []*Ref) {
return r.resourceParts(types.ModuleFieldRbacResourceTpl())
}
func (r *ComposeModuleField) ResourceTranslationParts() (resource string, ref *Ref, path []*Ref) {
return r.resourceParts(types.ModuleFieldResourceTranslationTpl())
}
func (r *ComposeModuleField) ResourceTranslations() ([]*ResourceTranslation, error) {
out := make([]*ResourceTranslation, 0, 10)
@@ -213,7 +221,7 @@ func ComposeModuleFieldErrUnresolved(ii Identifiers) error {
return fmt.Errorf("compose module field unresolved %v", ii.StringSlice())
}
func NewComposeModuleField(res *types.ModuleField, nsRef, modRef string) *ComposeModuleField {
func NewComposeModuleField(res *types.ModuleField, nsRef, modRef *Ref) *ComposeModuleField {
r := &ComposeModuleField{
base: &base{},
}
@@ -222,8 +230,8 @@ func NewComposeModuleField(res *types.ModuleField, nsRef, modRef string) *Compos
r.AddIdentifier(identifiers(res.Name, res.ID)...)
r.RefNs = r.AddRef(types.NamespaceResourceType, nsRef)
r.RefMod = r.AddRef(types.ModuleResourceType, modRef)
r.RefNs = r.addRef(nsRef)
r.RefMod = r.addRef(modRef).Constraint(r.RefNs)
// Initial timestamps
r.SetTimestamps(MakeTimestampsCUDA(&res.CreatedAt, res.UpdatedAt, res.DeletedAt, nil))

View File

@@ -26,7 +26,7 @@ type (
}
)
func NewComposePage(pg *types.Page, nsRef, modRef, parentRef string) *ComposePage {
func NewComposePage(pg *types.Page, nsRef, modRef, parentRef *Ref) *ComposePage {
r := &ComposePage{
base: &base{},
WfRefs: make(RefSet, 0, 10),
@@ -39,13 +39,13 @@ func NewComposePage(pg *types.Page, nsRef, modRef, parentRef string) *ComposePag
r.AddIdentifier(identifiers(pg.Handle, pg.Title, pg.ID)...)
r.RefNs = r.AddRef(types.NamespaceResourceType, nsRef)
if modRef != "" {
r.RefMod = r.AddRef(types.ModuleResourceType, modRef).Constraint(r.RefNs)
r.RefNs = r.addRef(nsRef)
if modRef != nil {
r.RefMod = r.addRef(modRef).Constraint(r.RefNs)
}
if parentRef != "" {
r.RefParent = r.AddRef(types.PageResourceType, parentRef).Constraint(r.RefNs)
if parentRef != nil {
r.RefParent = r.addRef(parentRef).Constraint(r.RefNs)
}
var ref *Ref
@@ -129,14 +129,15 @@ func NewComposePage(pg *types.Page, nsRef, modRef, parentRef string) *ComposePag
return r
}
func UnpackComposePage(p *types.Page) (*types.Page, string, string) {
modRef := ""
parentRef := ""
func UnpackComposePage(p *types.Page) (*types.Page, *Ref, *Ref) {
var modRef *Ref
var parentRef *Ref
if p.ModuleID != 0 {
modRef = strconv.FormatUint(p.ModuleID, 10)
modRef = MakeModuleRef(p.ModuleID, "", "")
}
if p.SelfID != 0 {
parentRef = strconv.FormatUint(p.SelfID, 10)
parentRef = MakePageRef(p.SelfID, "", "")
}
return p, modRef, parentRef
@@ -206,20 +207,20 @@ func (r *ComposePage) SysID() uint64 {
return r.Res.ID
}
func (r *ComposePage) RBACParts() (resource string, ref *Ref, path []*Ref) {
ref = r.Ref()
func (r *ComposePage) resourceParts(tpl string) (resource string, ref *Ref, path []*Ref) {
ref = r.Ref().Constraint(r.RefNs)
path = []*Ref{r.RefNs}
resource = fmt.Sprintf(types.PageRbacResourceTpl(), types.PageResourceType, r.RefNs.Identifiers.First(), firstOkString(strconv.FormatUint(r.Res.ID, 10), r.Res.Handle))
return
}
func (r *ComposePage) ResourceTranslationParts() (resource string, ref *Ref, path []*Ref) {
ref = r.Ref()
path = []*Ref{r.RefNs}
resource = fmt.Sprintf(types.PageResourceTranslationTpl(), types.PageResourceTranslationType, r.RefNs.Identifiers.First(), firstOkString(strconv.FormatUint(r.Res.ID, 10), r.Res.Handle))
func (r *ComposePage) RBACParts() (resource string, ref *Ref, path []*Ref) {
return r.resourceParts(types.PageRbacResourceTpl())
}
return
func (r *ComposePage) ResourceTranslationParts() (resource string, ref *Ref, path []*Ref) {
return r.resourceParts(types.PageResourceTranslationTpl())
}
func (r *ComposePage) encodeTranslations() ([]*ResourceTranslation, error) {

View File

@@ -5,7 +5,6 @@ import (
composeTypes "github.com/cortezaproject/corteza-server/compose/types"
"github.com/cortezaproject/corteza-server/pkg/rbac"
"github.com/cortezaproject/corteza-server/system/types"
)
type (
@@ -20,21 +19,34 @@ type (
}
)
func NewRbacRule(res *rbac.Rule, refRole string, refRes *Ref, refResource string, refPath ...*Ref) *RbacRule {
func NewRbacRule(res *rbac.Rule, refRole, refRes *Ref, refResource string, refPath ...*Ref) *RbacRule {
r := &RbacRule{base: &base{}}
r.SetResourceType(RbacResourceType)
r.Res = res
r.RefRole = r.AddRef(types.RoleResourceType, refRole)
r.RefRole = r.addRef(refRole)
r.RefResource = refResource
if refRes != nil {
r.RefRes = r.AddRef(refRes.ResourceType, refRes.Identifiers.StringSlice()...)
r.RefRes = r.addRef(refRes)
}
// any additional constraints
for _, rp := range refPath {
r.RefPath = append(r.RefPath, r.AddRef(rp.ResourceType, rp.Identifiers.StringSlice()...))
for i, rp := range refPath {
ref := MakeRef(rp.ResourceType, rp.Identifiers)
if r.RefRes != nil {
r.RefRes.Constraint(ref)
}
if i > 0 {
for j := i - 1; j < i; j++ {
aux := refPath[j]
ref = ref.Constraint(MakeRef(aux.ResourceType, aux.Identifiers))
}
}
r.RefPath = append(r.RefPath, r.addRef(ref))
}
// Handle cases for nested resources
@@ -54,6 +66,26 @@ func (r *RbacRule) Resource() interface{} {
return r.Res
}
func (r *RbacRule) ReRef(old RefSet, new RefSet) {
r.base.ReRef(old, new)
// Care for wildcards
if r.RefRes != nil {
for i, o := range old {
if o.equals(r.RefRes) {
r.RefRes = new[i]
break
}
}
}
for i, o := range old {
if RefSet(r.RefPath).findRef(o) > -1 {
r.RefPath = RefSet(r.RefPath).replaceRef(o, new[i])
}
}
}
func (r *RbacRule) handleComposeRecord(res *rbac.Rule, refPath []*Ref) {
// records are grouped under module

View File

@@ -3,7 +3,6 @@ package resource
import (
"fmt"
composeTypes "github.com/cortezaproject/corteza-server/compose/types"
"github.com/cortezaproject/corteza-server/system/types"
"golang.org/x/text/language"
)
@@ -31,15 +30,18 @@ func NewResourceTranslation(res types.ResourceTranslationSet, refResource string
r.Res = res
r.RefResource = refResource
r.RefRes = r.AddRef(refRes.ResourceType, refRes.Identifiers.StringSlice()...)
r.RefRes = r.addRef(refRes)
// any additional constraints
for i, rp := range refPath {
ref := MakeRef(rp.ResourceType, rp.Identifiers)
// @todo generalize when needed; for now only module field resource translations require this
if i == 1 && refRes.ResourceType == composeTypes.ModuleFieldResourceType {
ref = ref.Constraint(r.RefPath[0])
r.RefRes.Constraint(ref)
if i > 0 {
for j := i - 1; j < i; j++ {
aux := refPath[j]
ref = ref.Constraint(MakeRef(aux.ResourceType, aux.Identifiers))
}
}
r.RefPath = append(r.RefPath, r.addRef(ref))

View File

@@ -276,6 +276,34 @@ func (rr RefSet) HasRef(ref *Ref) bool {
return rr.findRef(ref) > -1
}
// IsSbubset checks if aa is subset of bb
//
// Order is important; primary use is RBAC and res. tr. path checking.
func (aa RefSet) IsSubset(bb RefSet) bool {
if len(bb) > len(aa) {
return false
}
return aa[0:len(bb)].Equals(bb)
}
// Equals checks if two RefSets match
//
// They match if everything matches, even constraints (important)
func (aa RefSet) Equals(bb RefSet) bool {
if len(aa) != len(bb) {
return false
}
for i, a := range aa {
if !a.equals(bb[i]) {
return false
}
}
return true
}
// Unique returns only unique references
//
// Uniqueness is defined as "two references may not define

View File

@@ -2,6 +2,9 @@ package resource
import (
"time"
"github.com/cortezaproject/corteza-server/compose/types"
systemTypes "github.com/cortezaproject/corteza-server/system/types"
)
func firstOkString(ss ...string) string {
@@ -38,3 +41,40 @@ func toTime(v string) *time.Time {
return nil
}
// Ref builders
func MakeNamespaceRef(id uint64, handle, name string) *Ref {
return makeGenericRef(types.NamespaceResourceType, id, handle, name)
}
func MakeModuleRef(id uint64, handle, name string) *Ref {
return makeGenericRef(types.ModuleResourceType, id, handle, name)
}
func MakePageRef(id uint64, handle, title string) *Ref {
return makeGenericRef(types.PageResourceType, id, handle, title)
}
func MakeRoleRef(id uint64, handle, name string) *Ref {
return makeGenericRef(systemTypes.RoleResourceType, id, handle, name)
}
func makeGenericRef(t string, id uint64, ii ...string) *Ref {
args := make([]interface{}, len(ii)+1)
args[0] = id
for i := range ii {
args[i+1] = ii[i]
}
aux := &Ref{
ResourceType: t,
Identifiers: identifiers(args...),
}
if t == "" || len(aux.Identifiers) == 0 {
return nil
}
return aux
}

View File

@@ -1,8 +1,6 @@
package store
import (
"strconv"
"github.com/cortezaproject/corteza-server/compose/types"
"github.com/cortezaproject/corteza-server/pkg/envoy"
"github.com/cortezaproject/corteza-server/pkg/envoy/resource"
@@ -15,10 +13,10 @@ func newComposeChart(chr *types.Chart) *composeChart {
}
func (chr *composeChart) MarshalEnvoy() ([]resource.Interface, error) {
refNs := strconv.FormatUint(chr.chr.NamespaceID, 10)
refMods := make([]string, 0, 2)
refNs := resource.MakeNamespaceRef(chr.chr.NamespaceID, "", "")
refMods := make(resource.RefSet, 0, 2)
for _, r := range chr.chr.Config.Reports {
refMods = append(refMods, strconv.FormatUint(r.ModuleID, 10))
refMods = append(refMods, resource.MakeModuleRef(r.ModuleID, "", ""))
}
return envoy.CollectNodes(

View File

@@ -1,8 +1,6 @@
package store
import (
"strconv"
"github.com/cortezaproject/corteza-server/compose/types"
"github.com/cortezaproject/corteza-server/pkg/envoy"
"github.com/cortezaproject/corteza-server/pkg/envoy/resource"
@@ -15,8 +13,8 @@ func newComposeModule(mod *types.Module) *composeModule {
}
func (mod *composeModule) MarshalEnvoy() ([]resource.Interface, error) {
refNs := strconv.FormatUint(mod.mod.NamespaceID, 10)
refMod := strconv.FormatUint(mod.mod.ID, 10)
refNs := resource.MakeNamespaceRef(mod.mod.NamespaceID, "", "")
refMod := resource.MakeModuleRef(mod.mod.ID, mod.mod.Handle, mod.mod.Name)
rMod := resource.NewComposeModule(mod.mod, refNs)
for _, f := range mod.mod.Fields {

View File

@@ -1,8 +1,6 @@
package store
import (
"strconv"
"github.com/cortezaproject/corteza-server/compose/types"
"github.com/cortezaproject/corteza-server/pkg/envoy"
"github.com/cortezaproject/corteza-server/pkg/envoy/resource"
@@ -15,14 +13,16 @@ func newComposePage(pg *types.Page) *composePage {
}
func (pg *composePage) MarshalEnvoy() ([]resource.Interface, error) {
refNs := strconv.FormatUint(pg.pg.NamespaceID, 10)
refMod := ""
refParent := ""
var (
refNs = resource.MakeNamespaceRef(pg.pg.NamespaceID, "", "")
refMod *resource.Ref
refParent *resource.Ref
)
if pg.pg.ModuleID > 0 {
refMod = strconv.FormatUint(pg.pg.ModuleID, 10)
refMod = resource.MakeModuleRef(pg.pg.ModuleID, "", "")
}
if pg.pg.SelfID > 0 {
refParent = strconv.FormatUint(pg.pg.SelfID, 10)
refParent = resource.MakePageRef(pg.pg.SelfID, "", "")
}
return envoy.CollectNodes(

View File

@@ -1,7 +1,6 @@
package store
import (
"fmt"
"strconv"
"github.com/cortezaproject/corteza-server/pkg/envoy"
@@ -28,19 +27,6 @@ func newRbacRule(rl *rbac.Rule) (*rbacRule, error) {
func (rl *rbacRule) MarshalEnvoy() ([]resource.Interface, error) {
return envoy.CollectNodes(
resource.NewRbacRule(rl.rule, rl.refRole.Identifiers.First(), rl.refRbacRes, rl.refRbacResource, rl.refPathRes...),
resource.NewRbacRule(rl.rule, rl.refRole, rl.refRbacRes, rl.refRbacResource, rl.refPathRes...),
)
}
func rbacResToRef(rr string) (*resource.Ref, error) {
if rr == "" {
return nil, nil
}
ref := &resource.Ref{}
if ref.ResourceType = rbac.ResourceType(rr); ref.ResourceType != "" {
return ref, nil
}
return nil, fmt.Errorf("invalid resource provided: %s", rr)
}

View File

@@ -83,6 +83,10 @@ func (n *resourceTranslation) Encode(ctx context.Context, pl *payload) (err erro
ll := make(types.ResourceTranslationSet, 0, len(n.locales))
for _, l := range n.locales {
if l.Message == "" {
continue
}
old, ok := gResourceTranslations[l.Lang.Tag][resourceTranslationIndex(l)]
// not exist

View File

@@ -110,11 +110,11 @@ func (wset composeChartSet) MarshalEnvoy() ([]resource.Interface, error) {
}
func (wrap composeChart) MarshalEnvoy() ([]resource.Interface, error) {
vv := make([]string, 0, len(wrap.refReportModules))
vv := make(resource.RefSet, 0, len(wrap.refReportModules))
for _, v := range wrap.refReportModules {
vv = append(vv, v)
vv = append(vv, resource.MakeModuleRef(0, v, ""))
}
rs := resource.NewComposeChart(wrap.res, wrap.refNamespace, vv)
rs := resource.NewComposeChart(wrap.res, resource.MakeNamespaceRef(0, wrap.refNamespace, ""), vv)
rs.SetTimestamps(wrap.ts)
rs.SetConfig(wrap.envoyConfig)
return envoy.CollectNodes(

View File

@@ -122,7 +122,9 @@ func (wset composeModuleSet) MarshalEnvoy() ([]resource.Interface, error) {
}
func (wrap composeModule) MarshalEnvoy() ([]resource.Interface, error) {
rs := resource.NewComposeModule(wrap.res, wrap.refNamespace)
nsRef := resource.MakeNamespaceRef(0, wrap.refNamespace, "")
rs := resource.NewComposeModule(wrap.res, nsRef)
rs.SetTimestamps(wrap.ts)
rs.SetConfig(wrap.envoyConfig)
@@ -144,7 +146,7 @@ func (wrap composeModule) MarshalEnvoy() ([]resource.Interface, error) {
defaultFieldTranslations := make([]resource.Interface, 0)
for _, wrapField := range wrap.fields {
// generic field things
f := resource.NewComposeModuleField(wrapField.res, wrap.refNamespace, rs.Ref().Identifiers.First())
f := resource.NewComposeModuleField(wrapField.res, nsRef, rs.Ref())
rs.AddField(f)
fieldTranslations = append(fieldTranslations, wrapField.locale.bindResource(f)...)

View File

@@ -160,7 +160,13 @@ func (wset composePageSet) MarshalEnvoy() ([]resource.Interface, error) {
}
func (wrap composePage) MarshalEnvoy() ([]resource.Interface, error) {
rs := resource.NewComposePage(wrap.res, wrap.refNamespace, wrap.refModule, wrap.refParent)
rs := resource.NewComposePage(
wrap.res,
resource.MakeNamespaceRef(0, wrap.refNamespace, ""),
resource.MakeModuleRef(0, wrap.refModule, ""),
resource.MakePageRef(0, wrap.refParent, ""),
)
rs.SetTimestamps(wrap.ts)
rs.SetConfig(wrap.envoyConfig)

View File

@@ -93,7 +93,7 @@ func (rr rbacRuleSet) MarshalEnvoy() ([]resource.Interface, error) {
var nn = make([]resource.Interface, 0, len(rr))
for _, r := range rr {
nn = append(nn, resource.NewRbacRule(r.res, r.refRole.Identifiers.First(), r.refRbacRes, r.refRbacResource, r.refPathRes...))
nn = append(nn, resource.NewRbacRule(r.res, r.refRole, r.refRbacRes, r.refRbacResource, r.refPathRes...))
}
return nn, nil
}