Improve envoy system values
Handle timestamps & user stamps.
This commit is contained in:
@@ -5,12 +5,30 @@ type (
|
||||
rt string
|
||||
ii Identifiers
|
||||
rr RefSet
|
||||
|
||||
ts *Timestamps
|
||||
us *Userstamps
|
||||
urefs RefSet
|
||||
}
|
||||
|
||||
EnvoyConfig struct {
|
||||
// SkipIf determines when the encoding should be skipped for this resource
|
||||
SkipIf string
|
||||
}
|
||||
|
||||
Timestamps struct {
|
||||
CreatedAt string
|
||||
UpdatedAt string
|
||||
DeletedAt string
|
||||
ArchivedAt string
|
||||
SuspendedAt string
|
||||
}
|
||||
Userstamps struct {
|
||||
CreatedBy string
|
||||
UpdatedBy string
|
||||
DeletedBy string
|
||||
OwnedBy string
|
||||
}
|
||||
)
|
||||
|
||||
// State management methods
|
||||
@@ -48,6 +66,40 @@ func (t *base) SetResourceType(rt string) {
|
||||
t.rt = rt
|
||||
}
|
||||
|
||||
func (t *base) SetTimestamps(ts *Timestamps) {
|
||||
t.ts = ts
|
||||
}
|
||||
func (t *base) Timestamps() *Timestamps {
|
||||
return t.ts
|
||||
}
|
||||
|
||||
func (t *base) SetUserstamps(us *Userstamps) {
|
||||
t.us = us
|
||||
|
||||
if us != nil {
|
||||
uu := []string{us.CreatedBy, us.UpdatedBy, us.DeletedBy, us.OwnedBy}
|
||||
t.SetUserRefs(uu)
|
||||
}
|
||||
}
|
||||
func (t *base) Userstamps() *Userstamps {
|
||||
return t.us
|
||||
}
|
||||
|
||||
func (t *base) SetUserRefs(uu []string) {
|
||||
if t.urefs == nil {
|
||||
t.urefs = make(RefSet, 0, 4)
|
||||
}
|
||||
|
||||
for _, u := range uu {
|
||||
if u != "" {
|
||||
t.urefs = append(t.urefs, t.AddRef(USER_RESOURCE_TYPE, u))
|
||||
}
|
||||
}
|
||||
}
|
||||
func (t *base) UserRefs() RefSet {
|
||||
return t.urefs
|
||||
}
|
||||
|
||||
// Resource interface methods
|
||||
|
||||
func (t *base) Identifiers() Identifiers {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package resource
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/compose/types"
|
||||
)
|
||||
|
||||
@@ -17,10 +15,12 @@ type (
|
||||
DeletedBy string
|
||||
}
|
||||
ComposeRecordRaw struct {
|
||||
ID string
|
||||
Values map[string]string
|
||||
SysValues *rawSysValues
|
||||
RefUsers map[string]string
|
||||
ID string
|
||||
Values map[string]string
|
||||
|
||||
Ts *Timestamps
|
||||
Us *Userstamps
|
||||
RefUsers map[string]string
|
||||
|
||||
Config *EnvoyConfig
|
||||
}
|
||||
@@ -58,42 +58,3 @@ func NewComposeRecordSet(w crsWalker, nsRef, modRef string) *ComposeRecord {
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// ApplyValues takes in a raw map of things and creates a proper structure for it
|
||||
func (cr *ComposeRecordRaw) ApplyValues(vv map[string]string) {
|
||||
if cr.RefUsers == nil {
|
||||
cr.RefUsers = make(map[string]string)
|
||||
}
|
||||
if cr.SysValues == nil {
|
||||
cr.SysValues = &rawSysValues{}
|
||||
}
|
||||
if cr.Values == nil {
|
||||
cr.Values = make(map[string]string)
|
||||
}
|
||||
|
||||
for k, v := range vv {
|
||||
switch strings.ToLower(k) {
|
||||
case "ownedby":
|
||||
cr.SysValues.OwnedBy = v
|
||||
cr.RefUsers[v] = ""
|
||||
case "createdat":
|
||||
cr.SysValues.CreatedAt = v
|
||||
case "createdby":
|
||||
cr.SysValues.CreatedBy = v
|
||||
cr.RefUsers[v] = ""
|
||||
case "updatedat":
|
||||
cr.SysValues.UpdatedAt = v
|
||||
case "updatedby":
|
||||
cr.SysValues.UpdatedBy = v
|
||||
cr.RefUsers[v] = ""
|
||||
case "deletedat":
|
||||
cr.SysValues.DeletedAt = v
|
||||
case "deletedby":
|
||||
cr.SysValues.DeletedBy = v
|
||||
cr.RefUsers[v] = ""
|
||||
|
||||
default:
|
||||
cr.Values[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,9 +47,9 @@ func (crt *composeRecordShaper) toResource(def *ComposeRecordTemplate, dt *Resou
|
||||
|
||||
// Get the bits in order
|
||||
rRaw := &ComposeRecordRaw{
|
||||
ID: crt.getKey(mr, def.Key),
|
||||
ID: crt.getKey(mr, def.Key),
|
||||
Values: crt.mapValues(mr, def.FieldMap),
|
||||
}
|
||||
rRaw.ApplyValues(crt.mapValues(mr, def.FieldMap))
|
||||
|
||||
// Process it
|
||||
err = f(rRaw)
|
||||
|
||||
@@ -65,6 +65,23 @@ func (n *applicationState) Encode(ctx context.Context, s store.Storer, state *en
|
||||
return nil
|
||||
}
|
||||
|
||||
// Timestamps
|
||||
ts := n.res.Timestamps()
|
||||
if ts != nil {
|
||||
if ts.CreatedAt != "" {
|
||||
t := toTime(ts.CreatedAt)
|
||||
if t != nil {
|
||||
res.CreatedAt = *t
|
||||
}
|
||||
}
|
||||
if ts.UpdatedAt != "" {
|
||||
res.UpdatedAt = toTime(ts.UpdatedAt)
|
||||
}
|
||||
if ts.DeletedAt != "" {
|
||||
res.DeletedAt = toTime(ts.DeletedAt)
|
||||
}
|
||||
}
|
||||
|
||||
// Create fresh application
|
||||
if !exists {
|
||||
return store.CreateApplication(ctx, s, res)
|
||||
|
||||
@@ -87,6 +87,23 @@ func (n *composeChartState) Encode(ctx context.Context, s store.Storer, state *e
|
||||
return nil
|
||||
}
|
||||
|
||||
// Timestamps
|
||||
ts := n.res.Timestamps()
|
||||
if ts != nil {
|
||||
if ts.CreatedAt != "" {
|
||||
t := toTime(ts.CreatedAt)
|
||||
if t != nil {
|
||||
res.CreatedAt = *t
|
||||
}
|
||||
}
|
||||
if ts.UpdatedAt != "" {
|
||||
res.UpdatedAt = toTime(ts.UpdatedAt)
|
||||
}
|
||||
if ts.DeletedAt != "" {
|
||||
res.DeletedAt = toTime(ts.DeletedAt)
|
||||
}
|
||||
}
|
||||
|
||||
// Namespace
|
||||
res.NamespaceID = n.relNS.ID
|
||||
if res.NamespaceID <= 0 {
|
||||
|
||||
@@ -115,6 +115,23 @@ func (n *composeModuleState) Encode(ctx context.Context, s store.Storer, state *
|
||||
return nil
|
||||
}
|
||||
|
||||
// Timestamps
|
||||
ts := n.res.Timestamps()
|
||||
if ts != nil {
|
||||
if ts.CreatedAt != "" {
|
||||
t := toTime(ts.CreatedAt)
|
||||
if t != nil {
|
||||
res.CreatedAt = *t
|
||||
}
|
||||
}
|
||||
if ts.UpdatedAt != "" {
|
||||
res.UpdatedAt = toTime(ts.UpdatedAt)
|
||||
}
|
||||
if ts.DeletedAt != "" {
|
||||
res.DeletedAt = toTime(ts.DeletedAt)
|
||||
}
|
||||
}
|
||||
|
||||
// Namespace
|
||||
res.NamespaceID = n.relNS.ID
|
||||
if res.NamespaceID <= 0 {
|
||||
|
||||
@@ -63,6 +63,23 @@ func (n *composeNamespaceState) Encode(ctx context.Context, s store.Storer, stat
|
||||
return nil
|
||||
}
|
||||
|
||||
// Timestamps
|
||||
ts := n.res.Timestamps()
|
||||
if ts != nil {
|
||||
if ts.CreatedAt != "" {
|
||||
t := toTime(ts.CreatedAt)
|
||||
if t != nil {
|
||||
res.CreatedAt = *t
|
||||
}
|
||||
}
|
||||
if ts.UpdatedAt != "" {
|
||||
res.UpdatedAt = toTime(ts.UpdatedAt)
|
||||
}
|
||||
if ts.DeletedAt != "" {
|
||||
res.DeletedAt = toTime(ts.DeletedAt)
|
||||
}
|
||||
}
|
||||
|
||||
// Create a fresh namespace
|
||||
if !exists {
|
||||
return store.CreateComposeNamespace(ctx, s, res)
|
||||
|
||||
@@ -134,6 +134,23 @@ func (n *composePageState) Encode(ctx context.Context, s store.Storer, state *en
|
||||
return nil
|
||||
}
|
||||
|
||||
// Timestamps
|
||||
ts := n.res.Timestamps()
|
||||
if ts != nil {
|
||||
if ts.CreatedAt != "" {
|
||||
t := toTime(ts.CreatedAt)
|
||||
if t != nil {
|
||||
res.CreatedAt = *t
|
||||
}
|
||||
}
|
||||
if ts.UpdatedAt != "" {
|
||||
res.UpdatedAt = toTime(ts.UpdatedAt)
|
||||
}
|
||||
if ts.DeletedAt != "" {
|
||||
res.DeletedAt = toTime(ts.DeletedAt)
|
||||
}
|
||||
}
|
||||
|
||||
// Namespace
|
||||
res.NamespaceID = n.relNS.ID
|
||||
if res.NamespaceID <= 0 {
|
||||
|
||||
@@ -21,6 +21,7 @@ type (
|
||||
|
||||
relNS *types.Namespace
|
||||
relMod *types.Module
|
||||
relUsr map[string]uint64
|
||||
|
||||
// Little helper flag for conditional encoding
|
||||
missing bool
|
||||
@@ -81,6 +82,12 @@ func (n *composeRecordState) Prepare(ctx context.Context, s store.Storer, state
|
||||
return composeModuleErrUnresolved(n.res.ModRef.Identifiers)
|
||||
}
|
||||
|
||||
// Sys users
|
||||
n.relUsr = make(map[string]uint64)
|
||||
if err = resolveUserRefs(ctx, s, state.ParentResources, n.res.UserRefs(), n.relUsr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add missing refs
|
||||
for _, f := range n.relMod.Fields {
|
||||
switch f.Kind {
|
||||
@@ -140,6 +147,15 @@ func (n *composeRecordState) Encode(ctx context.Context, s store.Storer, state *
|
||||
mod.ID = m.ID
|
||||
}
|
||||
|
||||
// Sys users
|
||||
for idf, ID := range n.relUsr {
|
||||
if ID != 0 {
|
||||
continue
|
||||
}
|
||||
u := findUserR(ctx, state.ParentResources, resource.MakeIdentifiers(idf))
|
||||
n.relUsr[idf] = u.ID
|
||||
}
|
||||
|
||||
// Some pointing
|
||||
rm := n.res.RecMap
|
||||
im := n.res.IDMap
|
||||
@@ -211,11 +227,36 @@ func (n *composeRecordState) Encode(ctx context.Context, s store.Storer, state *
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sys values
|
||||
// @todo
|
||||
//
|
||||
// for k, v := range r.SysValues {
|
||||
// }
|
||||
// Timestamps
|
||||
if r.Ts != nil {
|
||||
if r.Ts.CreatedAt != "" {
|
||||
t := toTime(r.Ts.CreatedAt)
|
||||
if t != nil {
|
||||
rec.CreatedAt = *t
|
||||
}
|
||||
}
|
||||
if r.Ts.UpdatedAt != "" {
|
||||
rec.UpdatedAt = toTime(r.Ts.UpdatedAt)
|
||||
}
|
||||
if r.Ts.DeletedAt != "" {
|
||||
rec.DeletedAt = toTime(r.Ts.DeletedAt)
|
||||
}
|
||||
}
|
||||
// Userstamps
|
||||
if r.Us != nil {
|
||||
if r.Us.CreatedBy != "" {
|
||||
rec.CreatedBy = n.relUsr[r.Us.CreatedBy]
|
||||
}
|
||||
if r.Us.UpdatedBy != "" {
|
||||
rec.UpdatedBy = n.relUsr[r.Us.UpdatedBy]
|
||||
}
|
||||
if r.Us.DeletedBy != "" {
|
||||
rec.DeletedBy = n.relUsr[r.Us.DeletedBy]
|
||||
}
|
||||
if r.Us.OwnedBy != "" {
|
||||
rec.OwnedBy = n.relUsr[r.Us.OwnedBy]
|
||||
}
|
||||
}
|
||||
|
||||
rvs := make(types.RecordValueSet, 0, len(r.Values))
|
||||
for k, v := range r.Values {
|
||||
|
||||
@@ -2,9 +2,10 @@ package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cortezaproject/corteza-server/messaging/types"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/messaging/types"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/envoy"
|
||||
"github.com/cortezaproject/corteza-server/pkg/envoy/resource"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
@@ -16,6 +17,8 @@ type (
|
||||
|
||||
res *resource.MessagingChannel
|
||||
ch *types.Channel
|
||||
|
||||
relUsr map[string]uint64
|
||||
}
|
||||
)
|
||||
|
||||
@@ -32,6 +35,12 @@ func (n *messagingChannelState) Prepare(ctx context.Context, s store.Storer, rs
|
||||
n.res.Res.CreatedAt = time.Now()
|
||||
}
|
||||
|
||||
// Sys users
|
||||
n.relUsr = make(map[string]uint64)
|
||||
if err = resolveUserRefs(ctx, s, rs.ParentResources, n.res.UserRefs(), n.relUsr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the existing channel
|
||||
n.ch, err = findMessagingChannelS(ctx, s, makeGenericFilter(n.res.Identifiers()))
|
||||
if err != nil {
|
||||
@@ -57,11 +66,48 @@ func (n *messagingChannelState) Encode(ctx context.Context, s store.Storer, stat
|
||||
res.ID = NextID()
|
||||
}
|
||||
|
||||
// Sys users
|
||||
for idf, ID := range n.relUsr {
|
||||
if ID != 0 {
|
||||
continue
|
||||
}
|
||||
u := findUserR(ctx, state.ParentResources, resource.MakeIdentifiers(idf))
|
||||
n.relUsr[idf] = u.ID
|
||||
}
|
||||
|
||||
// This is not possible, but let's do it anyway
|
||||
if state.Conflicting {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Timestamps
|
||||
ts := n.res.Timestamps()
|
||||
if ts != nil {
|
||||
if ts.CreatedAt != "" {
|
||||
t := toTime(ts.CreatedAt)
|
||||
if t != nil {
|
||||
res.CreatedAt = *t
|
||||
}
|
||||
}
|
||||
if ts.UpdatedAt != "" {
|
||||
res.UpdatedAt = toTime(ts.UpdatedAt)
|
||||
}
|
||||
if ts.DeletedAt != "" {
|
||||
res.DeletedAt = toTime(ts.DeletedAt)
|
||||
}
|
||||
if ts.ArchivedAt != "" {
|
||||
res.ArchivedAt = toTime(ts.ArchivedAt)
|
||||
}
|
||||
}
|
||||
|
||||
// Userstamps
|
||||
us := n.res.Userstamps()
|
||||
if us != nil {
|
||||
if us.CreatedBy != "" {
|
||||
res.CreatorID = n.relUsr[us.CreatedBy]
|
||||
}
|
||||
}
|
||||
|
||||
// Create fresh messagingChannel
|
||||
if !exists {
|
||||
return store.CreateMessagingChannel(ctx, s, res)
|
||||
|
||||
@@ -62,6 +62,26 @@ func (n *roleState) Encode(ctx context.Context, s store.Storer, state *envoy.Res
|
||||
return nil
|
||||
}
|
||||
|
||||
// Timestamps
|
||||
ts := n.res.Timestamps()
|
||||
if ts != nil {
|
||||
if ts.CreatedAt != "" {
|
||||
t := toTime(ts.CreatedAt)
|
||||
if t != nil {
|
||||
rl.CreatedAt = *t
|
||||
}
|
||||
}
|
||||
if ts.UpdatedAt != "" {
|
||||
rl.UpdatedAt = toTime(ts.UpdatedAt)
|
||||
}
|
||||
if ts.DeletedAt != "" {
|
||||
rl.DeletedAt = toTime(ts.DeletedAt)
|
||||
}
|
||||
if ts.ArchivedAt != "" {
|
||||
rl.ArchivedAt = toTime(ts.ArchivedAt)
|
||||
}
|
||||
}
|
||||
|
||||
// Create a fresh role
|
||||
if !exists {
|
||||
return store.CreateRole(ctx, s, rl)
|
||||
|
||||
@@ -2,6 +2,7 @@ package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/envoy"
|
||||
@@ -63,6 +64,26 @@ func (n *userState) Encode(ctx context.Context, s store.Storer, state *envoy.Res
|
||||
return nil
|
||||
}
|
||||
|
||||
// Timestamps
|
||||
ts := n.res.Timestamps()
|
||||
if ts != nil {
|
||||
if ts.CreatedAt != "" {
|
||||
t := toTime(ts.CreatedAt)
|
||||
if t != nil {
|
||||
res.CreatedAt = *t
|
||||
}
|
||||
}
|
||||
if ts.UpdatedAt != "" {
|
||||
res.UpdatedAt = toTime(ts.UpdatedAt)
|
||||
}
|
||||
if ts.DeletedAt != "" {
|
||||
res.DeletedAt = toTime(ts.DeletedAt)
|
||||
}
|
||||
if ts.SuspendedAt != "" {
|
||||
res.SuspendedAt = toTime(ts.SuspendedAt)
|
||||
}
|
||||
}
|
||||
|
||||
// Create a fresh user
|
||||
if !exists {
|
||||
return store.CreateUser(ctx, s, res)
|
||||
@@ -164,7 +185,7 @@ func findUserR(ctx context.Context, rr resource.InterfaceSet, ii resource.Identi
|
||||
return nil
|
||||
}
|
||||
|
||||
if uRes.Identifiers().HasAny(ii) {
|
||||
if ur.Identifiers().HasAny(ii) {
|
||||
uRes = ur
|
||||
}
|
||||
return nil
|
||||
@@ -177,3 +198,7 @@ func findUserR(ctx context.Context, rr resource.InterfaceSet, ii resource.Identi
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func userErrUnresolved(ii resource.Identifiers) error {
|
||||
return fmt.Errorf("user unresolved %v", ii.StringSlice())
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/envoy/resource"
|
||||
"github.com/cortezaproject/corteza-server/pkg/expr"
|
||||
"github.com/cortezaproject/corteza-server/pkg/handle"
|
||||
"github.com/cortezaproject/corteza-server/pkg/id"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -55,3 +58,50 @@ func makeGenericFilter(ii resource.Identifiers) (f genericFilter) {
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
// Taken from compose/service/values/sanitizer.go
|
||||
func toTime(v string) *time.Time {
|
||||
ff := []string{
|
||||
time.RFC3339,
|
||||
time.RFC1123Z,
|
||||
time.RFC1123,
|
||||
time.RFC850,
|
||||
time.RFC822Z,
|
||||
time.RFC822,
|
||||
time.RubyDate,
|
||||
time.UnixDate,
|
||||
time.ANSIC,
|
||||
"2006/_1/_2 15:04:05",
|
||||
"2006/_1/_2 15:04",
|
||||
}
|
||||
|
||||
for _, f := range ff {
|
||||
parsed, err := time.Parse(f, v)
|
||||
if err == nil {
|
||||
return &parsed
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resolveUserRefs(ctx context.Context, s store.Storer, pr []resource.Interface, refs resource.RefSet, dst map[string]uint64) (err error) {
|
||||
for _, uRef := range refs {
|
||||
u := findUserR(ctx, pr, uRef.Identifiers)
|
||||
if u == nil {
|
||||
u, err = findUserS(ctx, s, makeGenericFilter(uRef.Identifiers))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if u == nil {
|
||||
return userErrUnresolved(uRef.Identifiers)
|
||||
}
|
||||
|
||||
// Unexisting users will have ID 0, but that's ok, as long as they exist
|
||||
for i := range uRef.Identifiers {
|
||||
dst[i] = u.ID
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ type (
|
||||
application struct {
|
||||
// when application is at least partially defined
|
||||
res *types.Application `yaml:",inline"`
|
||||
ts *resource.Timestamps
|
||||
|
||||
// module's RBAC rules
|
||||
rbac rbacRuleSet
|
||||
@@ -43,7 +44,7 @@ func (wset *applicationSet) UnmarshalYAML(n *yaml.Node) error {
|
||||
}
|
||||
|
||||
case yaml.MappingNode:
|
||||
if err = v.Decode(&wrap.res); err != nil {
|
||||
if err = v.Decode(&wrap); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -77,6 +78,9 @@ func (wrap *application) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
if wrap.res == nil {
|
||||
wrap.res = &types.Application{}
|
||||
}
|
||||
if wrap.ts, err = decodeTimestamps(n); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = n.Decode(&wrap.res); err != nil {
|
||||
return
|
||||
@@ -91,6 +95,8 @@ func (wrap *application) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
|
||||
func (wrap application) MarshalEnvoy() ([]resource.Interface, error) {
|
||||
rs := resource.NewApplication(wrap.res)
|
||||
rs.SetTimestamps(wrap.ts)
|
||||
|
||||
return envoy.CollectNodes(
|
||||
rs,
|
||||
wrap.rbac.bindResource(rs),
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
type (
|
||||
composeChart struct {
|
||||
res *types.Chart
|
||||
ts *resource.Timestamps
|
||||
refNamespace string
|
||||
|
||||
// pointer to report and module reference
|
||||
@@ -97,6 +98,10 @@ func (wrap *composeChart) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if wrap.ts, err = decodeTimestamps(n); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return eachMap(n, func(k, v *yaml.Node) (err error) {
|
||||
switch k.Value {
|
||||
case "handle":
|
||||
@@ -129,6 +134,7 @@ func (wrap composeChart) MarshalEnvoy() ([]resource.Interface, error) {
|
||||
vv = append(vv, v)
|
||||
}
|
||||
rs := resource.NewComposeChart(wrap.res, wrap.refNamespace, vv)
|
||||
rs.SetTimestamps(wrap.ts)
|
||||
return envoy.CollectNodes(
|
||||
rs,
|
||||
wrap.rbac.bindResource(rs),
|
||||
|
||||
@@ -25,6 +25,7 @@ type (
|
||||
|
||||
composeModule struct {
|
||||
res *types.Module
|
||||
ts *resource.Timestamps
|
||||
refNamespace string
|
||||
rbac rbacRuleSet
|
||||
|
||||
@@ -107,6 +108,10 @@ func (wrap *composeModule) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if wrap.ts, err = decodeTimestamps(n); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return eachMap(n, func(k, v *yaml.Node) (err error) {
|
||||
switch k.Value {
|
||||
case "name":
|
||||
@@ -146,6 +151,7 @@ func (wrap *composeModule) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
|
||||
func (wrap composeModule) MarshalEnvoy() ([]resource.Interface, error) {
|
||||
rs := resource.NewComposeModule(wrap.res, wrap.refNamespace)
|
||||
rs.SetTimestamps(wrap.ts)
|
||||
|
||||
var crs *resource.ComposeRecordTemplate
|
||||
if wrap.recTpl != nil {
|
||||
|
||||
@@ -12,6 +12,7 @@ type (
|
||||
composeNamespace struct {
|
||||
// when namespace is at least partially defined
|
||||
res *types.Namespace `yaml:",inline"`
|
||||
ts *resource.Timestamps
|
||||
|
||||
// all known modules on a namespace
|
||||
modules composeModuleSet
|
||||
@@ -103,6 +104,10 @@ func (wrap *composeNamespace) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if wrap.ts, err = decodeTimestamps(n); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return each(n, func(k, v *yaml.Node) (err error) {
|
||||
switch k.Value {
|
||||
case "modules":
|
||||
@@ -125,6 +130,8 @@ func (wrap *composeNamespace) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
|
||||
func (wrap composeNamespace) MarshalEnvoy() ([]resource.Interface, error) {
|
||||
nsr := resource.NewComposeNamespace(wrap.res)
|
||||
nsr.SetTimestamps(wrap.ts)
|
||||
|
||||
return envoy.CollectNodes(
|
||||
nsr,
|
||||
wrap.modules,
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
type (
|
||||
composePage struct {
|
||||
res *types.Page
|
||||
ts *resource.Timestamps
|
||||
children composePageSet
|
||||
|
||||
refNamespace string
|
||||
@@ -109,6 +110,10 @@ func (wrap *composePage) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if wrap.ts, err = decodeTimestamps(n); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return eachMap(n, func(k, v *yaml.Node) (err error) {
|
||||
switch k.Value {
|
||||
case "title":
|
||||
@@ -149,6 +154,7 @@ func (wrap *composePage) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
|
||||
func (wrap composePage) MarshalEnvoy() ([]resource.Interface, error) {
|
||||
rs := resource.NewComposePage(wrap.res, wrap.refNamespace, wrap.refModule, wrap.refParent)
|
||||
rs.SetTimestamps(wrap.ts)
|
||||
|
||||
return envoy.CollectNodes(
|
||||
rs,
|
||||
|
||||
@@ -10,15 +10,14 @@ import (
|
||||
|
||||
type (
|
||||
composeRecord struct {
|
||||
values map[string]string
|
||||
sysValues map[string]string
|
||||
values map[string]string
|
||||
ts *resource.Timestamps
|
||||
us *resource.Userstamps
|
||||
|
||||
eCfg *resource.EnvoyConfig
|
||||
|
||||
refModule string
|
||||
refNamespace string
|
||||
// createdBy, updatedBy, deletedBy, ownedBy
|
||||
refUser map[string]string
|
||||
}
|
||||
composeRecordSet []*composeRecord
|
||||
|
||||
@@ -77,9 +76,10 @@ func (wset composeRecordSet) MarshalEnvoy() ([]resource.Interface, error) {
|
||||
|
||||
type (
|
||||
rw struct {
|
||||
rr resource.ComposeRecordRawSet
|
||||
nsRef string
|
||||
modRef string
|
||||
rr resource.ComposeRecordRawSet
|
||||
nsRef string
|
||||
modRef string
|
||||
refUser resource.Identifiers
|
||||
}
|
||||
)
|
||||
|
||||
@@ -89,9 +89,10 @@ func (wset composeRecordSet) MarshalEnvoy() ([]resource.Interface, error) {
|
||||
for _, res := range wset {
|
||||
if recMap[res.refModule] == nil {
|
||||
recMap[res.refModule] = &rw{
|
||||
rr: make(resource.ComposeRecordRawSet, 0, 10),
|
||||
nsRef: res.refNamespace,
|
||||
modRef: res.refModule,
|
||||
rr: make(resource.ComposeRecordRawSet, 0, 10),
|
||||
nsRef: res.refNamespace,
|
||||
modRef: res.refModule,
|
||||
refUser: make(resource.Identifiers),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,9 +100,17 @@ func (wset composeRecordSet) MarshalEnvoy() ([]resource.Interface, error) {
|
||||
// @todo change this probably
|
||||
ID: res.values["id"],
|
||||
Config: res.eCfg,
|
||||
Values: res.values,
|
||||
Ts: res.ts,
|
||||
Us: res.us,
|
||||
}
|
||||
r.ApplyValues(res.values)
|
||||
r.ApplyValues(res.sysValues)
|
||||
|
||||
recMap[res.refModule].refUser.Add(
|
||||
res.us.CreatedBy,
|
||||
res.us.UpdatedBy,
|
||||
res.us.DeletedBy,
|
||||
res.us.OwnedBy,
|
||||
)
|
||||
|
||||
recMap[res.refModule].rr = append(recMap[res.refModule].rr, r)
|
||||
}
|
||||
@@ -118,6 +127,7 @@ func (wset composeRecordSet) MarshalEnvoy() ([]resource.Interface, error) {
|
||||
}
|
||||
|
||||
n := resource.NewComposeRecordSet(walker, w.nsRef, w.modRef)
|
||||
n.SetUserRefs(w.refUser.StringSlice())
|
||||
for _, r := range w.rr {
|
||||
n.IDMap[r.ID] = 0
|
||||
}
|
||||
@@ -141,15 +151,9 @@ func (wset composeRecordSet) setNamespaceRef(ref string) error {
|
||||
}
|
||||
|
||||
func (wrap *composeRecord) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
if wrap.refUser == nil {
|
||||
wrap.refUser = make(map[string]string)
|
||||
}
|
||||
if wrap.values == nil {
|
||||
wrap.values = make(map[string]string)
|
||||
}
|
||||
if wrap.sysValues == nil {
|
||||
wrap.sysValues = make(map[string]string)
|
||||
}
|
||||
|
||||
// @todo enable when records are ready for RBAC
|
||||
//if wrap.rbac, err = decodeRbac(types.RecordRBACResource, n); err != nil {
|
||||
@@ -160,6 +164,13 @@ func (wrap *composeRecord) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if wrap.ts, err = decodeTimestamps(n); err != nil {
|
||||
return
|
||||
}
|
||||
if wrap.us, err = decodeUserstamps(n); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return eachMap(n, func(k, v *yaml.Node) error {
|
||||
switch k.Value {
|
||||
case "module":
|
||||
@@ -172,28 +183,6 @@ func (wrap *composeRecord) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
}
|
||||
return nil
|
||||
|
||||
case "createdAt":
|
||||
wrap.sysValues["createdAt"] = v.Value
|
||||
return nil
|
||||
case "updatedAt":
|
||||
wrap.sysValues["updatedAt"] = v.Value
|
||||
return nil
|
||||
case "deletedAt":
|
||||
wrap.sysValues["deletedAt"] = v.Value
|
||||
return nil
|
||||
case "createdBy":
|
||||
wrap.refUser["createdBy"] = v.Value
|
||||
return nil
|
||||
case "updatedBy":
|
||||
wrap.refUser["updatedBy"] = v.Value
|
||||
return nil
|
||||
case "deletedBy":
|
||||
wrap.refUser["deletedBy"] = v.Value
|
||||
return nil
|
||||
case "ownedBy":
|
||||
wrap.refUser["ownedBy"] = v.Value
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -11,9 +11,7 @@ func TestComposeRecord_UnmarshalYAML(t *testing.T) {
|
||||
var (
|
||||
parseString = func(src string) (*composeRecord, error) {
|
||||
w := &composeRecord{
|
||||
values: make(map[string]string),
|
||||
sysValues: make(map[string]string),
|
||||
refUser: make(map[string]string),
|
||||
values: make(map[string]string),
|
||||
}
|
||||
return w, yaml.Unmarshal([]byte(src), w)
|
||||
}
|
||||
@@ -35,7 +33,8 @@ func TestComposeRecord_UnmarshalYAML(t *testing.T) {
|
||||
req.NoError(err)
|
||||
req.NotNil(w)
|
||||
req.NotEmpty(w.values)
|
||||
req.NotEmpty(w.sysValues)
|
||||
req.NotNil(w.ts)
|
||||
req.NotNil(w.us)
|
||||
req.Equal("bar", w.values["foo"])
|
||||
})
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ type (
|
||||
roles roleSet
|
||||
users userSet
|
||||
applications applicationSet
|
||||
settings settings
|
||||
settings *settings
|
||||
rbac rbacRuleSet
|
||||
}
|
||||
)
|
||||
|
||||
@@ -11,6 +11,8 @@ type (
|
||||
messagingChannel struct {
|
||||
// when messagingChannel is at least partially defined
|
||||
res *types.Channel `yaml:",inline"`
|
||||
ts *resource.Timestamps
|
||||
us *resource.Userstamps
|
||||
|
||||
// module's RBAC rules
|
||||
rbac rbacRuleSet
|
||||
@@ -35,7 +37,7 @@ func (wset *messagingChannelSet) UnmarshalYAML(n *yaml.Node) error {
|
||||
}
|
||||
|
||||
wrap.res = &types.Channel{}
|
||||
if err = v.Decode(&wrap.res); err != nil {
|
||||
if err = v.Decode(&wrap); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -76,11 +78,20 @@ func (wrap *messagingChannel) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if wrap.ts, err = decodeTimestamps(n); err != nil {
|
||||
return
|
||||
}
|
||||
if wrap.us, err = decodeUserstamps(n); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (wrap messagingChannel) MarshalEnvoy() ([]resource.Interface, error) {
|
||||
rs := resource.NewMessagingChannel(wrap.res)
|
||||
rs.SetTimestamps(wrap.ts)
|
||||
rs.SetUserstamps(wrap.us)
|
||||
return envoy.CollectNodes(
|
||||
rs,
|
||||
wrap.rbac.bindResource(rs),
|
||||
|
||||
@@ -11,6 +11,7 @@ type (
|
||||
role struct {
|
||||
// when role is at least partially defined
|
||||
res *types.Role
|
||||
ts *resource.Timestamps
|
||||
|
||||
// all known modules on a role
|
||||
modules composeModuleSet
|
||||
@@ -47,7 +48,7 @@ func (wset *roleSet) UnmarshalYAML(n *yaml.Node) error {
|
||||
}
|
||||
|
||||
case yaml.MappingNode:
|
||||
if err = v.Decode(&wrap.res); err != nil {
|
||||
if err = v.Decode(&wrap); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -93,11 +94,17 @@ func (wrap *role) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if wrap.ts, err = decodeTimestamps(n); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (wrap role) MarshalEnvoy() ([]resource.Interface, error) {
|
||||
rs := resource.NewRole(wrap.res)
|
||||
rs.SetTimestamps(wrap.ts)
|
||||
|
||||
return envoy.CollectNodes(
|
||||
rs,
|
||||
wrap.rbac.bindResource(rs),
|
||||
|
||||
@@ -2,14 +2,43 @@ package yaml
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/pkg/envoy/resource"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type (
|
||||
settings map[string]interface{}
|
||||
settings struct {
|
||||
res map[string]interface{}
|
||||
ts *resource.Timestamps
|
||||
us *resource.Userstamps
|
||||
}
|
||||
)
|
||||
|
||||
func (wrap *settings) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
if !isKind(n, yaml.MappingNode) {
|
||||
return nodeErr(n, "role definition must be a map")
|
||||
}
|
||||
|
||||
if wrap.res == nil {
|
||||
wrap.res = make(map[string]interface{})
|
||||
}
|
||||
|
||||
if err = n.Decode(&wrap.res); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if wrap.ts, err = decodeTimestamps(n); err != nil {
|
||||
return
|
||||
}
|
||||
if wrap.us, err = decodeUserstamps(n); err != nil {
|
||||
return
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (wrap settings) MarshalEnvoy() (nn []resource.Interface, err error) {
|
||||
n := resource.NewSettings(wrap)
|
||||
n := resource.NewSettings(wrap.res)
|
||||
n.SetTimestamps(wrap.ts)
|
||||
n.SetUserstamps(wrap.us)
|
||||
|
||||
return []resource.Interface{n}, nil
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ func TestSettings_UnmarshalYAML(t *testing.T) {
|
||||
doc, err := parseDocument("settings_1")
|
||||
req.NoError(err)
|
||||
req.NotNil(doc)
|
||||
req.Len(doc.settings, 20)
|
||||
req.Contains(doc.settings, "privacy.mask.email")
|
||||
req.Equal(true, doc.settings["privacy.mask.email"])
|
||||
req.Len(doc.settings.res, 20)
|
||||
req.Contains(doc.settings.res, "privacy.mask.email")
|
||||
req.Equal(true, doc.settings.res["privacy.mask.email"])
|
||||
})
|
||||
}
|
||||
|
||||
51
pkg/envoy/yaml/stamps.go
Normal file
51
pkg/envoy/yaml/stamps.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/envoy/resource"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func decodeTimestamps(n *yaml.Node) (*resource.Timestamps, error) {
|
||||
var (
|
||||
st = &resource.Timestamps{}
|
||||
)
|
||||
|
||||
return st, eachMap(n, func(k, v *yaml.Node) (err error) {
|
||||
switch strings.ToLower(k.Value) {
|
||||
case "createdat":
|
||||
return decodeScalar(v, "created at", &st.CreatedAt)
|
||||
case "updatedat":
|
||||
return decodeScalar(v, "updated at", &st.UpdatedAt)
|
||||
case "deletedat":
|
||||
return decodeScalar(v, "deleted at", &st.DeletedAt)
|
||||
case "suspendedat":
|
||||
return decodeScalar(v, "suspended at", &st.SuspendedAt)
|
||||
case "archivedat":
|
||||
return decodeScalar(v, "archived at", &st.ArchivedAt)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func decodeUserstamps(n *yaml.Node) (*resource.Userstamps, error) {
|
||||
var (
|
||||
us = &resource.Userstamps{}
|
||||
)
|
||||
|
||||
return us, eachMap(n, func(k, v *yaml.Node) (err error) {
|
||||
switch strings.ToLower(k.Value) {
|
||||
case "createdby",
|
||||
"creatorid":
|
||||
return decodeScalar(v, "created by", &us.CreatedBy)
|
||||
case "updatedby":
|
||||
return decodeScalar(v, "updated by", &us.UpdatedBy)
|
||||
case "deletedby":
|
||||
return decodeScalar(v, "deleted by", &us.DeletedBy)
|
||||
case "ownedby":
|
||||
return decodeScalar(v, "owned by", &us.OwnedBy)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -11,6 +11,7 @@ type (
|
||||
user struct {
|
||||
// when user is at least partially defined
|
||||
res *types.User `yaml:",inline"`
|
||||
ts *resource.Timestamps
|
||||
|
||||
// module's RBAC rules
|
||||
rbac rbacRuleSet
|
||||
@@ -44,7 +45,7 @@ func (wset *userSet) UnmarshalYAML(n *yaml.Node) error {
|
||||
}
|
||||
|
||||
case yaml.MappingNode:
|
||||
if err = v.Decode(&wrap.res); err != nil {
|
||||
if err = v.Decode(&wrap); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -94,11 +95,17 @@ func (wrap *user) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if wrap.ts, err = decodeTimestamps(n); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (wrap user) MarshalEnvoy() ([]resource.Interface, error) {
|
||||
rs := resource.NewUser(wrap.res)
|
||||
rs.SetTimestamps(wrap.ts)
|
||||
|
||||
return envoy.CollectNodes(
|
||||
rs,
|
||||
wrap.rbac.bindResource(rs),
|
||||
|
||||
Reference in New Issue
Block a user