diff --git a/compose/importer/chart.go b/compose/importer/chart.go index 7fdcf724f..533d56cfb 100644 --- a/compose/importer/chart.go +++ b/compose/importer/chart.go @@ -2,10 +2,8 @@ package importer import ( "context" + "errors" "fmt" - - "github.com/pkg/errors" - "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/deinterfacer" "github.com/cortezaproject/corteza-server/pkg/importer" @@ -50,7 +48,7 @@ func NewChartImporter(imp *Importer, ns *types.Namespace) *Chart { func (pImp *Chart) getModule(handle string) (*types.Module, error) { if g, ok := pImp.imp.namespaces.modules[pImp.namespace.Slug]; !ok { - return nil, errors.Errorf("could not get modules %q from non existing namespace %q", handle, pImp.namespace.Slug) + return nil, fmt.Errorf("could not get modules %q from non existing namespace %q", handle, pImp.namespace.Slug) } else { return g.Get(handle) } @@ -73,13 +71,13 @@ func (cImp *Chart) CastSet(set interface{}) error { // { : { chart } } or [ { chart }, ... ] func (cImp *Chart) Cast(handle string, def interface{}) (err error) { if !deinterfacer.IsMap(def) { - return errors.New("expecting map of values for chart") + return fmt.Errorf("expecting map of values for chart") } var chart *types.Chart if !importer.IsValidHandle(handle) { - return errors.New("invalid chart handle") + return fmt.Errorf("invalid chart handle") } handle = importer.NormalizeHandle(handle) @@ -93,7 +91,7 @@ func (cImp *Chart) Cast(handle string, def interface{}) (err error) { cImp.set = append(cImp.set, chart) } else if chart.ID == 0 { - return errors.Errorf("chart handle %q already defined in this import session", chart.Handle) + return fmt.Errorf("chart handle %q already defined in this import session", chart.Handle) } else { cImp.dirty[chart.ID] = true } @@ -187,7 +185,7 @@ func (cImp *Chart) castConfigReports(chart *types.Chart, def interface{}) ([]*ty func (cImp *Chart) Get(handle string) (*types.Chart, error) { handle = importer.NormalizeHandle(handle) if !importer.IsValidHandle(handle) { - return nil, errors.New("invalid chart handle") + return nil, fmt.Errorf("invalid chart handle") } return cImp.set.FindByHandle(handle), nil @@ -208,6 +206,10 @@ func (cImp *Chart) Store(ctx context.Context, k chartKeeper) (err error) { chart, err = k.Update(chart) } + for errors.Unwrap(err) != nil { + err = errors.Unwrap(err) + } + if err != nil { return } @@ -225,17 +227,17 @@ func (cImp *Chart) resolveRefs() error { for _, ref := range cImp.modRefs { chart := cImp.set.FindByHandle(ref.ch) if chart == nil { - return errors.Errorf("invalid reference, unknown chart (%v)", ref) + return fmt.Errorf("invalid reference, unknown chart (%v)", ref) } if ref.ri > len(chart.Config.Reports) { - return errors.Errorf("invalid reference, report index out of range (%v)", ref) + return fmt.Errorf("invalid reference, report index out of range (%v)", ref) } if module, err := cImp.getModule(ref.mh); err != nil { - return errors.Errorf("invalid reference, module loading error: %v", err) + return fmt.Errorf("invalid reference, module loading error: %v", err) } else if module == nil { - return errors.Errorf("invalid reference, unknown module (%v)", ref) + return fmt.Errorf("invalid reference, unknown module (%v)", ref) } else { chart.Config.Reports[ref.ri].ModuleID = module.ID } diff --git a/compose/importer/default.go b/compose/importer/default.go index 4c7a0e7d6..be8e486fb 100644 --- a/compose/importer/default.go +++ b/compose/importer/default.go @@ -2,15 +2,14 @@ package importer import ( "context" - "io" - - "gopkg.in/yaml.v2" - + "errors" "github.com/cortezaproject/corteza-server/compose/service" "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/permissions" "github.com/cortezaproject/corteza-server/pkg/settings" sysTypes "github.com/cortezaproject/corteza-server/system/types" + "gopkg.in/yaml.v2" + "io" ) // Import performs standard import procedure with default services @@ -52,6 +51,10 @@ func Import(ctx context.Context, ns *types.Namespace, ff ...io.Reader) (err erro err = imp.Cast(aux) } + for errors.Unwrap(err) != nil { + err = errors.Unwrap(err) + } + if err != nil { return } @@ -75,7 +78,6 @@ func Import(ctx context.Context, ns *types.Namespace, ff ...io.Reader) (err erro service.DefaultPage.With(ctx), recordService, service.DefaultAccessControl, - service.DefaultSettings, roles, ) } diff --git a/compose/importer/importer.go b/compose/importer/importer.go index 239687a65..2bf23b7c0 100644 --- a/compose/importer/importer.go +++ b/compose/importer/importer.go @@ -9,7 +9,6 @@ import ( "github.com/cortezaproject/corteza-server/pkg/deinterfacer" "github.com/cortezaproject/corteza-server/pkg/importer" "github.com/cortezaproject/corteza-server/pkg/permissions" - "github.com/cortezaproject/corteza-server/pkg/settings" sysTypes "github.com/cortezaproject/corteza-server/system/types" ) @@ -110,11 +109,6 @@ func (imp *Importer) Cast(def interface{}) (err error) { return imp.namespaces.CastSet([]interface{}{val}) } - case "settings": - if imp.settings != nil { - return imp.settings.CastSet(val) - } - case "allow", "deny": if imp.permissions != nil { return imp.permissions.CastResourcesSet(key, val) @@ -136,7 +130,6 @@ func (imp *Importer) Store( pStore pageKeeper, rStore recordKeeper, pk permissions.ImportKeeper, - sk settings.ImportKeeper, roles sysTypes.RoleSet, ) (err error) { if imp.namespaces != nil { @@ -160,12 +153,5 @@ func (imp *Importer) Store( } } - if imp.settings != nil { - err = imp.settings.Store(ctx, sk) - if err != nil { - return errors.Wrap(err, "could not import settings") - } - } - return nil } diff --git a/compose/importer/module.go b/compose/importer/module.go index de2809d1c..0551392f3 100644 --- a/compose/importer/module.go +++ b/compose/importer/module.go @@ -3,16 +3,14 @@ package importer import ( "context" "encoding/json" + "errors" "fmt" - "sort" - "strconv" - - "github.com/pkg/errors" - "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/deinterfacer" "github.com/cortezaproject/corteza-server/pkg/handle" "github.com/cortezaproject/corteza-server/pkg/importer" + "sort" + "strconv" ) type ( @@ -46,7 +44,7 @@ func NewModuleImporter(imp *Importer, ns *types.Namespace) *Module { func (pImp *Module) getPageImporter() (*Page, error) { if pi, ok := pImp.imp.namespaces.pages[pImp.namespace.Slug]; !ok { - return nil, errors.Errorf("non existing namespace %q", pImp.namespace.Slug) + return nil, fmt.Errorf("non existing namespace %q", pImp.namespace.Slug) } else { return pi, nil } @@ -69,13 +67,13 @@ func (mImp *Module) CastSet(set interface{}) error { // { : { module } } or [ { module }, ... ] func (mImp *Module) Cast(handle string, def interface{}) (err error) { if !deinterfacer.IsMap(def) { - return errors.New("expecting map of values for module") + return fmt.Errorf("expecting map of values for module") } var module *types.Module if !importer.IsValidHandle(handle) { - return errors.New("invalid module handle") + return fmt.Errorf("invalid module handle") } handle = importer.NormalizeHandle(handle) @@ -89,7 +87,7 @@ func (mImp *Module) Cast(handle string, def interface{}) (err error) { mImp.set = append(mImp.set, module) } else if module.ID == 0 { - return errors.Errorf("module handle %q already defined in this import session", module.Handle) + return fmt.Errorf("module handle %q already defined in this import session", module.Handle) } mImp.dirty[module.ID] = true @@ -222,7 +220,7 @@ func (mImp *Module) castFieldOptions(field *types.ModuleField, def interface{}) func (mImp *Module) Get(handle string) (*types.Module, error) { handle = importer.NormalizeHandle(handle) if !importer.IsValidHandle(handle) { - return nil, errors.New("invalid module handle") + return nil, fmt.Errorf("invalid module handle") } return mImp.set.FindByHandle(handle), nil @@ -240,6 +238,10 @@ func (mImp *Module) Store(ctx context.Context, k moduleKeeper) (err error) { module, err = k.Update(module) } + for errors.Unwrap(err) != nil { + err = errors.Unwrap(err) + } + if err != nil { return } @@ -258,13 +260,16 @@ func (mImp *Module) Store(ctx context.Context, k moduleKeeper) (err error) { for _, module := range mImp.set { if refs, err = mImp.resolveRefs(module); err != nil { - return errors.Wrap(err, "could not resolve refs") + return fmt.Errorf("could not resolve refs: %w", err) } else if refs >= 0 { module.UpdatedAt = nil if _, err = k.Update(module); err != nil { - return errors.Wrap(err, "could not update resolved refs") - } + for errors.Unwrap(err) != nil { + err = errors.Unwrap(err) + } + return fmt.Errorf("could not update resolved refs: %w", err) + } } } @@ -285,18 +290,18 @@ func (mImp *Module) resolveRefs(module *types.Module) (uint, error) { refHandle := deinterfacer.ToString(h) if refHandle == "" { - return errors.Errorf("empty module reference handle on module %q, field %q options", + return fmt.Errorf("empty module reference handle on module %q, field %q options", module.Handle, field.Name) } if !handle.IsValid(refHandle) { - return errors.Errorf("invalid module handle %q used for reference on module %q, field %q options", + return fmt.Errorf("invalid module handle %q used for reference on module %q, field %q options", refHandle, module.Handle, field.Name) } if refmod, err := mImp.Get(refHandle); err != nil || refmod == nil { - return errors.Errorf("could not load module %q on module %q, field %q options (err: %v)", + return fmt.Errorf("could not load module %q on module %q, field %q options: %w", refHandle, module.Handle, field.Name, err) } else { refs++ diff --git a/compose/importer/namespace.go b/compose/importer/namespace.go index b7de404ca..154adba11 100644 --- a/compose/importer/namespace.go +++ b/compose/importer/namespace.go @@ -2,9 +2,8 @@ package importer import ( "context" + "errors" "fmt" - "github.com/pkg/errors" - "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/deinterfacer" "github.com/cortezaproject/corteza-server/pkg/importer" @@ -79,13 +78,13 @@ func (nsImp *Namespace) CastSet(set interface{}) error { // { : { namespace } } or [ { namespace }, ... ] func (nsImp *Namespace) Cast(handle string, def interface{}) (err error) { if !deinterfacer.IsMap(def) { - return errors.New("expecting map of values for namespace") + return fmt.Errorf("expecting map of values for namespace") } var namespace *types.Namespace if !importer.IsValidHandle(handle) { - return errors.New("invalid namespace handle") + return fmt.Errorf("invalid namespace handle") } handle = importer.NormalizeHandle(handle) @@ -207,7 +206,7 @@ func (nsImp *Namespace) Get(handle string) (*types.Namespace, error) { handle = importer.NormalizeHandle(handle) if !importer.IsValidHandle(handle) { - return nil, errors.New("invalid namespace handle") + return nil, fmt.Errorf("invalid namespace handle") } return nsImp.set.FindByHandle(handle), nil @@ -236,6 +235,10 @@ func (nsImp *Namespace) Store(ctx context.Context, nsk namespaceKeeper, mk modul namespace, err = nsk.Update(namespace) } + for errors.Unwrap(err) != nil { + err = errors.Unwrap(err) + } + if err != nil { return } @@ -246,22 +249,22 @@ func (nsImp *Namespace) Store(ctx context.Context, nsk namespaceKeeper, mk modul if _, ok := nsImp.modules[handle]; ok { nsImp.modules[handle].namespace = namespace if err = nsImp.modules[handle].Store(ctx, mk); err != nil { - return errors.Wrap(err, "could not import modules") + return fmt.Errorf("could not import modules: %w", err) } nsImp.charts[handle].namespace = namespace if err = nsImp.charts[handle].Store(ctx, ck); err != nil { - return errors.Wrap(err, "could not import charts") + return fmt.Errorf("could not import charts: %w", err) } nsImp.pages[handle].namespace = namespace if err = nsImp.pages[handle].Store(ctx, pk); err != nil { - return errors.Wrap(err, "could not import pages") + return fmt.Errorf("could not import pages: %w", err) } nsImp.records[handle].namespace = namespace if err = nsImp.records[handle].Store(ctx, rk); err != nil { - return errors.Wrap(err, "could not import records") + return fmt.Errorf("could not import records: %w", err) } } diff --git a/compose/importer/page.go b/compose/importer/page.go index d48d8dffc..56a73f495 100644 --- a/compose/importer/page.go +++ b/compose/importer/page.go @@ -2,15 +2,13 @@ package importer import ( "context" + "errors" "fmt" - "strconv" - "strings" - - "github.com/pkg/errors" - "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/deinterfacer" "github.com/cortezaproject/corteza-server/pkg/importer" + "strconv" + "strings" ) type ( @@ -56,7 +54,7 @@ func NewPageImporter(imp *Importer, ns *types.Namespace) *Page { func (pImp *Page) getModule(handle string) (*types.Module, error) { if g, ok := pImp.imp.namespaces.modules[pImp.namespace.Slug]; !ok { - return nil, errors.Errorf("could not get modules %q from non existing namespace %q", handle, pImp.namespace.Slug) + return nil, fmt.Errorf("could not get modules %q from non existing namespace %q", handle, pImp.namespace.Slug) } else { return g.Get(handle) } @@ -64,7 +62,7 @@ func (pImp *Page) getModule(handle string) (*types.Module, error) { func (pImp *Page) getChart(handle string) (*types.Chart, error) { if g, ok := pImp.imp.namespaces.charts[pImp.namespace.Slug]; !ok { - return nil, errors.Errorf("could not get chart %q from non existing namespace %q", handle, pImp.namespace.Slug) + return nil, fmt.Errorf("could not get chart %q from non existing namespace %q", handle, pImp.namespace.Slug) } else { return g.Get(handle) } @@ -99,7 +97,7 @@ func (pImp *Page) cast(parent, handle string, def interface{}) (err error) { var page *types.Page if !importer.IsValidHandle(handle) { - return errors.New("invalid page handle") + return fmt.Errorf("invalid page handle") } handle = importer.NormalizeHandle(handle) @@ -115,7 +113,7 @@ func (pImp *Page) cast(parent, handle string, def interface{}) (err error) { pImp.set = append(pImp.set, page) } else if page.ID == 0 { - return errors.Errorf("page handle %q already defined in this import session", page.Handle) + return fmt.Errorf("page handle %q already defined in this import session", page.Handle) } else { pImp.dirty[page.ID] = true } @@ -198,7 +196,7 @@ func (pImp *Page) castBlocks(page *types.Page, def interface{}) error { case "XYWH", "xywh", "dim", "dimension": xywh := deinterfacer.ToInts(val) if len(xywh) != 4 { - return errors.New("invalid dimension (xywh) value, expecting slice with 4 integers") + return fmt.Errorf("invalid dimension (xywh) value, expecting slice with 4 integers") } block.XYWH = [4]int{xywh[0], xywh[1], xywh[2], xywh[3]} @@ -276,7 +274,7 @@ func (pImp *Page) sanitizeAutomationBlock(b types.PageBlock) types.PageBlock { func (pImp *Page) Get(handle string) (*types.Page, error) { handle = importer.NormalizeHandle(handle) if !importer.IsValidHandle(handle) { - return nil, errors.New("invalid page handle") + return nil, fmt.Errorf("invalid page handle") } return pImp.set.FindByHandle(handle), nil @@ -298,7 +296,11 @@ func (pImp *Page) Store(ctx context.Context, k pageKeeper) (err error) { // make sure we do not get stale-data error page.UpdatedAt = nil if _, err = k.Update(page); err != nil { - return errors.Wrap(err, "could not update resolved refs") + for errors.Unwrap(err) != nil { + err = errors.Unwrap(err) + } + + return fmt.Errorf("could not update resolved refs: %w", err) } } } @@ -319,7 +321,7 @@ func (pImp *Page) storeChildren(ctx context.Context, parent string, k pageKeeper if err != nil { return } else if parentPage == nil { - return errors.Errorf("could not load parent %q", parent) + return fmt.Errorf("could not load parent %q", parent) } } @@ -343,6 +345,10 @@ func (pImp *Page) storeChildren(ctx context.Context, parent string, k pageKeeper page, err = k.Update(page) } + for errors.Unwrap(err) != nil { + err = errors.Unwrap(err) + } + if err != nil { return } @@ -396,7 +402,7 @@ func (pImp *Page) resolveRefs(page *types.Page) (uint, error) { return refs, func() error { if moduleHandle, ok := pImp.modules[page.Handle]; ok { if refm, err := pImp.getModule(moduleHandle); err != nil || refm == nil { - return errors.Errorf("could not load module %q for page %q (err: %v)", + return fmt.Errorf("could not load module %q for page %q: %w", moduleHandle, page.Handle, err) } else { page.ModuleID = refm.ID @@ -415,7 +421,7 @@ func (pImp *Page) resolveRefs(page *types.Page) (uint, error) { if h, ok := b.Options["page"]; ok { if refp, err := pImp.Get(deinterfacer.ToString(h)); err != nil || refp == nil { - return errors.Errorf("could not load page %q for page %q block #%d (err: %v)", + return fmt.Errorf("could not load page %q for page %q block #%d: %w", h, page.Handle, i+1, err) } else { b.Options["pageID"] = strconv.FormatUint(refp.ID, 10) @@ -426,7 +432,7 @@ func (pImp *Page) resolveRefs(page *types.Page) (uint, error) { if h, ok := b.Options["chart"]; ok { if refc, err := pImp.getChart(deinterfacer.ToString(h)); err != nil || refc == nil { - return errors.Errorf("could not load chart %q for page %q block #%d (err: %v)", + return fmt.Errorf("could not load chart %q for page %q block #%d: %w", h, page.Handle, i+1, err) } else { b.Options["chartID"] = strconv.FormatUint(refc.ID, 10) diff --git a/compose/importer/record.go b/compose/importer/record.go index 6cf18063a..b338a8a02 100644 --- a/compose/importer/record.go +++ b/compose/importer/record.go @@ -2,10 +2,8 @@ package importer import ( "context" + "errors" "fmt" - - "github.com/pkg/errors" - "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/deinterfacer" ) @@ -44,7 +42,7 @@ func NewRecordImporter(imp *Importer, ns *types.Namespace) *Record { func (rImp *Record) getModule(handle string) (*types.Module, error) { if g, ok := rImp.imp.namespaces.modules[rImp.namespace.Slug]; !ok { - return nil, errors.Errorf("could not get modules %q from non existing namespace %q", handle, rImp.namespace.Slug) + return nil, fmt.Errorf("could not get modules %q from non existing namespace %q", handle, rImp.namespace.Slug) } else { return g.Get(handle) } @@ -62,7 +60,7 @@ func (rImp *Record) CastSet(set interface{}) error { // { : [ { record }, ... ] func (rImp *Record) Cast(moduleHandle string, def interface{}) (err error) { if !deinterfacer.IsSlice(def) { - return errors.New("expecting set of records") + return fmt.Errorf("expecting set of records") } var ( @@ -73,7 +71,7 @@ func (rImp *Record) Cast(moduleHandle string, def interface{}) (err error) { if module, err = rImp.getModule(moduleHandle); err != nil { return } else if module == nil { - return errors.Errorf("unexisting module %q", moduleHandle) + return fmt.Errorf("unexisting module %q", moduleHandle) } if _, has := rImp.set[module.Handle]; !has { @@ -151,6 +149,10 @@ func (rImp *Record) Store(ctx context.Context, k recordKeeper) (err error) { record, err = k.Update(record) } + for errors.Unwrap(err) != nil { + err = errors.Unwrap(err) + } + if err != nil { return } diff --git a/compose/service/access_control.go b/compose/service/access_control.go index 432903021..79143c336 100644 --- a/compose/service/access_control.go +++ b/compose/service/access_control.go @@ -2,9 +2,9 @@ package service import ( "context" - "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/actionlog" + "github.com/cortezaproject/corteza-server/pkg/auth" "github.com/cortezaproject/corteza-server/pkg/permissions" ) @@ -15,14 +15,15 @@ type ( } accessControlPermissionServicer interface { - Can(context.Context, permissions.Resource, permissions.Operation, ...permissions.CheckAccessFunc) bool + Can([]uint64, permissions.Resource, permissions.Operation, ...permissions.CheckAccessFunc) bool Grant(context.Context, permissions.Whitelist, ...*permissions.Rule) error FindRulesByRoleID(roleID uint64) (rr permissions.RuleSet) - ResourceFilter(context.Context, permissions.Resource, permissions.Operation, permissions.Access) *permissions.ResourceFilter + ResourceFilter([]uint64, permissions.Resource, permissions.Operation, permissions.Access) *permissions.ResourceFilter } - permissionResource interface { + secureResource interface { PermissionResource() permissions.Resource + DynamicRoles(uint64) []uint64 } ) @@ -71,7 +72,7 @@ func (svc accessControl) CanReadNamespace(ctx context.Context, r *types.Namespac } func (svc accessControl) FilterReadableNamespaces(ctx context.Context) *permissions.ResourceFilter { - return svc.permissions.ResourceFilter(ctx, types.NamespacePermissionResource, "read", permissions.Deny) + return svc.filter(ctx, types.NamespacePermissionResource, "read", permissions.Deny) } func (svc accessControl) CanUpdateNamespace(ctx context.Context, r *types.Namespace) bool { @@ -95,7 +96,7 @@ func (svc accessControl) CanReadModule(ctx context.Context, r *types.Module) boo } func (svc accessControl) FilterReadableModules(ctx context.Context) *permissions.ResourceFilter { - return svc.permissions.ResourceFilter(ctx, types.ModulePermissionResource, "read", permissions.Deny) + return svc.filter(ctx, types.ModulePermissionResource, "read", permissions.Deny) } func (svc accessControl) CanUpdateModule(ctx context.Context, r *types.Module) bool { @@ -143,7 +144,7 @@ func (svc accessControl) CanReadChart(ctx context.Context, r *types.Chart) bool } func (svc accessControl) FilterReadableCharts(ctx context.Context) *permissions.ResourceFilter { - return svc.permissions.ResourceFilter(ctx, types.ChartPermissionResource, "read", permissions.Deny) + return svc.filter(ctx, types.ChartPermissionResource, "read", permissions.Deny) } func (svc accessControl) CanUpdateChart(ctx context.Context, r *types.Chart) bool { @@ -164,7 +165,7 @@ func (svc accessControl) CanReadPage(ctx context.Context, r *types.Page) bool { } func (svc accessControl) FilterReadablePages(ctx context.Context) *permissions.ResourceFilter { - return svc.permissions.ResourceFilter(ctx, types.PagePermissionResource, "read", permissions.Deny) + return svc.filter(ctx, types.PagePermissionResource, "read", permissions.Deny) } func (svc accessControl) CanUpdatePage(ctx context.Context, r *types.Page) bool { @@ -175,8 +176,40 @@ func (svc accessControl) CanDeletePage(ctx context.Context, r *types.Page) bool return svc.can(ctx, r, "delete") } -func (svc accessControl) can(ctx context.Context, res permissionResource, op permissions.Operation, ff ...permissions.CheckAccessFunc) bool { - return svc.permissions.Can(ctx, res.PermissionResource(), op, ff...) +func (svc accessControl) can(ctx context.Context, res secureResource, op permissions.Operation, ff ...permissions.CheckAccessFunc) bool { + var u = auth.GetIdentityFromContext(ctx) + + if auth.IsSuperUser(u) { + // Temp solution to allow migration from passing context to ResourceFilter + // and checking "superuser" privileges there to more sustainable solution + // (eg: creating super-role with allow-all) + return true + } + + return svc.permissions.Can( + append(u.Roles(), res.DynamicRoles(u.Identity())...), + res.PermissionResource(), + op, + ff..., + ) +} + +func (svc accessControl) filter(ctx context.Context, res permissions.Resource, op permissions.Operation, a permissions.Access) *permissions.ResourceFilter { + var u = auth.GetIdentityFromContext(ctx) + + if auth.IsSuperUser(u) { + // Temp solution to allow migration from passing context to ResourceFilter + //and checking "superuser" privileges there + // to more sustainable solution (eg: creating super-role with allow-all) + return permissions.NewSuperuserFilter() + } + + return svc.permissions.ResourceFilter( + append(u.Roles(), res.DynamicRoles(u.Identity())...), + res, + op, + a, + ) } func (svc accessControl) Grant(ctx context.Context, rr ...*permissions.Rule) error { diff --git a/compose/service/access_control_actions.gen.go b/compose/service/access_control_actions.gen.go index a8e225817..5aa3c6f80 100644 --- a/compose/service/access_control_actions.gen.go +++ b/compose/service/access_control_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from compose/service/access_control_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// compose/service/access_control_actions.yaml import ( "context" diff --git a/compose/service/attachment_actions.gen.go b/compose/service/attachment_actions.gen.go index e42346e6e..12338051f 100644 --- a/compose/service/attachment_actions.gen.go +++ b/compose/service/attachment_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from compose/service/attachment_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// compose/service/attachment_actions.yaml import ( "context" diff --git a/compose/service/chart_actions.gen.go b/compose/service/chart_actions.gen.go index 5142ad2db..63fdaa7e9 100644 --- a/compose/service/chart_actions.gen.go +++ b/compose/service/chart_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from compose/service/chart_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// compose/service/chart_actions.yaml import ( "context" diff --git a/compose/service/event/compose.gen.go b/compose/service/event/compose.gen.go deleted file mode 100644 index ad1f638ca..000000000 --- a/compose/service/event/compose.gen.go +++ /dev/null @@ -1,188 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// compose/service/event/events.yaml -// -// Regenerate with: -// go run codegen/v2/events.go --service compose -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // composeBase - // - // This type is auto-generated. - composeBase struct { - immutable bool - invoker auth.Identifiable - } - - // composeOnManual - // - // This type is auto-generated. - composeOnManual struct { - *composeBase - } - - // composeOnInterval - // - // This type is auto-generated. - composeOnInterval struct { - *composeBase - } - - // composeOnTimestamp - // - // This type is auto-generated. - composeOnTimestamp struct { - *composeBase - } -) - -// ResourceType returns "compose" -// -// This function is auto-generated. -func (composeBase) ResourceType() string { - return "compose" -} - -// EventType on composeOnManual returns "onManual" -// -// This function is auto-generated. -func (composeOnManual) EventType() string { - return "onManual" -} - -// EventType on composeOnInterval returns "onInterval" -// -// This function is auto-generated. -func (composeOnInterval) EventType() string { - return "onInterval" -} - -// EventType on composeOnTimestamp returns "onTimestamp" -// -// This function is auto-generated. -func (composeOnTimestamp) EventType() string { - return "onTimestamp" -} - -// ComposeOnManual creates onManual for compose resource -// -// This function is auto-generated. -func ComposeOnManual() *composeOnManual { - return &composeOnManual{ - composeBase: &composeBase{ - immutable: false, - }, - } -} - -// ComposeOnManualImmutable creates onManual for compose resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ComposeOnManualImmutable() *composeOnManual { - return &composeOnManual{ - composeBase: &composeBase{ - immutable: true, - }, - } -} - -// ComposeOnInterval creates onInterval for compose resource -// -// This function is auto-generated. -func ComposeOnInterval() *composeOnInterval { - return &composeOnInterval{ - composeBase: &composeBase{ - immutable: false, - }, - } -} - -// ComposeOnIntervalImmutable creates onInterval for compose resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ComposeOnIntervalImmutable() *composeOnInterval { - return &composeOnInterval{ - composeBase: &composeBase{ - immutable: true, - }, - } -} - -// ComposeOnTimestamp creates onTimestamp for compose resource -// -// This function is auto-generated. -func ComposeOnTimestamp() *composeOnTimestamp { - return &composeOnTimestamp{ - composeBase: &composeBase{ - immutable: false, - }, - } -} - -// ComposeOnTimestampImmutable creates onTimestamp for compose resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ComposeOnTimestampImmutable() *composeOnTimestamp { - return &composeOnTimestamp{ - composeBase: &composeBase{ - immutable: true, - }, - } -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *composeBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res composeBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res composeBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *composeBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/compose/service/event/events.gen.go b/compose/service/event/events.gen.go new file mode 100644 index 000000000..217f091eb --- /dev/null +++ b/compose/service/event/events.gen.go @@ -0,0 +1,2238 @@ +package event + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// compose/service/event/events.yaml + +import ( + "encoding/json" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/pkg/auth" +) + +// dummy placing to simplify import generation logic +var _ = json.NewEncoder + +type ( + + // composeBase + // + // This type is auto-generated. + composeBase struct { + immutable bool + invoker auth.Identifiable + } + + // composeOnManual + // + // This type is auto-generated. + composeOnManual struct { + *composeBase + } + + // composeOnInterval + // + // This type is auto-generated. + composeOnInterval struct { + *composeBase + } + + // composeOnTimestamp + // + // This type is auto-generated. + composeOnTimestamp struct { + *composeBase + } + + // moduleBase + // + // This type is auto-generated. + moduleBase struct { + immutable bool + module *types.Module + oldModule *types.Module + namespace *types.Namespace + invoker auth.Identifiable + } + + // moduleOnManual + // + // This type is auto-generated. + moduleOnManual struct { + *moduleBase + } + + // moduleBeforeCreate + // + // This type is auto-generated. + moduleBeforeCreate struct { + *moduleBase + } + + // moduleBeforeUpdate + // + // This type is auto-generated. + moduleBeforeUpdate struct { + *moduleBase + } + + // moduleBeforeDelete + // + // This type is auto-generated. + moduleBeforeDelete struct { + *moduleBase + } + + // moduleAfterCreate + // + // This type is auto-generated. + moduleAfterCreate struct { + *moduleBase + } + + // moduleAfterUpdate + // + // This type is auto-generated. + moduleAfterUpdate struct { + *moduleBase + } + + // moduleAfterDelete + // + // This type is auto-generated. + moduleAfterDelete struct { + *moduleBase + } + + // namespaceBase + // + // This type is auto-generated. + namespaceBase struct { + immutable bool + namespace *types.Namespace + oldNamespace *types.Namespace + invoker auth.Identifiable + } + + // namespaceOnManual + // + // This type is auto-generated. + namespaceOnManual struct { + *namespaceBase + } + + // namespaceBeforeCreate + // + // This type is auto-generated. + namespaceBeforeCreate struct { + *namespaceBase + } + + // namespaceBeforeUpdate + // + // This type is auto-generated. + namespaceBeforeUpdate struct { + *namespaceBase + } + + // namespaceBeforeDelete + // + // This type is auto-generated. + namespaceBeforeDelete struct { + *namespaceBase + } + + // namespaceAfterCreate + // + // This type is auto-generated. + namespaceAfterCreate struct { + *namespaceBase + } + + // namespaceAfterUpdate + // + // This type is auto-generated. + namespaceAfterUpdate struct { + *namespaceBase + } + + // namespaceAfterDelete + // + // This type is auto-generated. + namespaceAfterDelete struct { + *namespaceBase + } + + // pageBase + // + // This type is auto-generated. + pageBase struct { + immutable bool + page *types.Page + oldPage *types.Page + namespace *types.Namespace + invoker auth.Identifiable + } + + // pageOnManual + // + // This type is auto-generated. + pageOnManual struct { + *pageBase + } + + // pageBeforeCreate + // + // This type is auto-generated. + pageBeforeCreate struct { + *pageBase + } + + // pageBeforeUpdate + // + // This type is auto-generated. + pageBeforeUpdate struct { + *pageBase + } + + // pageBeforeDelete + // + // This type is auto-generated. + pageBeforeDelete struct { + *pageBase + } + + // pageAfterCreate + // + // This type is auto-generated. + pageAfterCreate struct { + *pageBase + } + + // pageAfterUpdate + // + // This type is auto-generated. + pageAfterUpdate struct { + *pageBase + } + + // pageAfterDelete + // + // This type is auto-generated. + pageAfterDelete struct { + *pageBase + } + + // recordBase + // + // This type is auto-generated. + recordBase struct { + immutable bool + record *types.Record + oldRecord *types.Record + module *types.Module + namespace *types.Namespace + recordValueErrors *types.RecordValueErrorSet + invoker auth.Identifiable + } + + // recordOnManual + // + // This type is auto-generated. + recordOnManual struct { + *recordBase + } + + // recordOnIteration + // + // This type is auto-generated. + recordOnIteration struct { + *recordBase + } + + // recordBeforeCreate + // + // This type is auto-generated. + recordBeforeCreate struct { + *recordBase + } + + // recordBeforeUpdate + // + // This type is auto-generated. + recordBeforeUpdate struct { + *recordBase + } + + // recordBeforeDelete + // + // This type is auto-generated. + recordBeforeDelete struct { + *recordBase + } + + // recordAfterCreate + // + // This type is auto-generated. + recordAfterCreate struct { + *recordBase + } + + // recordAfterUpdate + // + // This type is auto-generated. + recordAfterUpdate struct { + *recordBase + } + + // recordAfterDelete + // + // This type is auto-generated. + recordAfterDelete struct { + *recordBase + } +) + +// ResourceType returns "compose" +// +// This function is auto-generated. +func (composeBase) ResourceType() string { + return "compose" +} + +// EventType on composeOnManual returns "onManual" +// +// This function is auto-generated. +func (composeOnManual) EventType() string { + return "onManual" +} + +// EventType on composeOnInterval returns "onInterval" +// +// This function is auto-generated. +func (composeOnInterval) EventType() string { + return "onInterval" +} + +// EventType on composeOnTimestamp returns "onTimestamp" +// +// This function is auto-generated. +func (composeOnTimestamp) EventType() string { + return "onTimestamp" +} + +// ComposeOnManual creates onManual for compose resource +// +// This function is auto-generated. +func ComposeOnManual() *composeOnManual { + return &composeOnManual{ + composeBase: &composeBase{ + immutable: false, + }, + } +} + +// ComposeOnManualImmutable creates onManual for compose resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ComposeOnManualImmutable() *composeOnManual { + return &composeOnManual{ + composeBase: &composeBase{ + immutable: true, + }, + } +} + +// ComposeOnInterval creates onInterval for compose resource +// +// This function is auto-generated. +func ComposeOnInterval() *composeOnInterval { + return &composeOnInterval{ + composeBase: &composeBase{ + immutable: false, + }, + } +} + +// ComposeOnIntervalImmutable creates onInterval for compose resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ComposeOnIntervalImmutable() *composeOnInterval { + return &composeOnInterval{ + composeBase: &composeBase{ + immutable: true, + }, + } +} + +// ComposeOnTimestamp creates onTimestamp for compose resource +// +// This function is auto-generated. +func ComposeOnTimestamp() *composeOnTimestamp { + return &composeOnTimestamp{ + composeBase: &composeBase{ + immutable: false, + }, + } +} + +// ComposeOnTimestampImmutable creates onTimestamp for compose resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ComposeOnTimestampImmutable() *composeOnTimestamp { + return &composeOnTimestamp{ + composeBase: &composeBase{ + immutable: true, + }, + } +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *composeBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res composeBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res composeBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *composeBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} + +// ResourceType returns "compose:module" +// +// This function is auto-generated. +func (moduleBase) ResourceType() string { + return "compose:module" +} + +// EventType on moduleOnManual returns "onManual" +// +// This function is auto-generated. +func (moduleOnManual) EventType() string { + return "onManual" +} + +// EventType on moduleBeforeCreate returns "beforeCreate" +// +// This function is auto-generated. +func (moduleBeforeCreate) EventType() string { + return "beforeCreate" +} + +// EventType on moduleBeforeUpdate returns "beforeUpdate" +// +// This function is auto-generated. +func (moduleBeforeUpdate) EventType() string { + return "beforeUpdate" +} + +// EventType on moduleBeforeDelete returns "beforeDelete" +// +// This function is auto-generated. +func (moduleBeforeDelete) EventType() string { + return "beforeDelete" +} + +// EventType on moduleAfterCreate returns "afterCreate" +// +// This function is auto-generated. +func (moduleAfterCreate) EventType() string { + return "afterCreate" +} + +// EventType on moduleAfterUpdate returns "afterUpdate" +// +// This function is auto-generated. +func (moduleAfterUpdate) EventType() string { + return "afterUpdate" +} + +// EventType on moduleAfterDelete returns "afterDelete" +// +// This function is auto-generated. +func (moduleAfterDelete) EventType() string { + return "afterDelete" +} + +// ModuleOnManual creates onManual for compose:module resource +// +// This function is auto-generated. +func ModuleOnManual( + argModule *types.Module, + argOldModule *types.Module, + argNamespace *types.Namespace, +) *moduleOnManual { + return &moduleOnManual{ + moduleBase: &moduleBase{ + immutable: false, + module: argModule, + oldModule: argOldModule, + namespace: argNamespace, + }, + } +} + +// ModuleOnManualImmutable creates onManual for compose:module resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ModuleOnManualImmutable( + argModule *types.Module, + argOldModule *types.Module, + argNamespace *types.Namespace, +) *moduleOnManual { + return &moduleOnManual{ + moduleBase: &moduleBase{ + immutable: true, + module: argModule, + oldModule: argOldModule, + namespace: argNamespace, + }, + } +} + +// ModuleBeforeCreate creates beforeCreate for compose:module resource +// +// This function is auto-generated. +func ModuleBeforeCreate( + argModule *types.Module, + argOldModule *types.Module, + argNamespace *types.Namespace, +) *moduleBeforeCreate { + return &moduleBeforeCreate{ + moduleBase: &moduleBase{ + immutable: false, + module: argModule, + oldModule: argOldModule, + namespace: argNamespace, + }, + } +} + +// ModuleBeforeCreateImmutable creates beforeCreate for compose:module resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ModuleBeforeCreateImmutable( + argModule *types.Module, + argOldModule *types.Module, + argNamespace *types.Namespace, +) *moduleBeforeCreate { + return &moduleBeforeCreate{ + moduleBase: &moduleBase{ + immutable: true, + module: argModule, + oldModule: argOldModule, + namespace: argNamespace, + }, + } +} + +// ModuleBeforeUpdate creates beforeUpdate for compose:module resource +// +// This function is auto-generated. +func ModuleBeforeUpdate( + argModule *types.Module, + argOldModule *types.Module, + argNamespace *types.Namespace, +) *moduleBeforeUpdate { + return &moduleBeforeUpdate{ + moduleBase: &moduleBase{ + immutable: false, + module: argModule, + oldModule: argOldModule, + namespace: argNamespace, + }, + } +} + +// ModuleBeforeUpdateImmutable creates beforeUpdate for compose:module resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ModuleBeforeUpdateImmutable( + argModule *types.Module, + argOldModule *types.Module, + argNamespace *types.Namespace, +) *moduleBeforeUpdate { + return &moduleBeforeUpdate{ + moduleBase: &moduleBase{ + immutable: true, + module: argModule, + oldModule: argOldModule, + namespace: argNamespace, + }, + } +} + +// ModuleBeforeDelete creates beforeDelete for compose:module resource +// +// This function is auto-generated. +func ModuleBeforeDelete( + argModule *types.Module, + argOldModule *types.Module, + argNamespace *types.Namespace, +) *moduleBeforeDelete { + return &moduleBeforeDelete{ + moduleBase: &moduleBase{ + immutable: false, + module: argModule, + oldModule: argOldModule, + namespace: argNamespace, + }, + } +} + +// ModuleBeforeDeleteImmutable creates beforeDelete for compose:module resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ModuleBeforeDeleteImmutable( + argModule *types.Module, + argOldModule *types.Module, + argNamespace *types.Namespace, +) *moduleBeforeDelete { + return &moduleBeforeDelete{ + moduleBase: &moduleBase{ + immutable: true, + module: argModule, + oldModule: argOldModule, + namespace: argNamespace, + }, + } +} + +// ModuleAfterCreate creates afterCreate for compose:module resource +// +// This function is auto-generated. +func ModuleAfterCreate( + argModule *types.Module, + argOldModule *types.Module, + argNamespace *types.Namespace, +) *moduleAfterCreate { + return &moduleAfterCreate{ + moduleBase: &moduleBase{ + immutable: false, + module: argModule, + oldModule: argOldModule, + namespace: argNamespace, + }, + } +} + +// ModuleAfterCreateImmutable creates afterCreate for compose:module resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ModuleAfterCreateImmutable( + argModule *types.Module, + argOldModule *types.Module, + argNamespace *types.Namespace, +) *moduleAfterCreate { + return &moduleAfterCreate{ + moduleBase: &moduleBase{ + immutable: true, + module: argModule, + oldModule: argOldModule, + namespace: argNamespace, + }, + } +} + +// ModuleAfterUpdate creates afterUpdate for compose:module resource +// +// This function is auto-generated. +func ModuleAfterUpdate( + argModule *types.Module, + argOldModule *types.Module, + argNamespace *types.Namespace, +) *moduleAfterUpdate { + return &moduleAfterUpdate{ + moduleBase: &moduleBase{ + immutable: false, + module: argModule, + oldModule: argOldModule, + namespace: argNamespace, + }, + } +} + +// ModuleAfterUpdateImmutable creates afterUpdate for compose:module resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ModuleAfterUpdateImmutable( + argModule *types.Module, + argOldModule *types.Module, + argNamespace *types.Namespace, +) *moduleAfterUpdate { + return &moduleAfterUpdate{ + moduleBase: &moduleBase{ + immutable: true, + module: argModule, + oldModule: argOldModule, + namespace: argNamespace, + }, + } +} + +// ModuleAfterDelete creates afterDelete for compose:module resource +// +// This function is auto-generated. +func ModuleAfterDelete( + argModule *types.Module, + argOldModule *types.Module, + argNamespace *types.Namespace, +) *moduleAfterDelete { + return &moduleAfterDelete{ + moduleBase: &moduleBase{ + immutable: false, + module: argModule, + oldModule: argOldModule, + namespace: argNamespace, + }, + } +} + +// ModuleAfterDeleteImmutable creates afterDelete for compose:module resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ModuleAfterDeleteImmutable( + argModule *types.Module, + argOldModule *types.Module, + argNamespace *types.Namespace, +) *moduleAfterDelete { + return &moduleAfterDelete{ + moduleBase: &moduleBase{ + immutable: true, + module: argModule, + oldModule: argOldModule, + namespace: argNamespace, + }, + } +} + +// SetModule sets new module value +// +// This function is auto-generated. +func (res *moduleBase) SetModule(argModule *types.Module) { + res.module = argModule +} + +// Module returns module +// +// This function is auto-generated. +func (res moduleBase) Module() *types.Module { + return res.module +} + +// OldModule returns oldModule +// +// This function is auto-generated. +func (res moduleBase) OldModule() *types.Module { + return res.oldModule +} + +// Namespace returns namespace +// +// This function is auto-generated. +func (res moduleBase) Namespace() *types.Namespace { + return res.namespace +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *moduleBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res moduleBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res moduleBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["module"], err = json.Marshal(res.module); err != nil { + return nil, err + } + + if args["oldModule"], err = json.Marshal(res.oldModule); err != nil { + return nil, err + } + + if args["namespace"], err = json.Marshal(res.namespace); err != nil { + return nil, err + } + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *moduleBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.module != nil { + if r, ok := results["result"]; ok && len(results) == 1 { + if err = json.Unmarshal(r, res.module); err != nil { + return + } + } + } + + if res.module != nil { + if r, ok := results["module"]; ok { + if err = json.Unmarshal(r, res.module); err != nil { + return + } + } + } + + // Do not decode oldModule; marked as immutable + + // Do not decode namespace; marked as immutable + + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} + +// ResourceType returns "compose:namespace" +// +// This function is auto-generated. +func (namespaceBase) ResourceType() string { + return "compose:namespace" +} + +// EventType on namespaceOnManual returns "onManual" +// +// This function is auto-generated. +func (namespaceOnManual) EventType() string { + return "onManual" +} + +// EventType on namespaceBeforeCreate returns "beforeCreate" +// +// This function is auto-generated. +func (namespaceBeforeCreate) EventType() string { + return "beforeCreate" +} + +// EventType on namespaceBeforeUpdate returns "beforeUpdate" +// +// This function is auto-generated. +func (namespaceBeforeUpdate) EventType() string { + return "beforeUpdate" +} + +// EventType on namespaceBeforeDelete returns "beforeDelete" +// +// This function is auto-generated. +func (namespaceBeforeDelete) EventType() string { + return "beforeDelete" +} + +// EventType on namespaceAfterCreate returns "afterCreate" +// +// This function is auto-generated. +func (namespaceAfterCreate) EventType() string { + return "afterCreate" +} + +// EventType on namespaceAfterUpdate returns "afterUpdate" +// +// This function is auto-generated. +func (namespaceAfterUpdate) EventType() string { + return "afterUpdate" +} + +// EventType on namespaceAfterDelete returns "afterDelete" +// +// This function is auto-generated. +func (namespaceAfterDelete) EventType() string { + return "afterDelete" +} + +// NamespaceOnManual creates onManual for compose:namespace resource +// +// This function is auto-generated. +func NamespaceOnManual( + argNamespace *types.Namespace, + argOldNamespace *types.Namespace, +) *namespaceOnManual { + return &namespaceOnManual{ + namespaceBase: &namespaceBase{ + immutable: false, + namespace: argNamespace, + oldNamespace: argOldNamespace, + }, + } +} + +// NamespaceOnManualImmutable creates onManual for compose:namespace resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func NamespaceOnManualImmutable( + argNamespace *types.Namespace, + argOldNamespace *types.Namespace, +) *namespaceOnManual { + return &namespaceOnManual{ + namespaceBase: &namespaceBase{ + immutable: true, + namespace: argNamespace, + oldNamespace: argOldNamespace, + }, + } +} + +// NamespaceBeforeCreate creates beforeCreate for compose:namespace resource +// +// This function is auto-generated. +func NamespaceBeforeCreate( + argNamespace *types.Namespace, + argOldNamespace *types.Namespace, +) *namespaceBeforeCreate { + return &namespaceBeforeCreate{ + namespaceBase: &namespaceBase{ + immutable: false, + namespace: argNamespace, + oldNamespace: argOldNamespace, + }, + } +} + +// NamespaceBeforeCreateImmutable creates beforeCreate for compose:namespace resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func NamespaceBeforeCreateImmutable( + argNamespace *types.Namespace, + argOldNamespace *types.Namespace, +) *namespaceBeforeCreate { + return &namespaceBeforeCreate{ + namespaceBase: &namespaceBase{ + immutable: true, + namespace: argNamespace, + oldNamespace: argOldNamespace, + }, + } +} + +// NamespaceBeforeUpdate creates beforeUpdate for compose:namespace resource +// +// This function is auto-generated. +func NamespaceBeforeUpdate( + argNamespace *types.Namespace, + argOldNamespace *types.Namespace, +) *namespaceBeforeUpdate { + return &namespaceBeforeUpdate{ + namespaceBase: &namespaceBase{ + immutable: false, + namespace: argNamespace, + oldNamespace: argOldNamespace, + }, + } +} + +// NamespaceBeforeUpdateImmutable creates beforeUpdate for compose:namespace resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func NamespaceBeforeUpdateImmutable( + argNamespace *types.Namespace, + argOldNamespace *types.Namespace, +) *namespaceBeforeUpdate { + return &namespaceBeforeUpdate{ + namespaceBase: &namespaceBase{ + immutable: true, + namespace: argNamespace, + oldNamespace: argOldNamespace, + }, + } +} + +// NamespaceBeforeDelete creates beforeDelete for compose:namespace resource +// +// This function is auto-generated. +func NamespaceBeforeDelete( + argNamespace *types.Namespace, + argOldNamespace *types.Namespace, +) *namespaceBeforeDelete { + return &namespaceBeforeDelete{ + namespaceBase: &namespaceBase{ + immutable: false, + namespace: argNamespace, + oldNamespace: argOldNamespace, + }, + } +} + +// NamespaceBeforeDeleteImmutable creates beforeDelete for compose:namespace resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func NamespaceBeforeDeleteImmutable( + argNamespace *types.Namespace, + argOldNamespace *types.Namespace, +) *namespaceBeforeDelete { + return &namespaceBeforeDelete{ + namespaceBase: &namespaceBase{ + immutable: true, + namespace: argNamespace, + oldNamespace: argOldNamespace, + }, + } +} + +// NamespaceAfterCreate creates afterCreate for compose:namespace resource +// +// This function is auto-generated. +func NamespaceAfterCreate( + argNamespace *types.Namespace, + argOldNamespace *types.Namespace, +) *namespaceAfterCreate { + return &namespaceAfterCreate{ + namespaceBase: &namespaceBase{ + immutable: false, + namespace: argNamespace, + oldNamespace: argOldNamespace, + }, + } +} + +// NamespaceAfterCreateImmutable creates afterCreate for compose:namespace resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func NamespaceAfterCreateImmutable( + argNamespace *types.Namespace, + argOldNamespace *types.Namespace, +) *namespaceAfterCreate { + return &namespaceAfterCreate{ + namespaceBase: &namespaceBase{ + immutable: true, + namespace: argNamespace, + oldNamespace: argOldNamespace, + }, + } +} + +// NamespaceAfterUpdate creates afterUpdate for compose:namespace resource +// +// This function is auto-generated. +func NamespaceAfterUpdate( + argNamespace *types.Namespace, + argOldNamespace *types.Namespace, +) *namespaceAfterUpdate { + return &namespaceAfterUpdate{ + namespaceBase: &namespaceBase{ + immutable: false, + namespace: argNamespace, + oldNamespace: argOldNamespace, + }, + } +} + +// NamespaceAfterUpdateImmutable creates afterUpdate for compose:namespace resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func NamespaceAfterUpdateImmutable( + argNamespace *types.Namespace, + argOldNamespace *types.Namespace, +) *namespaceAfterUpdate { + return &namespaceAfterUpdate{ + namespaceBase: &namespaceBase{ + immutable: true, + namespace: argNamespace, + oldNamespace: argOldNamespace, + }, + } +} + +// NamespaceAfterDelete creates afterDelete for compose:namespace resource +// +// This function is auto-generated. +func NamespaceAfterDelete( + argNamespace *types.Namespace, + argOldNamespace *types.Namespace, +) *namespaceAfterDelete { + return &namespaceAfterDelete{ + namespaceBase: &namespaceBase{ + immutable: false, + namespace: argNamespace, + oldNamespace: argOldNamespace, + }, + } +} + +// NamespaceAfterDeleteImmutable creates afterDelete for compose:namespace resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func NamespaceAfterDeleteImmutable( + argNamespace *types.Namespace, + argOldNamespace *types.Namespace, +) *namespaceAfterDelete { + return &namespaceAfterDelete{ + namespaceBase: &namespaceBase{ + immutable: true, + namespace: argNamespace, + oldNamespace: argOldNamespace, + }, + } +} + +// SetNamespace sets new namespace value +// +// This function is auto-generated. +func (res *namespaceBase) SetNamespace(argNamespace *types.Namespace) { + res.namespace = argNamespace +} + +// Namespace returns namespace +// +// This function is auto-generated. +func (res namespaceBase) Namespace() *types.Namespace { + return res.namespace +} + +// OldNamespace returns oldNamespace +// +// This function is auto-generated. +func (res namespaceBase) OldNamespace() *types.Namespace { + return res.oldNamespace +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *namespaceBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res namespaceBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res namespaceBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["namespace"], err = json.Marshal(res.namespace); err != nil { + return nil, err + } + + if args["oldNamespace"], err = json.Marshal(res.oldNamespace); err != nil { + return nil, err + } + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *namespaceBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.namespace != nil { + if r, ok := results["result"]; ok && len(results) == 1 { + if err = json.Unmarshal(r, res.namespace); err != nil { + return + } + } + } + + if res.namespace != nil { + if r, ok := results["namespace"]; ok { + if err = json.Unmarshal(r, res.namespace); err != nil { + return + } + } + } + + // Do not decode oldNamespace; marked as immutable + + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} + +// ResourceType returns "compose:page" +// +// This function is auto-generated. +func (pageBase) ResourceType() string { + return "compose:page" +} + +// EventType on pageOnManual returns "onManual" +// +// This function is auto-generated. +func (pageOnManual) EventType() string { + return "onManual" +} + +// EventType on pageBeforeCreate returns "beforeCreate" +// +// This function is auto-generated. +func (pageBeforeCreate) EventType() string { + return "beforeCreate" +} + +// EventType on pageBeforeUpdate returns "beforeUpdate" +// +// This function is auto-generated. +func (pageBeforeUpdate) EventType() string { + return "beforeUpdate" +} + +// EventType on pageBeforeDelete returns "beforeDelete" +// +// This function is auto-generated. +func (pageBeforeDelete) EventType() string { + return "beforeDelete" +} + +// EventType on pageAfterCreate returns "afterCreate" +// +// This function is auto-generated. +func (pageAfterCreate) EventType() string { + return "afterCreate" +} + +// EventType on pageAfterUpdate returns "afterUpdate" +// +// This function is auto-generated. +func (pageAfterUpdate) EventType() string { + return "afterUpdate" +} + +// EventType on pageAfterDelete returns "afterDelete" +// +// This function is auto-generated. +func (pageAfterDelete) EventType() string { + return "afterDelete" +} + +// PageOnManual creates onManual for compose:page resource +// +// This function is auto-generated. +func PageOnManual( + argPage *types.Page, + argOldPage *types.Page, + argNamespace *types.Namespace, +) *pageOnManual { + return &pageOnManual{ + pageBase: &pageBase{ + immutable: false, + page: argPage, + oldPage: argOldPage, + namespace: argNamespace, + }, + } +} + +// PageOnManualImmutable creates onManual for compose:page resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func PageOnManualImmutable( + argPage *types.Page, + argOldPage *types.Page, + argNamespace *types.Namespace, +) *pageOnManual { + return &pageOnManual{ + pageBase: &pageBase{ + immutable: true, + page: argPage, + oldPage: argOldPage, + namespace: argNamespace, + }, + } +} + +// PageBeforeCreate creates beforeCreate for compose:page resource +// +// This function is auto-generated. +func PageBeforeCreate( + argPage *types.Page, + argOldPage *types.Page, + argNamespace *types.Namespace, +) *pageBeforeCreate { + return &pageBeforeCreate{ + pageBase: &pageBase{ + immutable: false, + page: argPage, + oldPage: argOldPage, + namespace: argNamespace, + }, + } +} + +// PageBeforeCreateImmutable creates beforeCreate for compose:page resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func PageBeforeCreateImmutable( + argPage *types.Page, + argOldPage *types.Page, + argNamespace *types.Namespace, +) *pageBeforeCreate { + return &pageBeforeCreate{ + pageBase: &pageBase{ + immutable: true, + page: argPage, + oldPage: argOldPage, + namespace: argNamespace, + }, + } +} + +// PageBeforeUpdate creates beforeUpdate for compose:page resource +// +// This function is auto-generated. +func PageBeforeUpdate( + argPage *types.Page, + argOldPage *types.Page, + argNamespace *types.Namespace, +) *pageBeforeUpdate { + return &pageBeforeUpdate{ + pageBase: &pageBase{ + immutable: false, + page: argPage, + oldPage: argOldPage, + namespace: argNamespace, + }, + } +} + +// PageBeforeUpdateImmutable creates beforeUpdate for compose:page resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func PageBeforeUpdateImmutable( + argPage *types.Page, + argOldPage *types.Page, + argNamespace *types.Namespace, +) *pageBeforeUpdate { + return &pageBeforeUpdate{ + pageBase: &pageBase{ + immutable: true, + page: argPage, + oldPage: argOldPage, + namespace: argNamespace, + }, + } +} + +// PageBeforeDelete creates beforeDelete for compose:page resource +// +// This function is auto-generated. +func PageBeforeDelete( + argPage *types.Page, + argOldPage *types.Page, + argNamespace *types.Namespace, +) *pageBeforeDelete { + return &pageBeforeDelete{ + pageBase: &pageBase{ + immutable: false, + page: argPage, + oldPage: argOldPage, + namespace: argNamespace, + }, + } +} + +// PageBeforeDeleteImmutable creates beforeDelete for compose:page resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func PageBeforeDeleteImmutable( + argPage *types.Page, + argOldPage *types.Page, + argNamespace *types.Namespace, +) *pageBeforeDelete { + return &pageBeforeDelete{ + pageBase: &pageBase{ + immutable: true, + page: argPage, + oldPage: argOldPage, + namespace: argNamespace, + }, + } +} + +// PageAfterCreate creates afterCreate for compose:page resource +// +// This function is auto-generated. +func PageAfterCreate( + argPage *types.Page, + argOldPage *types.Page, + argNamespace *types.Namespace, +) *pageAfterCreate { + return &pageAfterCreate{ + pageBase: &pageBase{ + immutable: false, + page: argPage, + oldPage: argOldPage, + namespace: argNamespace, + }, + } +} + +// PageAfterCreateImmutable creates afterCreate for compose:page resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func PageAfterCreateImmutable( + argPage *types.Page, + argOldPage *types.Page, + argNamespace *types.Namespace, +) *pageAfterCreate { + return &pageAfterCreate{ + pageBase: &pageBase{ + immutable: true, + page: argPage, + oldPage: argOldPage, + namespace: argNamespace, + }, + } +} + +// PageAfterUpdate creates afterUpdate for compose:page resource +// +// This function is auto-generated. +func PageAfterUpdate( + argPage *types.Page, + argOldPage *types.Page, + argNamespace *types.Namespace, +) *pageAfterUpdate { + return &pageAfterUpdate{ + pageBase: &pageBase{ + immutable: false, + page: argPage, + oldPage: argOldPage, + namespace: argNamespace, + }, + } +} + +// PageAfterUpdateImmutable creates afterUpdate for compose:page resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func PageAfterUpdateImmutable( + argPage *types.Page, + argOldPage *types.Page, + argNamespace *types.Namespace, +) *pageAfterUpdate { + return &pageAfterUpdate{ + pageBase: &pageBase{ + immutable: true, + page: argPage, + oldPage: argOldPage, + namespace: argNamespace, + }, + } +} + +// PageAfterDelete creates afterDelete for compose:page resource +// +// This function is auto-generated. +func PageAfterDelete( + argPage *types.Page, + argOldPage *types.Page, + argNamespace *types.Namespace, +) *pageAfterDelete { + return &pageAfterDelete{ + pageBase: &pageBase{ + immutable: false, + page: argPage, + oldPage: argOldPage, + namespace: argNamespace, + }, + } +} + +// PageAfterDeleteImmutable creates afterDelete for compose:page resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func PageAfterDeleteImmutable( + argPage *types.Page, + argOldPage *types.Page, + argNamespace *types.Namespace, +) *pageAfterDelete { + return &pageAfterDelete{ + pageBase: &pageBase{ + immutable: true, + page: argPage, + oldPage: argOldPage, + namespace: argNamespace, + }, + } +} + +// SetPage sets new page value +// +// This function is auto-generated. +func (res *pageBase) SetPage(argPage *types.Page) { + res.page = argPage +} + +// Page returns page +// +// This function is auto-generated. +func (res pageBase) Page() *types.Page { + return res.page +} + +// OldPage returns oldPage +// +// This function is auto-generated. +func (res pageBase) OldPage() *types.Page { + return res.oldPage +} + +// Namespace returns namespace +// +// This function is auto-generated. +func (res pageBase) Namespace() *types.Namespace { + return res.namespace +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *pageBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res pageBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res pageBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["page"], err = json.Marshal(res.page); err != nil { + return nil, err + } + + if args["oldPage"], err = json.Marshal(res.oldPage); err != nil { + return nil, err + } + + if args["namespace"], err = json.Marshal(res.namespace); err != nil { + return nil, err + } + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *pageBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.page != nil { + if r, ok := results["result"]; ok && len(results) == 1 { + if err = json.Unmarshal(r, res.page); err != nil { + return + } + } + } + + if res.page != nil { + if r, ok := results["page"]; ok { + if err = json.Unmarshal(r, res.page); err != nil { + return + } + } + } + + // Do not decode oldPage; marked as immutable + + // Do not decode namespace; marked as immutable + + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} + +// ResourceType returns "compose:record" +// +// This function is auto-generated. +func (recordBase) ResourceType() string { + return "compose:record" +} + +// EventType on recordOnManual returns "onManual" +// +// This function is auto-generated. +func (recordOnManual) EventType() string { + return "onManual" +} + +// EventType on recordOnIteration returns "onIteration" +// +// This function is auto-generated. +func (recordOnIteration) EventType() string { + return "onIteration" +} + +// EventType on recordBeforeCreate returns "beforeCreate" +// +// This function is auto-generated. +func (recordBeforeCreate) EventType() string { + return "beforeCreate" +} + +// EventType on recordBeforeUpdate returns "beforeUpdate" +// +// This function is auto-generated. +func (recordBeforeUpdate) EventType() string { + return "beforeUpdate" +} + +// EventType on recordBeforeDelete returns "beforeDelete" +// +// This function is auto-generated. +func (recordBeforeDelete) EventType() string { + return "beforeDelete" +} + +// EventType on recordAfterCreate returns "afterCreate" +// +// This function is auto-generated. +func (recordAfterCreate) EventType() string { + return "afterCreate" +} + +// EventType on recordAfterUpdate returns "afterUpdate" +// +// This function is auto-generated. +func (recordAfterUpdate) EventType() string { + return "afterUpdate" +} + +// EventType on recordAfterDelete returns "afterDelete" +// +// This function is auto-generated. +func (recordAfterDelete) EventType() string { + return "afterDelete" +} + +// RecordOnManual creates onManual for compose:record resource +// +// This function is auto-generated. +func RecordOnManual( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordOnManual { + return &recordOnManual{ + recordBase: &recordBase{ + immutable: false, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// RecordOnManualImmutable creates onManual for compose:record resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RecordOnManualImmutable( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordOnManual { + return &recordOnManual{ + recordBase: &recordBase{ + immutable: true, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// RecordOnIteration creates onIteration for compose:record resource +// +// This function is auto-generated. +func RecordOnIteration( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordOnIteration { + return &recordOnIteration{ + recordBase: &recordBase{ + immutable: false, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// RecordOnIterationImmutable creates onIteration for compose:record resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RecordOnIterationImmutable( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordOnIteration { + return &recordOnIteration{ + recordBase: &recordBase{ + immutable: true, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// RecordBeforeCreate creates beforeCreate for compose:record resource +// +// This function is auto-generated. +func RecordBeforeCreate( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordBeforeCreate { + return &recordBeforeCreate{ + recordBase: &recordBase{ + immutable: false, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// RecordBeforeCreateImmutable creates beforeCreate for compose:record resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RecordBeforeCreateImmutable( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordBeforeCreate { + return &recordBeforeCreate{ + recordBase: &recordBase{ + immutable: true, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// RecordBeforeUpdate creates beforeUpdate for compose:record resource +// +// This function is auto-generated. +func RecordBeforeUpdate( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordBeforeUpdate { + return &recordBeforeUpdate{ + recordBase: &recordBase{ + immutable: false, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// RecordBeforeUpdateImmutable creates beforeUpdate for compose:record resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RecordBeforeUpdateImmutable( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordBeforeUpdate { + return &recordBeforeUpdate{ + recordBase: &recordBase{ + immutable: true, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// RecordBeforeDelete creates beforeDelete for compose:record resource +// +// This function is auto-generated. +func RecordBeforeDelete( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordBeforeDelete { + return &recordBeforeDelete{ + recordBase: &recordBase{ + immutable: false, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// RecordBeforeDeleteImmutable creates beforeDelete for compose:record resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RecordBeforeDeleteImmutable( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordBeforeDelete { + return &recordBeforeDelete{ + recordBase: &recordBase{ + immutable: true, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// RecordAfterCreate creates afterCreate for compose:record resource +// +// This function is auto-generated. +func RecordAfterCreate( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordAfterCreate { + return &recordAfterCreate{ + recordBase: &recordBase{ + immutable: false, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// RecordAfterCreateImmutable creates afterCreate for compose:record resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RecordAfterCreateImmutable( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordAfterCreate { + return &recordAfterCreate{ + recordBase: &recordBase{ + immutable: true, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// RecordAfterUpdate creates afterUpdate for compose:record resource +// +// This function is auto-generated. +func RecordAfterUpdate( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordAfterUpdate { + return &recordAfterUpdate{ + recordBase: &recordBase{ + immutable: false, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// RecordAfterUpdateImmutable creates afterUpdate for compose:record resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RecordAfterUpdateImmutable( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordAfterUpdate { + return &recordAfterUpdate{ + recordBase: &recordBase{ + immutable: true, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// RecordAfterDelete creates afterDelete for compose:record resource +// +// This function is auto-generated. +func RecordAfterDelete( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordAfterDelete { + return &recordAfterDelete{ + recordBase: &recordBase{ + immutable: false, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// RecordAfterDeleteImmutable creates afterDelete for compose:record resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RecordAfterDeleteImmutable( + argRecord *types.Record, + argOldRecord *types.Record, + argModule *types.Module, + argNamespace *types.Namespace, + argRecordValueErrors *types.RecordValueErrorSet, +) *recordAfterDelete { + return &recordAfterDelete{ + recordBase: &recordBase{ + immutable: true, + record: argRecord, + oldRecord: argOldRecord, + module: argModule, + namespace: argNamespace, + recordValueErrors: argRecordValueErrors, + }, + } +} + +// SetRecord sets new record value +// +// This function is auto-generated. +func (res *recordBase) SetRecord(argRecord *types.Record) { + res.record = argRecord +} + +// Record returns record +// +// This function is auto-generated. +func (res recordBase) Record() *types.Record { + return res.record +} + +// OldRecord returns oldRecord +// +// This function is auto-generated. +func (res recordBase) OldRecord() *types.Record { + return res.oldRecord +} + +// Module returns module +// +// This function is auto-generated. +func (res recordBase) Module() *types.Module { + return res.module +} + +// Namespace returns namespace +// +// This function is auto-generated. +func (res recordBase) Namespace() *types.Namespace { + return res.namespace +} + +// SetRecordValueErrors sets new recordValueErrors value +// +// This function is auto-generated. +func (res *recordBase) SetRecordValueErrors(argRecordValueErrors *types.RecordValueErrorSet) { + res.recordValueErrors = argRecordValueErrors +} + +// RecordValueErrors returns recordValueErrors +// +// This function is auto-generated. +func (res recordBase) RecordValueErrors() *types.RecordValueErrorSet { + return res.recordValueErrors +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *recordBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res recordBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res recordBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["record"], err = json.Marshal(res.record); err != nil { + return nil, err + } + + if args["oldRecord"], err = json.Marshal(res.oldRecord); err != nil { + return nil, err + } + + if args["module"], err = json.Marshal(res.module); err != nil { + return nil, err + } + + if args["namespace"], err = json.Marshal(res.namespace); err != nil { + return nil, err + } + + if args["recordValueErrors"], err = json.Marshal(res.recordValueErrors); err != nil { + return nil, err + } + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *recordBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.record != nil { + if r, ok := results["result"]; ok && len(results) == 1 { + if err = json.Unmarshal(r, res.record); err != nil { + return + } + } + } + + if res.record != nil { + if r, ok := results["record"]; ok { + if err = json.Unmarshal(r, res.record); err != nil { + return + } + } + } + + // Do not decode oldRecord; marked as immutable + + // Do not decode module; marked as immutable + + // Do not decode namespace; marked as immutable + + if res.recordValueErrors != nil { + if r, ok := results["recordValueErrors"]; ok { + if err = json.Unmarshal(r, res.recordValueErrors); err != nil { + return + } + } + } + + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} diff --git a/compose/service/event/module.gen.go b/compose/service/event/module.gen.go deleted file mode 100644 index e4ffb524a..000000000 --- a/compose/service/event/module.gen.go +++ /dev/null @@ -1,499 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// compose/service/event/events.yaml -// -// Regenerate with: -// go run codegen/v2/events.go --service compose -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/compose/types" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // moduleBase - // - // This type is auto-generated. - moduleBase struct { - immutable bool - module *types.Module - oldModule *types.Module - namespace *types.Namespace - invoker auth.Identifiable - } - - // moduleOnManual - // - // This type is auto-generated. - moduleOnManual struct { - *moduleBase - } - - // moduleBeforeCreate - // - // This type is auto-generated. - moduleBeforeCreate struct { - *moduleBase - } - - // moduleBeforeUpdate - // - // This type is auto-generated. - moduleBeforeUpdate struct { - *moduleBase - } - - // moduleBeforeDelete - // - // This type is auto-generated. - moduleBeforeDelete struct { - *moduleBase - } - - // moduleAfterCreate - // - // This type is auto-generated. - moduleAfterCreate struct { - *moduleBase - } - - // moduleAfterUpdate - // - // This type is auto-generated. - moduleAfterUpdate struct { - *moduleBase - } - - // moduleAfterDelete - // - // This type is auto-generated. - moduleAfterDelete struct { - *moduleBase - } -) - -// ResourceType returns "compose:module" -// -// This function is auto-generated. -func (moduleBase) ResourceType() string { - return "compose:module" -} - -// EventType on moduleOnManual returns "onManual" -// -// This function is auto-generated. -func (moduleOnManual) EventType() string { - return "onManual" -} - -// EventType on moduleBeforeCreate returns "beforeCreate" -// -// This function is auto-generated. -func (moduleBeforeCreate) EventType() string { - return "beforeCreate" -} - -// EventType on moduleBeforeUpdate returns "beforeUpdate" -// -// This function is auto-generated. -func (moduleBeforeUpdate) EventType() string { - return "beforeUpdate" -} - -// EventType on moduleBeforeDelete returns "beforeDelete" -// -// This function is auto-generated. -func (moduleBeforeDelete) EventType() string { - return "beforeDelete" -} - -// EventType on moduleAfterCreate returns "afterCreate" -// -// This function is auto-generated. -func (moduleAfterCreate) EventType() string { - return "afterCreate" -} - -// EventType on moduleAfterUpdate returns "afterUpdate" -// -// This function is auto-generated. -func (moduleAfterUpdate) EventType() string { - return "afterUpdate" -} - -// EventType on moduleAfterDelete returns "afterDelete" -// -// This function is auto-generated. -func (moduleAfterDelete) EventType() string { - return "afterDelete" -} - -// ModuleOnManual creates onManual for compose:module resource -// -// This function is auto-generated. -func ModuleOnManual( - argModule *types.Module, - argOldModule *types.Module, - argNamespace *types.Namespace, -) *moduleOnManual { - return &moduleOnManual{ - moduleBase: &moduleBase{ - immutable: false, - module: argModule, - oldModule: argOldModule, - namespace: argNamespace, - }, - } -} - -// ModuleOnManualImmutable creates onManual for compose:module resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ModuleOnManualImmutable( - argModule *types.Module, - argOldModule *types.Module, - argNamespace *types.Namespace, -) *moduleOnManual { - return &moduleOnManual{ - moduleBase: &moduleBase{ - immutable: true, - module: argModule, - oldModule: argOldModule, - namespace: argNamespace, - }, - } -} - -// ModuleBeforeCreate creates beforeCreate for compose:module resource -// -// This function is auto-generated. -func ModuleBeforeCreate( - argModule *types.Module, - argOldModule *types.Module, - argNamespace *types.Namespace, -) *moduleBeforeCreate { - return &moduleBeforeCreate{ - moduleBase: &moduleBase{ - immutable: false, - module: argModule, - oldModule: argOldModule, - namespace: argNamespace, - }, - } -} - -// ModuleBeforeCreateImmutable creates beforeCreate for compose:module resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ModuleBeforeCreateImmutable( - argModule *types.Module, - argOldModule *types.Module, - argNamespace *types.Namespace, -) *moduleBeforeCreate { - return &moduleBeforeCreate{ - moduleBase: &moduleBase{ - immutable: true, - module: argModule, - oldModule: argOldModule, - namespace: argNamespace, - }, - } -} - -// ModuleBeforeUpdate creates beforeUpdate for compose:module resource -// -// This function is auto-generated. -func ModuleBeforeUpdate( - argModule *types.Module, - argOldModule *types.Module, - argNamespace *types.Namespace, -) *moduleBeforeUpdate { - return &moduleBeforeUpdate{ - moduleBase: &moduleBase{ - immutable: false, - module: argModule, - oldModule: argOldModule, - namespace: argNamespace, - }, - } -} - -// ModuleBeforeUpdateImmutable creates beforeUpdate for compose:module resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ModuleBeforeUpdateImmutable( - argModule *types.Module, - argOldModule *types.Module, - argNamespace *types.Namespace, -) *moduleBeforeUpdate { - return &moduleBeforeUpdate{ - moduleBase: &moduleBase{ - immutable: true, - module: argModule, - oldModule: argOldModule, - namespace: argNamespace, - }, - } -} - -// ModuleBeforeDelete creates beforeDelete for compose:module resource -// -// This function is auto-generated. -func ModuleBeforeDelete( - argModule *types.Module, - argOldModule *types.Module, - argNamespace *types.Namespace, -) *moduleBeforeDelete { - return &moduleBeforeDelete{ - moduleBase: &moduleBase{ - immutable: false, - module: argModule, - oldModule: argOldModule, - namespace: argNamespace, - }, - } -} - -// ModuleBeforeDeleteImmutable creates beforeDelete for compose:module resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ModuleBeforeDeleteImmutable( - argModule *types.Module, - argOldModule *types.Module, - argNamespace *types.Namespace, -) *moduleBeforeDelete { - return &moduleBeforeDelete{ - moduleBase: &moduleBase{ - immutable: true, - module: argModule, - oldModule: argOldModule, - namespace: argNamespace, - }, - } -} - -// ModuleAfterCreate creates afterCreate for compose:module resource -// -// This function is auto-generated. -func ModuleAfterCreate( - argModule *types.Module, - argOldModule *types.Module, - argNamespace *types.Namespace, -) *moduleAfterCreate { - return &moduleAfterCreate{ - moduleBase: &moduleBase{ - immutable: false, - module: argModule, - oldModule: argOldModule, - namespace: argNamespace, - }, - } -} - -// ModuleAfterCreateImmutable creates afterCreate for compose:module resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ModuleAfterCreateImmutable( - argModule *types.Module, - argOldModule *types.Module, - argNamespace *types.Namespace, -) *moduleAfterCreate { - return &moduleAfterCreate{ - moduleBase: &moduleBase{ - immutable: true, - module: argModule, - oldModule: argOldModule, - namespace: argNamespace, - }, - } -} - -// ModuleAfterUpdate creates afterUpdate for compose:module resource -// -// This function is auto-generated. -func ModuleAfterUpdate( - argModule *types.Module, - argOldModule *types.Module, - argNamespace *types.Namespace, -) *moduleAfterUpdate { - return &moduleAfterUpdate{ - moduleBase: &moduleBase{ - immutable: false, - module: argModule, - oldModule: argOldModule, - namespace: argNamespace, - }, - } -} - -// ModuleAfterUpdateImmutable creates afterUpdate for compose:module resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ModuleAfterUpdateImmutable( - argModule *types.Module, - argOldModule *types.Module, - argNamespace *types.Namespace, -) *moduleAfterUpdate { - return &moduleAfterUpdate{ - moduleBase: &moduleBase{ - immutable: true, - module: argModule, - oldModule: argOldModule, - namespace: argNamespace, - }, - } -} - -// ModuleAfterDelete creates afterDelete for compose:module resource -// -// This function is auto-generated. -func ModuleAfterDelete( - argModule *types.Module, - argOldModule *types.Module, - argNamespace *types.Namespace, -) *moduleAfterDelete { - return &moduleAfterDelete{ - moduleBase: &moduleBase{ - immutable: false, - module: argModule, - oldModule: argOldModule, - namespace: argNamespace, - }, - } -} - -// ModuleAfterDeleteImmutable creates afterDelete for compose:module resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ModuleAfterDeleteImmutable( - argModule *types.Module, - argOldModule *types.Module, - argNamespace *types.Namespace, -) *moduleAfterDelete { - return &moduleAfterDelete{ - moduleBase: &moduleBase{ - immutable: true, - module: argModule, - oldModule: argOldModule, - namespace: argNamespace, - }, - } -} - -// SetModule sets new module value -// -// This function is auto-generated. -func (res *moduleBase) SetModule(argModule *types.Module) { - res.module = argModule -} - -// Module returns module -// -// This function is auto-generated. -func (res moduleBase) Module() *types.Module { - return res.module -} - -// OldModule returns oldModule -// -// This function is auto-generated. -func (res moduleBase) OldModule() *types.Module { - return res.oldModule -} - -// Namespace returns namespace -// -// This function is auto-generated. -func (res moduleBase) Namespace() *types.Namespace { - return res.namespace -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *moduleBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res moduleBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res moduleBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["module"], err = json.Marshal(res.module); err != nil { - return nil, err - } - - if args["oldModule"], err = json.Marshal(res.oldModule); err != nil { - return nil, err - } - - if args["namespace"], err = json.Marshal(res.namespace); err != nil { - return nil, err - } - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *moduleBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.module != nil { - if r, ok := results["result"]; ok && len(results) == 1 { - if err = json.Unmarshal(r, res.module); err != nil { - return - } - } - } - - if res.module != nil { - if r, ok := results["module"]; ok { - if err = json.Unmarshal(r, res.module); err != nil { - return - } - } - } - - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/compose/service/event/namespace.gen.go b/compose/service/event/namespace.gen.go deleted file mode 100644 index 5d4a4c331..000000000 --- a/compose/service/event/namespace.gen.go +++ /dev/null @@ -1,459 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// compose/service/event/events.yaml -// -// Regenerate with: -// go run codegen/v2/events.go --service compose -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/compose/types" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // namespaceBase - // - // This type is auto-generated. - namespaceBase struct { - immutable bool - namespace *types.Namespace - oldNamespace *types.Namespace - invoker auth.Identifiable - } - - // namespaceOnManual - // - // This type is auto-generated. - namespaceOnManual struct { - *namespaceBase - } - - // namespaceBeforeCreate - // - // This type is auto-generated. - namespaceBeforeCreate struct { - *namespaceBase - } - - // namespaceBeforeUpdate - // - // This type is auto-generated. - namespaceBeforeUpdate struct { - *namespaceBase - } - - // namespaceBeforeDelete - // - // This type is auto-generated. - namespaceBeforeDelete struct { - *namespaceBase - } - - // namespaceAfterCreate - // - // This type is auto-generated. - namespaceAfterCreate struct { - *namespaceBase - } - - // namespaceAfterUpdate - // - // This type is auto-generated. - namespaceAfterUpdate struct { - *namespaceBase - } - - // namespaceAfterDelete - // - // This type is auto-generated. - namespaceAfterDelete struct { - *namespaceBase - } -) - -// ResourceType returns "compose:namespace" -// -// This function is auto-generated. -func (namespaceBase) ResourceType() string { - return "compose:namespace" -} - -// EventType on namespaceOnManual returns "onManual" -// -// This function is auto-generated. -func (namespaceOnManual) EventType() string { - return "onManual" -} - -// EventType on namespaceBeforeCreate returns "beforeCreate" -// -// This function is auto-generated. -func (namespaceBeforeCreate) EventType() string { - return "beforeCreate" -} - -// EventType on namespaceBeforeUpdate returns "beforeUpdate" -// -// This function is auto-generated. -func (namespaceBeforeUpdate) EventType() string { - return "beforeUpdate" -} - -// EventType on namespaceBeforeDelete returns "beforeDelete" -// -// This function is auto-generated. -func (namespaceBeforeDelete) EventType() string { - return "beforeDelete" -} - -// EventType on namespaceAfterCreate returns "afterCreate" -// -// This function is auto-generated. -func (namespaceAfterCreate) EventType() string { - return "afterCreate" -} - -// EventType on namespaceAfterUpdate returns "afterUpdate" -// -// This function is auto-generated. -func (namespaceAfterUpdate) EventType() string { - return "afterUpdate" -} - -// EventType on namespaceAfterDelete returns "afterDelete" -// -// This function is auto-generated. -func (namespaceAfterDelete) EventType() string { - return "afterDelete" -} - -// NamespaceOnManual creates onManual for compose:namespace resource -// -// This function is auto-generated. -func NamespaceOnManual( - argNamespace *types.Namespace, - argOldNamespace *types.Namespace, -) *namespaceOnManual { - return &namespaceOnManual{ - namespaceBase: &namespaceBase{ - immutable: false, - namespace: argNamespace, - oldNamespace: argOldNamespace, - }, - } -} - -// NamespaceOnManualImmutable creates onManual for compose:namespace resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func NamespaceOnManualImmutable( - argNamespace *types.Namespace, - argOldNamespace *types.Namespace, -) *namespaceOnManual { - return &namespaceOnManual{ - namespaceBase: &namespaceBase{ - immutable: true, - namespace: argNamespace, - oldNamespace: argOldNamespace, - }, - } -} - -// NamespaceBeforeCreate creates beforeCreate for compose:namespace resource -// -// This function is auto-generated. -func NamespaceBeforeCreate( - argNamespace *types.Namespace, - argOldNamespace *types.Namespace, -) *namespaceBeforeCreate { - return &namespaceBeforeCreate{ - namespaceBase: &namespaceBase{ - immutable: false, - namespace: argNamespace, - oldNamespace: argOldNamespace, - }, - } -} - -// NamespaceBeforeCreateImmutable creates beforeCreate for compose:namespace resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func NamespaceBeforeCreateImmutable( - argNamespace *types.Namespace, - argOldNamespace *types.Namespace, -) *namespaceBeforeCreate { - return &namespaceBeforeCreate{ - namespaceBase: &namespaceBase{ - immutable: true, - namespace: argNamespace, - oldNamespace: argOldNamespace, - }, - } -} - -// NamespaceBeforeUpdate creates beforeUpdate for compose:namespace resource -// -// This function is auto-generated. -func NamespaceBeforeUpdate( - argNamespace *types.Namespace, - argOldNamespace *types.Namespace, -) *namespaceBeforeUpdate { - return &namespaceBeforeUpdate{ - namespaceBase: &namespaceBase{ - immutable: false, - namespace: argNamespace, - oldNamespace: argOldNamespace, - }, - } -} - -// NamespaceBeforeUpdateImmutable creates beforeUpdate for compose:namespace resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func NamespaceBeforeUpdateImmutable( - argNamespace *types.Namespace, - argOldNamespace *types.Namespace, -) *namespaceBeforeUpdate { - return &namespaceBeforeUpdate{ - namespaceBase: &namespaceBase{ - immutable: true, - namespace: argNamespace, - oldNamespace: argOldNamespace, - }, - } -} - -// NamespaceBeforeDelete creates beforeDelete for compose:namespace resource -// -// This function is auto-generated. -func NamespaceBeforeDelete( - argNamespace *types.Namespace, - argOldNamespace *types.Namespace, -) *namespaceBeforeDelete { - return &namespaceBeforeDelete{ - namespaceBase: &namespaceBase{ - immutable: false, - namespace: argNamespace, - oldNamespace: argOldNamespace, - }, - } -} - -// NamespaceBeforeDeleteImmutable creates beforeDelete for compose:namespace resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func NamespaceBeforeDeleteImmutable( - argNamespace *types.Namespace, - argOldNamespace *types.Namespace, -) *namespaceBeforeDelete { - return &namespaceBeforeDelete{ - namespaceBase: &namespaceBase{ - immutable: true, - namespace: argNamespace, - oldNamespace: argOldNamespace, - }, - } -} - -// NamespaceAfterCreate creates afterCreate for compose:namespace resource -// -// This function is auto-generated. -func NamespaceAfterCreate( - argNamespace *types.Namespace, - argOldNamespace *types.Namespace, -) *namespaceAfterCreate { - return &namespaceAfterCreate{ - namespaceBase: &namespaceBase{ - immutable: false, - namespace: argNamespace, - oldNamespace: argOldNamespace, - }, - } -} - -// NamespaceAfterCreateImmutable creates afterCreate for compose:namespace resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func NamespaceAfterCreateImmutable( - argNamespace *types.Namespace, - argOldNamespace *types.Namespace, -) *namespaceAfterCreate { - return &namespaceAfterCreate{ - namespaceBase: &namespaceBase{ - immutable: true, - namespace: argNamespace, - oldNamespace: argOldNamespace, - }, - } -} - -// NamespaceAfterUpdate creates afterUpdate for compose:namespace resource -// -// This function is auto-generated. -func NamespaceAfterUpdate( - argNamespace *types.Namespace, - argOldNamespace *types.Namespace, -) *namespaceAfterUpdate { - return &namespaceAfterUpdate{ - namespaceBase: &namespaceBase{ - immutable: false, - namespace: argNamespace, - oldNamespace: argOldNamespace, - }, - } -} - -// NamespaceAfterUpdateImmutable creates afterUpdate for compose:namespace resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func NamespaceAfterUpdateImmutable( - argNamespace *types.Namespace, - argOldNamespace *types.Namespace, -) *namespaceAfterUpdate { - return &namespaceAfterUpdate{ - namespaceBase: &namespaceBase{ - immutable: true, - namespace: argNamespace, - oldNamespace: argOldNamespace, - }, - } -} - -// NamespaceAfterDelete creates afterDelete for compose:namespace resource -// -// This function is auto-generated. -func NamespaceAfterDelete( - argNamespace *types.Namespace, - argOldNamespace *types.Namespace, -) *namespaceAfterDelete { - return &namespaceAfterDelete{ - namespaceBase: &namespaceBase{ - immutable: false, - namespace: argNamespace, - oldNamespace: argOldNamespace, - }, - } -} - -// NamespaceAfterDeleteImmutable creates afterDelete for compose:namespace resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func NamespaceAfterDeleteImmutable( - argNamespace *types.Namespace, - argOldNamespace *types.Namespace, -) *namespaceAfterDelete { - return &namespaceAfterDelete{ - namespaceBase: &namespaceBase{ - immutable: true, - namespace: argNamespace, - oldNamespace: argOldNamespace, - }, - } -} - -// SetNamespace sets new namespace value -// -// This function is auto-generated. -func (res *namespaceBase) SetNamespace(argNamespace *types.Namespace) { - res.namespace = argNamespace -} - -// Namespace returns namespace -// -// This function is auto-generated. -func (res namespaceBase) Namespace() *types.Namespace { - return res.namespace -} - -// OldNamespace returns oldNamespace -// -// This function is auto-generated. -func (res namespaceBase) OldNamespace() *types.Namespace { - return res.oldNamespace -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *namespaceBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res namespaceBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res namespaceBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["namespace"], err = json.Marshal(res.namespace); err != nil { - return nil, err - } - - if args["oldNamespace"], err = json.Marshal(res.oldNamespace); err != nil { - return nil, err - } - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *namespaceBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.namespace != nil { - if r, ok := results["result"]; ok && len(results) == 1 { - if err = json.Unmarshal(r, res.namespace); err != nil { - return - } - } - } - - if res.namespace != nil { - if r, ok := results["namespace"]; ok { - if err = json.Unmarshal(r, res.namespace); err != nil { - return - } - } - } - - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/compose/service/event/page.gen.go b/compose/service/event/page.gen.go deleted file mode 100644 index 678abc3fb..000000000 --- a/compose/service/event/page.gen.go +++ /dev/null @@ -1,499 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// compose/service/event/events.yaml -// -// Regenerate with: -// go run codegen/v2/events.go --service compose -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/compose/types" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // pageBase - // - // This type is auto-generated. - pageBase struct { - immutable bool - page *types.Page - oldPage *types.Page - namespace *types.Namespace - invoker auth.Identifiable - } - - // pageOnManual - // - // This type is auto-generated. - pageOnManual struct { - *pageBase - } - - // pageBeforeCreate - // - // This type is auto-generated. - pageBeforeCreate struct { - *pageBase - } - - // pageBeforeUpdate - // - // This type is auto-generated. - pageBeforeUpdate struct { - *pageBase - } - - // pageBeforeDelete - // - // This type is auto-generated. - pageBeforeDelete struct { - *pageBase - } - - // pageAfterCreate - // - // This type is auto-generated. - pageAfterCreate struct { - *pageBase - } - - // pageAfterUpdate - // - // This type is auto-generated. - pageAfterUpdate struct { - *pageBase - } - - // pageAfterDelete - // - // This type is auto-generated. - pageAfterDelete struct { - *pageBase - } -) - -// ResourceType returns "compose:page" -// -// This function is auto-generated. -func (pageBase) ResourceType() string { - return "compose:page" -} - -// EventType on pageOnManual returns "onManual" -// -// This function is auto-generated. -func (pageOnManual) EventType() string { - return "onManual" -} - -// EventType on pageBeforeCreate returns "beforeCreate" -// -// This function is auto-generated. -func (pageBeforeCreate) EventType() string { - return "beforeCreate" -} - -// EventType on pageBeforeUpdate returns "beforeUpdate" -// -// This function is auto-generated. -func (pageBeforeUpdate) EventType() string { - return "beforeUpdate" -} - -// EventType on pageBeforeDelete returns "beforeDelete" -// -// This function is auto-generated. -func (pageBeforeDelete) EventType() string { - return "beforeDelete" -} - -// EventType on pageAfterCreate returns "afterCreate" -// -// This function is auto-generated. -func (pageAfterCreate) EventType() string { - return "afterCreate" -} - -// EventType on pageAfterUpdate returns "afterUpdate" -// -// This function is auto-generated. -func (pageAfterUpdate) EventType() string { - return "afterUpdate" -} - -// EventType on pageAfterDelete returns "afterDelete" -// -// This function is auto-generated. -func (pageAfterDelete) EventType() string { - return "afterDelete" -} - -// PageOnManual creates onManual for compose:page resource -// -// This function is auto-generated. -func PageOnManual( - argPage *types.Page, - argOldPage *types.Page, - argNamespace *types.Namespace, -) *pageOnManual { - return &pageOnManual{ - pageBase: &pageBase{ - immutable: false, - page: argPage, - oldPage: argOldPage, - namespace: argNamespace, - }, - } -} - -// PageOnManualImmutable creates onManual for compose:page resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func PageOnManualImmutable( - argPage *types.Page, - argOldPage *types.Page, - argNamespace *types.Namespace, -) *pageOnManual { - return &pageOnManual{ - pageBase: &pageBase{ - immutable: true, - page: argPage, - oldPage: argOldPage, - namespace: argNamespace, - }, - } -} - -// PageBeforeCreate creates beforeCreate for compose:page resource -// -// This function is auto-generated. -func PageBeforeCreate( - argPage *types.Page, - argOldPage *types.Page, - argNamespace *types.Namespace, -) *pageBeforeCreate { - return &pageBeforeCreate{ - pageBase: &pageBase{ - immutable: false, - page: argPage, - oldPage: argOldPage, - namespace: argNamespace, - }, - } -} - -// PageBeforeCreateImmutable creates beforeCreate for compose:page resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func PageBeforeCreateImmutable( - argPage *types.Page, - argOldPage *types.Page, - argNamespace *types.Namespace, -) *pageBeforeCreate { - return &pageBeforeCreate{ - pageBase: &pageBase{ - immutable: true, - page: argPage, - oldPage: argOldPage, - namespace: argNamespace, - }, - } -} - -// PageBeforeUpdate creates beforeUpdate for compose:page resource -// -// This function is auto-generated. -func PageBeforeUpdate( - argPage *types.Page, - argOldPage *types.Page, - argNamespace *types.Namespace, -) *pageBeforeUpdate { - return &pageBeforeUpdate{ - pageBase: &pageBase{ - immutable: false, - page: argPage, - oldPage: argOldPage, - namespace: argNamespace, - }, - } -} - -// PageBeforeUpdateImmutable creates beforeUpdate for compose:page resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func PageBeforeUpdateImmutable( - argPage *types.Page, - argOldPage *types.Page, - argNamespace *types.Namespace, -) *pageBeforeUpdate { - return &pageBeforeUpdate{ - pageBase: &pageBase{ - immutable: true, - page: argPage, - oldPage: argOldPage, - namespace: argNamespace, - }, - } -} - -// PageBeforeDelete creates beforeDelete for compose:page resource -// -// This function is auto-generated. -func PageBeforeDelete( - argPage *types.Page, - argOldPage *types.Page, - argNamespace *types.Namespace, -) *pageBeforeDelete { - return &pageBeforeDelete{ - pageBase: &pageBase{ - immutable: false, - page: argPage, - oldPage: argOldPage, - namespace: argNamespace, - }, - } -} - -// PageBeforeDeleteImmutable creates beforeDelete for compose:page resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func PageBeforeDeleteImmutable( - argPage *types.Page, - argOldPage *types.Page, - argNamespace *types.Namespace, -) *pageBeforeDelete { - return &pageBeforeDelete{ - pageBase: &pageBase{ - immutable: true, - page: argPage, - oldPage: argOldPage, - namespace: argNamespace, - }, - } -} - -// PageAfterCreate creates afterCreate for compose:page resource -// -// This function is auto-generated. -func PageAfterCreate( - argPage *types.Page, - argOldPage *types.Page, - argNamespace *types.Namespace, -) *pageAfterCreate { - return &pageAfterCreate{ - pageBase: &pageBase{ - immutable: false, - page: argPage, - oldPage: argOldPage, - namespace: argNamespace, - }, - } -} - -// PageAfterCreateImmutable creates afterCreate for compose:page resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func PageAfterCreateImmutable( - argPage *types.Page, - argOldPage *types.Page, - argNamespace *types.Namespace, -) *pageAfterCreate { - return &pageAfterCreate{ - pageBase: &pageBase{ - immutable: true, - page: argPage, - oldPage: argOldPage, - namespace: argNamespace, - }, - } -} - -// PageAfterUpdate creates afterUpdate for compose:page resource -// -// This function is auto-generated. -func PageAfterUpdate( - argPage *types.Page, - argOldPage *types.Page, - argNamespace *types.Namespace, -) *pageAfterUpdate { - return &pageAfterUpdate{ - pageBase: &pageBase{ - immutable: false, - page: argPage, - oldPage: argOldPage, - namespace: argNamespace, - }, - } -} - -// PageAfterUpdateImmutable creates afterUpdate for compose:page resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func PageAfterUpdateImmutable( - argPage *types.Page, - argOldPage *types.Page, - argNamespace *types.Namespace, -) *pageAfterUpdate { - return &pageAfterUpdate{ - pageBase: &pageBase{ - immutable: true, - page: argPage, - oldPage: argOldPage, - namespace: argNamespace, - }, - } -} - -// PageAfterDelete creates afterDelete for compose:page resource -// -// This function is auto-generated. -func PageAfterDelete( - argPage *types.Page, - argOldPage *types.Page, - argNamespace *types.Namespace, -) *pageAfterDelete { - return &pageAfterDelete{ - pageBase: &pageBase{ - immutable: false, - page: argPage, - oldPage: argOldPage, - namespace: argNamespace, - }, - } -} - -// PageAfterDeleteImmutable creates afterDelete for compose:page resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func PageAfterDeleteImmutable( - argPage *types.Page, - argOldPage *types.Page, - argNamespace *types.Namespace, -) *pageAfterDelete { - return &pageAfterDelete{ - pageBase: &pageBase{ - immutable: true, - page: argPage, - oldPage: argOldPage, - namespace: argNamespace, - }, - } -} - -// SetPage sets new page value -// -// This function is auto-generated. -func (res *pageBase) SetPage(argPage *types.Page) { - res.page = argPage -} - -// Page returns page -// -// This function is auto-generated. -func (res pageBase) Page() *types.Page { - return res.page -} - -// OldPage returns oldPage -// -// This function is auto-generated. -func (res pageBase) OldPage() *types.Page { - return res.oldPage -} - -// Namespace returns namespace -// -// This function is auto-generated. -func (res pageBase) Namespace() *types.Namespace { - return res.namespace -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *pageBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res pageBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res pageBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["page"], err = json.Marshal(res.page); err != nil { - return nil, err - } - - if args["oldPage"], err = json.Marshal(res.oldPage); err != nil { - return nil, err - } - - if args["namespace"], err = json.Marshal(res.namespace); err != nil { - return nil, err - } - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *pageBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.page != nil { - if r, ok := results["result"]; ok && len(results) == 1 { - if err = json.Unmarshal(r, res.page); err != nil { - return - } - } - } - - if res.page != nil { - if r, ok := results["page"]; ok { - if err = json.Unmarshal(r, res.page); err != nil { - return - } - } - } - - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/compose/service/event/record.gen.go b/compose/service/event/record.gen.go deleted file mode 100644 index e3ed2f349..000000000 --- a/compose/service/event/record.gen.go +++ /dev/null @@ -1,654 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// compose/service/event/events.yaml -// -// Regenerate with: -// go run codegen/v2/events.go --service compose -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/compose/types" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // recordBase - // - // This type is auto-generated. - recordBase struct { - immutable bool - record *types.Record - oldRecord *types.Record - module *types.Module - namespace *types.Namespace - recordValueErrors *types.RecordValueErrorSet - invoker auth.Identifiable - } - - // recordOnManual - // - // This type is auto-generated. - recordOnManual struct { - *recordBase - } - - // recordOnIteration - // - // This type is auto-generated. - recordOnIteration struct { - *recordBase - } - - // recordBeforeCreate - // - // This type is auto-generated. - recordBeforeCreate struct { - *recordBase - } - - // recordBeforeUpdate - // - // This type is auto-generated. - recordBeforeUpdate struct { - *recordBase - } - - // recordBeforeDelete - // - // This type is auto-generated. - recordBeforeDelete struct { - *recordBase - } - - // recordAfterCreate - // - // This type is auto-generated. - recordAfterCreate struct { - *recordBase - } - - // recordAfterUpdate - // - // This type is auto-generated. - recordAfterUpdate struct { - *recordBase - } - - // recordAfterDelete - // - // This type is auto-generated. - recordAfterDelete struct { - *recordBase - } -) - -// ResourceType returns "compose:record" -// -// This function is auto-generated. -func (recordBase) ResourceType() string { - return "compose:record" -} - -// EventType on recordOnManual returns "onManual" -// -// This function is auto-generated. -func (recordOnManual) EventType() string { - return "onManual" -} - -// EventType on recordOnIteration returns "onIteration" -// -// This function is auto-generated. -func (recordOnIteration) EventType() string { - return "onIteration" -} - -// EventType on recordBeforeCreate returns "beforeCreate" -// -// This function is auto-generated. -func (recordBeforeCreate) EventType() string { - return "beforeCreate" -} - -// EventType on recordBeforeUpdate returns "beforeUpdate" -// -// This function is auto-generated. -func (recordBeforeUpdate) EventType() string { - return "beforeUpdate" -} - -// EventType on recordBeforeDelete returns "beforeDelete" -// -// This function is auto-generated. -func (recordBeforeDelete) EventType() string { - return "beforeDelete" -} - -// EventType on recordAfterCreate returns "afterCreate" -// -// This function is auto-generated. -func (recordAfterCreate) EventType() string { - return "afterCreate" -} - -// EventType on recordAfterUpdate returns "afterUpdate" -// -// This function is auto-generated. -func (recordAfterUpdate) EventType() string { - return "afterUpdate" -} - -// EventType on recordAfterDelete returns "afterDelete" -// -// This function is auto-generated. -func (recordAfterDelete) EventType() string { - return "afterDelete" -} - -// RecordOnManual creates onManual for compose:record resource -// -// This function is auto-generated. -func RecordOnManual( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordOnManual { - return &recordOnManual{ - recordBase: &recordBase{ - immutable: false, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// RecordOnManualImmutable creates onManual for compose:record resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RecordOnManualImmutable( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordOnManual { - return &recordOnManual{ - recordBase: &recordBase{ - immutable: true, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// RecordOnIteration creates onIteration for compose:record resource -// -// This function is auto-generated. -func RecordOnIteration( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordOnIteration { - return &recordOnIteration{ - recordBase: &recordBase{ - immutable: false, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// RecordOnIterationImmutable creates onIteration for compose:record resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RecordOnIterationImmutable( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordOnIteration { - return &recordOnIteration{ - recordBase: &recordBase{ - immutable: true, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// RecordBeforeCreate creates beforeCreate for compose:record resource -// -// This function is auto-generated. -func RecordBeforeCreate( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordBeforeCreate { - return &recordBeforeCreate{ - recordBase: &recordBase{ - immutable: false, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// RecordBeforeCreateImmutable creates beforeCreate for compose:record resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RecordBeforeCreateImmutable( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordBeforeCreate { - return &recordBeforeCreate{ - recordBase: &recordBase{ - immutable: true, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// RecordBeforeUpdate creates beforeUpdate for compose:record resource -// -// This function is auto-generated. -func RecordBeforeUpdate( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordBeforeUpdate { - return &recordBeforeUpdate{ - recordBase: &recordBase{ - immutable: false, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// RecordBeforeUpdateImmutable creates beforeUpdate for compose:record resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RecordBeforeUpdateImmutable( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordBeforeUpdate { - return &recordBeforeUpdate{ - recordBase: &recordBase{ - immutable: true, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// RecordBeforeDelete creates beforeDelete for compose:record resource -// -// This function is auto-generated. -func RecordBeforeDelete( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordBeforeDelete { - return &recordBeforeDelete{ - recordBase: &recordBase{ - immutable: false, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// RecordBeforeDeleteImmutable creates beforeDelete for compose:record resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RecordBeforeDeleteImmutable( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordBeforeDelete { - return &recordBeforeDelete{ - recordBase: &recordBase{ - immutable: true, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// RecordAfterCreate creates afterCreate for compose:record resource -// -// This function is auto-generated. -func RecordAfterCreate( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordAfterCreate { - return &recordAfterCreate{ - recordBase: &recordBase{ - immutable: false, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// RecordAfterCreateImmutable creates afterCreate for compose:record resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RecordAfterCreateImmutable( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordAfterCreate { - return &recordAfterCreate{ - recordBase: &recordBase{ - immutable: true, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// RecordAfterUpdate creates afterUpdate for compose:record resource -// -// This function is auto-generated. -func RecordAfterUpdate( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordAfterUpdate { - return &recordAfterUpdate{ - recordBase: &recordBase{ - immutable: false, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// RecordAfterUpdateImmutable creates afterUpdate for compose:record resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RecordAfterUpdateImmutable( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordAfterUpdate { - return &recordAfterUpdate{ - recordBase: &recordBase{ - immutable: true, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// RecordAfterDelete creates afterDelete for compose:record resource -// -// This function is auto-generated. -func RecordAfterDelete( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordAfterDelete { - return &recordAfterDelete{ - recordBase: &recordBase{ - immutable: false, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// RecordAfterDeleteImmutable creates afterDelete for compose:record resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RecordAfterDeleteImmutable( - argRecord *types.Record, - argOldRecord *types.Record, - argModule *types.Module, - argNamespace *types.Namespace, - argRecordValueErrors *types.RecordValueErrorSet, -) *recordAfterDelete { - return &recordAfterDelete{ - recordBase: &recordBase{ - immutable: true, - record: argRecord, - oldRecord: argOldRecord, - module: argModule, - namespace: argNamespace, - recordValueErrors: argRecordValueErrors, - }, - } -} - -// SetRecord sets new record value -// -// This function is auto-generated. -func (res *recordBase) SetRecord(argRecord *types.Record) { - res.record = argRecord -} - -// Record returns record -// -// This function is auto-generated. -func (res recordBase) Record() *types.Record { - return res.record -} - -// OldRecord returns oldRecord -// -// This function is auto-generated. -func (res recordBase) OldRecord() *types.Record { - return res.oldRecord -} - -// Module returns module -// -// This function is auto-generated. -func (res recordBase) Module() *types.Module { - return res.module -} - -// Namespace returns namespace -// -// This function is auto-generated. -func (res recordBase) Namespace() *types.Namespace { - return res.namespace -} - -// SetRecordValueErrors sets new recordValueErrors value -// -// This function is auto-generated. -func (res *recordBase) SetRecordValueErrors(argRecordValueErrors *types.RecordValueErrorSet) { - res.recordValueErrors = argRecordValueErrors -} - -// RecordValueErrors returns recordValueErrors -// -// This function is auto-generated. -func (res recordBase) RecordValueErrors() *types.RecordValueErrorSet { - return res.recordValueErrors -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *recordBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res recordBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res recordBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["record"], err = json.Marshal(res.record); err != nil { - return nil, err - } - - if args["oldRecord"], err = json.Marshal(res.oldRecord); err != nil { - return nil, err - } - - if args["module"], err = json.Marshal(res.module); err != nil { - return nil, err - } - - if args["namespace"], err = json.Marshal(res.namespace); err != nil { - return nil, err - } - - if args["recordValueErrors"], err = json.Marshal(res.recordValueErrors); err != nil { - return nil, err - } - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *recordBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.record != nil { - if r, ok := results["result"]; ok && len(results) == 1 { - if err = json.Unmarshal(r, res.record); err != nil { - return - } - } - } - - if res.record != nil { - if r, ok := results["record"]; ok { - if err = json.Unmarshal(r, res.record); err != nil { - return - } - } - } - - if res.recordValueErrors != nil { - if r, ok := results["recordValueErrors"]; ok { - if err = json.Unmarshal(r, res.recordValueErrors); err != nil { - return - } - } - } - - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/compose/service/import_session_test.go b/compose/service/import_session_test.go index 35e13cd41..f7672acaf 100644 --- a/compose/service/import_session_test.go +++ b/compose/service/import_session_test.go @@ -8,9 +8,8 @@ import ( "go.uber.org/zap" ) -var ctx context.Context = context.WithValue(context.Background(), "testing", true) - func TestImportSession_FindByID(t *testing.T) { + var ctx = context.Background() DefaultLogger = zap.New(nil, nil) svc := ImportSession() ss, _ := svc.SetByID(ctx, 1, 0, 0, nil, nil, nil) @@ -44,6 +43,7 @@ func TestImportSession_FindByID(t *testing.T) { } func TestImportSession_SetByID(t *testing.T) { + var ctx = context.Background() DefaultLogger = zap.New(nil, nil) svc := ImportSession() @@ -77,6 +77,7 @@ func TestImportSession_SetByID(t *testing.T) { } func TestImportSession_DeleteByID(t *testing.T) { + var ctx = context.Background() DefaultLogger = zap.New(nil, nil) svc := ImportSession() ss, _ := svc.SetByID(ctx, 1, 0, 0, nil, nil, nil) diff --git a/compose/service/module_actions.gen.go b/compose/service/module_actions.gen.go index e5a79cc90..f902c06aa 100644 --- a/compose/service/module_actions.gen.go +++ b/compose/service/module_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from compose/service/module_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// compose/service/module_actions.yaml import ( "context" diff --git a/compose/service/namespace_actions.gen.go b/compose/service/namespace_actions.gen.go index ca3af4ce9..a92dda713 100644 --- a/compose/service/namespace_actions.gen.go +++ b/compose/service/namespace_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from compose/service/namespace_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// compose/service/namespace_actions.yaml import ( "context" diff --git a/compose/service/notifications_actions.gen.go b/compose/service/notifications_actions.gen.go index b0a71a44d..4da3dba75 100644 --- a/compose/service/notifications_actions.gen.go +++ b/compose/service/notifications_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from compose/service/notifications_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// compose/service/notifications_actions.yaml import ( "context" diff --git a/compose/service/page_actions.gen.go b/compose/service/page_actions.gen.go index f3a482fa3..e7211c912 100644 --- a/compose/service/page_actions.gen.go +++ b/compose/service/page_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from compose/service/page_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// compose/service/page_actions.yaml import ( "context" diff --git a/compose/service/record_actions.gen.go b/compose/service/record_actions.gen.go index 6ef6f9ec4..2aa5373d1 100644 --- a/compose/service/record_actions.gen.go +++ b/compose/service/record_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from compose/service/record_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// compose/service/record_actions.yaml import ( "context" diff --git a/compose/service/record_test.go b/compose/service/record_test.go index 5ab65e9ef..5a20ec2cb 100644 --- a/compose/service/record_test.go +++ b/compose/service/record_test.go @@ -1,6 +1,7 @@ package service import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -16,7 +17,8 @@ func TestGeneralValueSetValidation(t *testing.T) { req = require.New(t) svc = record{ - ac: AccessControl(&permissions.ServiceAllowAll{}), + ctx: context.Background(), + ac: AccessControl(&permissions.ServiceAllowAll{}), } module = &types.Module{ Fields: types.ModuleFieldSet{ diff --git a/compose/service/service.go b/compose/service/service.go index cca47fe2f..02a2a2dad 100644 --- a/compose/service/service.go +++ b/compose/service/service.go @@ -3,20 +3,17 @@ package service import ( "context" "errors" + "fmt" "github.com/cortezaproject/corteza-server/pkg/healthcheck" "go.uber.org/zap" "time" - "github.com/cortezaproject/corteza-server/compose/repository" "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/actionlog" - actionlogRepository "github.com/cortezaproject/corteza-server/pkg/actionlog/repository" - "github.com/cortezaproject/corteza-server/pkg/app/options" - "github.com/cortezaproject/corteza-server/pkg/auth" "github.com/cortezaproject/corteza-server/pkg/corredor" "github.com/cortezaproject/corteza-server/pkg/eventbus" + "github.com/cortezaproject/corteza-server/pkg/options" "github.com/cortezaproject/corteza-server/pkg/permissions" - "github.com/cortezaproject/corteza-server/pkg/settings" "github.com/cortezaproject/corteza-server/pkg/store" "github.com/cortezaproject/corteza-server/pkg/store/minio" "github.com/cortezaproject/corteza-server/pkg/store/plain" @@ -30,9 +27,8 @@ type ( } Config struct { - ActionLog options.ActionLogOpt - Storage options.StorageOpt - GRPCClientSystem options.GRPCServerOpt + ActionLog options.ActionLogOpt + Storage options.StorageOpt } eventDispatcher interface { @@ -44,21 +40,21 @@ type ( var ( DefaultStore store.Store + // DefaultNgStore is an interface to storage backend(s) + // ng (next-gen) is a temporary prefix + // so that we can differentiate between it and the file-only store + DefaultNgStore storeInterface + DefaultLogger *zap.Logger DefaultActionlog actionlog.Recorder - DefaultSettings settings.Service - // DefaultPermissions Retrieves & stores permissions DefaultPermissions permissionServicer // DefaultAccessControl Access control checking DefaultAccessControl *accessControl - // CurrentSettings represents current compose settings - CurrentSettings = &types.Settings{} - DefaultNamespace NamespaceService DefaultImportSession ImportSessionService DefaultRecord RecordService @@ -78,10 +74,19 @@ var ( ) // Initializes compose-only services -func Initialize(ctx context.Context, log *zap.Logger, c Config) (err error) { - hcd := healthcheck.Defaults() +func Initialize(ctx context.Context, log *zap.Logger, s interface{}, c Config) (err error) { + var ( + hcd = healthcheck.Defaults() - var db = repository.DB(ctx) + cmpStore storeInterface + ok bool + ) + + // we're doing conversion to avoid having + // store interface exposed or generated inside app package + if cmpStore, ok = s.(storeInterface); !ok { + return fmt.Errorf("store %T is incompatible with compose storeInterface", s) + } DefaultLogger = log.Named("service") @@ -96,30 +101,17 @@ func Initialize(ctx context.Context, log *zap.Logger, c Config) (err error) { tee = log } - DefaultActionlog = actionlog.NewService( - // will log directly to system schema for now - actionlogRepository.Mysql(repository.DB(ctx).Quiet(), "sys_actionlog"), - log, - tee, - policy, - ) + DefaultActionlog = actionlog.NewService(DefaultNgStore, log, tee, policy) } if DefaultPermissions == nil { // Do not override permissions service stored under DefaultPermissions // to allow integration tests to inject own permission service - DefaultPermissions = permissions.Service(ctx, DefaultLogger, db, "compose_permission_rules") + DefaultPermissions = permissions.Service(ctx, DefaultLogger, cmpStore) } DefaultAccessControl = AccessControl(DefaultPermissions) - DefaultSettings = settings.NewService( - settings.NewRepository(repository.DB(ctx), "compose_settings"), - DefaultLogger, - DefaultAccessControl, - CurrentSettings, - ) - if DefaultStore == nil { const svcPath = "compose" if c.Storage.MinioEndpoint != "" { @@ -161,15 +153,6 @@ func Initialize(ctx context.Context, log *zap.Logger, c Config) (err error) { DefaultNamespace = Namespace() DefaultModule = Module() - //{ - // systemClientConn, err := NewSystemGRPCClient(ctx, c.GRPCClientSystem, DefaultLogger) - // if err != nil { - // return err - // } - // - // DefaultSystemUser = SystemUser(systemProto.NewUsersClient(systemClientConn)) - // DefaultSystemRole = SystemRole(systemProto.NewRolesClient(systemClientConn)) - //} DefaultSystemUser = systemService.DefaultUser DefaultImportSession = ImportSession() @@ -185,12 +168,6 @@ func Initialize(ctx context.Context, log *zap.Logger, c Config) (err error) { } func Activate(ctx context.Context) (err error) { - // Run initial update of current settings with super-user credentials - err = DefaultSettings.UpdateCurrent(auth.SetSuperUserContext(ctx)) - if err != nil { - return - } - return } diff --git a/compose/service/store_interface.gen.go b/compose/service/store_interface.gen.go new file mode 100644 index 000000000..7930914c1 --- /dev/null +++ b/compose/service/store_interface.gen.go @@ -0,0 +1,28 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/actionlog.yaml +// - store/compose_charts.yaml +// - store/compose_module_fields.yaml +// - store/compose_modules.yaml +// - store/compose_namespaces.yaml +// - store/compose_pages.yaml +// - store/rbac_rules.yaml + +type ( + // Interface combines interfaces of all supported store interfaces + storeInterface interface { + actionlogsStore + composeChartsStore + composeModuleFieldsStore + composeModulesStore + composeNamespacesStore + composePagesStore + rbacRulesStore + } +) diff --git a/compose/service/store_interface_actionlog.gen.go b/compose/service/store_interface_actionlog.gen.go new file mode 100644 index 000000000..1b67c3e64 --- /dev/null +++ b/compose/service/store_interface_actionlog.gen.go @@ -0,0 +1,27 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/actionlog.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/actionlog" +) + +type ( + actionlogsStore interface { + SearchActionlogs(ctx context.Context, f actionlog.Filter) (actionlog.ActionSet, actionlog.Filter, error) + CreateActionlog(ctx context.Context, rr ...*actionlog.Action) error + UpdateActionlog(ctx context.Context, rr ...*actionlog.Action) error + PartialUpdateActionlog(ctx context.Context, onlyColumns []string, rr ...*actionlog.Action) error + RemoveActionlog(ctx context.Context, rr ...*actionlog.Action) error + RemoveActionlogByID(ctx context.Context, ID uint64) error + + TruncateActionlogs(ctx context.Context) error + } +) diff --git a/compose/service/store_interface_compose_charts.gen.go b/compose/service/store_interface_compose_charts.gen.go new file mode 100644 index 000000000..6d711c03a --- /dev/null +++ b/compose/service/store_interface_compose_charts.gen.go @@ -0,0 +1,29 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/compose_charts.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeChartsStore interface { + SearchComposeCharts(ctx context.Context, f types.ChartFilter) (types.ChartSet, types.ChartFilter, error) + LookupComposeChartByID(ctx context.Context, id uint64) (*types.Chart, error) + LookupComposeChartByHandle(ctx context.Context, handle string) (*types.Chart, error) + CreateComposeChart(ctx context.Context, rr ...*types.Chart) error + UpdateComposeChart(ctx context.Context, rr ...*types.Chart) error + PartialUpdateComposeChart(ctx context.Context, onlyColumns []string, rr ...*types.Chart) error + RemoveComposeChart(ctx context.Context, rr ...*types.Chart) error + RemoveComposeChartByID(ctx context.Context, ID uint64) error + + TruncateComposeCharts(ctx context.Context) error + } +) diff --git a/compose/service/store_interface_compose_module_fields.gen.go b/compose/service/store_interface_compose_module_fields.gen.go new file mode 100644 index 000000000..c2893bf6e --- /dev/null +++ b/compose/service/store_interface_compose_module_fields.gen.go @@ -0,0 +1,26 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/compose_module_fields.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeModuleFieldsStore interface { + CreateComposeModuleField(ctx context.Context, rr ...*types.ModuleField) error + UpdateComposeModuleField(ctx context.Context, rr ...*types.ModuleField) error + PartialUpdateComposeModuleField(ctx context.Context, onlyColumns []string, rr ...*types.ModuleField) error + RemoveComposeModuleField(ctx context.Context, rr ...*types.ModuleField) error + RemoveComposeModuleFieldByID(ctx context.Context, ID uint64) error + + TruncateComposeModuleFields(ctx context.Context) error + } +) diff --git a/compose/service/store_interface_compose_modules.gen.go b/compose/service/store_interface_compose_modules.gen.go new file mode 100644 index 000000000..89f83f6e2 --- /dev/null +++ b/compose/service/store_interface_compose_modules.gen.go @@ -0,0 +1,29 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/compose_modules.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeModulesStore interface { + SearchComposeModules(ctx context.Context, f types.ModuleFilter) (types.ModuleSet, types.ModuleFilter, error) + LookupComposeModuleByHandle(ctx context.Context, handle string) (*types.Module, error) + LookupComposeModuleByID(ctx context.Context, id uint64) (*types.Module, error) + CreateComposeModule(ctx context.Context, rr ...*types.Module) error + UpdateComposeModule(ctx context.Context, rr ...*types.Module) error + PartialUpdateComposeModule(ctx context.Context, onlyColumns []string, rr ...*types.Module) error + RemoveComposeModule(ctx context.Context, rr ...*types.Module) error + RemoveComposeModuleByID(ctx context.Context, ID uint64) error + + TruncateComposeModules(ctx context.Context) error + } +) diff --git a/compose/service/store_interface_compose_namespaces.gen.go b/compose/service/store_interface_compose_namespaces.gen.go new file mode 100644 index 000000000..7bb68236e --- /dev/null +++ b/compose/service/store_interface_compose_namespaces.gen.go @@ -0,0 +1,29 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/compose_namespaces.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeNamespacesStore interface { + SearchComposeNamespaces(ctx context.Context, f types.NamespaceFilter) (types.NamespaceSet, types.NamespaceFilter, error) + LookupComposeNamespaceBySlug(ctx context.Context, slug string) (*types.Namespace, error) + LookupComposeNamespaceByID(ctx context.Context, id uint64) (*types.Namespace, error) + CreateComposeNamespace(ctx context.Context, rr ...*types.Namespace) error + UpdateComposeNamespace(ctx context.Context, rr ...*types.Namespace) error + PartialUpdateComposeNamespace(ctx context.Context, onlyColumns []string, rr ...*types.Namespace) error + RemoveComposeNamespace(ctx context.Context, rr ...*types.Namespace) error + RemoveComposeNamespaceByID(ctx context.Context, ID uint64) error + + TruncateComposeNamespaces(ctx context.Context) error + } +) diff --git a/compose/service/store_interface_compose_pages.gen.go b/compose/service/store_interface_compose_pages.gen.go new file mode 100644 index 000000000..8632ea81c --- /dev/null +++ b/compose/service/store_interface_compose_pages.gen.go @@ -0,0 +1,29 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/compose_pages.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composePagesStore interface { + SearchComposePages(ctx context.Context, f types.PageFilter) (types.PageSet, types.PageFilter, error) + LookupComposePageByHandle(ctx context.Context, handle string) (*types.Page, error) + LookupComposePageByID(ctx context.Context, id uint64) (*types.Page, error) + CreateComposePage(ctx context.Context, rr ...*types.Page) error + UpdateComposePage(ctx context.Context, rr ...*types.Page) error + PartialUpdateComposePage(ctx context.Context, onlyColumns []string, rr ...*types.Page) error + RemoveComposePage(ctx context.Context, rr ...*types.Page) error + RemoveComposePageByID(ctx context.Context, ID uint64) error + + TruncateComposePages(ctx context.Context) error + } +) diff --git a/compose/service/store_interface_rbac_rules.gen.go b/compose/service/store_interface_rbac_rules.gen.go new file mode 100644 index 000000000..c244d22ab --- /dev/null +++ b/compose/service/store_interface_rbac_rules.gen.go @@ -0,0 +1,27 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/rbac_rules.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/permissions" +) + +type ( + rbacRulesStore interface { + SearchRbacRules(ctx context.Context, f permissions.RuleFilter) (permissions.RuleSet, permissions.RuleFilter, error) + CreateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + UpdateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + PartialUpdateRbacRule(ctx context.Context, onlyColumns []string, rr ...*permissions.Rule) error + RemoveRbacRule(ctx context.Context, rr ...*permissions.Rule) error + RemoveRbacRuleByRoleIDResourceOperation(ctx context.Context, roleID uint64, resource string, operation string) error + + TruncateRbacRules(ctx context.Context) error + } +) diff --git a/compose/service/system_grpc_client.go b/compose/service/system_grpc_client.go deleted file mode 100644 index 82dca7cb2..000000000 --- a/compose/service/system_grpc_client.go +++ /dev/null @@ -1,33 +0,0 @@ -package service - -import ( - "context" - - "go.uber.org/zap" - "go.uber.org/zap/zapgrpc" - "google.golang.org/grpc" - "google.golang.org/grpc/grpclog" - - "github.com/cortezaproject/corteza-server/pkg/app/options" -) - -// Connects to system gRPC server -func NewSystemGRPCClient(ctx context.Context, opt options.GRPCServerOpt, logger *zap.Logger) (c *grpc.ClientConn, err error) { - if opt.ClientLog { - // Send logs to zap - // - // waiting for https://github.com/uber-go/zap/pull/538 - grpclog.SetLogger(zapgrpc.NewLogger(logger.Named("grpc-client-system"))) - } - - var dopts = []grpc.DialOption{ - // @todo insecure? - grpc.WithInsecure(), - } - - if opt.ClientMaxBackoffDelay > 0 { - dopts = append(dopts, grpc.WithBackoffMaxDelay(opt.ClientMaxBackoffDelay)) - } - - return grpc.DialContext(ctx, opt.Addr, dopts...) -} diff --git a/compose/service/system_role.go b/compose/service/system_role.go deleted file mode 100644 index 2acd96b7f..000000000 --- a/compose/service/system_role.go +++ /dev/null @@ -1,48 +0,0 @@ -package service - -import ( - "context" - - "google.golang.org/grpc/metadata" - - "github.com/cortezaproject/corteza-server/pkg/auth" - "github.com/cortezaproject/corteza-server/system/proto" - "github.com/cortezaproject/corteza-server/system/types" -) - -// gRPC client for - -type ( - systemRole struct { - client proto.RolesClient - } -) - -func SystemRole(c proto.RolesClient) *systemRole { - return &systemRole{ - client: c, - } -} - -func (svc systemRole) Find(ctx context.Context) (rr types.RoleSet, err error) { - ctx = metadata.NewOutgoingContext(ctx, metadata.MD{ - "jwt": []string{auth.GetJwtFromContext(ctx)}, - }) - - rsp, err := svc.client.Find(ctx, &proto.FindRoleRequest{}) - if err != nil { - return nil, err - } - - rr = make([]*types.Role, len(rsp.Roles)) - - for i := range rsp.Roles { - rr[i] = &types.Role{ - ID: rsp.Roles[i].ID, - Name: rsp.Roles[i].Name, - Handle: rsp.Roles[i].Handle, - } - } - - return rr, nil -} diff --git a/compose/service/system_user.go b/compose/service/system_user.go deleted file mode 100644 index 355eeb0c3..000000000 --- a/compose/service/system_user.go +++ /dev/null @@ -1,58 +0,0 @@ -package service - -import ( - "context" - - "google.golang.org/grpc" - "google.golang.org/grpc/metadata" - - "github.com/cortezaproject/corteza-server/pkg/auth" - "github.com/cortezaproject/corteza-server/system/proto" - "github.com/cortezaproject/corteza-server/system/types" -) - -// gRPC client for - -type ( - systemUser struct { - client proto.UsersClient - } -) - -func SystemUser(c proto.UsersClient) *systemUser { - return &systemUser{ - client: c, - } -} - -func (svc systemUser) MakeJWT(ctx context.Context, ID uint64) (string, error) { - ctx = metadata.NewOutgoingContext(ctx, metadata.MD{ - "jwt": []string{auth.GetJwtFromContext(ctx)}, - }) - - rsp, err := svc.client.MakeJWT(ctx, &proto.MakeJWTUserRequest{UserID: ID}, grpc.WaitForReady(true)) - if err != nil { - return "", err - } - - return rsp.JWT, nil -} - -func (svc systemUser) FindByID(ctx context.Context, ID uint64) (*types.User, error) { - ctx = metadata.NewOutgoingContext(ctx, metadata.MD{ - "jwt": []string{auth.GetJwtFromContext(ctx)}, - }) - - rsp, err := svc.client.FindByID(ctx, &proto.FindByIDUserRequest{UserID: ID}) - if err != nil { - return nil, err - } - - return &types.User{ - ID: rsp.User.ID, - Email: rsp.User.Email, - Name: rsp.User.Name, - Handle: rsp.User.Handle, - Kind: types.UserKind(rsp.User.Kind), - }, nil -} diff --git a/messaging/importer/channel.go b/messaging/importer/channel.go index 893b91682..2fe817d12 100644 --- a/messaging/importer/channel.go +++ b/messaging/importer/channel.go @@ -2,10 +2,8 @@ package importer import ( "context" + "errors" "fmt" - - "github.com/pkg/errors" - "github.com/cortezaproject/corteza-server/messaging/types" "github.com/cortezaproject/corteza-server/pkg/deinterfacer" "github.com/cortezaproject/corteza-server/pkg/importer" @@ -67,7 +65,7 @@ func (cImp *Channel) Cast(name string, def interface{}) (err error) { cImp.set = append(cImp.set, channel) } else if channel.ID == 0 { - return errors.Errorf("channel name %q already defined in this import session", channel.Name) + return fmt.Errorf("channel name %q already defined in this import session", channel.Name) } else { cImp.dirty[channel.ID] = true } @@ -122,6 +120,10 @@ func (cImp *Channel) Store(ctx context.Context, k channelKeeper) error { channel, err = k.Update(channel) } + for errors.Unwrap(err) != nil { + err = errors.Unwrap(err) + } + if err != nil { return } diff --git a/messaging/importer/default.go b/messaging/importer/default.go index 4ba19976b..54c903238 100644 --- a/messaging/importer/default.go +++ b/messaging/importer/default.go @@ -2,15 +2,14 @@ package importer import ( "context" - "io" - - "gopkg.in/yaml.v2" - "github.com/cortezaproject/corteza-server/messaging/service" "github.com/cortezaproject/corteza-server/messaging/types" "github.com/cortezaproject/corteza-server/pkg/permissions" "github.com/cortezaproject/corteza-server/pkg/settings" + sysService "github.com/cortezaproject/corteza-server/system/service" sysTypes "github.com/cortezaproject/corteza-server/system/types" + "gopkg.in/yaml.v2" + "io" ) // Import performs standard import procedure with default services @@ -58,7 +57,7 @@ func Import(ctx context.Context, ff ...io.Reader) (err error) { ctx, service.DefaultChannel.With(ctx), service.DefaultAccessControl, - service.DefaultSettings, + sysService.DefaultSettings, roles, ) } diff --git a/messaging/service/access_control.go b/messaging/service/access_control.go index 8a31197df..af44884e8 100644 --- a/messaging/service/access_control.go +++ b/messaging/service/access_control.go @@ -16,14 +16,10 @@ type ( } accessControlPermissionServicer interface { - Can(context.Context, permissions.Resource, permissions.Operation, ...permissions.CheckAccessFunc) bool + Can([]uint64, permissions.Resource, permissions.Operation, ...permissions.CheckAccessFunc) bool Grant(context.Context, permissions.Whitelist, ...*permissions.Rule) error FindRulesByRoleID(roleID uint64) (rr permissions.RuleSet) - ResourceFilter(context.Context, permissions.Resource, permissions.Operation, permissions.Access) *permissions.ResourceFilter - } - - permissionResource interface { - PermissionResource() permissions.Resource + ResourceFilter([]uint64, permissions.Resource, permissions.Operation, permissions.Access) *permissions.ResourceFilter } ) @@ -78,39 +74,39 @@ func (svc accessControl) CanCreateGroupChannel(ctx context.Context) bool { } func (svc accessControl) CanUpdateChannel(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "update", svc.isChannelOwnerFallback(ctx, ch)) + return svc.can(ctx, ch.PermissionResource(), "update", svc.isChannelOwnerFallback(ctx, ch)) } func (svc accessControl) CanReadChannel(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "read", svc.canReadFallback(ch)) + return svc.can(ctx, ch.PermissionResource(), "read", svc.canReadFallback(ch)) } func (svc accessControl) CanJoinChannel(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "join", svc.canJoinFallback(ctx, ch)) + return svc.can(ctx, ch.PermissionResource(), "join", svc.canJoinFallback(ctx, ch)) } func (svc accessControl) CanLeaveChannel(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "leave", permissions.Allowed) + return svc.can(ctx, ch.PermissionResource(), "leave", permissions.Allowed) } func (svc accessControl) CanArchiveChannel(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "archive", svc.isChannelOwnerFallback(ctx, ch)) + return svc.can(ctx, ch.PermissionResource(), "archive", svc.isChannelOwnerFallback(ctx, ch)) } func (svc accessControl) CanUnarchiveChannel(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "unarchive", svc.isChannelOwnerFallback(ctx, ch)) + return svc.can(ctx, ch.PermissionResource(), "unarchive", svc.isChannelOwnerFallback(ctx, ch)) } func (svc accessControl) CanDeleteChannel(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "delete", svc.isChannelOwnerFallback(ctx, ch)) + return svc.can(ctx, ch.PermissionResource(), "delete", svc.isChannelOwnerFallback(ctx, ch)) } func (svc accessControl) CanUndeleteChannel(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "undelete", svc.isChannelOwnerFallback(ctx, ch)) + return svc.can(ctx, ch.PermissionResource(), "undelete", svc.isChannelOwnerFallback(ctx, ch)) } func (svc accessControl) CanManageChannelMembers(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "members.manage", svc.isChannelOwnerFallback(ctx, ch)) + return svc.can(ctx, ch.PermissionResource(), "members.manage", svc.isChannelOwnerFallback(ctx, ch)) } func (svc accessControl) CanChangeChannelMembershipPolicy(ctx context.Context, ch *types.Channel) bool { @@ -119,44 +115,44 @@ func (svc accessControl) CanChangeChannelMembershipPolicy(ctx context.Context, c } func (svc accessControl) CanManageChannelAttachments(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "attachments.manage") + return svc.can(ctx, ch.PermissionResource(), "attachments.manage") } func (svc accessControl) CanSendMessage(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "message.send", svc.canSendMessagesFallback(ch)) + return svc.can(ctx, ch.PermissionResource(), "message.send", svc.canSendMessagesFallback(ch)) } func (svc accessControl) CanReplyMessage(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "message.reply", permissions.Allowed) + return svc.can(ctx, ch.PermissionResource(), "message.reply", permissions.Allowed) } func (svc accessControl) CanEmbedMessage(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "message.embed", permissions.Allowed) + return svc.can(ctx, ch.PermissionResource(), "message.embed", permissions.Allowed) } func (svc accessControl) CanAttachMessage(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "message.attach", svc.canSendMessagesFallback(ch)) + return svc.can(ctx, ch.PermissionResource(), "message.attach", svc.canSendMessagesFallback(ch)) } func (svc accessControl) CanUpdateOwnMessages(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "message.update.own", permissions.Allowed) + return svc.can(ctx, ch.PermissionResource(), "message.update.own", permissions.Allowed) } func (svc accessControl) CanUpdateMessages(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "message.update.all") + return svc.can(ctx, ch.PermissionResource(), "message.update.all") } func (svc accessControl) CanDeleteOwnMessages(ctx context.Context, ch *types.Channel) bool { // @todo implement - return svc.can(ctx, ch, "message.delete.own", permissions.Allowed) + return svc.can(ctx, ch.PermissionResource(), "message.delete.own", permissions.Allowed) } func (svc accessControl) CanDeleteMessages(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "message.delete.all") + return svc.can(ctx, ch.PermissionResource(), "message.delete.all") } func (svc accessControl) CanReactMessage(ctx context.Context, ch *types.Channel) bool { - return svc.can(ctx, ch, "message.react", permissions.Allowed) + return svc.can(ctx, ch.PermissionResource(), "message.react", permissions.Allowed) } func (svc accessControl) canJoinFallback(ctx context.Context, ch *types.Channel) func() permissions.Access { @@ -208,8 +204,36 @@ func (svc accessControl) isChannelOwnerFallback(ctx context.Context, ch *types.C } } -func (svc accessControl) can(ctx context.Context, res permissionResource, op permissions.Operation, ff ...permissions.CheckAccessFunc) bool { - return svc.permissions.Can(ctx, res.PermissionResource(), op, ff...) +func (svc accessControl) can(ctx context.Context, res permissions.Resource, op permissions.Operation, ff ...permissions.CheckAccessFunc) bool { + var ( + u = auth.GetIdentityFromContext(ctx) + roles = u.Roles() + ) + + if auth.IsSuperUser(u) { + // Temp solution to allow migration from passing context to ResourceFilter + // and checking "superuser" privileges there to more sustainable solution + // (eg: creating super-role with allow-all) + return true + } + + return svc.permissions.Can(roles, res, op, ff...) +} + +func (svc accessControl) filter(ctx context.Context, res permissions.Resource, op permissions.Operation, a permissions.Access) *permissions.ResourceFilter { + var ( + u = auth.GetIdentityFromContext(ctx) + roles = u.Roles() + ) + + if auth.IsSuperUser(u) { + // Temp solution to allow migration from passing context to ResourceFilter + // and checking "superuser" privileges there to more sustainable solution + // (eg: creating super-role with allow-all) + return permissions.NewSuperuserFilter() + } + + return svc.permissions.ResourceFilter(roles, res, op, a) } func (svc accessControl) Grant(ctx context.Context, rr ...*permissions.Rule) error { diff --git a/messaging/service/access_control_actions.gen.go b/messaging/service/access_control_actions.gen.go index 77ad9beff..af5f7cd61 100644 --- a/messaging/service/access_control_actions.gen.go +++ b/messaging/service/access_control_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from messaging/service/access_control_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// messaging/service/access_control_actions.yaml import ( "context" diff --git a/messaging/service/attachment_actions.gen.go b/messaging/service/attachment_actions.gen.go index bb74f50e5..50bfcac19 100644 --- a/messaging/service/attachment_actions.gen.go +++ b/messaging/service/attachment_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from messaging/service/attachment_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// messaging/service/attachment_actions.yaml import ( "context" diff --git a/messaging/service/channel_actions.gen.go b/messaging/service/channel_actions.gen.go index 076faff5d..dab2ca87a 100644 --- a/messaging/service/channel_actions.gen.go +++ b/messaging/service/channel_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from messaging/service/channel_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// messaging/service/channel_actions.yaml import ( "context" diff --git a/messaging/service/event/channel.gen.go b/messaging/service/event/channel.gen.go deleted file mode 100644 index d17d7fa4a..000000000 --- a/messaging/service/event/channel.gen.go +++ /dev/null @@ -1,459 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// messaging/service/event/events.yaml -// -// Regenerate with: -// go run codegen/v2/events.go --service messaging -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/messaging/types" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // channelBase - // - // This type is auto-generated. - channelBase struct { - immutable bool - channel *types.Channel - oldChannel *types.Channel - invoker auth.Identifiable - } - - // channelOnManual - // - // This type is auto-generated. - channelOnManual struct { - *channelBase - } - - // channelBeforeCreate - // - // This type is auto-generated. - channelBeforeCreate struct { - *channelBase - } - - // channelBeforeUpdate - // - // This type is auto-generated. - channelBeforeUpdate struct { - *channelBase - } - - // channelBeforeDelete - // - // This type is auto-generated. - channelBeforeDelete struct { - *channelBase - } - - // channelAfterCreate - // - // This type is auto-generated. - channelAfterCreate struct { - *channelBase - } - - // channelAfterUpdate - // - // This type is auto-generated. - channelAfterUpdate struct { - *channelBase - } - - // channelAfterDelete - // - // This type is auto-generated. - channelAfterDelete struct { - *channelBase - } -) - -// ResourceType returns "messaging:channel" -// -// This function is auto-generated. -func (channelBase) ResourceType() string { - return "messaging:channel" -} - -// EventType on channelOnManual returns "onManual" -// -// This function is auto-generated. -func (channelOnManual) EventType() string { - return "onManual" -} - -// EventType on channelBeforeCreate returns "beforeCreate" -// -// This function is auto-generated. -func (channelBeforeCreate) EventType() string { - return "beforeCreate" -} - -// EventType on channelBeforeUpdate returns "beforeUpdate" -// -// This function is auto-generated. -func (channelBeforeUpdate) EventType() string { - return "beforeUpdate" -} - -// EventType on channelBeforeDelete returns "beforeDelete" -// -// This function is auto-generated. -func (channelBeforeDelete) EventType() string { - return "beforeDelete" -} - -// EventType on channelAfterCreate returns "afterCreate" -// -// This function is auto-generated. -func (channelAfterCreate) EventType() string { - return "afterCreate" -} - -// EventType on channelAfterUpdate returns "afterUpdate" -// -// This function is auto-generated. -func (channelAfterUpdate) EventType() string { - return "afterUpdate" -} - -// EventType on channelAfterDelete returns "afterDelete" -// -// This function is auto-generated. -func (channelAfterDelete) EventType() string { - return "afterDelete" -} - -// ChannelOnManual creates onManual for messaging:channel resource -// -// This function is auto-generated. -func ChannelOnManual( - argChannel *types.Channel, - argOldChannel *types.Channel, -) *channelOnManual { - return &channelOnManual{ - channelBase: &channelBase{ - immutable: false, - channel: argChannel, - oldChannel: argOldChannel, - }, - } -} - -// ChannelOnManualImmutable creates onManual for messaging:channel resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ChannelOnManualImmutable( - argChannel *types.Channel, - argOldChannel *types.Channel, -) *channelOnManual { - return &channelOnManual{ - channelBase: &channelBase{ - immutable: true, - channel: argChannel, - oldChannel: argOldChannel, - }, - } -} - -// ChannelBeforeCreate creates beforeCreate for messaging:channel resource -// -// This function is auto-generated. -func ChannelBeforeCreate( - argChannel *types.Channel, - argOldChannel *types.Channel, -) *channelBeforeCreate { - return &channelBeforeCreate{ - channelBase: &channelBase{ - immutable: false, - channel: argChannel, - oldChannel: argOldChannel, - }, - } -} - -// ChannelBeforeCreateImmutable creates beforeCreate for messaging:channel resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ChannelBeforeCreateImmutable( - argChannel *types.Channel, - argOldChannel *types.Channel, -) *channelBeforeCreate { - return &channelBeforeCreate{ - channelBase: &channelBase{ - immutable: true, - channel: argChannel, - oldChannel: argOldChannel, - }, - } -} - -// ChannelBeforeUpdate creates beforeUpdate for messaging:channel resource -// -// This function is auto-generated. -func ChannelBeforeUpdate( - argChannel *types.Channel, - argOldChannel *types.Channel, -) *channelBeforeUpdate { - return &channelBeforeUpdate{ - channelBase: &channelBase{ - immutable: false, - channel: argChannel, - oldChannel: argOldChannel, - }, - } -} - -// ChannelBeforeUpdateImmutable creates beforeUpdate for messaging:channel resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ChannelBeforeUpdateImmutable( - argChannel *types.Channel, - argOldChannel *types.Channel, -) *channelBeforeUpdate { - return &channelBeforeUpdate{ - channelBase: &channelBase{ - immutable: true, - channel: argChannel, - oldChannel: argOldChannel, - }, - } -} - -// ChannelBeforeDelete creates beforeDelete for messaging:channel resource -// -// This function is auto-generated. -func ChannelBeforeDelete( - argChannel *types.Channel, - argOldChannel *types.Channel, -) *channelBeforeDelete { - return &channelBeforeDelete{ - channelBase: &channelBase{ - immutable: false, - channel: argChannel, - oldChannel: argOldChannel, - }, - } -} - -// ChannelBeforeDeleteImmutable creates beforeDelete for messaging:channel resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ChannelBeforeDeleteImmutable( - argChannel *types.Channel, - argOldChannel *types.Channel, -) *channelBeforeDelete { - return &channelBeforeDelete{ - channelBase: &channelBase{ - immutable: true, - channel: argChannel, - oldChannel: argOldChannel, - }, - } -} - -// ChannelAfterCreate creates afterCreate for messaging:channel resource -// -// This function is auto-generated. -func ChannelAfterCreate( - argChannel *types.Channel, - argOldChannel *types.Channel, -) *channelAfterCreate { - return &channelAfterCreate{ - channelBase: &channelBase{ - immutable: false, - channel: argChannel, - oldChannel: argOldChannel, - }, - } -} - -// ChannelAfterCreateImmutable creates afterCreate for messaging:channel resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ChannelAfterCreateImmutable( - argChannel *types.Channel, - argOldChannel *types.Channel, -) *channelAfterCreate { - return &channelAfterCreate{ - channelBase: &channelBase{ - immutable: true, - channel: argChannel, - oldChannel: argOldChannel, - }, - } -} - -// ChannelAfterUpdate creates afterUpdate for messaging:channel resource -// -// This function is auto-generated. -func ChannelAfterUpdate( - argChannel *types.Channel, - argOldChannel *types.Channel, -) *channelAfterUpdate { - return &channelAfterUpdate{ - channelBase: &channelBase{ - immutable: false, - channel: argChannel, - oldChannel: argOldChannel, - }, - } -} - -// ChannelAfterUpdateImmutable creates afterUpdate for messaging:channel resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ChannelAfterUpdateImmutable( - argChannel *types.Channel, - argOldChannel *types.Channel, -) *channelAfterUpdate { - return &channelAfterUpdate{ - channelBase: &channelBase{ - immutable: true, - channel: argChannel, - oldChannel: argOldChannel, - }, - } -} - -// ChannelAfterDelete creates afterDelete for messaging:channel resource -// -// This function is auto-generated. -func ChannelAfterDelete( - argChannel *types.Channel, - argOldChannel *types.Channel, -) *channelAfterDelete { - return &channelAfterDelete{ - channelBase: &channelBase{ - immutable: false, - channel: argChannel, - oldChannel: argOldChannel, - }, - } -} - -// ChannelAfterDeleteImmutable creates afterDelete for messaging:channel resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ChannelAfterDeleteImmutable( - argChannel *types.Channel, - argOldChannel *types.Channel, -) *channelAfterDelete { - return &channelAfterDelete{ - channelBase: &channelBase{ - immutable: true, - channel: argChannel, - oldChannel: argOldChannel, - }, - } -} - -// SetChannel sets new channel value -// -// This function is auto-generated. -func (res *channelBase) SetChannel(argChannel *types.Channel) { - res.channel = argChannel -} - -// Channel returns channel -// -// This function is auto-generated. -func (res channelBase) Channel() *types.Channel { - return res.channel -} - -// OldChannel returns oldChannel -// -// This function is auto-generated. -func (res channelBase) OldChannel() *types.Channel { - return res.oldChannel -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *channelBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res channelBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res channelBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["channel"], err = json.Marshal(res.channel); err != nil { - return nil, err - } - - if args["oldChannel"], err = json.Marshal(res.oldChannel); err != nil { - return nil, err - } - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *channelBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.channel != nil { - if r, ok := results["result"]; ok && len(results) == 1 { - if err = json.Unmarshal(r, res.channel); err != nil { - return - } - } - } - - if res.channel != nil { - if r, ok := results["channel"]; ok { - if err = json.Unmarshal(r, res.channel); err != nil { - return - } - } - } - - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/messaging/service/event/channel_member.gen.go b/messaging/service/event/channel_member.gen.go deleted file mode 100644 index f69af28d9..000000000 --- a/messaging/service/event/channel_member.gen.go +++ /dev/null @@ -1,522 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// messaging/service/event/events.yaml -// -// Regenerate with: -// go run codegen/v2/events.go --service messaging -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/messaging/types" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // channelMemberBase - // - // This type is auto-generated. - channelMemberBase struct { - immutable bool - member *types.ChannelMember - channel *types.Channel - invoker auth.Identifiable - } - - // channelMemberBeforeJoin - // - // This type is auto-generated. - channelMemberBeforeJoin struct { - *channelMemberBase - } - - // channelMemberBeforePart - // - // This type is auto-generated. - channelMemberBeforePart struct { - *channelMemberBase - } - - // channelMemberBeforeAdd - // - // This type is auto-generated. - channelMemberBeforeAdd struct { - *channelMemberBase - } - - // channelMemberBeforeRemove - // - // This type is auto-generated. - channelMemberBeforeRemove struct { - *channelMemberBase - } - - // channelMemberAfterJoin - // - // This type is auto-generated. - channelMemberAfterJoin struct { - *channelMemberBase - } - - // channelMemberAfterPart - // - // This type is auto-generated. - channelMemberAfterPart struct { - *channelMemberBase - } - - // channelMemberAfterAdd - // - // This type is auto-generated. - channelMemberAfterAdd struct { - *channelMemberBase - } - - // channelMemberAfterRemove - // - // This type is auto-generated. - channelMemberAfterRemove struct { - *channelMemberBase - } -) - -// ResourceType returns "messaging:channel:member" -// -// This function is auto-generated. -func (channelMemberBase) ResourceType() string { - return "messaging:channel:member" -} - -// EventType on channelMemberBeforeJoin returns "beforeJoin" -// -// This function is auto-generated. -func (channelMemberBeforeJoin) EventType() string { - return "beforeJoin" -} - -// EventType on channelMemberBeforePart returns "beforePart" -// -// This function is auto-generated. -func (channelMemberBeforePart) EventType() string { - return "beforePart" -} - -// EventType on channelMemberBeforeAdd returns "beforeAdd" -// -// This function is auto-generated. -func (channelMemberBeforeAdd) EventType() string { - return "beforeAdd" -} - -// EventType on channelMemberBeforeRemove returns "beforeRemove" -// -// This function is auto-generated. -func (channelMemberBeforeRemove) EventType() string { - return "beforeRemove" -} - -// EventType on channelMemberAfterJoin returns "afterJoin" -// -// This function is auto-generated. -func (channelMemberAfterJoin) EventType() string { - return "afterJoin" -} - -// EventType on channelMemberAfterPart returns "afterPart" -// -// This function is auto-generated. -func (channelMemberAfterPart) EventType() string { - return "afterPart" -} - -// EventType on channelMemberAfterAdd returns "afterAdd" -// -// This function is auto-generated. -func (channelMemberAfterAdd) EventType() string { - return "afterAdd" -} - -// EventType on channelMemberAfterRemove returns "afterRemove" -// -// This function is auto-generated. -func (channelMemberAfterRemove) EventType() string { - return "afterRemove" -} - -// ChannelMemberBeforeJoin creates beforeJoin for messaging:channel:member resource -// -// This function is auto-generated. -func ChannelMemberBeforeJoin( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberBeforeJoin { - return &channelMemberBeforeJoin{ - channelMemberBase: &channelMemberBase{ - immutable: false, - member: argMember, - channel: argChannel, - }, - } -} - -// ChannelMemberBeforeJoinImmutable creates beforeJoin for messaging:channel:member resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ChannelMemberBeforeJoinImmutable( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberBeforeJoin { - return &channelMemberBeforeJoin{ - channelMemberBase: &channelMemberBase{ - immutable: true, - member: argMember, - channel: argChannel, - }, - } -} - -// ChannelMemberBeforePart creates beforePart for messaging:channel:member resource -// -// This function is auto-generated. -func ChannelMemberBeforePart( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberBeforePart { - return &channelMemberBeforePart{ - channelMemberBase: &channelMemberBase{ - immutable: false, - member: argMember, - channel: argChannel, - }, - } -} - -// ChannelMemberBeforePartImmutable creates beforePart for messaging:channel:member resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ChannelMemberBeforePartImmutable( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberBeforePart { - return &channelMemberBeforePart{ - channelMemberBase: &channelMemberBase{ - immutable: true, - member: argMember, - channel: argChannel, - }, - } -} - -// ChannelMemberBeforeAdd creates beforeAdd for messaging:channel:member resource -// -// This function is auto-generated. -func ChannelMemberBeforeAdd( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberBeforeAdd { - return &channelMemberBeforeAdd{ - channelMemberBase: &channelMemberBase{ - immutable: false, - member: argMember, - channel: argChannel, - }, - } -} - -// ChannelMemberBeforeAddImmutable creates beforeAdd for messaging:channel:member resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ChannelMemberBeforeAddImmutable( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberBeforeAdd { - return &channelMemberBeforeAdd{ - channelMemberBase: &channelMemberBase{ - immutable: true, - member: argMember, - channel: argChannel, - }, - } -} - -// ChannelMemberBeforeRemove creates beforeRemove for messaging:channel:member resource -// -// This function is auto-generated. -func ChannelMemberBeforeRemove( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberBeforeRemove { - return &channelMemberBeforeRemove{ - channelMemberBase: &channelMemberBase{ - immutable: false, - member: argMember, - channel: argChannel, - }, - } -} - -// ChannelMemberBeforeRemoveImmutable creates beforeRemove for messaging:channel:member resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ChannelMemberBeforeRemoveImmutable( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberBeforeRemove { - return &channelMemberBeforeRemove{ - channelMemberBase: &channelMemberBase{ - immutable: true, - member: argMember, - channel: argChannel, - }, - } -} - -// ChannelMemberAfterJoin creates afterJoin for messaging:channel:member resource -// -// This function is auto-generated. -func ChannelMemberAfterJoin( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberAfterJoin { - return &channelMemberAfterJoin{ - channelMemberBase: &channelMemberBase{ - immutable: false, - member: argMember, - channel: argChannel, - }, - } -} - -// ChannelMemberAfterJoinImmutable creates afterJoin for messaging:channel:member resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ChannelMemberAfterJoinImmutable( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberAfterJoin { - return &channelMemberAfterJoin{ - channelMemberBase: &channelMemberBase{ - immutable: true, - member: argMember, - channel: argChannel, - }, - } -} - -// ChannelMemberAfterPart creates afterPart for messaging:channel:member resource -// -// This function is auto-generated. -func ChannelMemberAfterPart( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberAfterPart { - return &channelMemberAfterPart{ - channelMemberBase: &channelMemberBase{ - immutable: false, - member: argMember, - channel: argChannel, - }, - } -} - -// ChannelMemberAfterPartImmutable creates afterPart for messaging:channel:member resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ChannelMemberAfterPartImmutable( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberAfterPart { - return &channelMemberAfterPart{ - channelMemberBase: &channelMemberBase{ - immutable: true, - member: argMember, - channel: argChannel, - }, - } -} - -// ChannelMemberAfterAdd creates afterAdd for messaging:channel:member resource -// -// This function is auto-generated. -func ChannelMemberAfterAdd( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberAfterAdd { - return &channelMemberAfterAdd{ - channelMemberBase: &channelMemberBase{ - immutable: false, - member: argMember, - channel: argChannel, - }, - } -} - -// ChannelMemberAfterAddImmutable creates afterAdd for messaging:channel:member resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ChannelMemberAfterAddImmutable( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberAfterAdd { - return &channelMemberAfterAdd{ - channelMemberBase: &channelMemberBase{ - immutable: true, - member: argMember, - channel: argChannel, - }, - } -} - -// ChannelMemberAfterRemove creates afterRemove for messaging:channel:member resource -// -// This function is auto-generated. -func ChannelMemberAfterRemove( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberAfterRemove { - return &channelMemberAfterRemove{ - channelMemberBase: &channelMemberBase{ - immutable: false, - member: argMember, - channel: argChannel, - }, - } -} - -// ChannelMemberAfterRemoveImmutable creates afterRemove for messaging:channel:member resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ChannelMemberAfterRemoveImmutable( - argMember *types.ChannelMember, - argChannel *types.Channel, -) *channelMemberAfterRemove { - return &channelMemberAfterRemove{ - channelMemberBase: &channelMemberBase{ - immutable: true, - member: argMember, - channel: argChannel, - }, - } -} - -// SetMember sets new member value -// -// This function is auto-generated. -func (res *channelMemberBase) SetMember(argMember *types.ChannelMember) { - res.member = argMember -} - -// Member returns member -// -// This function is auto-generated. -func (res channelMemberBase) Member() *types.ChannelMember { - return res.member -} - -// SetChannel sets new channel value -// -// This function is auto-generated. -func (res *channelMemberBase) SetChannel(argChannel *types.Channel) { - res.channel = argChannel -} - -// Channel returns channel -// -// This function is auto-generated. -func (res channelMemberBase) Channel() *types.Channel { - return res.channel -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *channelMemberBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res channelMemberBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res channelMemberBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["member"], err = json.Marshal(res.member); err != nil { - return nil, err - } - - if args["channel"], err = json.Marshal(res.channel); err != nil { - return nil, err - } - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *channelMemberBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.member != nil { - if r, ok := results["result"]; ok && len(results) == 1 { - if err = json.Unmarshal(r, res.member); err != nil { - return - } - } - } - - if res.member != nil { - if r, ok := results["member"]; ok { - if err = json.Unmarshal(r, res.member); err != nil { - return - } - } - } - - if res.channel != nil { - if r, ok := results["channel"]; ok { - if err = json.Unmarshal(r, res.channel); err != nil { - return - } - } - } - - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/messaging/service/event/command.gen.go b/messaging/service/event/command.gen.go deleted file mode 100644 index 6729c8d88..000000000 --- a/messaging/service/event/command.gen.go +++ /dev/null @@ -1,156 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// messaging/service/event/events.yaml -// -// Regenerate with: -// go run codegen/v2/events.go --service messaging -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/messaging/types" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // commandBase - // - // This type is auto-generated. - commandBase struct { - immutable bool - command *types.Command - channel *types.Channel - invoker auth.Identifiable - } - - // commandOnInvoke - // - // This type is auto-generated. - commandOnInvoke struct { - *commandBase - } -) - -// ResourceType returns "messaging:command" -// -// This function is auto-generated. -func (commandBase) ResourceType() string { - return "messaging:command" -} - -// EventType on commandOnInvoke returns "onInvoke" -// -// This function is auto-generated. -func (commandOnInvoke) EventType() string { - return "onInvoke" -} - -// CommandOnInvoke creates onInvoke for messaging:command resource -// -// This function is auto-generated. -func CommandOnInvoke( - argCommand *types.Command, - argChannel *types.Channel, -) *commandOnInvoke { - return &commandOnInvoke{ - commandBase: &commandBase{ - immutable: false, - command: argCommand, - channel: argChannel, - }, - } -} - -// CommandOnInvokeImmutable creates onInvoke for messaging:command resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func CommandOnInvokeImmutable( - argCommand *types.Command, - argChannel *types.Channel, -) *commandOnInvoke { - return &commandOnInvoke{ - commandBase: &commandBase{ - immutable: true, - command: argCommand, - channel: argChannel, - }, - } -} - -// Command returns command -// -// This function is auto-generated. -func (res commandBase) Command() *types.Command { - return res.command -} - -// Channel returns channel -// -// This function is auto-generated. -func (res commandBase) Channel() *types.Channel { - return res.channel -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *commandBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res commandBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res commandBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["command"], err = json.Marshal(res.command); err != nil { - return nil, err - } - - if args["channel"], err = json.Marshal(res.channel); err != nil { - return nil, err - } - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *commandBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.command != nil { - if r, ok := results["result"]; ok && len(results) == 1 { - if err = json.Unmarshal(r, res.command); err != nil { - return - } - } - } - - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/messaging/service/event/events.gen.go b/messaging/service/event/events.gen.go new file mode 100644 index 000000000..27f89ad62 --- /dev/null +++ b/messaging/service/event/events.gen.go @@ -0,0 +1,1770 @@ +package event + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// messaging/service/event/events.yaml + +import ( + "encoding/json" + "github.com/cortezaproject/corteza-server/messaging/types" + "github.com/cortezaproject/corteza-server/pkg/auth" +) + +// dummy placing to simplify import generation logic +var _ = json.NewEncoder + +type ( + + // messagingBase + // + // This type is auto-generated. + messagingBase struct { + immutable bool + invoker auth.Identifiable + } + + // messagingOnManual + // + // This type is auto-generated. + messagingOnManual struct { + *messagingBase + } + + // messagingOnInterval + // + // This type is auto-generated. + messagingOnInterval struct { + *messagingBase + } + + // messagingOnTimestamp + // + // This type is auto-generated. + messagingOnTimestamp struct { + *messagingBase + } + + // channelBase + // + // This type is auto-generated. + channelBase struct { + immutable bool + channel *types.Channel + oldChannel *types.Channel + invoker auth.Identifiable + } + + // channelOnManual + // + // This type is auto-generated. + channelOnManual struct { + *channelBase + } + + // channelBeforeCreate + // + // This type is auto-generated. + channelBeforeCreate struct { + *channelBase + } + + // channelBeforeUpdate + // + // This type is auto-generated. + channelBeforeUpdate struct { + *channelBase + } + + // channelBeforeDelete + // + // This type is auto-generated. + channelBeforeDelete struct { + *channelBase + } + + // channelAfterCreate + // + // This type is auto-generated. + channelAfterCreate struct { + *channelBase + } + + // channelAfterUpdate + // + // This type is auto-generated. + channelAfterUpdate struct { + *channelBase + } + + // channelAfterDelete + // + // This type is auto-generated. + channelAfterDelete struct { + *channelBase + } + + // channelMemberBase + // + // This type is auto-generated. + channelMemberBase struct { + immutable bool + member *types.ChannelMember + channel *types.Channel + invoker auth.Identifiable + } + + // channelMemberBeforeJoin + // + // This type is auto-generated. + channelMemberBeforeJoin struct { + *channelMemberBase + } + + // channelMemberBeforePart + // + // This type is auto-generated. + channelMemberBeforePart struct { + *channelMemberBase + } + + // channelMemberBeforeAdd + // + // This type is auto-generated. + channelMemberBeforeAdd struct { + *channelMemberBase + } + + // channelMemberBeforeRemove + // + // This type is auto-generated. + channelMemberBeforeRemove struct { + *channelMemberBase + } + + // channelMemberAfterJoin + // + // This type is auto-generated. + channelMemberAfterJoin struct { + *channelMemberBase + } + + // channelMemberAfterPart + // + // This type is auto-generated. + channelMemberAfterPart struct { + *channelMemberBase + } + + // channelMemberAfterAdd + // + // This type is auto-generated. + channelMemberAfterAdd struct { + *channelMemberBase + } + + // channelMemberAfterRemove + // + // This type is auto-generated. + channelMemberAfterRemove struct { + *channelMemberBase + } + + // commandBase + // + // This type is auto-generated. + commandBase struct { + immutable bool + command *types.Command + channel *types.Channel + invoker auth.Identifiable + } + + // commandOnInvoke + // + // This type is auto-generated. + commandOnInvoke struct { + *commandBase + } + + // messageBase + // + // This type is auto-generated. + messageBase struct { + immutable bool + message *types.Message + oldMessage *types.Message + channel *types.Channel + invoker auth.Identifiable + } + + // messageOnManual + // + // This type is auto-generated. + messageOnManual struct { + *messageBase + } + + // messageBeforeCreate + // + // This type is auto-generated. + messageBeforeCreate struct { + *messageBase + } + + // messageBeforeUpdate + // + // This type is auto-generated. + messageBeforeUpdate struct { + *messageBase + } + + // messageBeforeDelete + // + // This type is auto-generated. + messageBeforeDelete struct { + *messageBase + } + + // messageAfterCreate + // + // This type is auto-generated. + messageAfterCreate struct { + *messageBase + } + + // messageAfterUpdate + // + // This type is auto-generated. + messageAfterUpdate struct { + *messageBase + } + + // messageAfterDelete + // + // This type is auto-generated. + messageAfterDelete struct { + *messageBase + } +) + +// ResourceType returns "messaging" +// +// This function is auto-generated. +func (messagingBase) ResourceType() string { + return "messaging" +} + +// EventType on messagingOnManual returns "onManual" +// +// This function is auto-generated. +func (messagingOnManual) EventType() string { + return "onManual" +} + +// EventType on messagingOnInterval returns "onInterval" +// +// This function is auto-generated. +func (messagingOnInterval) EventType() string { + return "onInterval" +} + +// EventType on messagingOnTimestamp returns "onTimestamp" +// +// This function is auto-generated. +func (messagingOnTimestamp) EventType() string { + return "onTimestamp" +} + +// MessagingOnManual creates onManual for messaging resource +// +// This function is auto-generated. +func MessagingOnManual() *messagingOnManual { + return &messagingOnManual{ + messagingBase: &messagingBase{ + immutable: false, + }, + } +} + +// MessagingOnManualImmutable creates onManual for messaging resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func MessagingOnManualImmutable() *messagingOnManual { + return &messagingOnManual{ + messagingBase: &messagingBase{ + immutable: true, + }, + } +} + +// MessagingOnInterval creates onInterval for messaging resource +// +// This function is auto-generated. +func MessagingOnInterval() *messagingOnInterval { + return &messagingOnInterval{ + messagingBase: &messagingBase{ + immutable: false, + }, + } +} + +// MessagingOnIntervalImmutable creates onInterval for messaging resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func MessagingOnIntervalImmutable() *messagingOnInterval { + return &messagingOnInterval{ + messagingBase: &messagingBase{ + immutable: true, + }, + } +} + +// MessagingOnTimestamp creates onTimestamp for messaging resource +// +// This function is auto-generated. +func MessagingOnTimestamp() *messagingOnTimestamp { + return &messagingOnTimestamp{ + messagingBase: &messagingBase{ + immutable: false, + }, + } +} + +// MessagingOnTimestampImmutable creates onTimestamp for messaging resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func MessagingOnTimestampImmutable() *messagingOnTimestamp { + return &messagingOnTimestamp{ + messagingBase: &messagingBase{ + immutable: true, + }, + } +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *messagingBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res messagingBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res messagingBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *messagingBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} + +// ResourceType returns "messaging:channel" +// +// This function is auto-generated. +func (channelBase) ResourceType() string { + return "messaging:channel" +} + +// EventType on channelOnManual returns "onManual" +// +// This function is auto-generated. +func (channelOnManual) EventType() string { + return "onManual" +} + +// EventType on channelBeforeCreate returns "beforeCreate" +// +// This function is auto-generated. +func (channelBeforeCreate) EventType() string { + return "beforeCreate" +} + +// EventType on channelBeforeUpdate returns "beforeUpdate" +// +// This function is auto-generated. +func (channelBeforeUpdate) EventType() string { + return "beforeUpdate" +} + +// EventType on channelBeforeDelete returns "beforeDelete" +// +// This function is auto-generated. +func (channelBeforeDelete) EventType() string { + return "beforeDelete" +} + +// EventType on channelAfterCreate returns "afterCreate" +// +// This function is auto-generated. +func (channelAfterCreate) EventType() string { + return "afterCreate" +} + +// EventType on channelAfterUpdate returns "afterUpdate" +// +// This function is auto-generated. +func (channelAfterUpdate) EventType() string { + return "afterUpdate" +} + +// EventType on channelAfterDelete returns "afterDelete" +// +// This function is auto-generated. +func (channelAfterDelete) EventType() string { + return "afterDelete" +} + +// ChannelOnManual creates onManual for messaging:channel resource +// +// This function is auto-generated. +func ChannelOnManual( + argChannel *types.Channel, + argOldChannel *types.Channel, +) *channelOnManual { + return &channelOnManual{ + channelBase: &channelBase{ + immutable: false, + channel: argChannel, + oldChannel: argOldChannel, + }, + } +} + +// ChannelOnManualImmutable creates onManual for messaging:channel resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ChannelOnManualImmutable( + argChannel *types.Channel, + argOldChannel *types.Channel, +) *channelOnManual { + return &channelOnManual{ + channelBase: &channelBase{ + immutable: true, + channel: argChannel, + oldChannel: argOldChannel, + }, + } +} + +// ChannelBeforeCreate creates beforeCreate for messaging:channel resource +// +// This function is auto-generated. +func ChannelBeforeCreate( + argChannel *types.Channel, + argOldChannel *types.Channel, +) *channelBeforeCreate { + return &channelBeforeCreate{ + channelBase: &channelBase{ + immutable: false, + channel: argChannel, + oldChannel: argOldChannel, + }, + } +} + +// ChannelBeforeCreateImmutable creates beforeCreate for messaging:channel resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ChannelBeforeCreateImmutable( + argChannel *types.Channel, + argOldChannel *types.Channel, +) *channelBeforeCreate { + return &channelBeforeCreate{ + channelBase: &channelBase{ + immutable: true, + channel: argChannel, + oldChannel: argOldChannel, + }, + } +} + +// ChannelBeforeUpdate creates beforeUpdate for messaging:channel resource +// +// This function is auto-generated. +func ChannelBeforeUpdate( + argChannel *types.Channel, + argOldChannel *types.Channel, +) *channelBeforeUpdate { + return &channelBeforeUpdate{ + channelBase: &channelBase{ + immutable: false, + channel: argChannel, + oldChannel: argOldChannel, + }, + } +} + +// ChannelBeforeUpdateImmutable creates beforeUpdate for messaging:channel resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ChannelBeforeUpdateImmutable( + argChannel *types.Channel, + argOldChannel *types.Channel, +) *channelBeforeUpdate { + return &channelBeforeUpdate{ + channelBase: &channelBase{ + immutable: true, + channel: argChannel, + oldChannel: argOldChannel, + }, + } +} + +// ChannelBeforeDelete creates beforeDelete for messaging:channel resource +// +// This function is auto-generated. +func ChannelBeforeDelete( + argChannel *types.Channel, + argOldChannel *types.Channel, +) *channelBeforeDelete { + return &channelBeforeDelete{ + channelBase: &channelBase{ + immutable: false, + channel: argChannel, + oldChannel: argOldChannel, + }, + } +} + +// ChannelBeforeDeleteImmutable creates beforeDelete for messaging:channel resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ChannelBeforeDeleteImmutable( + argChannel *types.Channel, + argOldChannel *types.Channel, +) *channelBeforeDelete { + return &channelBeforeDelete{ + channelBase: &channelBase{ + immutable: true, + channel: argChannel, + oldChannel: argOldChannel, + }, + } +} + +// ChannelAfterCreate creates afterCreate for messaging:channel resource +// +// This function is auto-generated. +func ChannelAfterCreate( + argChannel *types.Channel, + argOldChannel *types.Channel, +) *channelAfterCreate { + return &channelAfterCreate{ + channelBase: &channelBase{ + immutable: false, + channel: argChannel, + oldChannel: argOldChannel, + }, + } +} + +// ChannelAfterCreateImmutable creates afterCreate for messaging:channel resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ChannelAfterCreateImmutable( + argChannel *types.Channel, + argOldChannel *types.Channel, +) *channelAfterCreate { + return &channelAfterCreate{ + channelBase: &channelBase{ + immutable: true, + channel: argChannel, + oldChannel: argOldChannel, + }, + } +} + +// ChannelAfterUpdate creates afterUpdate for messaging:channel resource +// +// This function is auto-generated. +func ChannelAfterUpdate( + argChannel *types.Channel, + argOldChannel *types.Channel, +) *channelAfterUpdate { + return &channelAfterUpdate{ + channelBase: &channelBase{ + immutable: false, + channel: argChannel, + oldChannel: argOldChannel, + }, + } +} + +// ChannelAfterUpdateImmutable creates afterUpdate for messaging:channel resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ChannelAfterUpdateImmutable( + argChannel *types.Channel, + argOldChannel *types.Channel, +) *channelAfterUpdate { + return &channelAfterUpdate{ + channelBase: &channelBase{ + immutable: true, + channel: argChannel, + oldChannel: argOldChannel, + }, + } +} + +// ChannelAfterDelete creates afterDelete for messaging:channel resource +// +// This function is auto-generated. +func ChannelAfterDelete( + argChannel *types.Channel, + argOldChannel *types.Channel, +) *channelAfterDelete { + return &channelAfterDelete{ + channelBase: &channelBase{ + immutable: false, + channel: argChannel, + oldChannel: argOldChannel, + }, + } +} + +// ChannelAfterDeleteImmutable creates afterDelete for messaging:channel resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ChannelAfterDeleteImmutable( + argChannel *types.Channel, + argOldChannel *types.Channel, +) *channelAfterDelete { + return &channelAfterDelete{ + channelBase: &channelBase{ + immutable: true, + channel: argChannel, + oldChannel: argOldChannel, + }, + } +} + +// SetChannel sets new channel value +// +// This function is auto-generated. +func (res *channelBase) SetChannel(argChannel *types.Channel) { + res.channel = argChannel +} + +// Channel returns channel +// +// This function is auto-generated. +func (res channelBase) Channel() *types.Channel { + return res.channel +} + +// OldChannel returns oldChannel +// +// This function is auto-generated. +func (res channelBase) OldChannel() *types.Channel { + return res.oldChannel +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *channelBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res channelBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res channelBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["channel"], err = json.Marshal(res.channel); err != nil { + return nil, err + } + + if args["oldChannel"], err = json.Marshal(res.oldChannel); err != nil { + return nil, err + } + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *channelBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.channel != nil { + if r, ok := results["result"]; ok && len(results) == 1 { + if err = json.Unmarshal(r, res.channel); err != nil { + return + } + } + } + + if res.channel != nil { + if r, ok := results["channel"]; ok { + if err = json.Unmarshal(r, res.channel); err != nil { + return + } + } + } + + // Do not decode oldChannel; marked as immutable + + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} + +// ResourceType returns "messaging:channel:member" +// +// This function is auto-generated. +func (channelMemberBase) ResourceType() string { + return "messaging:channel:member" +} + +// EventType on channelMemberBeforeJoin returns "beforeJoin" +// +// This function is auto-generated. +func (channelMemberBeforeJoin) EventType() string { + return "beforeJoin" +} + +// EventType on channelMemberBeforePart returns "beforePart" +// +// This function is auto-generated. +func (channelMemberBeforePart) EventType() string { + return "beforePart" +} + +// EventType on channelMemberBeforeAdd returns "beforeAdd" +// +// This function is auto-generated. +func (channelMemberBeforeAdd) EventType() string { + return "beforeAdd" +} + +// EventType on channelMemberBeforeRemove returns "beforeRemove" +// +// This function is auto-generated. +func (channelMemberBeforeRemove) EventType() string { + return "beforeRemove" +} + +// EventType on channelMemberAfterJoin returns "afterJoin" +// +// This function is auto-generated. +func (channelMemberAfterJoin) EventType() string { + return "afterJoin" +} + +// EventType on channelMemberAfterPart returns "afterPart" +// +// This function is auto-generated. +func (channelMemberAfterPart) EventType() string { + return "afterPart" +} + +// EventType on channelMemberAfterAdd returns "afterAdd" +// +// This function is auto-generated. +func (channelMemberAfterAdd) EventType() string { + return "afterAdd" +} + +// EventType on channelMemberAfterRemove returns "afterRemove" +// +// This function is auto-generated. +func (channelMemberAfterRemove) EventType() string { + return "afterRemove" +} + +// ChannelMemberBeforeJoin creates beforeJoin for messaging:channel:member resource +// +// This function is auto-generated. +func ChannelMemberBeforeJoin( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberBeforeJoin { + return &channelMemberBeforeJoin{ + channelMemberBase: &channelMemberBase{ + immutable: false, + member: argMember, + channel: argChannel, + }, + } +} + +// ChannelMemberBeforeJoinImmutable creates beforeJoin for messaging:channel:member resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ChannelMemberBeforeJoinImmutable( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberBeforeJoin { + return &channelMemberBeforeJoin{ + channelMemberBase: &channelMemberBase{ + immutable: true, + member: argMember, + channel: argChannel, + }, + } +} + +// ChannelMemberBeforePart creates beforePart for messaging:channel:member resource +// +// This function is auto-generated. +func ChannelMemberBeforePart( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberBeforePart { + return &channelMemberBeforePart{ + channelMemberBase: &channelMemberBase{ + immutable: false, + member: argMember, + channel: argChannel, + }, + } +} + +// ChannelMemberBeforePartImmutable creates beforePart for messaging:channel:member resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ChannelMemberBeforePartImmutable( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberBeforePart { + return &channelMemberBeforePart{ + channelMemberBase: &channelMemberBase{ + immutable: true, + member: argMember, + channel: argChannel, + }, + } +} + +// ChannelMemberBeforeAdd creates beforeAdd for messaging:channel:member resource +// +// This function is auto-generated. +func ChannelMemberBeforeAdd( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberBeforeAdd { + return &channelMemberBeforeAdd{ + channelMemberBase: &channelMemberBase{ + immutable: false, + member: argMember, + channel: argChannel, + }, + } +} + +// ChannelMemberBeforeAddImmutable creates beforeAdd for messaging:channel:member resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ChannelMemberBeforeAddImmutable( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberBeforeAdd { + return &channelMemberBeforeAdd{ + channelMemberBase: &channelMemberBase{ + immutable: true, + member: argMember, + channel: argChannel, + }, + } +} + +// ChannelMemberBeforeRemove creates beforeRemove for messaging:channel:member resource +// +// This function is auto-generated. +func ChannelMemberBeforeRemove( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberBeforeRemove { + return &channelMemberBeforeRemove{ + channelMemberBase: &channelMemberBase{ + immutable: false, + member: argMember, + channel: argChannel, + }, + } +} + +// ChannelMemberBeforeRemoveImmutable creates beforeRemove for messaging:channel:member resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ChannelMemberBeforeRemoveImmutable( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberBeforeRemove { + return &channelMemberBeforeRemove{ + channelMemberBase: &channelMemberBase{ + immutable: true, + member: argMember, + channel: argChannel, + }, + } +} + +// ChannelMemberAfterJoin creates afterJoin for messaging:channel:member resource +// +// This function is auto-generated. +func ChannelMemberAfterJoin( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberAfterJoin { + return &channelMemberAfterJoin{ + channelMemberBase: &channelMemberBase{ + immutable: false, + member: argMember, + channel: argChannel, + }, + } +} + +// ChannelMemberAfterJoinImmutable creates afterJoin for messaging:channel:member resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ChannelMemberAfterJoinImmutable( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberAfterJoin { + return &channelMemberAfterJoin{ + channelMemberBase: &channelMemberBase{ + immutable: true, + member: argMember, + channel: argChannel, + }, + } +} + +// ChannelMemberAfterPart creates afterPart for messaging:channel:member resource +// +// This function is auto-generated. +func ChannelMemberAfterPart( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberAfterPart { + return &channelMemberAfterPart{ + channelMemberBase: &channelMemberBase{ + immutable: false, + member: argMember, + channel: argChannel, + }, + } +} + +// ChannelMemberAfterPartImmutable creates afterPart for messaging:channel:member resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ChannelMemberAfterPartImmutable( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberAfterPart { + return &channelMemberAfterPart{ + channelMemberBase: &channelMemberBase{ + immutable: true, + member: argMember, + channel: argChannel, + }, + } +} + +// ChannelMemberAfterAdd creates afterAdd for messaging:channel:member resource +// +// This function is auto-generated. +func ChannelMemberAfterAdd( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberAfterAdd { + return &channelMemberAfterAdd{ + channelMemberBase: &channelMemberBase{ + immutable: false, + member: argMember, + channel: argChannel, + }, + } +} + +// ChannelMemberAfterAddImmutable creates afterAdd for messaging:channel:member resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ChannelMemberAfterAddImmutable( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberAfterAdd { + return &channelMemberAfterAdd{ + channelMemberBase: &channelMemberBase{ + immutable: true, + member: argMember, + channel: argChannel, + }, + } +} + +// ChannelMemberAfterRemove creates afterRemove for messaging:channel:member resource +// +// This function is auto-generated. +func ChannelMemberAfterRemove( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberAfterRemove { + return &channelMemberAfterRemove{ + channelMemberBase: &channelMemberBase{ + immutable: false, + member: argMember, + channel: argChannel, + }, + } +} + +// ChannelMemberAfterRemoveImmutable creates afterRemove for messaging:channel:member resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ChannelMemberAfterRemoveImmutable( + argMember *types.ChannelMember, + argChannel *types.Channel, +) *channelMemberAfterRemove { + return &channelMemberAfterRemove{ + channelMemberBase: &channelMemberBase{ + immutable: true, + member: argMember, + channel: argChannel, + }, + } +} + +// SetMember sets new member value +// +// This function is auto-generated. +func (res *channelMemberBase) SetMember(argMember *types.ChannelMember) { + res.member = argMember +} + +// Member returns member +// +// This function is auto-generated. +func (res channelMemberBase) Member() *types.ChannelMember { + return res.member +} + +// SetChannel sets new channel value +// +// This function is auto-generated. +func (res *channelMemberBase) SetChannel(argChannel *types.Channel) { + res.channel = argChannel +} + +// Channel returns channel +// +// This function is auto-generated. +func (res channelMemberBase) Channel() *types.Channel { + return res.channel +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *channelMemberBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res channelMemberBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res channelMemberBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["member"], err = json.Marshal(res.member); err != nil { + return nil, err + } + + if args["channel"], err = json.Marshal(res.channel); err != nil { + return nil, err + } + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *channelMemberBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.member != nil { + if r, ok := results["result"]; ok && len(results) == 1 { + if err = json.Unmarshal(r, res.member); err != nil { + return + } + } + } + + if res.member != nil { + if r, ok := results["member"]; ok { + if err = json.Unmarshal(r, res.member); err != nil { + return + } + } + } + + if res.channel != nil { + if r, ok := results["channel"]; ok { + if err = json.Unmarshal(r, res.channel); err != nil { + return + } + } + } + + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} + +// ResourceType returns "messaging:command" +// +// This function is auto-generated. +func (commandBase) ResourceType() string { + return "messaging:command" +} + +// EventType on commandOnInvoke returns "onInvoke" +// +// This function is auto-generated. +func (commandOnInvoke) EventType() string { + return "onInvoke" +} + +// CommandOnInvoke creates onInvoke for messaging:command resource +// +// This function is auto-generated. +func CommandOnInvoke( + argCommand *types.Command, + argChannel *types.Channel, +) *commandOnInvoke { + return &commandOnInvoke{ + commandBase: &commandBase{ + immutable: false, + command: argCommand, + channel: argChannel, + }, + } +} + +// CommandOnInvokeImmutable creates onInvoke for messaging:command resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func CommandOnInvokeImmutable( + argCommand *types.Command, + argChannel *types.Channel, +) *commandOnInvoke { + return &commandOnInvoke{ + commandBase: &commandBase{ + immutable: true, + command: argCommand, + channel: argChannel, + }, + } +} + +// Command returns command +// +// This function is auto-generated. +func (res commandBase) Command() *types.Command { + return res.command +} + +// Channel returns channel +// +// This function is auto-generated. +func (res commandBase) Channel() *types.Channel { + return res.channel +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *commandBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res commandBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res commandBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["command"], err = json.Marshal(res.command); err != nil { + return nil, err + } + + if args["channel"], err = json.Marshal(res.channel); err != nil { + return nil, err + } + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *commandBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.command != nil { + if r, ok := results["result"]; ok && len(results) == 1 { + if err = json.Unmarshal(r, res.command); err != nil { + return + } + } + } + + // Do not decode command; marked as immutable + + // Do not decode channel; marked as immutable + + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} + +// ResourceType returns "messaging:message" +// +// This function is auto-generated. +func (messageBase) ResourceType() string { + return "messaging:message" +} + +// EventType on messageOnManual returns "onManual" +// +// This function is auto-generated. +func (messageOnManual) EventType() string { + return "onManual" +} + +// EventType on messageBeforeCreate returns "beforeCreate" +// +// This function is auto-generated. +func (messageBeforeCreate) EventType() string { + return "beforeCreate" +} + +// EventType on messageBeforeUpdate returns "beforeUpdate" +// +// This function is auto-generated. +func (messageBeforeUpdate) EventType() string { + return "beforeUpdate" +} + +// EventType on messageBeforeDelete returns "beforeDelete" +// +// This function is auto-generated. +func (messageBeforeDelete) EventType() string { + return "beforeDelete" +} + +// EventType on messageAfterCreate returns "afterCreate" +// +// This function is auto-generated. +func (messageAfterCreate) EventType() string { + return "afterCreate" +} + +// EventType on messageAfterUpdate returns "afterUpdate" +// +// This function is auto-generated. +func (messageAfterUpdate) EventType() string { + return "afterUpdate" +} + +// EventType on messageAfterDelete returns "afterDelete" +// +// This function is auto-generated. +func (messageAfterDelete) EventType() string { + return "afterDelete" +} + +// MessageOnManual creates onManual for messaging:message resource +// +// This function is auto-generated. +func MessageOnManual( + argMessage *types.Message, + argOldMessage *types.Message, + argChannel *types.Channel, +) *messageOnManual { + return &messageOnManual{ + messageBase: &messageBase{ + immutable: false, + message: argMessage, + oldMessage: argOldMessage, + channel: argChannel, + }, + } +} + +// MessageOnManualImmutable creates onManual for messaging:message resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func MessageOnManualImmutable( + argMessage *types.Message, + argOldMessage *types.Message, + argChannel *types.Channel, +) *messageOnManual { + return &messageOnManual{ + messageBase: &messageBase{ + immutable: true, + message: argMessage, + oldMessage: argOldMessage, + channel: argChannel, + }, + } +} + +// MessageBeforeCreate creates beforeCreate for messaging:message resource +// +// This function is auto-generated. +func MessageBeforeCreate( + argMessage *types.Message, + argOldMessage *types.Message, + argChannel *types.Channel, +) *messageBeforeCreate { + return &messageBeforeCreate{ + messageBase: &messageBase{ + immutable: false, + message: argMessage, + oldMessage: argOldMessage, + channel: argChannel, + }, + } +} + +// MessageBeforeCreateImmutable creates beforeCreate for messaging:message resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func MessageBeforeCreateImmutable( + argMessage *types.Message, + argOldMessage *types.Message, + argChannel *types.Channel, +) *messageBeforeCreate { + return &messageBeforeCreate{ + messageBase: &messageBase{ + immutable: true, + message: argMessage, + oldMessage: argOldMessage, + channel: argChannel, + }, + } +} + +// MessageBeforeUpdate creates beforeUpdate for messaging:message resource +// +// This function is auto-generated. +func MessageBeforeUpdate( + argMessage *types.Message, + argOldMessage *types.Message, + argChannel *types.Channel, +) *messageBeforeUpdate { + return &messageBeforeUpdate{ + messageBase: &messageBase{ + immutable: false, + message: argMessage, + oldMessage: argOldMessage, + channel: argChannel, + }, + } +} + +// MessageBeforeUpdateImmutable creates beforeUpdate for messaging:message resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func MessageBeforeUpdateImmutable( + argMessage *types.Message, + argOldMessage *types.Message, + argChannel *types.Channel, +) *messageBeforeUpdate { + return &messageBeforeUpdate{ + messageBase: &messageBase{ + immutable: true, + message: argMessage, + oldMessage: argOldMessage, + channel: argChannel, + }, + } +} + +// MessageBeforeDelete creates beforeDelete for messaging:message resource +// +// This function is auto-generated. +func MessageBeforeDelete( + argMessage *types.Message, + argOldMessage *types.Message, + argChannel *types.Channel, +) *messageBeforeDelete { + return &messageBeforeDelete{ + messageBase: &messageBase{ + immutable: false, + message: argMessage, + oldMessage: argOldMessage, + channel: argChannel, + }, + } +} + +// MessageBeforeDeleteImmutable creates beforeDelete for messaging:message resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func MessageBeforeDeleteImmutable( + argMessage *types.Message, + argOldMessage *types.Message, + argChannel *types.Channel, +) *messageBeforeDelete { + return &messageBeforeDelete{ + messageBase: &messageBase{ + immutable: true, + message: argMessage, + oldMessage: argOldMessage, + channel: argChannel, + }, + } +} + +// MessageAfterCreate creates afterCreate for messaging:message resource +// +// This function is auto-generated. +func MessageAfterCreate( + argMessage *types.Message, + argOldMessage *types.Message, + argChannel *types.Channel, +) *messageAfterCreate { + return &messageAfterCreate{ + messageBase: &messageBase{ + immutable: false, + message: argMessage, + oldMessage: argOldMessage, + channel: argChannel, + }, + } +} + +// MessageAfterCreateImmutable creates afterCreate for messaging:message resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func MessageAfterCreateImmutable( + argMessage *types.Message, + argOldMessage *types.Message, + argChannel *types.Channel, +) *messageAfterCreate { + return &messageAfterCreate{ + messageBase: &messageBase{ + immutable: true, + message: argMessage, + oldMessage: argOldMessage, + channel: argChannel, + }, + } +} + +// MessageAfterUpdate creates afterUpdate for messaging:message resource +// +// This function is auto-generated. +func MessageAfterUpdate( + argMessage *types.Message, + argOldMessage *types.Message, + argChannel *types.Channel, +) *messageAfterUpdate { + return &messageAfterUpdate{ + messageBase: &messageBase{ + immutable: false, + message: argMessage, + oldMessage: argOldMessage, + channel: argChannel, + }, + } +} + +// MessageAfterUpdateImmutable creates afterUpdate for messaging:message resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func MessageAfterUpdateImmutable( + argMessage *types.Message, + argOldMessage *types.Message, + argChannel *types.Channel, +) *messageAfterUpdate { + return &messageAfterUpdate{ + messageBase: &messageBase{ + immutable: true, + message: argMessage, + oldMessage: argOldMessage, + channel: argChannel, + }, + } +} + +// MessageAfterDelete creates afterDelete for messaging:message resource +// +// This function is auto-generated. +func MessageAfterDelete( + argMessage *types.Message, + argOldMessage *types.Message, + argChannel *types.Channel, +) *messageAfterDelete { + return &messageAfterDelete{ + messageBase: &messageBase{ + immutable: false, + message: argMessage, + oldMessage: argOldMessage, + channel: argChannel, + }, + } +} + +// MessageAfterDeleteImmutable creates afterDelete for messaging:message resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func MessageAfterDeleteImmutable( + argMessage *types.Message, + argOldMessage *types.Message, + argChannel *types.Channel, +) *messageAfterDelete { + return &messageAfterDelete{ + messageBase: &messageBase{ + immutable: true, + message: argMessage, + oldMessage: argOldMessage, + channel: argChannel, + }, + } +} + +// SetMessage sets new message value +// +// This function is auto-generated. +func (res *messageBase) SetMessage(argMessage *types.Message) { + res.message = argMessage +} + +// Message returns message +// +// This function is auto-generated. +func (res messageBase) Message() *types.Message { + return res.message +} + +// OldMessage returns oldMessage +// +// This function is auto-generated. +func (res messageBase) OldMessage() *types.Message { + return res.oldMessage +} + +// SetChannel sets new channel value +// +// This function is auto-generated. +func (res *messageBase) SetChannel(argChannel *types.Channel) { + res.channel = argChannel +} + +// Channel returns channel +// +// This function is auto-generated. +func (res messageBase) Channel() *types.Channel { + return res.channel +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *messageBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res messageBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res messageBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["message"], err = json.Marshal(res.message); err != nil { + return nil, err + } + + if args["oldMessage"], err = json.Marshal(res.oldMessage); err != nil { + return nil, err + } + + if args["channel"], err = json.Marshal(res.channel); err != nil { + return nil, err + } + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *messageBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.message != nil { + if r, ok := results["result"]; ok && len(results) == 1 { + if err = json.Unmarshal(r, res.message); err != nil { + return + } + } + } + + if res.message != nil { + if r, ok := results["message"]; ok { + if err = json.Unmarshal(r, res.message); err != nil { + return + } + } + } + + // Do not decode oldMessage; marked as immutable + + if res.channel != nil { + if r, ok := results["channel"]; ok { + if err = json.Unmarshal(r, res.channel); err != nil { + return + } + } + } + + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} diff --git a/messaging/service/event/message.gen.go b/messaging/service/event/message.gen.go deleted file mode 100644 index a93bb1d37..000000000 --- a/messaging/service/event/message.gen.go +++ /dev/null @@ -1,514 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// messaging/service/event/events.yaml -// -// Regenerate with: -// go run codegen/v2/events.go --service messaging -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/messaging/types" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // messageBase - // - // This type is auto-generated. - messageBase struct { - immutable bool - message *types.Message - oldMessage *types.Message - channel *types.Channel - invoker auth.Identifiable - } - - // messageOnManual - // - // This type is auto-generated. - messageOnManual struct { - *messageBase - } - - // messageBeforeCreate - // - // This type is auto-generated. - messageBeforeCreate struct { - *messageBase - } - - // messageBeforeUpdate - // - // This type is auto-generated. - messageBeforeUpdate struct { - *messageBase - } - - // messageBeforeDelete - // - // This type is auto-generated. - messageBeforeDelete struct { - *messageBase - } - - // messageAfterCreate - // - // This type is auto-generated. - messageAfterCreate struct { - *messageBase - } - - // messageAfterUpdate - // - // This type is auto-generated. - messageAfterUpdate struct { - *messageBase - } - - // messageAfterDelete - // - // This type is auto-generated. - messageAfterDelete struct { - *messageBase - } -) - -// ResourceType returns "messaging:message" -// -// This function is auto-generated. -func (messageBase) ResourceType() string { - return "messaging:message" -} - -// EventType on messageOnManual returns "onManual" -// -// This function is auto-generated. -func (messageOnManual) EventType() string { - return "onManual" -} - -// EventType on messageBeforeCreate returns "beforeCreate" -// -// This function is auto-generated. -func (messageBeforeCreate) EventType() string { - return "beforeCreate" -} - -// EventType on messageBeforeUpdate returns "beforeUpdate" -// -// This function is auto-generated. -func (messageBeforeUpdate) EventType() string { - return "beforeUpdate" -} - -// EventType on messageBeforeDelete returns "beforeDelete" -// -// This function is auto-generated. -func (messageBeforeDelete) EventType() string { - return "beforeDelete" -} - -// EventType on messageAfterCreate returns "afterCreate" -// -// This function is auto-generated. -func (messageAfterCreate) EventType() string { - return "afterCreate" -} - -// EventType on messageAfterUpdate returns "afterUpdate" -// -// This function is auto-generated. -func (messageAfterUpdate) EventType() string { - return "afterUpdate" -} - -// EventType on messageAfterDelete returns "afterDelete" -// -// This function is auto-generated. -func (messageAfterDelete) EventType() string { - return "afterDelete" -} - -// MessageOnManual creates onManual for messaging:message resource -// -// This function is auto-generated. -func MessageOnManual( - argMessage *types.Message, - argOldMessage *types.Message, - argChannel *types.Channel, -) *messageOnManual { - return &messageOnManual{ - messageBase: &messageBase{ - immutable: false, - message: argMessage, - oldMessage: argOldMessage, - channel: argChannel, - }, - } -} - -// MessageOnManualImmutable creates onManual for messaging:message resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func MessageOnManualImmutable( - argMessage *types.Message, - argOldMessage *types.Message, - argChannel *types.Channel, -) *messageOnManual { - return &messageOnManual{ - messageBase: &messageBase{ - immutable: true, - message: argMessage, - oldMessage: argOldMessage, - channel: argChannel, - }, - } -} - -// MessageBeforeCreate creates beforeCreate for messaging:message resource -// -// This function is auto-generated. -func MessageBeforeCreate( - argMessage *types.Message, - argOldMessage *types.Message, - argChannel *types.Channel, -) *messageBeforeCreate { - return &messageBeforeCreate{ - messageBase: &messageBase{ - immutable: false, - message: argMessage, - oldMessage: argOldMessage, - channel: argChannel, - }, - } -} - -// MessageBeforeCreateImmutable creates beforeCreate for messaging:message resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func MessageBeforeCreateImmutable( - argMessage *types.Message, - argOldMessage *types.Message, - argChannel *types.Channel, -) *messageBeforeCreate { - return &messageBeforeCreate{ - messageBase: &messageBase{ - immutable: true, - message: argMessage, - oldMessage: argOldMessage, - channel: argChannel, - }, - } -} - -// MessageBeforeUpdate creates beforeUpdate for messaging:message resource -// -// This function is auto-generated. -func MessageBeforeUpdate( - argMessage *types.Message, - argOldMessage *types.Message, - argChannel *types.Channel, -) *messageBeforeUpdate { - return &messageBeforeUpdate{ - messageBase: &messageBase{ - immutable: false, - message: argMessage, - oldMessage: argOldMessage, - channel: argChannel, - }, - } -} - -// MessageBeforeUpdateImmutable creates beforeUpdate for messaging:message resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func MessageBeforeUpdateImmutable( - argMessage *types.Message, - argOldMessage *types.Message, - argChannel *types.Channel, -) *messageBeforeUpdate { - return &messageBeforeUpdate{ - messageBase: &messageBase{ - immutable: true, - message: argMessage, - oldMessage: argOldMessage, - channel: argChannel, - }, - } -} - -// MessageBeforeDelete creates beforeDelete for messaging:message resource -// -// This function is auto-generated. -func MessageBeforeDelete( - argMessage *types.Message, - argOldMessage *types.Message, - argChannel *types.Channel, -) *messageBeforeDelete { - return &messageBeforeDelete{ - messageBase: &messageBase{ - immutable: false, - message: argMessage, - oldMessage: argOldMessage, - channel: argChannel, - }, - } -} - -// MessageBeforeDeleteImmutable creates beforeDelete for messaging:message resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func MessageBeforeDeleteImmutable( - argMessage *types.Message, - argOldMessage *types.Message, - argChannel *types.Channel, -) *messageBeforeDelete { - return &messageBeforeDelete{ - messageBase: &messageBase{ - immutable: true, - message: argMessage, - oldMessage: argOldMessage, - channel: argChannel, - }, - } -} - -// MessageAfterCreate creates afterCreate for messaging:message resource -// -// This function is auto-generated. -func MessageAfterCreate( - argMessage *types.Message, - argOldMessage *types.Message, - argChannel *types.Channel, -) *messageAfterCreate { - return &messageAfterCreate{ - messageBase: &messageBase{ - immutable: false, - message: argMessage, - oldMessage: argOldMessage, - channel: argChannel, - }, - } -} - -// MessageAfterCreateImmutable creates afterCreate for messaging:message resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func MessageAfterCreateImmutable( - argMessage *types.Message, - argOldMessage *types.Message, - argChannel *types.Channel, -) *messageAfterCreate { - return &messageAfterCreate{ - messageBase: &messageBase{ - immutable: true, - message: argMessage, - oldMessage: argOldMessage, - channel: argChannel, - }, - } -} - -// MessageAfterUpdate creates afterUpdate for messaging:message resource -// -// This function is auto-generated. -func MessageAfterUpdate( - argMessage *types.Message, - argOldMessage *types.Message, - argChannel *types.Channel, -) *messageAfterUpdate { - return &messageAfterUpdate{ - messageBase: &messageBase{ - immutable: false, - message: argMessage, - oldMessage: argOldMessage, - channel: argChannel, - }, - } -} - -// MessageAfterUpdateImmutable creates afterUpdate for messaging:message resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func MessageAfterUpdateImmutable( - argMessage *types.Message, - argOldMessage *types.Message, - argChannel *types.Channel, -) *messageAfterUpdate { - return &messageAfterUpdate{ - messageBase: &messageBase{ - immutable: true, - message: argMessage, - oldMessage: argOldMessage, - channel: argChannel, - }, - } -} - -// MessageAfterDelete creates afterDelete for messaging:message resource -// -// This function is auto-generated. -func MessageAfterDelete( - argMessage *types.Message, - argOldMessage *types.Message, - argChannel *types.Channel, -) *messageAfterDelete { - return &messageAfterDelete{ - messageBase: &messageBase{ - immutable: false, - message: argMessage, - oldMessage: argOldMessage, - channel: argChannel, - }, - } -} - -// MessageAfterDeleteImmutable creates afterDelete for messaging:message resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func MessageAfterDeleteImmutable( - argMessage *types.Message, - argOldMessage *types.Message, - argChannel *types.Channel, -) *messageAfterDelete { - return &messageAfterDelete{ - messageBase: &messageBase{ - immutable: true, - message: argMessage, - oldMessage: argOldMessage, - channel: argChannel, - }, - } -} - -// SetMessage sets new message value -// -// This function is auto-generated. -func (res *messageBase) SetMessage(argMessage *types.Message) { - res.message = argMessage -} - -// Message returns message -// -// This function is auto-generated. -func (res messageBase) Message() *types.Message { - return res.message -} - -// OldMessage returns oldMessage -// -// This function is auto-generated. -func (res messageBase) OldMessage() *types.Message { - return res.oldMessage -} - -// SetChannel sets new channel value -// -// This function is auto-generated. -func (res *messageBase) SetChannel(argChannel *types.Channel) { - res.channel = argChannel -} - -// Channel returns channel -// -// This function is auto-generated. -func (res messageBase) Channel() *types.Channel { - return res.channel -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *messageBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res messageBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res messageBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["message"], err = json.Marshal(res.message); err != nil { - return nil, err - } - - if args["oldMessage"], err = json.Marshal(res.oldMessage); err != nil { - return nil, err - } - - if args["channel"], err = json.Marshal(res.channel); err != nil { - return nil, err - } - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *messageBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.message != nil { - if r, ok := results["result"]; ok && len(results) == 1 { - if err = json.Unmarshal(r, res.message); err != nil { - return - } - } - } - - if res.message != nil { - if r, ok := results["message"]; ok { - if err = json.Unmarshal(r, res.message); err != nil { - return - } - } - } - - if res.channel != nil { - if r, ok := results["channel"]; ok { - if err = json.Unmarshal(r, res.channel); err != nil { - return - } - } - } - - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/messaging/service/event/messaging.gen.go b/messaging/service/event/messaging.gen.go deleted file mode 100644 index 507967437..000000000 --- a/messaging/service/event/messaging.gen.go +++ /dev/null @@ -1,188 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// messaging/service/event/events.yaml -// -// Regenerate with: -// go run codegen/v2/events.go --service messaging -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // messagingBase - // - // This type is auto-generated. - messagingBase struct { - immutable bool - invoker auth.Identifiable - } - - // messagingOnManual - // - // This type is auto-generated. - messagingOnManual struct { - *messagingBase - } - - // messagingOnInterval - // - // This type is auto-generated. - messagingOnInterval struct { - *messagingBase - } - - // messagingOnTimestamp - // - // This type is auto-generated. - messagingOnTimestamp struct { - *messagingBase - } -) - -// ResourceType returns "messaging" -// -// This function is auto-generated. -func (messagingBase) ResourceType() string { - return "messaging" -} - -// EventType on messagingOnManual returns "onManual" -// -// This function is auto-generated. -func (messagingOnManual) EventType() string { - return "onManual" -} - -// EventType on messagingOnInterval returns "onInterval" -// -// This function is auto-generated. -func (messagingOnInterval) EventType() string { - return "onInterval" -} - -// EventType on messagingOnTimestamp returns "onTimestamp" -// -// This function is auto-generated. -func (messagingOnTimestamp) EventType() string { - return "onTimestamp" -} - -// MessagingOnManual creates onManual for messaging resource -// -// This function is auto-generated. -func MessagingOnManual() *messagingOnManual { - return &messagingOnManual{ - messagingBase: &messagingBase{ - immutable: false, - }, - } -} - -// MessagingOnManualImmutable creates onManual for messaging resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func MessagingOnManualImmutable() *messagingOnManual { - return &messagingOnManual{ - messagingBase: &messagingBase{ - immutable: true, - }, - } -} - -// MessagingOnInterval creates onInterval for messaging resource -// -// This function is auto-generated. -func MessagingOnInterval() *messagingOnInterval { - return &messagingOnInterval{ - messagingBase: &messagingBase{ - immutable: false, - }, - } -} - -// MessagingOnIntervalImmutable creates onInterval for messaging resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func MessagingOnIntervalImmutable() *messagingOnInterval { - return &messagingOnInterval{ - messagingBase: &messagingBase{ - immutable: true, - }, - } -} - -// MessagingOnTimestamp creates onTimestamp for messaging resource -// -// This function is auto-generated. -func MessagingOnTimestamp() *messagingOnTimestamp { - return &messagingOnTimestamp{ - messagingBase: &messagingBase{ - immutable: false, - }, - } -} - -// MessagingOnTimestampImmutable creates onTimestamp for messaging resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func MessagingOnTimestampImmutable() *messagingOnTimestamp { - return &messagingOnTimestamp{ - messagingBase: &messagingBase{ - immutable: true, - }, - } -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *messagingBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res messagingBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res messagingBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *messagingBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/messaging/service/message.go b/messaging/service/message.go index 99a011e77..4aa021891 100644 --- a/messaging/service/message.go +++ b/messaging/service/message.go @@ -824,7 +824,7 @@ func (svc message) extractMentions(m *types.Message) (mm types.MentionSet) { } for m := 0; m < len(match); m++ { - uid := payload.ParseUInt64(match[m][reSubID]) + uid := payload.ParseUint64(match[m][reSubID]) if len(mm.FindByUserID(uid)) == 0 { // Copy template & assign user id mnt := tpl diff --git a/messaging/service/service.go b/messaging/service/service.go index b1c62f788..4a29363a6 100644 --- a/messaging/service/service.go +++ b/messaging/service/service.go @@ -2,19 +2,15 @@ package service import ( "context" + "fmt" "github.com/cortezaproject/corteza-server/pkg/healthcheck" "time" "go.uber.org/zap" - "github.com/cortezaproject/corteza-server/messaging/repository" - "github.com/cortezaproject/corteza-server/messaging/types" "github.com/cortezaproject/corteza-server/pkg/actionlog" - actionlogRepository "github.com/cortezaproject/corteza-server/pkg/actionlog/repository" - "github.com/cortezaproject/corteza-server/pkg/app/options" - intAuth "github.com/cortezaproject/corteza-server/pkg/auth" + "github.com/cortezaproject/corteza-server/pkg/options" "github.com/cortezaproject/corteza-server/pkg/permissions" - "github.com/cortezaproject/corteza-server/pkg/settings" "github.com/cortezaproject/corteza-server/pkg/store" "github.com/cortezaproject/corteza-server/pkg/store/minio" "github.com/cortezaproject/corteza-server/pkg/store/plain" @@ -37,19 +33,21 @@ type ( ) var ( - DefaultStore store.Store + DefaultStore store.Store + + // DefaultNgStore is an interface to storage backend(s) + // ng (next-gen) is a temporary prefix + // so that we can differentiate between it and the file-only store + DefaultNgStore storeInterface + DefaultPermissions permissionServicer DefaultLogger *zap.Logger DefaultActionlog actionlog.Recorder - DefaultSettings settings.Service DefaultAccessControl *accessControl - // CurrentSettings represents current messaging settings - CurrentSettings = &types.Settings{} - DefaultAttachment AttachmentService DefaultChannel ChannelService DefaultMessage MessageService @@ -57,8 +55,20 @@ var ( DefaultCommand CommandService ) -func Initialize(ctx context.Context, log *zap.Logger, c Config) (err error) { - hcd := healthcheck.Defaults() +func Initialize(ctx context.Context, log *zap.Logger, s interface{}, c Config) (err error) { + var ( + hcd = healthcheck.Defaults() + + msgStore storeInterface + ok bool + ) + + // we're doing conversion to avoid having + // store interface exposed or generated inside app package + if msgStore, ok = s.(storeInterface); !ok { + return fmt.Errorf("store %T is incompatible with compose storeInterface", s) + } + DefaultLogger = log.Named("service") { @@ -72,30 +82,17 @@ func Initialize(ctx context.Context, log *zap.Logger, c Config) (err error) { tee = log } - DefaultActionlog = actionlog.NewService( - // will log directly to system schema for now - actionlogRepository.Mysql(repository.DB(ctx).Quiet(), "sys_actionlog"), - log, - tee, - policy, - ) + DefaultActionlog = actionlog.NewService(DefaultNgStore, log, tee, policy) } if DefaultPermissions == nil { // Do not override permissions service stored under DefaultPermissions // to allow integration tests to inject own permission service - DefaultPermissions = permissions.Service(ctx, DefaultLogger, repository.DB(ctx), "messaging_permission_rules") + DefaultPermissions = permissions.Service(ctx, DefaultLogger, msgStore) } DefaultAccessControl = AccessControl(DefaultPermissions) - DefaultSettings = settings.NewService( - settings.NewRepository(repository.DB(ctx), "messaging_settings"), - DefaultLogger, - DefaultAccessControl, - CurrentSettings, - ) - if DefaultStore == nil { const svcPath = "messaging" if c.Storage.MinioEndpoint != "" { @@ -144,12 +141,6 @@ func Initialize(ctx context.Context, log *zap.Logger, c Config) (err error) { } func Activate(ctx context.Context) (err error) { - // Run initial update of current settings with super-user credentials - err = DefaultSettings.UpdateCurrent(intAuth.SetSuperUserContext(ctx)) - if err != nil { - return - } - return } diff --git a/messaging/service/store_interface.gen.go b/messaging/service/store_interface.gen.go new file mode 100644 index 000000000..d7a73ce53 --- /dev/null +++ b/messaging/service/store_interface.gen.go @@ -0,0 +1,18 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/actionlog.yaml +// - store/rbac_rules.yaml + +type ( + // Interface combines interfaces of all supported store interfaces + storeInterface interface { + actionlogsStore + rbacRulesStore + } +) diff --git a/messaging/service/store_interface_actionlog.gen.go b/messaging/service/store_interface_actionlog.gen.go new file mode 100644 index 000000000..1b67c3e64 --- /dev/null +++ b/messaging/service/store_interface_actionlog.gen.go @@ -0,0 +1,27 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/actionlog.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/actionlog" +) + +type ( + actionlogsStore interface { + SearchActionlogs(ctx context.Context, f actionlog.Filter) (actionlog.ActionSet, actionlog.Filter, error) + CreateActionlog(ctx context.Context, rr ...*actionlog.Action) error + UpdateActionlog(ctx context.Context, rr ...*actionlog.Action) error + PartialUpdateActionlog(ctx context.Context, onlyColumns []string, rr ...*actionlog.Action) error + RemoveActionlog(ctx context.Context, rr ...*actionlog.Action) error + RemoveActionlogByID(ctx context.Context, ID uint64) error + + TruncateActionlogs(ctx context.Context) error + } +) diff --git a/messaging/service/store_interface_rbac_rules.gen.go b/messaging/service/store_interface_rbac_rules.gen.go new file mode 100644 index 000000000..c244d22ab --- /dev/null +++ b/messaging/service/store_interface_rbac_rules.gen.go @@ -0,0 +1,27 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/rbac_rules.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/permissions" +) + +type ( + rbacRulesStore interface { + SearchRbacRules(ctx context.Context, f permissions.RuleFilter) (permissions.RuleSet, permissions.RuleFilter, error) + CreateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + UpdateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + PartialUpdateRbacRule(ctx context.Context, onlyColumns []string, rr ...*permissions.Rule) error + RemoveRbacRule(ctx context.Context, rr ...*permissions.Rule) error + RemoveRbacRuleByRoleIDResourceOperation(ctx context.Context, roleID uint64, resource string, operation string) error + + TruncateRbacRules(ctx context.Context) error + } +) diff --git a/messaging/websocket/event_queue.go b/messaging/websocket/event_queue.go index 0f5381545..c9f128253 100644 --- a/messaging/websocket/event_queue.go +++ b/messaging/websocket/event_queue.go @@ -69,7 +69,7 @@ func (eq *eventQueue) feedSessions(ctx context.Context, qp repository.EventsRepo } if item.SubType == types.EventQueueItemSubTypeUser { - userID = payload.ParseUInt64(item.Subscriber) + userID = payload.ParseUint64(item.Subscriber) if userID == 0 { return errors.New("subscriber could not be parsed as uint64") } diff --git a/messaging/websocket/session_incoming_channel.go b/messaging/websocket/session_incoming_channel.go index ee9a7c16d..265263cbf 100644 --- a/messaging/websocket/session_incoming_channel.go +++ b/messaging/websocket/session_incoming_channel.go @@ -81,7 +81,7 @@ func (s *Session) channelCreate(ctx context.Context, p *incoming.ChannelCreate) } func (s *Session) channelUpdate(ctx context.Context, p *incoming.ChannelUpdate) error { - ch, err := s.svc.ch.With(ctx).FindByID(payload.ParseUInt64(p.ID)) + ch, err := s.svc.ch.With(ctx).FindByID(payload.ParseUint64(p.ID)) if err != nil { return err } diff --git a/messaging/websocket/session_incoming_message.go b/messaging/websocket/session_incoming_message.go index ea2cadd51..68e200ca1 100644 --- a/messaging/websocket/session_incoming_message.go +++ b/messaging/websocket/session_incoming_message.go @@ -10,7 +10,7 @@ import ( func (s *Session) messageCreate(ctx context.Context, p *incoming.MessageCreate) error { _, err := s.svc.msg.With(ctx).Create(&types.Message{ - ChannelID: payload.ParseUInt64(p.ChannelID), + ChannelID: payload.ParseUint64(p.ChannelID), ReplyTo: p.ReplyTo, Message: p.Message, }) @@ -20,7 +20,7 @@ func (s *Session) messageCreate(ctx context.Context, p *incoming.MessageCreate) func (s *Session) messageUpdate(ctx context.Context, p *incoming.MessageUpdate) error { _, err := s.svc.msg.With(ctx).Update(&types.Message{ - ID: payload.ParseUInt64(p.ID), + ID: payload.ParseUint64(p.ID), Message: p.Message, }) @@ -28,5 +28,5 @@ func (s *Session) messageUpdate(ctx context.Context, p *incoming.MessageUpdate) } func (s *Session) messageDelete(ctx context.Context, p *incoming.MessageDelete) error { - return s.svc.msg.With(ctx).Delete(payload.ParseUInt64(p.ID)) + return s.svc.msg.With(ctx).Delete(payload.ParseUint64(p.ID)) } diff --git a/pkg/actionlog/repository/mysql.go b/pkg/actionlog/repository/mysql.go deleted file mode 100644 index 3c058c2dc..000000000 --- a/pkg/actionlog/repository/mysql.go +++ /dev/null @@ -1,151 +0,0 @@ -package repository - -import ( - "context" - "encoding/json" - "fmt" - "github.com/Masterminds/squirrel" - "github.com/cortezaproject/corteza-server/pkg/actionlog" - "github.com/cortezaproject/corteza-server/pkg/rh" - "github.com/titpetric/factory" - "time" -) - -type ( - // Basic mysql storage backend for audit log events - // - // this does not follow the usual (one) repository pattern - // but tries to move towards multi-flavoured repository support - mysql struct { - dbh *factory.DB - tbl string - } - - event struct { - Timestamp time.Time `db:"ts"` - RequestOrigin string `db:"request_origin"` - RequestID string `db:"request_id"` - ActorIPAddr string `db:"actor_ip_addr"` - ActorID uint64 `db:"actor_id"` - Resource string `db:"resource"` - Action string `db:"action"` - Error string `db:"error"` - Severity int `db:"severity"` - Description string `db:"description"` - Meta json.RawMessage `db:"meta"` - } -) - -func Mysql(db *factory.DB, tbl string) *mysql { - return &mysql{ - // connection - dbh: db, - - // table to store the data - tbl: tbl, - } -} - -func (r *mysql) db() *factory.DB { - return r.dbh -} - -func (r mysql) columns() []string { - return []string{ - "ts", - "request_origin", - "request_id", - "actor_ip_addr", - "actor_id", - "resource", - "action", - "error", - "severity", - "description", - "meta", - } -} - -func (r mysql) query() squirrel.SelectBuilder { - return squirrel. - Select(r.columns()...). - From(r.tbl) -} - -func (r *mysql) Find(ctx context.Context, flt actionlog.Filter) (set actionlog.ActionSet, f actionlog.Filter, err error) { - f = flt - - query := r.query() - - if f.From != nil { - query = query.Where(squirrel.GtOrEq{"ts": f.From}) - } - - if f.To != nil { - query = query.Where(squirrel.LtOrEq{"ts": f.To}) - } - - if len(f.ActorID) > 0 { - query = query.Where(squirrel.Eq{"actor_id": f.ActorID}) - } - - if f.Resource != "" { - query = query.Where(squirrel.Eq{"resource": f.Resource}) - } - - if f.Action != "" { - query = query.Where(squirrel.Eq{"action": f.Action}) - } - - // @todo implement filtering with query (via pkg/ql) - - query = query.OrderBy("ts DESC") - - results := make([]*event, 0) - if err = rh.FetchPaged(r.db().With(ctx), query, f.PageFilter, &results); err != nil { - return nil, f, err - } - - set = make(actionlog.ActionSet, len(results)) - for i, r := range results { - set[i] = &actionlog.Action{ - Timestamp: r.Timestamp, - RequestOrigin: r.RequestOrigin, - RequestID: r.RequestID, - ActorIPAddr: r.ActorIPAddr, - ActorID: r.ActorID, - Resource: r.Resource, - Action: r.Action, - Error: r.Error, - Severity: actionlog.Severity(r.Severity), - Description: r.Description, - } - - // ignore all unmarshaling issues - _ = json.Unmarshal(r.Meta, &set[i].Meta) - } - - return set, f, nil -} - -// Record stores audit event -func (r *mysql) Record(ctx context.Context, e *actionlog.Action) error { - m, err := json.Marshal(e.Meta) - if err != nil { - return fmt.Errorf("could not format auditlog event: %w", err) - } - - return r.dbh.With(ctx).InsertIgnore(r.tbl, event{ - Timestamp: e.Timestamp, - RequestOrigin: e.RequestOrigin, - RequestID: e.RequestID, - ActorIPAddr: e.ActorIPAddr, - ActorID: e.ActorID, - Resource: e.Resource, - Action: e.Action, - Error: e.Error, - Severity: int(e.Severity), - Description: e.Description, - Meta: m, - }) -} diff --git a/pkg/actionlog/service.go b/pkg/actionlog/service.go index e13e16f18..949acb04a 100644 --- a/pkg/actionlog/service.go +++ b/pkg/actionlog/service.go @@ -2,6 +2,7 @@ package actionlog import ( "context" + "github.com/cortezaproject/corteza-server/pkg/id" "strings" "github.com/go-chi/chi/middleware" @@ -14,7 +15,7 @@ import ( type ( service struct { // where the audit log records are kept - repo recordKeeper + store actionlogStore // Also write audit events here tee *zap.Logger @@ -34,15 +35,15 @@ type ( Find(context.Context, Filter) (ActionSet, Filter, error) } - recordKeeper interface { - Record(context.Context, *Action) error - Find(context.Context, Filter) (ActionSet, Filter, error) + actionlogStore interface { + SearchActionlogs(ctx context.Context, f Filter) (ActionSet, Filter, error) + CreateActionlog(ctx context.Context, rr ...*Action) error } ) // NewService initializes action log service // -func NewService(r recordKeeper, logger, tee *zap.Logger, policy policyMatcher) (svc *service) { +func NewService(s actionlogStore, logger, tee *zap.Logger, policy policyMatcher) (svc *service) { if tee == nil { tee = zap.NewNop() } @@ -50,7 +51,7 @@ func NewService(r recordKeeper, logger, tee *zap.Logger, policy policyMatcher) ( svc = &service{ tee: tee.Named("actionlog"), logger: logger.Named("actionlog"), - repo: r, + store: s, policy: policy, } @@ -64,6 +65,7 @@ func (svc service) Record(ctx context.Context, l loggable) { } a := enrich(ctx, l.LoggableAction()) + a.ID = id.Next() svc.log(a) @@ -77,7 +79,7 @@ func (svc service) Record(ctx context.Context, l loggable) { // auditlog to fail... ctx = context.Background() - if err := svc.repo.Record(ctx, a); err != nil { + if err := svc.store.CreateActionlog(ctx, a); err != nil { svc.logger.With(zap.Error(err)).Error("could not record audit event") } } @@ -98,11 +100,22 @@ func (svc service) log(a *Action) { zap.Any("meta", a.Meta), } - svc.tee.With(zlf...).Debug(a.Description) + svc.tee. + With(zlf...). + // Skipping 3 callers (the most common stack) + // actionlog.service.log() + // actionlog.service.Record() + // (generated service function) + // + // One exception, access control, that calls Record fn directly, + // without going through generated actionlog helpers + WithOptions(zap.AddCallerSkip(3)). + // This is debug logger and we log all recordings as debug + Debug(a.Description) } func (svc service) Find(ctx context.Context, flt Filter) (ActionSet, Filter, error) { - return svc.repo.Find(ctx, flt) + return svc.store.SearchActionlogs(ctx, flt) } // Enriches action with additional info (ip, actor id, request id...) diff --git a/pkg/actionlog/types.go b/pkg/actionlog/types.go index b979d134e..d0afd81de 100644 --- a/pkg/actionlog/types.go +++ b/pkg/actionlog/types.go @@ -16,6 +16,8 @@ type ( // Standardized data structure for audit log events Action struct { + ID uint64 + // Timestamp of the raised event Timestamp time.Time `json:"timestamp"` diff --git a/pkg/auth/identity_context.go b/pkg/auth/identity_context.go index b82c58cb3..fb7fe381e 100644 --- a/pkg/auth/identity_context.go +++ b/pkg/auth/identity_context.go @@ -14,7 +14,7 @@ func SetIdentityToContext(ctx context.Context, identity Identifiable) context.Co } func GetIdentityFromContext(ctx context.Context) Identifiable { - if identity, ok := ctx.Value(identityCtxKey{}).(Identifiable); ok { + if identity, ok := ctx.Value(identityCtxKey{}).(Identifiable); ok && identity != nil { return identity } else { return NewIdentity(0) diff --git a/pkg/codegen/assets/store_rdbms.gen.go.tpl b/pkg/codegen/assets/store_rdbms.gen.go.tpl index 9ec3c8e04..63247da16 100644 --- a/pkg/codegen/assets/store_rdbms.gen.go.tpl +++ b/pkg/codegen/assets/store_rdbms.gen.go.tpl @@ -167,7 +167,7 @@ func (s Store) Remove{{ pubIdent $.Types.Singular }}(ctx context.Context, rr ... // Remove{{ pubIdent $.Types.Singular }}By{{ template "primaryKeySuffix" $.Fields }} removes row from the {{ $.RDBMS.Table }} table func (s Store) Remove{{ pubIdent $.Types.Singular }}By{{ template "primaryKeySuffix" $.Fields }}(ctx context.Context {{ template "primaryKeyArgs" $.Fields }}) error { - return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.{{ $.Types.Singular }}Table()).Where({{ template "filterByPrimaryKeysWithArgs" $.Fields }},)) + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.{{ $.Types.Singular }}Table({{ printf "%q" .RDBMS.Alias }})).Where({{ template "filterByPrimaryKeysWithArgs" $.Fields }},)) } diff --git a/pkg/corredor/conn.go b/pkg/corredor/conn.go index 5461ed6ae..e9c84c49b 100644 --- a/pkg/corredor/conn.go +++ b/pkg/corredor/conn.go @@ -8,7 +8,7 @@ import ( "io/ioutil" "os" - "github.com/cortezaproject/corteza-server/pkg/app/options" + "github.com/cortezaproject/corteza-server/pkg/options" "github.com/pkg/errors" "go.uber.org/zap" "google.golang.org/grpc" diff --git a/pkg/corredor/conn_test.go b/pkg/corredor/conn_test.go index 3a8980147..5b99f0868 100644 --- a/pkg/corredor/conn_test.go +++ b/pkg/corredor/conn_test.go @@ -14,8 +14,8 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/connectivity" - "github.com/cortezaproject/corteza-server/pkg/app/options" "github.com/cortezaproject/corteza-server/pkg/logger" + "github.com/cortezaproject/corteza-server/pkg/options" ) func init() { diff --git a/pkg/corredor/service.go b/pkg/corredor/service.go index 541b197d3..c6f3121a0 100644 --- a/pkg/corredor/service.go +++ b/pkg/corredor/service.go @@ -15,9 +15,9 @@ import ( "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" - "github.com/cortezaproject/corteza-server/pkg/app/options" "github.com/cortezaproject/corteza-server/pkg/auth" "github.com/cortezaproject/corteza-server/pkg/eventbus" + "github.com/cortezaproject/corteza-server/pkg/options" "github.com/cortezaproject/corteza-server/pkg/permissions" "github.com/cortezaproject/corteza-server/pkg/sentry" "github.com/cortezaproject/corteza-server/system/types" diff --git a/pkg/corredor/service_test.go b/pkg/corredor/service_test.go index 033d3a6d9..e45d34a2e 100644 --- a/pkg/corredor/service_test.go +++ b/pkg/corredor/service_test.go @@ -2,10 +2,10 @@ package corredor import ( "context" - "github.com/cortezaproject/corteza-server/pkg/app/options" "github.com/cortezaproject/corteza-server/pkg/auth" "github.com/cortezaproject/corteza-server/pkg/eventbus" "github.com/cortezaproject/corteza-server/pkg/logger" + "github.com/cortezaproject/corteza-server/pkg/options" "github.com/cortezaproject/corteza-server/pkg/permissions" "github.com/cortezaproject/corteza-server/system/types" "github.com/stretchr/testify/assert" diff --git a/pkg/db/connector.go b/pkg/db/connector.go index 0c094ce70..307e6f036 100644 --- a/pkg/db/connector.go +++ b/pkg/db/connector.go @@ -3,6 +3,7 @@ package db import ( "context" "regexp" + "strings" "time" "github.com/pkg/errors" @@ -10,7 +11,7 @@ import ( "github.com/titpetric/factory/logger" "go.uber.org/zap" - "github.com/cortezaproject/corteza-server/pkg/app/options" + "github.com/cortezaproject/corteza-server/pkg/options" "github.com/cortezaproject/corteza-server/pkg/sentry" ) @@ -26,6 +27,11 @@ func TryToConnect(ctx context.Context, log *zap.Logger, opt options.DBOpt) (db * name := "default" + // Trim off the schema, as titpetric/factory does not support it + if strings.HasPrefix(opt.DSN, "mysql://") { + opt.DSN = opt.DSN[8:] + } + factory.Database.Add(name, factory.DatabaseCredential{DSN: opt.DSN, DriverName: "mysql"}) var ( diff --git a/pkg/id/sonyflake.go b/pkg/id/sonyflake.go new file mode 100644 index 000000000..77d27f6cf --- /dev/null +++ b/pkg/id/sonyflake.go @@ -0,0 +1,32 @@ +package id + +import ( + "github.com/sony/sonyflake" + "time" +) + +// Midnight, January 1st 2017 +const jan1st2017 = 1483228800 + +var _sonyflake *sonyflake.Sonyflake + +func init() { + _sonyflake = sonyflake.NewSonyflake(sonyflake.Settings{ + StartTime: time.Unix(jan1st2017, 0), + }) +} + +// NextID returns uint64 ID, or panics +// +// See https://github.com/sony/sonyflake for details +func nextSonyflake() uint64 { + if id, err := _sonyflake.NextID(); err != nil { + panic(err) + } else { + return id + } +} + +func Next() uint64 { + return nextSonyflake() +} diff --git a/pkg/payload/util.go b/pkg/payload/util.go index f5a4ba11f..12a290fff 100644 --- a/pkg/payload/util.go +++ b/pkg/payload/util.go @@ -1,7 +1,16 @@ package payload import ( + "fmt" + "github.com/jmoiron/sqlx/types" + "regexp" "strconv" + "strings" + "time" +) + +var ( + truthy = regexp.MustCompile(`^\s*(t(rue)?|y(es)?|1)\s*$`) ) func Uint64toa(i uint64) string { @@ -17,8 +26,8 @@ func Uint64stoa(uu []uint64) []string { return ss } -// ParseUInt64 parses an string to uint64 -func ParseUInt64(s string) uint64 { +// ParseUint64 parses an string to uint64 +func ParseUint64(s string) uint64 { if s == "" { return 0 } @@ -26,12 +35,63 @@ func ParseUInt64(s string) uint64 { return i } -// ParseUInt64s parses a slice of strings into a slice of uint64s -func ParseUInt64s(ss []string) []uint64 { +// ParseUint64s parses a slice of strings into a slice of uint64s +func ParseUint64s(ss []string) []uint64 { uu := make([]uint64, len(ss)) for i, s := range ss { - uu[i] = ParseUInt64(s) + uu[i] = ParseUint64(s) } return uu } + +func ParseJSONTextWithErr(s string) (types.JSONText, error) { + result := &types.JSONText{} + err := fmt.Errorf("error parsing JSONText: %w", result.Scan(s)) + return *result, err +} + +func ParseISODateWithErr(s string) (time.Time, error) { + return time.Parse(time.RFC3339, s) +} + +func ParseISODatePtrWithErr(s string) (*time.Time, error) { + t, err := ParseISODateWithErr(s) + if err != nil { + return nil, err + } + + return &t, nil +} + +// ParseInt parses a string to int +func ParseInt(s string) int { + if s == "" { + return 0 + } + i, _ := strconv.Atoi(s) + return i +} + +// ParseUInt parses a string to uint64 +func ParseUint(s string) uint { + if s == "" { + return 0 + } + i, _ := strconv.ParseUint(s, 10, 32) + return uint(i) +} + +// ParseInt64 parses a string to int64 +func ParseInt64(s string) int64 { + if s == "" { + return 0 + } + i, _ := strconv.ParseInt(s, 10, 64) + return i +} + +// parseUInt64 parses a string to uint64 +func ParseBool(s string) bool { + return truthy.MatchString(strings.ToLower(s)) +} diff --git a/pkg/payload/util_test.go b/pkg/payload/util_test.go new file mode 100644 index 000000000..2a6ef8c9f --- /dev/null +++ b/pkg/payload/util_test.go @@ -0,0 +1,23 @@ +package payload + +import ( + "testing" +) + +func Test_parseBool(t *testing.T) { + truthies := []string{"y", "yes", "TRUE", "true", "t", "1", " T "} + falsies := []string{"a", "FALSE", "tr", "11111", " FALSE ", "0"} + + for _, truth := range truthies { + if !ParseBool(truth) { + t.Errorf("Must parse '%s' as boolean value TRUE", truth) + } + } + + for _, falsie := range falsies { + if ParseBool(falsie) { + t.Errorf("Must not parse '%s' as boolean value TRUE", falsie) + } + } + +} diff --git a/pkg/permissions/filter.go b/pkg/permissions/filter.go index ab17ed66c..302cb722e 100644 --- a/pkg/permissions/filter.go +++ b/pkg/permissions/filter.go @@ -11,7 +11,7 @@ import ( type ( // ResourceFilter is Helper for *Filter structs // - // It is used to provide filtering on DB level and meant to be used + // It is used to provide filtering on db level and meant to be used // mainly for checking for read operations. // // It creates a complex SQL syntax for permission checking depending on the @@ -46,6 +46,10 @@ type ( } ) +func NewSuperuserFilter() *ResourceFilter { + return &ResourceFilter{superuser: true} +} + func (rf *ResourceFilter) Build(pkColName string) *ResourceFilter { rf.pkColName = pkColName return rf diff --git a/pkg/permissions/permissions.go b/pkg/permissions/permissions.go index 494e2ac75..22f2e8b8d 100644 --- a/pkg/permissions/permissions.go +++ b/pkg/permissions/permissions.go @@ -24,11 +24,37 @@ type ( ) const ( - // Hardcoded Role ID for everyone + // EveryoneRoleID -- everyone EveryoneRoleID uint64 = 1 - // Hardcoded ID for Admin role + // AdminsRoleID - admins AdminsRoleID uint64 = 2 + + // OwnersDynamicRoleID for Owners role is dynamically assigned + // when current user is owner of the resource + OwnersDynamicRoleID uint64 = 10000 + + // CreatorsDynamicRoleID for Creators role is dynamically assigned + // when current user created the resource + CreatorsDynamicRoleID uint64 = 10010 + + // UpdatersDynamicRoleID for Updaters role is dynamically assigned + // when current user updated the resource + UpdatersDynamicRoleID uint64 = 10011 + + // DeletersDynamicRoleID for Deleters role is dynamically assigned + // when current user deleted the resource + DeletersDynamicRoleID uint64 = 10012 + + // MembersDynamicRoleID for Members role is dynamically assigned + // when current user member of the resource + // Can be used by resources that have members + MembersDynamicRoleID uint64 = 10020 + + // AssigneesDynamicRoleID for Assignees role is dynamically assigned + // when current user member of the resource + // Can be used by resources that have assignees + AssigneesDynamicRoleID uint64 = 10021 ) func (op Operation) String() string { @@ -119,3 +145,28 @@ func (wl Whitelist) Flatten() []whitelistFlatten { return wlf } + +// DynamicRoles is a utility function that compares +// given u with each odd element in cc +// and returns even element on a match +// +// In practice, pass userID as first argument and +// set of userID-roleID pairs. Function returns +// all roles that are paired with the same user +func DynamicRoles(u uint64, cc ...uint64) (rr []uint64) { + var l = len(cc) + + if l%2 == 1 { + panic("expecting even number of id/dynamic-role pairs") + } + + rr = make([]uint64, 0, l/2) + + for i := 0; i < l; i += 2 { + if cc[i] == u { + rr = append(rr, cc[i+1]) + } + } + + return +} diff --git a/pkg/permissions/permissions_test.go b/pkg/permissions/permissions_test.go new file mode 100644 index 000000000..007e1f558 --- /dev/null +++ b/pkg/permissions/permissions_test.go @@ -0,0 +1,53 @@ +package permissions + +import ( + "reflect" + "testing" +) + +func TestDynamicRoles(t *testing.T) { + tests := []struct { + name string + u uint64 + cc []uint64 + exp []uint64 + }{ + { + "empty", + 42, + nil, + []uint64{}, + }, + { + "only one", + 42, + []uint64{42, 2}, + []uint64{2}, + }, + { + "none", + 42, + []uint64{1, 2}, + []uint64{}, + }, + { + "few", + 42, + []uint64{42, 2, 43, 3}, + []uint64{2}, + }, + { + "all", + 42, + []uint64{42, 1, 42, 2}, + []uint64{1, 2}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if gotRr := DynamicRoles(tt.u, tt.cc...); !reflect.DeepEqual(gotRr, tt.exp) { + t.Errorf("DynamicRoles() = %v, want %v", gotRr, tt.exp) + } + }) + } +} diff --git a/pkg/permissions/resource.gen.go b/pkg/permissions/resource.gen.go deleted file mode 100644 index 05cb18175..000000000 --- a/pkg/permissions/resource.gen.go +++ /dev/null @@ -1,41 +0,0 @@ -package permissions - -// Hello! This file is auto-generated. - -type ( - - // ResourceSet slice of Resource - // - // This type is auto-generated. - ResourceSet []*Resource -) - -// Walk iterates through every slice item and calls w(Resource) err -// -// This function is auto-generated. -func (set ResourceSet) Walk(w func(*Resource) error) (err error) { - for i := range set { - if err = w(set[i]); err != nil { - return - } - } - - return -} - -// Filter iterates through every slice item, calls f(Resource) (bool, err) and return filtered slice -// -// This function is auto-generated. -func (set ResourceSet) Filter(f func(*Resource) (bool, error)) (out ResourceSet, err error) { - var ok bool - out = ResourceSet{} - for i := range set { - if ok, err = f(set[i]); err != nil { - return - } else if ok { - out = append(out, set[i]) - } - } - - return -} diff --git a/pkg/permissions/resource.gen_test.go b/pkg/permissions/resource.gen_test.go deleted file mode 100644 index 464d22b0c..000000000 --- a/pkg/permissions/resource.gen_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package permissions - -import ( - "testing" - - "errors" - - "github.com/stretchr/testify/require" -) - -// Hello! This file is auto-generated. - -func TestResourceSetWalk(t *testing.T) { - var ( - value = make(ResourceSet, 3) - req = require.New(t) - ) - - // check walk with no errors - { - err := value.Walk(func(*Resource) error { - return nil - }) - req.NoError(err) - } - - // check walk with error - req.Error(value.Walk(func(*Resource) error { return errors.New("walk error") })) - -} - -func TestResourceSetFilter(t *testing.T) { - var ( - value = make(ResourceSet, 3) - req = require.New(t) - ) - - // filter nothing - { - set, err := value.Filter(func(*Resource) (bool, error) { - return true, nil - }) - req.NoError(err) - req.Equal(len(set), len(value)) - } - - // filter one item - { - found := false - set, err := value.Filter(func(*Resource) (bool, error) { - if !found { - found = true - return found, nil - } - return false, nil - }) - req.NoError(err) - req.Len(set, 1) - } - - // filter error - { - _, err := value.Filter(func(*Resource) (bool, error) { - return false, errors.New("filter error") - }) - req.Error(err) - } -} diff --git a/pkg/permissions/resource.go b/pkg/permissions/resource.go index a32b218c5..d26583381 100644 --- a/pkg/permissions/resource.go +++ b/pkg/permissions/resource.go @@ -27,6 +27,12 @@ func (r Resource) PermissionResource() Resource { return r } +// DynamicRoles satisfies Resourcable interface when Resource is +// used directly +func (r Resource) DynamicRoles(i uint64) []uint64 { + return nil +} + func (r Resource) AppendID(ID uint64) Resource { return r.append(strconv.FormatUint(ID, 10)) } diff --git a/pkg/permissions/rule.gen.go b/pkg/permissions/rule.gen.go deleted file mode 100644 index aaa3f2720..000000000 --- a/pkg/permissions/rule.gen.go +++ /dev/null @@ -1,41 +0,0 @@ -package permissions - -// Hello! This file is auto-generated. - -type ( - - // RuleSet slice of Rule - // - // This type is auto-generated. - RuleSet []*Rule -) - -// Walk iterates through every slice item and calls w(Rule) err -// -// This function is auto-generated. -func (set RuleSet) Walk(w func(*Rule) error) (err error) { - for i := range set { - if err = w(set[i]); err != nil { - return - } - } - - return -} - -// Filter iterates through every slice item, calls f(Rule) (bool, err) and return filtered slice -// -// This function is auto-generated. -func (set RuleSet) Filter(f func(*Rule) (bool, error)) (out RuleSet, err error) { - var ok bool - out = RuleSet{} - for i := range set { - if ok, err = f(set[i]); err != nil { - return - } else if ok { - out = append(out, set[i]) - } - } - - return -} diff --git a/pkg/permissions/rule.gen_test.go b/pkg/permissions/rule.gen_test.go deleted file mode 100644 index c4fa775fb..000000000 --- a/pkg/permissions/rule.gen_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package permissions - -import ( - "testing" - - "errors" - - "github.com/stretchr/testify/require" -) - -// Hello! This file is auto-generated. - -func TestRuleSetWalk(t *testing.T) { - var ( - value = make(RuleSet, 3) - req = require.New(t) - ) - - // check walk with no errors - { - err := value.Walk(func(*Rule) error { - return nil - }) - req.NoError(err) - } - - // check walk with error - req.Error(value.Walk(func(*Rule) error { return errors.New("walk error") })) - -} - -func TestRuleSetFilter(t *testing.T) { - var ( - value = make(RuleSet, 3) - req = require.New(t) - ) - - // filter nothing - { - set, err := value.Filter(func(*Rule) (bool, error) { - return true, nil - }) - req.NoError(err) - req.Equal(len(set), len(value)) - } - - // filter one item - { - found := false - set, err := value.Filter(func(*Rule) (bool, error) { - if !found { - found = true - return found, nil - } - return false, nil - }) - req.NoError(err) - req.Len(set, 1) - } - - // filter error - { - _, err := value.Filter(func(*Rule) (bool, error) { - return false, errors.New("filter error") - }) - req.Error(err) - } -} diff --git a/pkg/permissions/service.go b/pkg/permissions/service.go index f86863d6e..bbbaa9e0a 100644 --- a/pkg/permissions/service.go +++ b/pkg/permissions/service.go @@ -6,10 +6,8 @@ import ( "time" "github.com/pkg/errors" - "github.com/titpetric/factory" "go.uber.org/zap" - "github.com/cortezaproject/corteza-server/pkg/auth" "github.com/cortezaproject/corteza-server/pkg/sentry" ) @@ -23,9 +21,11 @@ type ( rules RuleSet - repository *repository - dbTable string + repository rbacRulesStore } + + // RuleFilter is a dummy struct to satisfy store codegen + RuleFilter struct{} ) const ( @@ -36,14 +36,13 @@ const ( // // service{} struct preloads, checks, grants and flushes privileges to and from repository // It acts as a caching layer -func Service(ctx context.Context, logger *zap.Logger, db *factory.DB, tbl string) (svc *service) { +func Service(ctx context.Context, logger *zap.Logger, s rbacRulesStore) (svc *service) { svc = &service{ l: &sync.Mutex{}, f: make(chan bool), logger: logger.Named("permissions"), - repository: Repository(db, tbl), - dbTable: tbl, + repository: s, } svc.Reload(ctx) @@ -59,25 +58,9 @@ func Service(ctx context.Context, logger *zap.Logger, db *factory.DB, tbl string // System user is always allowed to do everything // // When not explicitly allowed through rules or fallbacks, function will return FALSE. -func (svc service) Can(ctx context.Context, res Resource, op Operation, ff ...CheckAccessFunc) bool { - { - // @todo remove this ASAP - // for now, we need it because of complex init/setup relations under system - ctxTestingVal := ctx.Value("testing") - if t, ok := ctxTestingVal.(bool); ok && t { - return true - } - } - - u := auth.GetIdentityFromContext(ctx) - - if auth.IsSuperUser(u) { - return true - } - - var roles = u.Roles() +func (svc service) Can(roles []uint64, res Resource, op Operation, ff ...CheckAccessFunc) bool { // Checking rules - var v = svc.Check(res, op, roles...) + var v = svc.Check(res.PermissionResource(), op, roles...) if v != Inherit { return v == Allow } @@ -177,7 +160,7 @@ func (svc *service) Reload(ctx context.Context) { svc.l.Lock() defer svc.l.Unlock() - rr, err := svc.repository.With(ctx).Load() + rr, _, err := svc.repository.SearchRbacRules(ctx, RuleFilter{}) svc.logger.Debug( "reloading rules", zap.Error(err), @@ -193,18 +176,14 @@ func (svc *service) Reload(ctx context.Context) { // ResourceFilter is repository helper that we use to filter resources directly in the database // // See ResourceFilter struct documentation for details -func (svc *service) ResourceFilter(ctx context.Context, r Resource, op Operation, fallback Access) *ResourceFilter { - u := auth.GetIdentityFromContext(ctx) - - if auth.IsSuperUser(u) { - return &ResourceFilter{superuser: true} - } - +// +// @deprecated +func (svc *service) ResourceFilter(roles []uint64, r Resource, op Operation, fallback Access) *ResourceFilter { return &ResourceFilter{ - roles: u.Roles(), + roles: roles, resource: r, operation: op, - dbTable: svc.dbTable, + dbTable: "rbac_rules", chk: svc, fallback: fallback, pkColName: "id", @@ -213,8 +192,13 @@ func (svc *service) ResourceFilter(ctx context.Context, r Resource, op Operation func (svc service) flush(ctx context.Context) (err error) { d, u := svc.rules.dirty() - err = svc.repository.With(ctx).Store(d, u) + err = svc.repository.RemoveRbacRule(ctx, d...) + if err != nil { + return + } + + err = svc.repository.UpdateRbacRule(ctx, u...) if err != nil { return } diff --git a/pkg/permissions/service_alt.go b/pkg/permissions/service_alt.go index ab677aec5..f317f86c8 100644 --- a/pkg/permissions/service_alt.go +++ b/pkg/permissions/service_alt.go @@ -6,7 +6,6 @@ import ( "strings" "sync" - "github.com/titpetric/factory" "go.uber.org/zap" ) @@ -18,15 +17,15 @@ type ( } ) -func (ServiceAllowAll) Can(ctx context.Context, res Resource, op Operation, ff ...CheckAccessFunc) bool { +func (ServiceAllowAll) Can([]uint64, Resource, Operation, ...CheckAccessFunc) bool { return true } -func (ServiceAllowAll) Check(res Resource, op Operation, roles ...uint64) (v Access) { +func (ServiceAllowAll) Check(Resource, Operation, ...uint64) (v Access) { return Allow } -func (ServiceAllowAll) Grant(ctx context.Context, wl Whitelist, rules ...*Rule) (err error) { +func (ServiceAllowAll) Grant(context.Context, Whitelist, ...*Rule) (err error) { return nil } @@ -34,28 +33,28 @@ func (ServiceAllowAll) FindRulesByRoleID(roleID uint64) (rr RuleSet) { return } -func (ServiceAllowAll) ResourceFilter(context.Context, Resource, Operation, Access) *ResourceFilter { +func (ServiceAllowAll) ResourceFilter([]uint64, Resource, Operation, Access) *ResourceFilter { return &ResourceFilter{superuser: true} } -func (ServiceDenyAll) Can(ctx context.Context, res Resource, op Operation, ff ...CheckAccessFunc) bool { +func (ServiceDenyAll) Can([]uint64, Resource, Operation, ...CheckAccessFunc) bool { return false } -func (ServiceDenyAll) Check(res Resource, op Operation, roles ...uint64) (v Access) { +func (ServiceDenyAll) Check(Resource, Operation, ...uint64) (v Access) { return Deny } -func (ServiceDenyAll) Grant(ctx context.Context, wl Whitelist, rules ...*Rule) (err error) { +func (ServiceDenyAll) Grant(context.Context, Whitelist, ...*Rule) (err error) { return nil } -func (ServiceDenyAll) FindRulesByRoleID(roleID uint64) (rr RuleSet) { +func (ServiceDenyAll) FindRulesByRoleID(uint64) (rr RuleSet) { return } func (svc *TestService) ClearGrants() { - svc.repository.Purge() + _ = svc.repository.TruncateRbacRules(context.Background()) svc.rules = RuleSet{} } @@ -74,15 +73,14 @@ func (svc *TestService) String() (out string) { return } -func NewTestService(ctx context.Context, logger *zap.Logger, db *factory.DB, tbl string) (svc *TestService) { +func NewTestService(ctx context.Context, logger *zap.Logger, s rbacRulesStore) (svc *TestService) { svc = &TestService{ service: service{ l: &sync.Mutex{}, f: make(chan bool), logger: logger.Named("permissions"), - repository: Repository(db, tbl), - dbTable: tbl, + repository: s, }, } diff --git a/pkg/permissions/store_interfaces.gen.go b/pkg/permissions/store_interfaces.gen.go new file mode 100644 index 000000000..abfc6b935 --- /dev/null +++ b/pkg/permissions/store_interfaces.gen.go @@ -0,0 +1,18 @@ +package permissions + +import ( + "context" +) + +type ( + rbacRulesStore interface { + SearchRbacRules(ctx context.Context, f RuleFilter) (RuleSet, RuleFilter, error) + CreateRbacRule(ctx context.Context, rr ...*Rule) error + UpdateRbacRule(ctx context.Context, rr ...*Rule) error + PartialUpdateRbacRule(ctx context.Context, onlyColumns []string, rr ...*Rule) error + RemoveRbacRule(ctx context.Context, rr ...*Rule) error + RemoveRbacRuleByRoleIDResourceOperation(ctx context.Context, roleID uint64, resource string, operation string) error + + TruncateRbacRules(ctx context.Context) error + } +) diff --git a/pkg/settings/exporter.go b/pkg/settings/exporter.go index d13198602..f8e834a01 100644 --- a/pkg/settings/exporter.go +++ b/pkg/settings/exporter.go @@ -2,12 +2,13 @@ package settings import ( "encoding/json" + "github.com/cortezaproject/corteza-server/system/types" "gopkg.in/yaml.v2" ) // Export transforms a given ValueSet into a yaml exportable structure -func Export(ss ValueSet) (o yaml.MapSlice) { +func Export(ss types.SettingValueSet) (o yaml.MapSlice) { o = yaml.MapSlice{} for _, s := range ss { var v interface{} diff --git a/pkg/settings/exporter_test.go b/pkg/settings/exporter_test.go index 6955564a5..eb7853a14 100644 --- a/pkg/settings/exporter_test.go +++ b/pkg/settings/exporter_test.go @@ -1,11 +1,11 @@ package settings import ( - "testing" - - "github.com/jmoiron/sqlx/types" + "github.com/cortezaproject/corteza-server/system/types" + sqlType "github.com/jmoiron/sqlx/types" "github.com/stretchr/testify/require" "gopkg.in/yaml.v2" + "testing" ) func TestExport(t *testing.T) { @@ -53,10 +53,10 @@ func TestExport(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - tt := Export(ValueSet{ - &Value{ + tt := Export(types.SettingValueSet{ + &types.SettingValue{ Name: test.name, - Value: types.JSONText(test.rawValue), + Value: sqlType.JSONText(test.rawValue), }, }) req.Len(tt, 1) diff --git a/pkg/settings/importer.go b/pkg/settings/importer.go index 848c06de5..31d103193 100644 --- a/pkg/settings/importer.go +++ b/pkg/settings/importer.go @@ -2,20 +2,18 @@ package settings import ( "context" - "encoding/json" - - "github.com/pkg/errors" - + "fmt" "github.com/cortezaproject/corteza-server/pkg/deinterfacer" + "github.com/cortezaproject/corteza-server/system/types" ) type ( Importer struct { - settings ValueSet + settings types.SettingValueSet } ImportKeeper interface { - BulkSet(ctx context.Context, vv ValueSet) (err error) + BulkSet(ctx context.Context, vv types.SettingValueSet) (err error) } ) @@ -24,10 +22,10 @@ func NewImporter() *Importer { } // CastSet - resolves settings: -// [ , ... ] +// [ , ... ] func (imp *Importer) CastSet(settings interface{}) (err error) { if !deinterfacer.IsMap(settings) { - return errors.New("expecting map of settings") + return fmt.Errorf("expecting map of settings") } return deinterfacer.Each(settings, func(_ int, name string, value interface{}) error { @@ -37,14 +35,10 @@ func (imp *Importer) CastSet(settings interface{}) (err error) { func (imp *Importer) addSetting(name string, value interface{}) (err error) { // Convert to interface{}, since json.Marshal cant handle map[interface{}]interface{} - v, err := json.Marshal(deinterfacer.Simplify(value)) - if err != nil { - return err - } + setting := &types.SettingValue{Name: name} - setting := &Value{ - Name: name, - Value: v, + if err = setting.SetValue(deinterfacer.Simplify(value)); err != nil { + return err } imp.settings = append(imp.settings, setting) @@ -55,6 +49,6 @@ func (imp *Importer) Store(ctx context.Context, k ImportKeeper) (err error) { return k.BulkSet(ctx, imp.settings) } -func (imp *Importer) GetValues() ValueSet { +func (imp *Importer) GetValues() types.SettingValueSet { return imp.settings } diff --git a/pkg/settings/kv_decoder.go b/pkg/settings/kv_decoder.go deleted file mode 100644 index 926eae5c7..000000000 --- a/pkg/settings/kv_decoder.go +++ /dev/null @@ -1,153 +0,0 @@ -package settings - -import ( - "github.com/pkg/errors" - "reflect" - "strings" -) - -type ( - // KVDecoder interface for custom decoding logic - KVDecoder interface { - DecodeKV(KV, string) error - } -) - -// DecodeKV converts key-value (KV) into structs using tags & field names -// -// Supports decoding into all scalar types, can handle nested structures and simple maps (1 dim, string as key) -// -// Example: -// key-value pairs: -// string1: "string" -// number: 42 -// -// struct{ -// String1 string `kv:"string1` -// Number int -// } -// -func DecodeKV(kv KV, dst interface{}, pp ...string) (err error) { - valueOf := reflect.ValueOf(dst) - if valueOf.Kind() != reflect.Ptr { - return errors.New("expecting a pointer, not a value") - } - - if valueOf.IsNil() { - return errors.New("nil pointer passed") - } - - var prefix string - if len(pp) > 0 { - // If called with prefix, join string slice + 1 empty string (to ensure tailing dot) - prefix = strings.Join(append(pp, ""), ".") - } - - valueOf = valueOf.Elem() - - length := valueOf.NumField() - - for i := 0; i < length; i++ { - var ( - structField = valueOf.Field(i) - tags = make(map[string]bool) - ) - - if !structField.CanSet() { - continue - } - - var ( - structFType = valueOf.Type().Field(i) - - // whe nwe use name of the struct field directly, remove upper-case from first letter - key = prefix + strings.ToLower(structFType.Name[:1]) + structFType.Name[1:] - - tag = structFType.Tag.Get("kv") - - tagFlags []string - ) - - if tag == "-" { - // Skip fields with kv tags equal to "-" - continue - } - - if tag != "" { - tagFlags = strings.Split(tag, ",") - - if tagFlags[0] != "" { - // key explicitly set via tag, use that! - key = prefix + tagFlags[0] - } - - for f := 1; f < len(tagFlags); f++ { - // @todo resolve i18n and other flags... - tags[tagFlags[f]] = true - } - } - - var structValue interface{} - - if structField.Kind() == reflect.Ptr { - structValue = structField.Interface() - } else { - structValue = structField.Addr().Interface() - } - - // Handle custom KVDecoder - if decodeMethod := reflect.ValueOf(structValue).MethodByName("DecodeKV"); decodeMethod.IsValid() { - if decode, ok := decodeMethod.Interface().(func(KV, string) error); !ok { - panic("invalid DecodeKV() function signature") - } else if err = decode(kv, key); err != nil { - return errors.Wrapf(err, "cannot decode settings for %q", key) - } else { - continue - } - } - - if !tags["final"] { - // Handles structs - // - // It calls DecodeKV recursively - if structField.Kind() == reflect.Struct { - if err = DecodeKV(kv.Filter(key), structValue, key); err != nil { - return - } - - continue - } - - // Handles map values - if structField.Kind() == reflect.Map { - if structField.IsNil() { - // allocate new map - structField.Set(reflect.MakeMap(structField.Type())) - } - - // cut KV key prefix and use the rest for the map key - for k, val := range kv.CutPrefix(key + ".") { - mapValue := reflect.New(structField.Type().Elem()) - err = val.Unmarshal(mapValue.Interface()) - if err != nil { - return errors.Wrapf(err, "cannot decode settings for %q", key) - } - - structField.SetMapIndex(reflect.ValueOf(k), mapValue.Elem()) - } - - continue - } - } - - // Native type - if val, ok := kv[key]; ok { - // Always use pointer to value - if err = val.Unmarshal(structField.Addr().Interface()); err != nil { - return errors.Wrapf(err, "cannot decode settings for %q", key) - } - } - } - - return -} diff --git a/pkg/settings/kv_decoder_test.go b/pkg/settings/kv_decoder_test.go deleted file mode 100644 index 8e1244097..000000000 --- a/pkg/settings/kv_decoder_test.go +++ /dev/null @@ -1,170 +0,0 @@ -package settings - -import ( - "testing" - - "github.com/jmoiron/sqlx/types" - "github.com/stretchr/testify/require" -) - -func TestDecode(t *testing.T) { - type ( - subdst struct { - S string `kv:"s"` - B bool `kv:"b"` - - Bar struct { - Foo string `kv:"foo"` - } `kv:"bar"` - } - - withHandler struct{} - - dst struct { - S string `kv:"s"` - B bool `kv:"b"` - N int `kv:"n"` - - NoKV string - - WH withHandler - - Ptr *string - - Sub subdst `kv:"sub"` - - Map map[string]string `kv:"sub.map"` - S2I map[string]int `kv:"sub.s2i"` - } - ) - - var ( - ptr = "point-me" - - aux = dst{} - kv = KV{ - "s": types.JSONText(`"string"`), - "b": types.JSONText("true"), - "n": types.JSONText("42"), - "sub.s": types.JSONText(`"string"`), - "sub.b": types.JSONText("true"), - "sub.bar": nil, - "sub.bar.foo": types.JSONText(`"foobar"`), - - "noKV": types.JSONText(`"NO-KV-!"`), - "ptr": types.JSONText(`"point-me"`), - - "sub.map.foo": types.JSONText(`"foo"`), - "sub.map.bar": types.JSONText(`"bar"`), - "sub.map.baz": types.JSONText(`"baz"`), - - "sub.s2i.one": types.JSONText(`1`), - "sub.s2i.two": types.JSONText(`2`), - } - - eq = dst{ - S: "string", - B: true, - N: 42, - - NoKV: "NO-KV-!", - Ptr: &ptr, - - Sub: subdst{ - S: "string", - B: true, - }, - - Map: map[string]string{ - "foo": "foo", - "bar": "bar", - "baz": "baz", - }, - - S2I: map[string]int{ - "one": 1, - "two": 2, - }, - } - ) - - // setting this externaly (embedded structs) - eq.Sub.Bar.Foo = "foobar" - - require.NoError(t, DecodeKV(kv, &aux)) - require.Equal(t, eq, aux) -} - -type ( - decodeHandlerBase struct { - Foo decodeHandlerSub - Bar *decodeHandlerSub - } - - decodeHandlerSub struct { - set int - } -) - -func (b *decodeHandlerSub) DecodeKV(kv KV, prefix string) error { - b.set++ - return nil -} - -var _ KVDecoder = &decodeHandlerSub{} - -func TestDecodeHandler(t *testing.T) { - var ( - kv = KV{ - // should panic if DecodeKV is not called: - // cannot unmarshal number into Go value of type settings.decodeHandlerSub - "foo": types.JSONText(`1`), - } - - aux = decodeHandlerBase{ - Foo: decodeHandlerSub{}, - Bar: &decodeHandlerSub{}, - } - ) - require.NoError(t, DecodeKV(kv, &aux)) - require.NotNil(t, aux.Foo) - require.NotNil(t, aux.Bar) - require.Equal(t, 1, aux.Foo.set) - require.Equal(t, 1, aux.Bar.set) -} - -func TestDecodeKV_WithFinalTag(t *testing.T) { - type ( - dst struct { - NotFinal struct { - Foo string - Sub struct { - SubFoo int - } - } - - IsFinal struct { - Foo string - Sub struct { - SubFoo int - } - } `kv:",final"` - } - ) - - var ( - r = require.New(t) - aux = dst{} - kv = KV{ - "notFinal.foo": types.JSONText(`"42"`), - "notFinal.sub.subFoo": types.JSONText(`42`), - "isFinal": types.JSONText(`{"Foo":"final42","Sub":{"SubFoo":42}}`), - } - ) - - r.NoError(DecodeKV(kv, &aux)) - r.Equal(aux.NotFinal.Foo, "42") - r.Equal(aux.NotFinal.Sub.SubFoo, 42) - r.Equal(aux.IsFinal.Foo, "final42") - r.Equal(aux.IsFinal.Sub.SubFoo, 42) -} diff --git a/pkg/settings/repository.go b/pkg/settings/repository.go deleted file mode 100644 index 7fa962403..000000000 --- a/pkg/settings/repository.go +++ /dev/null @@ -1,132 +0,0 @@ -package settings - -import ( - "context" - "fmt" - "time" - - "github.com/Masterminds/squirrel" - "github.com/pkg/errors" - "github.com/titpetric/factory" -) - -type ( - repository struct { - dbh *factory.DB - - // sql table reference - dbTable string - } - - Repository interface { - With(ctx context.Context) Repository - - Find(filter Filter) (ss ValueSet, err error) - - Get(name string, ownedBy uint64) (value *Value, err error) - Set(value *Value) error - BulkSet(vv ValueSet) error - Delete(name string, ownedBy uint64) (err error) - } -) - -func NewRepository(db *factory.DB, table string) Repository { - return &repository{ - dbTable: table, - dbh: db, - } -} - -func (r *repository) db() *factory.DB { - return r.dbh -} - -func (r repository) columns() []string { - return []string{ - "name", - "value", - "rel_owner", - "updated_at", - "updated_by", - } -} - -func (r *repository) With(ctx context.Context) Repository { - return &repository{ - dbTable: r.dbTable, - dbh: r.db().With(ctx), - } -} - -func (r *repository) Find(f Filter) (ss ValueSet, err error) { - f.Normalize() - lookup := squirrel. - Select(r.columns()...). - From(r.dbTable). - // Always filter by owner - Where("rel_owner = ?", f.OwnedBy) - - if len(f.Prefix) > 0 { - lookup = lookup.Where("name LIKE ?", f.Prefix+"%") - } - - if f.Page > 0 { - lookup = lookup.Offset(f.PerPage * f.Page) - } - - if f.PerPage > 0 { - lookup = lookup.Limit(f.PerPage) - } - - if query, args, err := lookup.ToSql(); err != nil { - return nil, errors.Wrap(err, "could not build lookup query for settings") - } else if err = r.db().Select(&ss, query, args...); err != nil { - return nil, errors.Wrap(err, "could not find settings") - } else { - return ss, nil - } -} - -func (r repository) BulkSet(vv ValueSet) error { - // Save all inside a db transaction - return r.db().Transaction(func() (err error) { - return vv.Walk(func(v *Value) error { - return r.Set(v) - }) - }) -} - -func (r *repository) Set(value *Value) error { - value.UpdatedAt = time.Now() - return r.db().Replace(r.dbTable, value) -} - -func (r *repository) Delete(name string, ownedBy uint64) error { - _, err := r.db().Exec( - fmt.Sprintf("DELETE FROM %s WHERE name = ? AND rel_owner = ? ", r.dbTable), - name, - ownedBy, - ) - return err -} - -func (r *repository) Get(name string, ownedBy uint64) (value *Value, err error) { - lookup := squirrel. - Select(r.columns()...). - From(r.dbTable). - Where("rel_owner = ?", ownedBy). - Where("name = ?", name) - - value = &Value{} - - if query, args, err := lookup.ToSql(); err != nil { - return nil, errors.Wrap(err, "could not build lookup query for settings") - } else if err = r.db().Get(value, query, args...); err != nil { - return nil, errors.Wrap(err, "could not get settings") - } else if value.Name == "" { - return nil, nil - } else { - return value, nil - } - -} diff --git a/pkg/settings/service.go b/pkg/settings/service.go deleted file mode 100644 index 72fd441a9..000000000 --- a/pkg/settings/service.go +++ /dev/null @@ -1,177 +0,0 @@ -package settings - -import ( - "context" - "strings" - - "github.com/pkg/errors" - "go.uber.org/zap" - "go.uber.org/zap/zapcore" - - "github.com/cortezaproject/corteza-server/pkg/logger" -) - -type ( - service struct { - repository Repository - accessControl accessController - logger *zap.Logger - current interface{} - } - - Service interface { - FindByPrefix(ctx context.Context, pp ...string) (vv ValueSet, err error) - BulkSet(ctx context.Context, vv ValueSet) (err error) - Set(ctx context.Context, v *Value) (err error) - Get(ctx context.Context, name string, ownedBy uint64) (out *Value, err error) - Delete(ctx context.Context, name string, ownedBy uint64) error - UpdateCurrent(ctx context.Context) error - } - - accessController interface { - CanReadSettings(ctx context.Context) bool - CanManageSettings(ctx context.Context) bool - } -) - -var ( - ErrNoReadPermission = errors.New("not allowed to read settings") - ErrNoManagePermission = errors.New("not allowed to manage settings") -) - -func NewService(r Repository, log *zap.Logger, ac accessController, current interface{}) *service { - svc := &service{ - repository: r, - accessControl: ac, - logger: log.Named("settings"), - current: current, - } - - return svc -} - -func (svc service) log(ctx context.Context, fields ...zapcore.Field) *zap.Logger { - return logger.AddRequestID(ctx, svc.logger).With(fields...) -} - -func (svc service) FindByPrefix(ctx context.Context, pp ...string) (ValueSet, error) { - if !svc.accessControl.CanReadSettings(ctx) { - return nil, ErrNoReadPermission - } - - var ( - f = Filter{ - Prefix: strings.Join(pp, "."), - } - ) - - return svc.repository.With(ctx).Find(f) -} - -func (svc service) Get(ctx context.Context, name string, ownedBy uint64) (out *Value, err error) { - if !svc.accessControl.CanReadSettings(ctx) { - return nil, ErrNoReadPermission - } - - return svc.repository.With(ctx).Get(name, ownedBy) -} - -func (svc service) UpdateCurrent(ctx context.Context) error { - if vv, err := svc.FindByPrefix(ctx); err != nil { - return err - } else { - return svc.updateCurrent(ctx, vv) - } -} - -func (svc service) updateCurrent(ctx context.Context, vv ValueSet) (err error) { - // update current settings with new values - if err = vv.KV().Decode(svc.current); err != nil { - return - } - - return -} - -func (svc service) Set(ctx context.Context, v *Value) (err error) { - if !svc.accessControl.CanManageSettings(ctx) { - return ErrNoManagePermission - } - - var current *Value - current, err = svc.repository.With(ctx).Get(v.Name, v.OwnedBy) - if err != nil || current.Eq(v) { - // Return on error or when there is nothing to update (same value) - return - } - - err = svc.repository.With(ctx).Set(v) - if err != nil { - return - } - - vv := ValueSet{v} - - svc.logChange(ctx, vv) - - return svc.updateCurrent(ctx, vv) -} - -func (svc service) BulkSet(ctx context.Context, vv ValueSet) (err error) { - if !svc.accessControl.CanManageSettings(ctx) { - return ErrNoManagePermission - } - - // Load current settings from repository - // and get changed values - var current ValueSet - if current, err = svc.FindByPrefix(ctx); err != nil { - return - } else { - vv = current.Changed(vv) - } - - err = svc.repository.With(ctx).BulkSet(vv) - if err != nil { - return - } - - svc.logChange(ctx, vv) - - return svc.updateCurrent(ctx, vv) -} - -func (svc service) logChange(ctx context.Context, vv ValueSet) { - for _, v := range vv { - svc.log(ctx, - zap.String("name", v.Name), - zap.Uint64("owned-by", v.OwnedBy), - zap.Stringer("value", v.Value)).Info("setting value updated") - } -} - -func (svc service) Delete(ctx context.Context, name string, ownedBy uint64) (err error) { - if !svc.accessControl.CanManageSettings(ctx) { - return ErrNoManagePermission - } - - var current *Value - current, err = svc.repository.With(ctx).Get(name, ownedBy) - if err != nil || current == nil { - // Return on error or when there is nothing to delete (there is no value) - return - } - - err = svc.repository.With(ctx).Delete(name, ownedBy) - if err != nil { - return - } - - vv := ValueSet{&Value{Name: name, OwnedBy: ownedBy}} - - svc.log(ctx, - zap.String("name", name), - zap.Uint64("owned-by", ownedBy)).Info("setting value removed") - - return svc.updateCurrent(ctx, vv) -} diff --git a/store/Makefile b/store/Makefile new file mode 100644 index 000000000..40fec9acf --- /dev/null +++ b/store/Makefile @@ -0,0 +1,13 @@ + +GOTOOL ?= go tool +GOTEST ?= go test +GOFLAGS ?= -mod=vendor + +COVER_MODE ?= count +COVER_PROFILE ?= .cover.out +COVER_FLAGS ?= -covermode=$(COVER_MODE) -coverprofile=$(COVER_PROFILE) + + +cover: + $(GOTEST) -coverprofile=$(COVER_PROFILE) -coverpkg=./... ./tests/... + $(GOTOOL) cover -html=$(COVER_PROFILE) diff --git a/store/README.txt b/store/README.txt new file mode 100644 index 000000000..104113351 --- /dev/null +++ b/store/README.txt @@ -0,0 +1,43 @@ +Goal + - multi-repository (different DB) support + - refactor old raw-sql migrations to logical and dynamic schema Upgrading + - (tbd) consolidation of system & compose (& messaging) subsystems + +File system: + /repository Holds all repository logic for all subsystems, for all core repository implementation + /internal Internal repository tools (pkg/ql, pgk/rh should be moved here) + / Individual core repository implementation + [mysql|postgresql|redis|memory|sqlite|elasticsearch|mongo] + /schema Schema Upgrading for individual repository implementation + + + + + +/corteza/store/rdbms + Basic RDBMS logic that should be reused across all + RDBMS-like implementations + +/corteza/store//sql_*.go + Database table definitions (used by Upgrade_*.go) + +/corteza/store//Upgrade_*.go + Upgrade logic, cascading (eg: Upgrade => UpgradeSystem => UpgradeUsers) + + + +FAQ: +Why are we changing create/update function signature (input struct is no longer returned)? +Because store functions are no longer manipulating the input. + +Why naming inconsistency between search/lookup and create/update/...? +To ensure function names sound more natural + +Why changing find prefix to search/lookup? +To be consistent with actions + +Why do we use custom mapping (and not db:... tag on struct)? +Separation of concerns + + consistency with store backends that do not support db tags + + de-cluttering types* namespace + diff --git a/store/actionlog.yaml b/store/actionlog.yaml new file mode 100644 index 000000000..6eecb26b8 --- /dev/null +++ b/store/actionlog.yaml @@ -0,0 +1,36 @@ +import: + - github.com/cortezaproject/corteza-server/pkg/actionlog + +interface: + - system/service + - compose/service + - messaging/service + +types: + package: actionlog + type: actionlog.Action + filterType: actionlog.Filter + +fields: + - { field: ID } + - { field: Timestamp, type: "time.Time", column: "ts" } + - { field: RequestOrigin } + - { field: RequestID, column: "request_id" } + - { field: ActorIPAddr } + - { field: ActorID, column: "actor_id" } + - { field: Resource } + - { field: Action } + - { field: Error } + - { field: Severity, type: "actionlog.Severity" } + - { field: Description } + - { field: Meta, type: "actionlog.UserMeta" } + +rdbms: + alias: alg + table: actionlog + customFilterConverter: true + customRowScanner: true + customEncoder: true + +search: + disablePaging: true diff --git a/store/applications.yaml b/store/applications.yaml new file mode 100644 index 000000000..3a520c100 --- /dev/null +++ b/store/applications.yaml @@ -0,0 +1,27 @@ +import: + - github.com/cortezaproject/corteza-server/system/types + +interface: + - system/service + +fields: + - { field: ID } + - { field: Name } + - { field: OwnerID } + - { field: Enabled } + - { field: Unify } + - { field: CreatedAt } + - { field: UpdatedAt } + - { field: DeletedAt } + +lookups: + - fields: [ ID ] + description: |- + searches for application by ID + + It returns application even if deleted + +rdbms: + alias: app + table: sys_application + customFilterConverter: true diff --git a/store/bulk/actionlog.gen.go b/store/bulk/actionlog.gen.go new file mode 100644 index 000000000..79275e1a4 --- /dev/null +++ b/store/bulk/actionlog.gen.go @@ -0,0 +1,72 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// Definitions file that controls how this file is generated: +// store/actionlog.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/actionlog" +) + +type ( + actionlogCreate struct { + Done chan struct{} + res *actionlog.Action + err error + } + + actionlogUpdate struct { + Done chan struct{} + res *actionlog.Action + err error + } + + actionlogRemove struct { + Done chan struct{} + res *actionlog.Action + err error + } +) + +// CreateActionlog creates a new Actionlog +// create job that can be pushed to store's transaction handler +func CreateActionlog(res *actionlog.Action) *actionlogCreate { + return &actionlogCreate{res: res} +} + +// Do Executes actionlogCreate job +func (j *actionlogCreate) Do(ctx context.Context, s storeInterface) error { + j.err = s.CreateActionlog(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// UpdateActionlog creates a new Actionlog +// update job that can be pushed to store's transaction handler +func UpdateActionlog(res *actionlog.Action) *actionlogUpdate { + return &actionlogUpdate{res: res} +} + +// Do Executes actionlogUpdate job +func (j *actionlogUpdate) Do(ctx context.Context, s storeInterface) error { + j.err = s.UpdateActionlog(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// RemoveActionlog creates a new Actionlog +// remove job that can be pushed to store's transaction handler +func RemoveActionlog(res *actionlog.Action) *actionlogRemove { + return &actionlogRemove{res: res} +} + +// Do Executes actionlogRemove job +func (j *actionlogRemove) Do(ctx context.Context, s storeInterface) error { + j.err = s.RemoveActionlog(ctx, j.res) + j.Done <- struct{}{} + return j.err +} diff --git a/store/bulk/applications.gen.go b/store/bulk/applications.gen.go new file mode 100644 index 000000000..937d18518 --- /dev/null +++ b/store/bulk/applications.gen.go @@ -0,0 +1,72 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// Definitions file that controls how this file is generated: +// store/applications.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + applicationCreate struct { + Done chan struct{} + res *types.Application + err error + } + + applicationUpdate struct { + Done chan struct{} + res *types.Application + err error + } + + applicationRemove struct { + Done chan struct{} + res *types.Application + err error + } +) + +// CreateApplication creates a new Application +// create job that can be pushed to store's transaction handler +func CreateApplication(res *types.Application) *applicationCreate { + return &applicationCreate{res: res} +} + +// Do Executes applicationCreate job +func (j *applicationCreate) Do(ctx context.Context, s storeInterface) error { + j.err = s.CreateApplication(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// UpdateApplication creates a new Application +// update job that can be pushed to store's transaction handler +func UpdateApplication(res *types.Application) *applicationUpdate { + return &applicationUpdate{res: res} +} + +// Do Executes applicationUpdate job +func (j *applicationUpdate) Do(ctx context.Context, s storeInterface) error { + j.err = s.UpdateApplication(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// RemoveApplication creates a new Application +// remove job that can be pushed to store's transaction handler +func RemoveApplication(res *types.Application) *applicationRemove { + return &applicationRemove{res: res} +} + +// Do Executes applicationRemove job +func (j *applicationRemove) Do(ctx context.Context, s storeInterface) error { + j.err = s.RemoveApplication(ctx, j.res) + j.Done <- struct{}{} + return j.err +} diff --git a/store/bulk/bulk.go b/store/bulk/bulk.go new file mode 100644 index 000000000..ee40f3fae --- /dev/null +++ b/store/bulk/bulk.go @@ -0,0 +1,11 @@ +package bulk + +import ( + "context" +) + +type ( + Job interface { + Do(ctx context.Context, s storeInterface) error + } +) diff --git a/store/bulk/compose_charts.gen.go b/store/bulk/compose_charts.gen.go new file mode 100644 index 000000000..40ea4f6cf --- /dev/null +++ b/store/bulk/compose_charts.gen.go @@ -0,0 +1,72 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// Definitions file that controls how this file is generated: +// store/compose_charts.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeChartCreate struct { + Done chan struct{} + res *types.Chart + err error + } + + composeChartUpdate struct { + Done chan struct{} + res *types.Chart + err error + } + + composeChartRemove struct { + Done chan struct{} + res *types.Chart + err error + } +) + +// CreateComposeChart creates a new ComposeChart +// create job that can be pushed to store's transaction handler +func CreateComposeChart(res *types.Chart) *composeChartCreate { + return &composeChartCreate{res: res} +} + +// Do Executes composeChartCreate job +func (j *composeChartCreate) Do(ctx context.Context, s storeInterface) error { + j.err = s.CreateComposeChart(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// UpdateComposeChart creates a new ComposeChart +// update job that can be pushed to store's transaction handler +func UpdateComposeChart(res *types.Chart) *composeChartUpdate { + return &composeChartUpdate{res: res} +} + +// Do Executes composeChartUpdate job +func (j *composeChartUpdate) Do(ctx context.Context, s storeInterface) error { + j.err = s.UpdateComposeChart(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// RemoveComposeChart creates a new ComposeChart +// remove job that can be pushed to store's transaction handler +func RemoveComposeChart(res *types.Chart) *composeChartRemove { + return &composeChartRemove{res: res} +} + +// Do Executes composeChartRemove job +func (j *composeChartRemove) Do(ctx context.Context, s storeInterface) error { + j.err = s.RemoveComposeChart(ctx, j.res) + j.Done <- struct{}{} + return j.err +} diff --git a/store/bulk/compose_module_fields.gen.go b/store/bulk/compose_module_fields.gen.go new file mode 100644 index 000000000..f1bb57764 --- /dev/null +++ b/store/bulk/compose_module_fields.gen.go @@ -0,0 +1,72 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// Definitions file that controls how this file is generated: +// store/compose_module_fields.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeModuleFieldCreate struct { + Done chan struct{} + res *types.ModuleField + err error + } + + composeModuleFieldUpdate struct { + Done chan struct{} + res *types.ModuleField + err error + } + + composeModuleFieldRemove struct { + Done chan struct{} + res *types.ModuleField + err error + } +) + +// CreateComposeModuleField creates a new ComposeModuleField +// create job that can be pushed to store's transaction handler +func CreateComposeModuleField(res *types.ModuleField) *composeModuleFieldCreate { + return &composeModuleFieldCreate{res: res} +} + +// Do Executes composeModuleFieldCreate job +func (j *composeModuleFieldCreate) Do(ctx context.Context, s storeInterface) error { + j.err = s.CreateComposeModuleField(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// UpdateComposeModuleField creates a new ComposeModuleField +// update job that can be pushed to store's transaction handler +func UpdateComposeModuleField(res *types.ModuleField) *composeModuleFieldUpdate { + return &composeModuleFieldUpdate{res: res} +} + +// Do Executes composeModuleFieldUpdate job +func (j *composeModuleFieldUpdate) Do(ctx context.Context, s storeInterface) error { + j.err = s.UpdateComposeModuleField(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// RemoveComposeModuleField creates a new ComposeModuleField +// remove job that can be pushed to store's transaction handler +func RemoveComposeModuleField(res *types.ModuleField) *composeModuleFieldRemove { + return &composeModuleFieldRemove{res: res} +} + +// Do Executes composeModuleFieldRemove job +func (j *composeModuleFieldRemove) Do(ctx context.Context, s storeInterface) error { + j.err = s.RemoveComposeModuleField(ctx, j.res) + j.Done <- struct{}{} + return j.err +} diff --git a/store/bulk/compose_modules.gen.go b/store/bulk/compose_modules.gen.go new file mode 100644 index 000000000..30902c9f4 --- /dev/null +++ b/store/bulk/compose_modules.gen.go @@ -0,0 +1,72 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// Definitions file that controls how this file is generated: +// store/compose_modules.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeModuleCreate struct { + Done chan struct{} + res *types.Module + err error + } + + composeModuleUpdate struct { + Done chan struct{} + res *types.Module + err error + } + + composeModuleRemove struct { + Done chan struct{} + res *types.Module + err error + } +) + +// CreateComposeModule creates a new ComposeModule +// create job that can be pushed to store's transaction handler +func CreateComposeModule(res *types.Module) *composeModuleCreate { + return &composeModuleCreate{res: res} +} + +// Do Executes composeModuleCreate job +func (j *composeModuleCreate) Do(ctx context.Context, s storeInterface) error { + j.err = s.CreateComposeModule(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// UpdateComposeModule creates a new ComposeModule +// update job that can be pushed to store's transaction handler +func UpdateComposeModule(res *types.Module) *composeModuleUpdate { + return &composeModuleUpdate{res: res} +} + +// Do Executes composeModuleUpdate job +func (j *composeModuleUpdate) Do(ctx context.Context, s storeInterface) error { + j.err = s.UpdateComposeModule(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// RemoveComposeModule creates a new ComposeModule +// remove job that can be pushed to store's transaction handler +func RemoveComposeModule(res *types.Module) *composeModuleRemove { + return &composeModuleRemove{res: res} +} + +// Do Executes composeModuleRemove job +func (j *composeModuleRemove) Do(ctx context.Context, s storeInterface) error { + j.err = s.RemoveComposeModule(ctx, j.res) + j.Done <- struct{}{} + return j.err +} diff --git a/store/bulk/compose_namespaces.gen.go b/store/bulk/compose_namespaces.gen.go new file mode 100644 index 000000000..208b884d7 --- /dev/null +++ b/store/bulk/compose_namespaces.gen.go @@ -0,0 +1,72 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// Definitions file that controls how this file is generated: +// store/compose_namespaces.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeNamespaceCreate struct { + Done chan struct{} + res *types.Namespace + err error + } + + composeNamespaceUpdate struct { + Done chan struct{} + res *types.Namespace + err error + } + + composeNamespaceRemove struct { + Done chan struct{} + res *types.Namespace + err error + } +) + +// CreateComposeNamespace creates a new ComposeNamespace +// create job that can be pushed to store's transaction handler +func CreateComposeNamespace(res *types.Namespace) *composeNamespaceCreate { + return &composeNamespaceCreate{res: res} +} + +// Do Executes composeNamespaceCreate job +func (j *composeNamespaceCreate) Do(ctx context.Context, s storeInterface) error { + j.err = s.CreateComposeNamespace(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// UpdateComposeNamespace creates a new ComposeNamespace +// update job that can be pushed to store's transaction handler +func UpdateComposeNamespace(res *types.Namespace) *composeNamespaceUpdate { + return &composeNamespaceUpdate{res: res} +} + +// Do Executes composeNamespaceUpdate job +func (j *composeNamespaceUpdate) Do(ctx context.Context, s storeInterface) error { + j.err = s.UpdateComposeNamespace(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// RemoveComposeNamespace creates a new ComposeNamespace +// remove job that can be pushed to store's transaction handler +func RemoveComposeNamespace(res *types.Namespace) *composeNamespaceRemove { + return &composeNamespaceRemove{res: res} +} + +// Do Executes composeNamespaceRemove job +func (j *composeNamespaceRemove) Do(ctx context.Context, s storeInterface) error { + j.err = s.RemoveComposeNamespace(ctx, j.res) + j.Done <- struct{}{} + return j.err +} diff --git a/store/bulk/compose_pages.gen.go b/store/bulk/compose_pages.gen.go new file mode 100644 index 000000000..875881377 --- /dev/null +++ b/store/bulk/compose_pages.gen.go @@ -0,0 +1,72 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// Definitions file that controls how this file is generated: +// store/compose_pages.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composePageCreate struct { + Done chan struct{} + res *types.Page + err error + } + + composePageUpdate struct { + Done chan struct{} + res *types.Page + err error + } + + composePageRemove struct { + Done chan struct{} + res *types.Page + err error + } +) + +// CreateComposePage creates a new ComposePage +// create job that can be pushed to store's transaction handler +func CreateComposePage(res *types.Page) *composePageCreate { + return &composePageCreate{res: res} +} + +// Do Executes composePageCreate job +func (j *composePageCreate) Do(ctx context.Context, s storeInterface) error { + j.err = s.CreateComposePage(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// UpdateComposePage creates a new ComposePage +// update job that can be pushed to store's transaction handler +func UpdateComposePage(res *types.Page) *composePageUpdate { + return &composePageUpdate{res: res} +} + +// Do Executes composePageUpdate job +func (j *composePageUpdate) Do(ctx context.Context, s storeInterface) error { + j.err = s.UpdateComposePage(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// RemoveComposePage creates a new ComposePage +// remove job that can be pushed to store's transaction handler +func RemoveComposePage(res *types.Page) *composePageRemove { + return &composePageRemove{res: res} +} + +// Do Executes composePageRemove job +func (j *composePageRemove) Do(ctx context.Context, s storeInterface) error { + j.err = s.RemoveComposePage(ctx, j.res) + j.Done <- struct{}{} + return j.err +} diff --git a/store/bulk/compose_records.go b/store/bulk/compose_records.go new file mode 100644 index 000000000..31d91424b --- /dev/null +++ b/store/bulk/compose_records.go @@ -0,0 +1,81 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// Definitions file that controls how this file is generated: +// store/compose_records.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeRecordCreate struct { + Done chan struct{} + rec *types.Record + mod *types.Module + err error + } + + composeRecordUpdate struct { + Done chan struct{} + rec *types.Record + mod *types.Module + err error + } + + composeRecordRemove struct { + Done chan struct{} + rec *types.Record + mod *types.Module + err error + } + + composeRecordStore interface { + CreateComposeRecord(context.Context, *types.Module, ...*types.Record) error + UpdateComposeRecord(context.Context, *types.Module, ...*types.Record) error + RemoveComposeRecord(context.Context, *types.Module, ...*types.Record) error + } +) + +// CreateComposeRecord creates a new ComposeRecord +// create job that can be pushed to store's transaction handler +func CreateComposeRecord(mod *types.Module, rec *types.Record) *composeRecordCreate { + return &composeRecordCreate{mod: mod, rec: rec} +} + +// Do Executes composeRecordCreate job +func (j *composeRecordCreate) Do(ctx context.Context, s composeRecordStore) error { + j.err = s.CreateComposeRecord(ctx, j.mod, j.rec) + j.Done <- struct{}{} + return j.err +} + +// UpdateComposeRecord creates a new ComposeRecord +// update job that can be pushed to store's transaction handler +func UpdateComposeRecord(mod *types.Module, rec *types.Record) *composeRecordUpdate { + return &composeRecordUpdate{mod: mod, rec: rec} +} + +// Do Executes composeRecordUpdate job +func (j *composeRecordUpdate) Do(ctx context.Context, s composeRecordStore) error { + j.err = s.UpdateComposeRecord(ctx, j.mod, j.rec) + j.Done <- struct{}{} + return j.err +} + +// RemoveComposeRecord creates a new ComposeRecord +// remove job that can be pushed to store's transaction handler +func RemoveComposeRecord(mod *types.Module, rec *types.Record) *composeRecordRemove { + return &composeRecordRemove{mod: mod, rec: rec} +} + +// Do Executes composeRecordRemove job +func (j *composeRecordRemove) Do(ctx context.Context, s composeRecordStore) error { + j.err = s.RemoveComposeRecord(ctx, j.mod, j.rec) + j.Done <- struct{}{} + return j.err +} diff --git a/store/bulk/credentials.gen.go b/store/bulk/credentials.gen.go new file mode 100644 index 000000000..aa7baa6a7 --- /dev/null +++ b/store/bulk/credentials.gen.go @@ -0,0 +1,72 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// Definitions file that controls how this file is generated: +// store/credentials.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + credentialsCreate struct { + Done chan struct{} + res *types.Credentials + err error + } + + credentialsUpdate struct { + Done chan struct{} + res *types.Credentials + err error + } + + credentialsRemove struct { + Done chan struct{} + res *types.Credentials + err error + } +) + +// CreateCredentials creates a new Credentials +// create job that can be pushed to store's transaction handler +func CreateCredentials(res *types.Credentials) *credentialsCreate { + return &credentialsCreate{res: res} +} + +// Do Executes credentialsCreate job +func (j *credentialsCreate) Do(ctx context.Context, s storeInterface) error { + j.err = s.CreateCredentials(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// UpdateCredentials creates a new Credentials +// update job that can be pushed to store's transaction handler +func UpdateCredentials(res *types.Credentials) *credentialsUpdate { + return &credentialsUpdate{res: res} +} + +// Do Executes credentialsUpdate job +func (j *credentialsUpdate) Do(ctx context.Context, s storeInterface) error { + j.err = s.UpdateCredentials(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// RemoveCredentials creates a new Credentials +// remove job that can be pushed to store's transaction handler +func RemoveCredentials(res *types.Credentials) *credentialsRemove { + return &credentialsRemove{res: res} +} + +// Do Executes credentialsRemove job +func (j *credentialsRemove) Do(ctx context.Context, s storeInterface) error { + j.err = s.RemoveCredentials(ctx, j.res) + j.Done <- struct{}{} + return j.err +} diff --git a/store/bulk/rbac_rules.gen.go b/store/bulk/rbac_rules.gen.go new file mode 100644 index 000000000..71f2f67a7 --- /dev/null +++ b/store/bulk/rbac_rules.gen.go @@ -0,0 +1,72 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// Definitions file that controls how this file is generated: +// store/rbac_rules.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/permissions" +) + +type ( + rbacRuleCreate struct { + Done chan struct{} + res *permissions.Rule + err error + } + + rbacRuleUpdate struct { + Done chan struct{} + res *permissions.Rule + err error + } + + rbacRuleRemove struct { + Done chan struct{} + res *permissions.Rule + err error + } +) + +// CreateRbacRule creates a new RbacRule +// create job that can be pushed to store's transaction handler +func CreateRbacRule(res *permissions.Rule) *rbacRuleCreate { + return &rbacRuleCreate{res: res} +} + +// Do Executes rbacRuleCreate job +func (j *rbacRuleCreate) Do(ctx context.Context, s storeInterface) error { + j.err = s.CreateRbacRule(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// UpdateRbacRule creates a new RbacRule +// update job that can be pushed to store's transaction handler +func UpdateRbacRule(res *permissions.Rule) *rbacRuleUpdate { + return &rbacRuleUpdate{res: res} +} + +// Do Executes rbacRuleUpdate job +func (j *rbacRuleUpdate) Do(ctx context.Context, s storeInterface) error { + j.err = s.UpdateRbacRule(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// RemoveRbacRule creates a new RbacRule +// remove job that can be pushed to store's transaction handler +func RemoveRbacRule(res *permissions.Rule) *rbacRuleRemove { + return &rbacRuleRemove{res: res} +} + +// Do Executes rbacRuleRemove job +func (j *rbacRuleRemove) Do(ctx context.Context, s storeInterface) error { + j.err = s.RemoveRbacRule(ctx, j.res) + j.Done <- struct{}{} + return j.err +} diff --git a/store/bulk/reminders.gen.go b/store/bulk/reminders.gen.go new file mode 100644 index 000000000..fcc116287 --- /dev/null +++ b/store/bulk/reminders.gen.go @@ -0,0 +1,72 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// Definitions file that controls how this file is generated: +// store/reminders.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + reminderCreate struct { + Done chan struct{} + res *types.Reminder + err error + } + + reminderUpdate struct { + Done chan struct{} + res *types.Reminder + err error + } + + reminderRemove struct { + Done chan struct{} + res *types.Reminder + err error + } +) + +// CreateReminder creates a new Reminder +// create job that can be pushed to store's transaction handler +func CreateReminder(res *types.Reminder) *reminderCreate { + return &reminderCreate{res: res} +} + +// Do Executes reminderCreate job +func (j *reminderCreate) Do(ctx context.Context, s storeInterface) error { + j.err = s.CreateReminder(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// UpdateReminder creates a new Reminder +// update job that can be pushed to store's transaction handler +func UpdateReminder(res *types.Reminder) *reminderUpdate { + return &reminderUpdate{res: res} +} + +// Do Executes reminderUpdate job +func (j *reminderUpdate) Do(ctx context.Context, s storeInterface) error { + j.err = s.UpdateReminder(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// RemoveReminder creates a new Reminder +// remove job that can be pushed to store's transaction handler +func RemoveReminder(res *types.Reminder) *reminderRemove { + return &reminderRemove{res: res} +} + +// Do Executes reminderRemove job +func (j *reminderRemove) Do(ctx context.Context, s storeInterface) error { + j.err = s.RemoveReminder(ctx, j.res) + j.Done <- struct{}{} + return j.err +} diff --git a/store/bulk/roles.gen.go b/store/bulk/roles.gen.go new file mode 100644 index 000000000..36fcb98dc --- /dev/null +++ b/store/bulk/roles.gen.go @@ -0,0 +1,72 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// Definitions file that controls how this file is generated: +// store/roles.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + roleCreate struct { + Done chan struct{} + res *types.Role + err error + } + + roleUpdate struct { + Done chan struct{} + res *types.Role + err error + } + + roleRemove struct { + Done chan struct{} + res *types.Role + err error + } +) + +// CreateRole creates a new Role +// create job that can be pushed to store's transaction handler +func CreateRole(res *types.Role) *roleCreate { + return &roleCreate{res: res} +} + +// Do Executes roleCreate job +func (j *roleCreate) Do(ctx context.Context, s storeInterface) error { + j.err = s.CreateRole(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// UpdateRole creates a new Role +// update job that can be pushed to store's transaction handler +func UpdateRole(res *types.Role) *roleUpdate { + return &roleUpdate{res: res} +} + +// Do Executes roleUpdate job +func (j *roleUpdate) Do(ctx context.Context, s storeInterface) error { + j.err = s.UpdateRole(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// RemoveRole creates a new Role +// remove job that can be pushed to store's transaction handler +func RemoveRole(res *types.Role) *roleRemove { + return &roleRemove{res: res} +} + +// Do Executes roleRemove job +func (j *roleRemove) Do(ctx context.Context, s storeInterface) error { + j.err = s.RemoveRole(ctx, j.res) + j.Done <- struct{}{} + return j.err +} diff --git a/store/bulk/settings.gen.go b/store/bulk/settings.gen.go new file mode 100644 index 000000000..1a8244649 --- /dev/null +++ b/store/bulk/settings.gen.go @@ -0,0 +1,72 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// Definitions file that controls how this file is generated: +// store/settings.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + settingCreate struct { + Done chan struct{} + res *types.SettingValue + err error + } + + settingUpdate struct { + Done chan struct{} + res *types.SettingValue + err error + } + + settingRemove struct { + Done chan struct{} + res *types.SettingValue + err error + } +) + +// CreateSetting creates a new Setting +// create job that can be pushed to store's transaction handler +func CreateSetting(res *types.SettingValue) *settingCreate { + return &settingCreate{res: res} +} + +// Do Executes settingCreate job +func (j *settingCreate) Do(ctx context.Context, s storeInterface) error { + j.err = s.CreateSetting(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// UpdateSetting creates a new Setting +// update job that can be pushed to store's transaction handler +func UpdateSetting(res *types.SettingValue) *settingUpdate { + return &settingUpdate{res: res} +} + +// Do Executes settingUpdate job +func (j *settingUpdate) Do(ctx context.Context, s storeInterface) error { + j.err = s.UpdateSetting(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// RemoveSetting creates a new Setting +// remove job that can be pushed to store's transaction handler +func RemoveSetting(res *types.SettingValue) *settingRemove { + return &settingRemove{res: res} +} + +// Do Executes settingRemove job +func (j *settingRemove) Do(ctx context.Context, s storeInterface) error { + j.err = s.RemoveSetting(ctx, j.res) + j.Done <- struct{}{} + return j.err +} diff --git a/store/bulk/store_interface.gen.go b/store/bulk/store_interface.gen.go new file mode 100644 index 000000000..283808586 --- /dev/null +++ b/store/bulk/store_interface.gen.go @@ -0,0 +1,42 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/actionlog.yaml +// - store/applications.yaml +// - store/compose_charts.yaml +// - store/compose_module_fields.yaml +// - store/compose_modules.yaml +// - store/compose_namespaces.yaml +// - store/compose_pages.yaml +// - store/credentials.yaml +// - store/rbac_rules.yaml +// - store/reminders.yaml +// - store/roles.yaml +// - store/settings.yaml +// - store/system_attachments.yaml +// - store/users.yaml + +type ( + // Interface combines interfaces of all supported store interfaces + storeInterface interface { + actionlogsStore + applicationsStore + composeChartsStore + composeModuleFieldsStore + composeModulesStore + composeNamespacesStore + composePagesStore + credentialsStore + rbacRulesStore + remindersStore + rolesStore + settingsStore + attachmentsStore + usersStore + } +) diff --git a/store/bulk/store_interface_actionlog.gen.go b/store/bulk/store_interface_actionlog.gen.go new file mode 100644 index 000000000..089af0f47 --- /dev/null +++ b/store/bulk/store_interface_actionlog.gen.go @@ -0,0 +1,27 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/actionlog.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/actionlog" +) + +type ( + actionlogsStore interface { + SearchActionlogs(ctx context.Context, f actionlog.Filter) (actionlog.ActionSet, actionlog.Filter, error) + CreateActionlog(ctx context.Context, rr ...*actionlog.Action) error + UpdateActionlog(ctx context.Context, rr ...*actionlog.Action) error + PartialUpdateActionlog(ctx context.Context, onlyColumns []string, rr ...*actionlog.Action) error + RemoveActionlog(ctx context.Context, rr ...*actionlog.Action) error + RemoveActionlogByID(ctx context.Context, ID uint64) error + + TruncateActionlogs(ctx context.Context) error + } +) diff --git a/store/bulk/store_interface_applications.gen.go b/store/bulk/store_interface_applications.gen.go new file mode 100644 index 000000000..3695bd896 --- /dev/null +++ b/store/bulk/store_interface_applications.gen.go @@ -0,0 +1,28 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/applications.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + applicationsStore interface { + SearchApplications(ctx context.Context, f types.ApplicationFilter) (types.ApplicationSet, types.ApplicationFilter, error) + LookupApplicationByID(ctx context.Context, id uint64) (*types.Application, error) + CreateApplication(ctx context.Context, rr ...*types.Application) error + UpdateApplication(ctx context.Context, rr ...*types.Application) error + PartialUpdateApplication(ctx context.Context, onlyColumns []string, rr ...*types.Application) error + RemoveApplication(ctx context.Context, rr ...*types.Application) error + RemoveApplicationByID(ctx context.Context, ID uint64) error + + TruncateApplications(ctx context.Context) error + } +) diff --git a/store/bulk/store_interface_compose_charts.gen.go b/store/bulk/store_interface_compose_charts.gen.go new file mode 100644 index 000000000..2103d7bcc --- /dev/null +++ b/store/bulk/store_interface_compose_charts.gen.go @@ -0,0 +1,29 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/compose_charts.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeChartsStore interface { + SearchComposeCharts(ctx context.Context, f types.ChartFilter) (types.ChartSet, types.ChartFilter, error) + LookupComposeChartByID(ctx context.Context, id uint64) (*types.Chart, error) + LookupComposeChartByHandle(ctx context.Context, handle string) (*types.Chart, error) + CreateComposeChart(ctx context.Context, rr ...*types.Chart) error + UpdateComposeChart(ctx context.Context, rr ...*types.Chart) error + PartialUpdateComposeChart(ctx context.Context, onlyColumns []string, rr ...*types.Chart) error + RemoveComposeChart(ctx context.Context, rr ...*types.Chart) error + RemoveComposeChartByID(ctx context.Context, ID uint64) error + + TruncateComposeCharts(ctx context.Context) error + } +) diff --git a/store/bulk/store_interface_compose_module_fields.gen.go b/store/bulk/store_interface_compose_module_fields.gen.go new file mode 100644 index 000000000..7573349f4 --- /dev/null +++ b/store/bulk/store_interface_compose_module_fields.gen.go @@ -0,0 +1,26 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/compose_module_fields.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeModuleFieldsStore interface { + CreateComposeModuleField(ctx context.Context, rr ...*types.ModuleField) error + UpdateComposeModuleField(ctx context.Context, rr ...*types.ModuleField) error + PartialUpdateComposeModuleField(ctx context.Context, onlyColumns []string, rr ...*types.ModuleField) error + RemoveComposeModuleField(ctx context.Context, rr ...*types.ModuleField) error + RemoveComposeModuleFieldByID(ctx context.Context, ID uint64) error + + TruncateComposeModuleFields(ctx context.Context) error + } +) diff --git a/store/bulk/store_interface_compose_modules.gen.go b/store/bulk/store_interface_compose_modules.gen.go new file mode 100644 index 000000000..2401b9275 --- /dev/null +++ b/store/bulk/store_interface_compose_modules.gen.go @@ -0,0 +1,29 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/compose_modules.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeModulesStore interface { + SearchComposeModules(ctx context.Context, f types.ModuleFilter) (types.ModuleSet, types.ModuleFilter, error) + LookupComposeModuleByHandle(ctx context.Context, handle string) (*types.Module, error) + LookupComposeModuleByID(ctx context.Context, id uint64) (*types.Module, error) + CreateComposeModule(ctx context.Context, rr ...*types.Module) error + UpdateComposeModule(ctx context.Context, rr ...*types.Module) error + PartialUpdateComposeModule(ctx context.Context, onlyColumns []string, rr ...*types.Module) error + RemoveComposeModule(ctx context.Context, rr ...*types.Module) error + RemoveComposeModuleByID(ctx context.Context, ID uint64) error + + TruncateComposeModules(ctx context.Context) error + } +) diff --git a/store/bulk/store_interface_compose_namespaces.gen.go b/store/bulk/store_interface_compose_namespaces.gen.go new file mode 100644 index 000000000..e153a9920 --- /dev/null +++ b/store/bulk/store_interface_compose_namespaces.gen.go @@ -0,0 +1,29 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/compose_namespaces.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeNamespacesStore interface { + SearchComposeNamespaces(ctx context.Context, f types.NamespaceFilter) (types.NamespaceSet, types.NamespaceFilter, error) + LookupComposeNamespaceBySlug(ctx context.Context, slug string) (*types.Namespace, error) + LookupComposeNamespaceByID(ctx context.Context, id uint64) (*types.Namespace, error) + CreateComposeNamespace(ctx context.Context, rr ...*types.Namespace) error + UpdateComposeNamespace(ctx context.Context, rr ...*types.Namespace) error + PartialUpdateComposeNamespace(ctx context.Context, onlyColumns []string, rr ...*types.Namespace) error + RemoveComposeNamespace(ctx context.Context, rr ...*types.Namespace) error + RemoveComposeNamespaceByID(ctx context.Context, ID uint64) error + + TruncateComposeNamespaces(ctx context.Context) error + } +) diff --git a/store/bulk/store_interface_compose_pages.gen.go b/store/bulk/store_interface_compose_pages.gen.go new file mode 100644 index 000000000..f6846db65 --- /dev/null +++ b/store/bulk/store_interface_compose_pages.gen.go @@ -0,0 +1,29 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/compose_pages.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composePagesStore interface { + SearchComposePages(ctx context.Context, f types.PageFilter) (types.PageSet, types.PageFilter, error) + LookupComposePageByHandle(ctx context.Context, handle string) (*types.Page, error) + LookupComposePageByID(ctx context.Context, id uint64) (*types.Page, error) + CreateComposePage(ctx context.Context, rr ...*types.Page) error + UpdateComposePage(ctx context.Context, rr ...*types.Page) error + PartialUpdateComposePage(ctx context.Context, onlyColumns []string, rr ...*types.Page) error + RemoveComposePage(ctx context.Context, rr ...*types.Page) error + RemoveComposePageByID(ctx context.Context, ID uint64) error + + TruncateComposePages(ctx context.Context) error + } +) diff --git a/store/bulk/store_interface_credentials.gen.go b/store/bulk/store_interface_credentials.gen.go new file mode 100644 index 000000000..c6a76eb7d --- /dev/null +++ b/store/bulk/store_interface_credentials.gen.go @@ -0,0 +1,28 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/credentials.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + credentialsStore interface { + SearchCredentials(ctx context.Context, f types.CredentialsFilter) (types.CredentialsSet, types.CredentialsFilter, error) + LookupCredentialsByID(ctx context.Context, id uint64) (*types.Credentials, error) + CreateCredentials(ctx context.Context, rr ...*types.Credentials) error + UpdateCredentials(ctx context.Context, rr ...*types.Credentials) error + PartialUpdateCredentials(ctx context.Context, onlyColumns []string, rr ...*types.Credentials) error + RemoveCredentials(ctx context.Context, rr ...*types.Credentials) error + RemoveCredentialsByID(ctx context.Context, ID uint64) error + + TruncateCredentials(ctx context.Context) error + } +) diff --git a/store/bulk/store_interface_rbac_rules.gen.go b/store/bulk/store_interface_rbac_rules.gen.go new file mode 100644 index 000000000..7e1711094 --- /dev/null +++ b/store/bulk/store_interface_rbac_rules.gen.go @@ -0,0 +1,27 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/rbac_rules.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/permissions" +) + +type ( + rbacRulesStore interface { + SearchRbacRules(ctx context.Context, f permissions.RuleFilter) (permissions.RuleSet, permissions.RuleFilter, error) + CreateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + UpdateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + PartialUpdateRbacRule(ctx context.Context, onlyColumns []string, rr ...*permissions.Rule) error + RemoveRbacRule(ctx context.Context, rr ...*permissions.Rule) error + RemoveRbacRuleByRoleIDResourceOperation(ctx context.Context, roleID uint64, resource string, operation string) error + + TruncateRbacRules(ctx context.Context) error + } +) diff --git a/store/bulk/store_interface_reminders.gen.go b/store/bulk/store_interface_reminders.gen.go new file mode 100644 index 000000000..6a1cb3612 --- /dev/null +++ b/store/bulk/store_interface_reminders.gen.go @@ -0,0 +1,28 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/reminders.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + remindersStore interface { + SearchReminders(ctx context.Context, f types.ReminderFilter) (types.ReminderSet, types.ReminderFilter, error) + LookupReminderByID(ctx context.Context, id uint64) (*types.Reminder, error) + CreateReminder(ctx context.Context, rr ...*types.Reminder) error + UpdateReminder(ctx context.Context, rr ...*types.Reminder) error + PartialUpdateReminder(ctx context.Context, onlyColumns []string, rr ...*types.Reminder) error + RemoveReminder(ctx context.Context, rr ...*types.Reminder) error + RemoveReminderByID(ctx context.Context, ID uint64) error + + TruncateReminders(ctx context.Context) error + } +) diff --git a/store/bulk/store_interface_roles.gen.go b/store/bulk/store_interface_roles.gen.go new file mode 100644 index 000000000..dc6c668f2 --- /dev/null +++ b/store/bulk/store_interface_roles.gen.go @@ -0,0 +1,30 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/roles.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + rolesStore interface { + SearchRoles(ctx context.Context, f types.RoleFilter) (types.RoleSet, types.RoleFilter, error) + LookupRoleByID(ctx context.Context, id uint64) (*types.Role, error) + LookupRoleByHandle(ctx context.Context, handle string) (*types.Role, error) + LookupRoleByName(ctx context.Context, name string) (*types.Role, error) + CreateRole(ctx context.Context, rr ...*types.Role) error + UpdateRole(ctx context.Context, rr ...*types.Role) error + PartialUpdateRole(ctx context.Context, onlyColumns []string, rr ...*types.Role) error + RemoveRole(ctx context.Context, rr ...*types.Role) error + RemoveRoleByID(ctx context.Context, ID uint64) error + + TruncateRoles(ctx context.Context) error + } +) diff --git a/store/bulk/store_interface_settings.gen.go b/store/bulk/store_interface_settings.gen.go new file mode 100644 index 000000000..38e3ab950 --- /dev/null +++ b/store/bulk/store_interface_settings.gen.go @@ -0,0 +1,28 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/settings.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + settingsStore interface { + SearchSettings(ctx context.Context, f types.SettingsFilter) (types.SettingValueSet, types.SettingsFilter, error) + LookupSettingByNameOwnedBy(ctx context.Context, name string, owned_by uint64) (*types.SettingValue, error) + CreateSetting(ctx context.Context, rr ...*types.SettingValue) error + UpdateSetting(ctx context.Context, rr ...*types.SettingValue) error + PartialUpdateSetting(ctx context.Context, onlyColumns []string, rr ...*types.SettingValue) error + RemoveSetting(ctx context.Context, rr ...*types.SettingValue) error + RemoveSettingByNameOwnedBy(ctx context.Context, name string, ownedBy uint64) error + + TruncateSettings(ctx context.Context) error + } +) diff --git a/store/bulk/store_interface_system_attachments.gen.go b/store/bulk/store_interface_system_attachments.gen.go new file mode 100644 index 000000000..55fcaf2dc --- /dev/null +++ b/store/bulk/store_interface_system_attachments.gen.go @@ -0,0 +1,28 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/system_attachments.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + attachmentsStore interface { + SearchAttachments(ctx context.Context, f types.AttachmentFilter) (types.AttachmentSet, types.AttachmentFilter, error) + LookupAttachmentByID(ctx context.Context, id uint64) (*types.Attachment, error) + CreateAttachment(ctx context.Context, rr ...*types.Attachment) error + UpdateAttachment(ctx context.Context, rr ...*types.Attachment) error + PartialUpdateAttachment(ctx context.Context, onlyColumns []string, rr ...*types.Attachment) error + RemoveAttachment(ctx context.Context, rr ...*types.Attachment) error + RemoveAttachmentByID(ctx context.Context, ID uint64) error + + TruncateAttachments(ctx context.Context) error + } +) diff --git a/store/bulk/store_interface_users.gen.go b/store/bulk/store_interface_users.gen.go new file mode 100644 index 000000000..82d39c247 --- /dev/null +++ b/store/bulk/store_interface_users.gen.go @@ -0,0 +1,31 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/users.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + usersStore interface { + SearchUsers(ctx context.Context, f types.UserFilter) (types.UserSet, types.UserFilter, error) + LookupUserByID(ctx context.Context, id uint64) (*types.User, error) + LookupUserByEmail(ctx context.Context, email string) (*types.User, error) + LookupUserByHandle(ctx context.Context, handle string) (*types.User, error) + LookupUserByUsername(ctx context.Context, username string) (*types.User, error) + CreateUser(ctx context.Context, rr ...*types.User) error + UpdateUser(ctx context.Context, rr ...*types.User) error + PartialUpdateUser(ctx context.Context, onlyColumns []string, rr ...*types.User) error + RemoveUser(ctx context.Context, rr ...*types.User) error + RemoveUserByID(ctx context.Context, ID uint64) error + + TruncateUsers(ctx context.Context) error + } +) diff --git a/store/bulk/system_attachments.gen.go b/store/bulk/system_attachments.gen.go new file mode 100644 index 000000000..523dbb9a5 --- /dev/null +++ b/store/bulk/system_attachments.gen.go @@ -0,0 +1,72 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// Definitions file that controls how this file is generated: +// store/system_attachments.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + attachmentCreate struct { + Done chan struct{} + res *types.Attachment + err error + } + + attachmentUpdate struct { + Done chan struct{} + res *types.Attachment + err error + } + + attachmentRemove struct { + Done chan struct{} + res *types.Attachment + err error + } +) + +// CreateAttachment creates a new Attachment +// create job that can be pushed to store's transaction handler +func CreateAttachment(res *types.Attachment) *attachmentCreate { + return &attachmentCreate{res: res} +} + +// Do Executes attachmentCreate job +func (j *attachmentCreate) Do(ctx context.Context, s storeInterface) error { + j.err = s.CreateAttachment(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// UpdateAttachment creates a new Attachment +// update job that can be pushed to store's transaction handler +func UpdateAttachment(res *types.Attachment) *attachmentUpdate { + return &attachmentUpdate{res: res} +} + +// Do Executes attachmentUpdate job +func (j *attachmentUpdate) Do(ctx context.Context, s storeInterface) error { + j.err = s.UpdateAttachment(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// RemoveAttachment creates a new Attachment +// remove job that can be pushed to store's transaction handler +func RemoveAttachment(res *types.Attachment) *attachmentRemove { + return &attachmentRemove{res: res} +} + +// Do Executes attachmentRemove job +func (j *attachmentRemove) Do(ctx context.Context, s storeInterface) error { + j.err = s.RemoveAttachment(ctx, j.res) + j.Done <- struct{}{} + return j.err +} diff --git a/store/bulk/users.gen.go b/store/bulk/users.gen.go new file mode 100644 index 000000000..66d93c360 --- /dev/null +++ b/store/bulk/users.gen.go @@ -0,0 +1,72 @@ +package bulk + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// Definitions file that controls how this file is generated: +// store/users.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + userCreate struct { + Done chan struct{} + res *types.User + err error + } + + userUpdate struct { + Done chan struct{} + res *types.User + err error + } + + userRemove struct { + Done chan struct{} + res *types.User + err error + } +) + +// CreateUser creates a new User +// create job that can be pushed to store's transaction handler +func CreateUser(res *types.User) *userCreate { + return &userCreate{res: res} +} + +// Do Executes userCreate job +func (j *userCreate) Do(ctx context.Context, s storeInterface) error { + j.err = s.CreateUser(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// UpdateUser creates a new User +// update job that can be pushed to store's transaction handler +func UpdateUser(res *types.User) *userUpdate { + return &userUpdate{res: res} +} + +// Do Executes userUpdate job +func (j *userUpdate) Do(ctx context.Context, s storeInterface) error { + j.err = s.UpdateUser(ctx, j.res) + j.Done <- struct{}{} + return j.err +} + +// RemoveUser creates a new User +// remove job that can be pushed to store's transaction handler +func RemoveUser(res *types.User) *userRemove { + return &userRemove{res: res} +} + +// Do Executes userRemove job +func (j *userRemove) Do(ctx context.Context, s storeInterface) error { + j.err = s.RemoveUser(ctx, j.res) + j.Done <- struct{}{} + return j.err +} diff --git a/store/compose_charts.yaml b/store/compose_charts.yaml new file mode 100644 index 000000000..b8d7fa390 --- /dev/null +++ b/store/compose_charts.yaml @@ -0,0 +1,33 @@ +import: + - github.com/cortezaproject/corteza-server/compose/types + +interface: + - compose/service + +types: + type: types.Chart + +fields: + - { field: ID } + - { field: Handle, lookupFilterPreprocessor: lower } + - { field: Name } + - { field: Config, type: "types.ChartConfig" } + - { field: NamespaceID } + - { field: CreatedAt } + - { field: UpdatedAt } + - { field: DeletedAt } + +lookups: + - fields: [ ID ] + description: |- + searches for compose chart by ID + + It returns compose chart even if deleted + - fields: [ Handle ] + description: |- + searches for compose chart by handle (case-insensitive) + +rdbms: + alias: cch + table: compose_chart + customFilterConverter: true diff --git a/store/compose_module_fields.yaml b/store/compose_module_fields.yaml new file mode 100644 index 000000000..8993df03c --- /dev/null +++ b/store/compose_module_fields.yaml @@ -0,0 +1,34 @@ +import: + - github.com/cortezaproject/corteza-server/compose/types + +interface: + - compose/service + +types: + type: types.ModuleField + +fields: + - { field: ID } + - { field: Name } + - { field: ModuleID } + - { field: Place, type: int } + - { field: Kind } + - { field: Label } + - { field: Options, type: "types.ModuleFieldOptions" } + - { field: Private, type: bool, column: is_private } + - { field: Required, type: bool, column: is_required } + - { field: Visible, type: bool, column: is_visible } + - { field: Multi, type: bool, column: is_multi } + - { field: DefaultValue, type: "types.RecordValueSet" } + - { field: CreatedAt } + - { field: UpdatedAt } + - { field: DeletedAt } + +rdbms: + alias: cmf + table: compose_module_field + customFilterConverter: true + + +search: + disable: true diff --git a/store/compose_modules.yaml b/store/compose_modules.yaml new file mode 100644 index 000000000..1bb6604e3 --- /dev/null +++ b/store/compose_modules.yaml @@ -0,0 +1,34 @@ +import: + - github.com/cortezaproject/corteza-server/compose/types + +interface: + - compose/service + +types: + type: types.Module + +fields: + - { field: ID } + - { field: Handle, lookupFilterPreprocessor: lower } + - { field: Name } + - { field: Meta, type: "types.JSONText" } + - { field: NamespaceID } + - { field: CreatedAt } + - { field: UpdatedAt } + - { field: DeletedAt } + +lookups: + - fields: [ Handle ] + description: |- + searches for compose module by handle (case-insensitive) + + - fields: [ ID ] + description: |- + searches for compose module by ID + + It returns compose module even if deleted + +rdbms: + alias: cmd + table: compose_module + customFilterConverter: true diff --git a/store/compose_namespaces.yaml b/store/compose_namespaces.yaml new file mode 100644 index 000000000..d5719842a --- /dev/null +++ b/store/compose_namespaces.yaml @@ -0,0 +1,41 @@ +import: + - github.com/cortezaproject/corteza-server/compose/types + +interface: + - compose/service + +types: + type: types.Namespace + +fields: + - { field: ID } + - { field: Name } + - { field: Slug, lookupFilterPreprocessor: lower } + - { field: Enabled } + - { field: Meta, type: "*types.NamespaceMeta" } + - { field: CreatedAt } + - { field: UpdatedAt } + - { field: DeletedAt } + +lookups: + - fields: [ Slug ] + description: |- + searches for namespace by slug (case-insensitive) + + - fields: [ ID ] + description: |- + searches for compose namespace by ID + + It returns compose namespace even if deleted + +partialUpdates: + - name: delete + set: { DeletedAt: now() } + - name: undelete + set: { DeletedAt: nil } + +rdbms: + alias: cns + table: compose_namespace + customFilterConverter: true + diff --git a/store/compose_pages.yaml b/store/compose_pages.yaml new file mode 100644 index 000000000..932df9b7b --- /dev/null +++ b/store/compose_pages.yaml @@ -0,0 +1,40 @@ +import: + - github.com/cortezaproject/corteza-server/compose/types + +interface: + - compose/service + +types: + type: types.Page + +fields: + - { field: ID } + - { field: SelfID, column: "self_id" } + - { field: NamespaceID } + - { field: ModuleID } + - { field: Handle, lookupFilterPreprocessor: lower } + - { field: Title } + - { field: Description, type: "string" } + - { field: Blocks, type: "types.PageBlocks" } + - { field: Visible, type: bool } + - { field: Weight, type: int } + - { field: CreatedAt } + - { field: UpdatedAt } + - { field: DeletedAt } + +lookups: + - fields: [ Handle ] + description: |- + searches for page chart by handle (case-insensitive) + + - fields: [ ID ] + description: |- + searches for compose page by ID + + It returns compose page even if deleted + +rdbms: + alias: cpg + table: compose_page + customFilterConverter: true + diff --git a/store/credentials.yaml b/store/credentials.yaml new file mode 100644 index 000000000..88aa04544 --- /dev/null +++ b/store/credentials.yaml @@ -0,0 +1,45 @@ +import: + - github.com/cortezaproject/corteza-server/system/types + +interface: + - system/service + +types: + singular: Credentials + plural: Credentials + + +fields: + - { field: ID } + - { field: OwnerID } + - { field: Kind } + - { field: Label } + - { field: Credentials } + - { field: Meta } + - { field: LastUsedAt } + - { field: ExpiresAt } + - { field: CreatedAt } + - { field: UpdatedAt } + - { field: DeletedAt } + +lookups: + - fields: [ ID ] + description: |- + searches for credentials by ID + + It returns credentials even if deleted + +search: + disablePaging: true + +partialUpdates: + - name: delete + set: { DeletedAt: now() } + - name: undelete + set: { DeletedAt: nil } + +rdbms: + alias: crd + table: sys_credentials + customFilterConverter: true + diff --git a/store/errors.go b/store/errors.go new file mode 100644 index 000000000..688f87389 --- /dev/null +++ b/store/errors.go @@ -0,0 +1,24 @@ +package store + +type ( + storeError struct { + msg string + err error + } +) + +func (e *storeError) Error() string { + return e.msg +} + +func (e *storeError) Unwrap() error { + return e.err +} + +var ( + ErrNotFound = &storeError{msg: "not found"} +) + +func Error(msg string, err error) error { + return &storeError{msg, err} +} diff --git a/store/mysql/mysql.go b/store/mysql/mysql.go new file mode 100644 index 000000000..2a90bf62a --- /dev/null +++ b/store/mysql/mysql.go @@ -0,0 +1,107 @@ +package mysql + +import ( + "context" + "errors" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/store/rdbms" + "github.com/go-sql-driver/mysql" + "go.uber.org/zap" + "strings" +) + +type ( + Store struct { + *rdbms.Store + } +) + +func New(ctx context.Context, dsn string) (s *Store, err error) { + var cfg *rdbms.Config + + if cfg, err = ProcDataSourceName(dsn); err != nil { + return nil, err + } + + cfg.PlaceholderFormat = squirrel.Question + cfg.TxRetryErrHandler = txRetryErrHandler + + s = new(Store) + if s.Store, err = rdbms.New(ctx, cfg); err != nil { + return nil, err + } + + return s, nil +} + +func (s *Store) Upgrade(ctx context.Context, log *zap.Logger) (err error) { + return (&rdbms.Schema{}).Upgrade(ctx, NewUpgrader(log, s)) +} + +//func (s *Store) Crea + +// ProcDataSourceName validates given DSN and ensures +// params are present and correct +// +// If param is missing it sets it to default but returns +// error in case of incorrect param value +// +// See https://github.com/go-sql-driver/mysql for available dsn params +// +// @todo similar fallback (autoconfig) for collation=utf8mb4_general_ci +// but allow different collation values +// +func ProcDataSourceName(in string) (*rdbms.Config, error) { + const ( + schemeDel = "://" + validScheme = "mysql" + ) + + var ( + endOfSchema = strings.Index(in, schemeDel) + c = &rdbms.Config{} + ) + + if endOfSchema > 0 && (in[:endOfSchema] == validScheme || strings.HasPrefix(in[:endOfSchema], validScheme+"+")) { + c.DriverName = in[:endOfSchema] + c.DataSourceName = in[endOfSchema+len(schemeDel):] + } else { + return nil, fmt.Errorf("expecting valid schema (mysql://) at the beginning of the DSN (%s)", in) + } + + if pdsn, err := mysql.ParseDSN(c.DataSourceName); err != nil { + return nil, err + } else { + // Ensure driver parses time + pdsn.ParseTime = true + + c.DataSourceName = pdsn.FormatDSN() + c.DBName = pdsn.DBName + } + + return c, nil +} + +func txRetryErrHandler(try int, err error) bool { + for errors.Unwrap(err) != nil { + err = errors.Unwrap(err) + } + + var mysqlErr, ok = err.(*mysql.MySQLError) + if !ok || mysqlErr == nil { + return false + } + + switch mysqlErr.Number { + case + 1205, // lock within transaction + 1206, // total number of locks exceeded the lock table size + 1208, // not allowed while thread is holding global read lock + 1213: // deadlock found + return true + + } + + return false +} diff --git a/store/mysql/mysql_test.go b/store/mysql/mysql_test.go new file mode 100644 index 000000000..b6b1bc001 --- /dev/null +++ b/store/mysql/mysql_test.go @@ -0,0 +1,26 @@ +package mysql + +import ( + "github.com/cortezaproject/corteza-server/store/rdbms" + "github.com/stretchr/testify/require" + "testing" +) + +func TestProcDataSourceName(t *testing.T) { + var ( + req = require.New(t) + c *rdbms.Config + err error + ) + + c, err = ProcDataSourceName("mysql://uid:@/dbname?parseTime=true") + req.NoError(err) + req.Contains(c.DataSourceName, "parseTime=true") + req.Equal(c.DBName, "dbname") + + c, err = ProcDataSourceName("mysql+foo://uid:@/dbname") + req.NoError(err) + req.Contains(c.DataSourceName, "parseTime=true") + req.Equal(c.DriverName, "mysql+foo") + req.Equal(c.DBName, "dbname") +} diff --git a/store/mysql/upgrade.go b/store/mysql/upgrade.go new file mode 100644 index 000000000..b1ce51902 --- /dev/null +++ b/store/mysql/upgrade.go @@ -0,0 +1,177 @@ +package mysql + +// MySQL specific prefixes, sql +// templates, functions and other helpers + +import ( + "context" + "database/sql" + "fmt" + "github.com/cortezaproject/corteza-server/store/rdbms" + "github.com/cortezaproject/corteza-server/store/rdbms/ddl" + _ "github.com/go-sql-driver/mysql" + "go.uber.org/zap" +) + +type ( + upgrader struct { + s *Store + log *zap.Logger + ddl *ddl.Generator + } +) + +// NewUpgrader returns MySQL schema upgrader +func NewUpgrader(log *zap.Logger, store *Store) *upgrader { + var u = &upgrader{store, log, ddl.NewGenerator(log)} + + // All modifications we need for the DDL generator + // to properly support MySQL dialect: + + u.ddl.AddTemplate("create-table-suffix", "ENGINE=InnoDB DEFAULT CHARSET=utf8") + + // Sadly, MySQL does not support partial indexes + u.ddl.AddTemplate("index-condition", " -- no support for partial indexes") + + // Cover mysql exceptions + u.ddl.AddTemplateFunc("columnType", func(ct *ddl.ColumnType) string { + switch ct.Type { + case ddl.ColumnTypeIdentifier: + return "BIGINT UNSIGNED" + case ddl.ColumnTypeText: + if y, has := ct.Flags["mysqlLongText"].(bool); has && y { + return "LONGTEXT" + } + + return "TEXT" + case ddl.ColumnTypeTimestamp: + return "DATETIME" + case ddl.ColumnTypeBoolean: + return "TINYINT(1)" + default: + return ddl.GenColumnType(ct) + } + }) + + return u +} + +// Before runs before all tables are upgraded +func (u upgrader) Before(ctx context.Context) error { + err := func() error { + const migrations = "migrations" + if exists, err := u.TableExists(ctx, migrations); err != nil || !exists { + return err + } + + if _, err := u.s.DB().ExecContext(ctx, fmt.Sprintf("DROP TABLE %s", migrations)); err != nil { + return err + } + + u.log.Debug(fmt.Sprintf("%s table removed", migrations)) + + return nil + }() + + if err != nil { + return err + } + + return rdbms.GenericUpgrades(u.log, u).Before(ctx) +} + +// After runs after all tables are upgraded +func (u upgrader) After(ctx context.Context) error { + return rdbms.GenericUpgrades(u.log, u).After(ctx) +} + +// CreateTable is triggered for every table defined in the rdbms package +// +// It checks if table is missing and creates it, otherwise +// it runs +func (u upgrader) CreateTable(ctx context.Context, t *ddl.Table) (err error) { + var exists bool + if exists, err = u.TableExists(ctx, t.Name); err != nil { + return + } + + if !exists { + if err = u.Exec(ctx, u.ddl.CreateTable(t)); err != nil { + return err + } + + for _, i := range t.Indexes { + if err = u.Exec(ctx, u.ddl.CreateIndex(i)); err != nil { + return fmt.Errorf("could not create index %s on table %s: %w", i.Name, i.Table, err) + } + } + } + + if err = u.upgradeTable(ctx, t); err != nil { + return + } + + return nil +} + +func (u upgrader) Exec(ctx context.Context, sql string, aa ...interface{}) error { + _, err := u.s.DB().ExecContext(ctx, sql, aa...) + return err +} + +// upgradeTable applies any necessary changes connected to that specific table +func (u upgrader) upgradeTable(ctx context.Context, t *ddl.Table) error { + g := rdbms.GenericUpgrades(u.log, u) + + switch t.Name { + default: + return g.Upgrade(ctx, t) + } +} + +func (u upgrader) TableExists(ctx context.Context, table string) (bool, error) { + var tmp interface{} + if err := u.s.DB().GetContext(ctx, &tmp, fmt.Sprintf("SHOW TABLES LIKE %q", table)); err == sql.ErrNoRows { + return false, nil + } else if err != nil { + return false, fmt.Errorf("could not check if table exists: %w", err) + } + + return true, nil +} + +func (u upgrader) AddColumn(ctx context.Context, table string, col *ddl.Column) (added bool, err error) { + var ( + lookup = `SELECT IS_NULLABLE = 'YES' AS IS_NULLABLE, + DATA_TYPE + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA = ? + AND TABLE_NAME = ? + AND COLUMN_NAME = ?` + + tmp struct { + IsNullable bool `db:"IS_NULLABLE"` + DataType string `db:"DATA_TYPE"` + } + ) + + if err = u.s.DB().GetContext(ctx, &tmp, lookup, u.s.Config().DBName, table, col.Name); err == sql.ErrNoRows { + if err = u.Exec(ctx, u.ddl.AddColumn(table, col)); err != nil { + return false, fmt.Errorf("could not add column %s to table %s: %w", table, col.Name, err) + } + + return true, nil + } else if err != nil { + return false, fmt.Errorf("could not check if column exists: %w", err) + } + + return false, nil +} + +func (u upgrader) AddPrimaryKey(ctx context.Context, table string, ind *ddl.Index) (added bool, err error) { + if err = u.Exec(ctx, u.ddl.AddPrimaryKey(table, ind)); err != nil { + return false, fmt.Errorf("could not add primary key to table %s: %w", table, err) + } + + return true, nil +} diff --git a/store/payload.go b/store/payload.go new file mode 100644 index 000000000..190c9cfd3 --- /dev/null +++ b/store/payload.go @@ -0,0 +1,53 @@ +package store + +import "github.com/cortezaproject/corteza-server/pkg/slice" + +type ( + // Payload servers as a generic interface between incoming structs scheduled + // for update or insertion and the db layer + Payload map[string]interface{} +) + +// Only returns new payload with subset fields (if empty slice is send, it returns entire payload) +func (p Payload) Only(ff ...string) Payload { + if len(ff) == 0 { + return p + } + + o := Payload{} + for _, k := range ff { + if v, has := p[k]; has { + o[k] = v + } + } // + + return o +} + +// Skip returns new payload with subset fields (if empty slice is send, it returns entire payload) +func (p Payload) Skip(ff ...string) Payload { + if len(ff) == 0 { + return p + } + + m := slice.ToStringBoolMap(ff) + + o := Payload{} + for k, v := range p { + if !m[k] { + o[k] = v + } + } + + return o +} + +// Alias adds alias (.) to all keys +func (p Payload) Alias(alias string) Payload { + o := Payload{} + for k, v := range p { + o[alias+"."+k] = v + } + + return o +} diff --git a/store/payload_test.go b/store/payload_test.go new file mode 100644 index 000000000..b4cf70f68 --- /dev/null +++ b/store/payload_test.go @@ -0,0 +1,22 @@ +package store + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestPayload_Only(t *testing.T) { + a := assert.New(t) + + p := Payload{"foo": 1, "bar": 1}.Only("foo") + a.Contains(p, "foo") + a.NotContains(p, "bar") +} + +func TestPayload_Skip(t *testing.T) { + a := assert.New(t) + + p := Payload{"foo": 1, "bar": 1}.Skip("bar") + a.Contains(p, "foo") + a.NotContains(p, "bar") +} diff --git a/store/pgsql/pgsql.go b/store/pgsql/pgsql.go new file mode 100644 index 000000000..dbec8969a --- /dev/null +++ b/store/pgsql/pgsql.go @@ -0,0 +1,70 @@ +package pgsql + +import ( + "context" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/store/rdbms" + _ "github.com/lib/pq" + "go.uber.org/zap" + "net/url" + "strings" +) + +type ( + Store struct { + *rdbms.Store + } +) + +func New(ctx context.Context, dsn string) (s *Store, err error) { + var cfg *rdbms.Config + + if cfg, err = ProcDataSourceName(dsn); err != nil { + return nil, err + } + + cfg.PlaceholderFormat = squirrel.Dollar + + s = new(Store) + if s.Store, err = rdbms.New(ctx, cfg); err != nil { + return nil, err + } + + return s, nil +} + +func (s *Store) Upgrade(ctx context.Context, log *zap.Logger) (err error) { + if err = (&rdbms.Schema{}).Upgrade(ctx, NewUpgrader(log, s)); err != nil { + return fmt.Errorf("can not upgrade postgresql schema: %w", err) + } + + return nil +} + +// ProcDataSourceName validates given DSN and ensures +// params are present and correct +func ProcDataSourceName(dsn string) (c *rdbms.Config, err error) { + const ( + validScheme = "postgres" + ) + var ( + scheme string + u *url.URL + ) + + if u, err = url.Parse(dsn); err != nil { + return nil, err + } + + if strings.HasPrefix(dsn, "postgres") { + scheme = u.Scheme + u.Scheme = validScheme + } + + return &rdbms.Config{ + DriverName: scheme, + DataSourceName: u.String(), + DBName: strings.Trim(u.Path, "/"), + }, nil +} diff --git a/store/pgsql/upgrade.go b/store/pgsql/upgrade.go new file mode 100644 index 000000000..b4cb3e299 --- /dev/null +++ b/store/pgsql/upgrade.go @@ -0,0 +1,131 @@ +package pgsql + +// PostgreSQL specific prefixes, sql +// templates, functions and other helpers + +import ( + "context" + "database/sql" + "fmt" + "github.com/cortezaproject/corteza-server/store/rdbms" + "github.com/cortezaproject/corteza-server/store/rdbms/ddl" + "go.uber.org/zap" +) + +type ( + upgrader struct { + s *Store + log *zap.Logger + ddl *ddl.Generator + } +) + +// NewUpgrader returns PostgreSQL schema upgrader +func NewUpgrader(log *zap.Logger, store *Store) *upgrader { + var g = &upgrader{store, log, ddl.NewGenerator(log)} + + // All modifications we need for the DDL generator + // to properly support PostgreSQL dialect + + g.ddl.AddTemplate("create-table-suffix", "WITHOUT OIDS") + + return g +} + +// Before runs before all tables are upgraded +func (u upgrader) Before(ctx context.Context) error { + return rdbms.GenericUpgrades(u.log, u).Before(ctx) +} + +// After runs after all tables are upgraded +func (u upgrader) After(ctx context.Context) error { + return rdbms.GenericUpgrades(u.log, u).After(ctx) +} + +// CreateTable is triggered for every table defined in the rdbms package +// +// It checks if table is missing and creates it, otherwise +// it runs +func (u upgrader) CreateTable(ctx context.Context, t *ddl.Table) (err error) { + var exists bool + if exists, err = u.TableExists(ctx, t.Name); err != nil { + return + } + + if !exists { + if err = u.Exec(ctx, u.ddl.CreateTable(t)); err != nil { + return err + } + + for _, i := range t.Indexes { + if err = u.Exec(ctx, u.ddl.CreateIndex(i)); err != nil { + return fmt.Errorf("could not create index %s on table %s: %w", i.Name, i.Table, err) + } + } + } else { + return u.upgradeTable(ctx, t) + } + + return nil +} + +func (u upgrader) Exec(ctx context.Context, sql string, aa ...interface{}) error { + _, err := u.s.DB().ExecContext(ctx, sql, aa...) + return err +} + +// upgradeTable applies any necessary changes connected to that specific table +func (u upgrader) upgradeTable(ctx context.Context, t *ddl.Table) error { + g := rdbms.GenericUpgrades(u.log, u) + + switch t.Name { + default: + return g.Upgrade(ctx, t) + } +} + +func (u upgrader) TableExists(ctx context.Context, table string) (bool, error) { + var exists bool + + if err := u.s.DB().GetContext(ctx, &exists, "SELECT TO_REGCLASS($1) IS NOT NULL", "public."+table); err != nil { + return false, fmt.Errorf("could not check if table exists: %w", err) + } + + return exists, nil +} + +func (u upgrader) AddColumn(ctx context.Context, table string, col *ddl.Column) (added bool, err error) { + var ( + lookup = `SELECT is_nullable = 'YES' AS is_nullable, + data_type + FROM information_schema.columns + WHERE table_catalog = $1 + AND table_name = $2 + AND column_name = $3` + + tmp struct { + IsNullable bool `db:"is_nullable"` + DataType string `db:"data_type"` + } + ) + + if err = u.s.DB().GetContext(ctx, &tmp, lookup, u.s.Config().DBName, table, col.Name); err == sql.ErrNoRows { + if err = u.Exec(ctx, u.ddl.AddColumn(table, col)); err != nil { + return false, fmt.Errorf("could not add column %s to table %s: %w", table, col.Name, err) + } + + return true, nil + } else if err != nil { + return false, fmt.Errorf("could not check if column exists: %w", err) + } + + return false, nil +} + +func (u upgrader) AddPrimaryKey(ctx context.Context, table string, ind *ddl.Index) (added bool, err error) { + if err = u.Exec(ctx, u.ddl.AddPrimaryKey(table, ind)); err != nil { + return false, fmt.Errorf("could not add primary key to table %s: %w", table, err) + } + + return true, nil +} diff --git a/store/rbac_rules.yaml b/store/rbac_rules.yaml new file mode 100644 index 000000000..f1d31ad62 --- /dev/null +++ b/store/rbac_rules.yaml @@ -0,0 +1,26 @@ +import: + - github.com/cortezaproject/corteza-server/pkg/permissions + +interface: + - system/service + - compose/service + - messaging/service + - tests/compose + - tests/messaging + - tests/system + +types: + type: permissions.Rule + +fields: + - { field: RoleID, isPrimaryKey: true } + - { field: Resource, isPrimaryKey: true } + - { field: Operation, isPrimaryKey: true } + - { field: Access } + +rdbms: + alias: rls + table: rbac_rules + +search: + disablePaging: true diff --git a/store/rdbms/actionlog.gen.go b/store/rdbms/actionlog.gen.go new file mode 100644 index 000000000..01de0b986 --- /dev/null +++ b/store/rdbms/actionlog.gen.go @@ -0,0 +1,215 @@ +package rdbms + +// This file is an auto-generated file +// +// Template: pkg/codegen/assets/store_rdbms.gen.go.tpl +// Definitions: store/actionlog.yaml +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/pkg/actionlog" + "github.com/cortezaproject/corteza-server/store" + "github.com/jmoiron/sqlx" +) + +// SearchActionlogs returns all matching rows +// +// This function calls convertActionlogFilter with the given +// actionlog.Filter and expects to receive a working squirrel.SelectBuilder +func (s Store) SearchActionlogs(ctx context.Context, f actionlog.Filter) (actionlog.ActionSet, actionlog.Filter, error) { + q, err := s.convertActionlogFilter(f) + if err != nil { + return nil, f, err + } + + scap := DefaultSliceCapacity + + var ( + set = make([]*actionlog.Action, 0, scap) + res *actionlog.Action + ) + + return set, f, func() error { + rows, err := s.Query(ctx, q) + if err != nil { + return err + } + + for rows.Next() { + if res, err = s.internalActionlogRowScanner(rows, rows.Err()); err != nil { + if cerr := rows.Close(); cerr != nil { + return fmt.Errorf("could not close rows (%v) after scan error: %w", cerr, err) + } + + return err + } + + set = append(set, res) + } + + return rows.Close() + }() +} + +// CreateActionlog creates one or more rows in actionlog table +func (s Store) CreateActionlog(ctx context.Context, rr ...*actionlog.Action) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ActionlogTable()).SetMap(s.internalActionlogEncoder(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// UpdateActionlog updates one or more existing rows in actionlog +func (s Store) UpdateActionlog(ctx context.Context, rr ...*actionlog.Action) error { + return s.PartialUpdateActionlog(ctx, nil, rr...) +} + +// PartialUpdateActionlog updates one or more existing rows in actionlog +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +func (s Store) PartialUpdateActionlog(ctx context.Context, onlyColumns []string, rr ...*actionlog.Action) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateActionlogs( + ctx, + squirrel.Eq{s.preprocessColumn("alg.id", ""): s.preprocessValue(res.ID, "")}, + s.internalActionlogEncoder(res).Skip("id").Only(onlyColumns...)) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveActionlog removes one or more rows from actionlog table +func (s Store) RemoveActionlog(ctx context.Context, rr ...*actionlog.Action) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ActionlogTable("alg")).Where(squirrel.Eq{s.preprocessColumn("alg.id", ""): s.preprocessValue(res.ID, "")})) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveActionlogByID removes row from the actionlog table +func (s Store) RemoveActionlogByID(ctx context.Context, ID uint64) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ActionlogTable("alg")).Where(squirrel.Eq{s.preprocessColumn("alg.id", ""): s.preprocessValue(ID, "")})) +} + +// TruncateActionlogs removes all rows from the actionlog table +func (s Store) TruncateActionlogs(ctx context.Context) error { + return Truncate(ctx, s.DB(), s.ActionlogTable()) +} + +// ExecUpdateActionlogs updates all matched (by cnd) rows in actionlog with given data +func (s Store) ExecUpdateActionlogs(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ActionlogTable("alg")).Where(cnd).SetMap(set)) +} + +// ActionlogLookup prepares Actionlog query and executes it, +// returning actionlog.Action (or error) +func (s Store) ActionlogLookup(ctx context.Context, cnd squirrel.Sqlizer) (*actionlog.Action, error) { + return s.internalActionlogRowScanner(s.QueryRow(ctx, s.QueryActionlogs().Where(cnd))) +} + +func (s Store) internalActionlogRowScanner(row rowScanner, err error) (*actionlog.Action, error) { + if err != nil { + return nil, err + } + + var res = &actionlog.Action{} + if _, has := s.config.RowScanners["actionlog"]; has { + scanner := s.config.RowScanners["actionlog"].(func(rowScanner, *actionlog.Action) error) + err = scanner(row, res) + } else { + err = s.scanActionlogRow(row, res) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for Actionlog: %w", err) + } else { + return res, nil + } +} + +// QueryActionlogs returns squirrel.SelectBuilder with set table and all columns +func (s Store) QueryActionlogs() squirrel.SelectBuilder { + return s.Select(s.ActionlogTable("alg"), s.ActionlogColumns("alg")...) +} + +// ActionlogTable name of the db table +func (Store) ActionlogTable(aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "actionlog" + alias +} + +// ActionlogColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) ActionlogColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "id", + alias + "ts", + alias + "request_origin", + alias + "request_id", + alias + "actor_ip_addr", + alias + "actor_id", + alias + "resource", + alias + "action", + alias + "error", + alias + "severity", + alias + "description", + alias + "meta", + } +} + +// internalActionlogEncoder encodes fields from actionlog.Action to store.Payload (map) +// +// Encoding is done by using generic approach or by calling encodeActionlog +// func when rdbms.customEncoder=true +func (s Store) internalActionlogEncoder(res *actionlog.Action) store.Payload { + return s.encodeActionlog(res) +} diff --git a/store/rdbms/actionlog.go b/store/rdbms/actionlog.go new file mode 100644 index 000000000..dafbaad52 --- /dev/null +++ b/store/rdbms/actionlog.go @@ -0,0 +1,75 @@ +package rdbms + +import ( + "encoding/json" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/pkg/actionlog" + "github.com/cortezaproject/corteza-server/store" +) + +func (s Store) convertActionlogFilter(f actionlog.Filter) (query squirrel.SelectBuilder, err error) { + query = s.QueryActionlogs() + + if f.From != nil { + query = query.Where(squirrel.GtOrEq{"ts": f.From}) + } + + if f.To != nil { + query = query.Where(squirrel.LtOrEq{"ts": f.To}) + } + + if len(f.ActorID) > 0 { + query = query.Where(squirrel.Eq{"actor_id": f.ActorID}) + } + + if f.Resource != "" { + query = query.Where(squirrel.Eq{"resource": f.Resource}) + } + + if f.Action != "" { + query = query.Where(squirrel.Eq{"action": f.Action}) + } + + return +} + +func (s Store) scanActionlogRow(row rowScanner, res *actionlog.Action) error { + return row.Scan( + &res.ID, + &res.Timestamp, + &res.RequestOrigin, + &res.RequestID, + &res.ActorIPAddr, + &res.ActorID, + &res.Resource, + &res.Action, + &res.Error, + &res.Severity, + &res.Description, + &res.Meta, + ) +} + +func (s Store) encodeActionlog(res *actionlog.Action) store.Payload { + // ActionlogEnc encodes fields from actionlog.Action to store.Payload (map) + out := store.Payload{ + "id": res.ID, + "ts": res.Timestamp, + "request_origin": res.RequestOrigin, + "request_id": res.RequestID, + "actor_ip_addr": res.ActorIPAddr, + "actor_id": res.ActorID, + "resource": res.Resource, + "action": res.Action, + "error": res.Error, + "severity": res.Severity, + "description": res.Description, + "meta": []byte{}, + } + + if res.Meta != nil { + out["meta"], _ = json.Marshal(res.Meta) + } + + return out +} diff --git a/store/rdbms/applications.gen.go b/store/rdbms/applications.gen.go new file mode 100644 index 000000000..18aa5a35b --- /dev/null +++ b/store/rdbms/applications.gen.go @@ -0,0 +1,246 @@ +package rdbms + +// This file is an auto-generated file +// +// Template: pkg/codegen/assets/store_rdbms.gen.go.tpl +// Definitions: store/applications.yaml +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/store" + "github.com/cortezaproject/corteza-server/system/types" + "github.com/jmoiron/sqlx" +) + +// SearchApplications returns all matching rows +// +// This function calls convertApplicationFilter with the given +// types.ApplicationFilter and expects to receive a working squirrel.SelectBuilder +func (s Store) SearchApplications(ctx context.Context, f types.ApplicationFilter) (types.ApplicationSet, types.ApplicationFilter, error) { + q, err := s.convertApplicationFilter(f) + if err != nil { + return nil, f, err + } + + q = ApplyPaging(q, f.PageFilter) + + scap := f.PerPage + if scap == 0 { + scap = DefaultSliceCapacity + } + + var ( + set = make([]*types.Application, 0, scap) + res *types.Application + ) + + return set, f, func() error { + if f.Count, err = Count(ctx, s.db, q); err != nil || f.Count == 0 { + return err + } + rows, err := s.Query(ctx, q) + if err != nil { + return err + } + + for rows.Next() { + if res, err = s.internalApplicationRowScanner(rows, rows.Err()); err != nil { + if cerr := rows.Close(); cerr != nil { + return fmt.Errorf("could not close rows (%v) after scan error: %w", cerr, err) + } + + return err + } + + set = append(set, res) + } + + return rows.Close() + }() +} + +// LookupApplicationByID searches for application by ID +// +// It returns application even if deleted +func (s Store) LookupApplicationByID(ctx context.Context, id uint64) (*types.Application, error) { + return s.ApplicationLookup(ctx, squirrel.Eq{ + "app.id": id, + }) +} + +// CreateApplication creates one or more rows in sys_application table +func (s Store) CreateApplication(ctx context.Context, rr ...*types.Application) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ApplicationTable()).SetMap(s.internalApplicationEncoder(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// UpdateApplication updates one or more existing rows in sys_application +func (s Store) UpdateApplication(ctx context.Context, rr ...*types.Application) error { + return s.PartialUpdateApplication(ctx, nil, rr...) +} + +// PartialUpdateApplication updates one or more existing rows in sys_application +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +func (s Store) PartialUpdateApplication(ctx context.Context, onlyColumns []string, rr ...*types.Application) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateApplications( + ctx, + squirrel.Eq{s.preprocessColumn("app.id", ""): s.preprocessValue(res.ID, "")}, + s.internalApplicationEncoder(res).Skip("id").Only(onlyColumns...)) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveApplication removes one or more rows from sys_application table +func (s Store) RemoveApplication(ctx context.Context, rr ...*types.Application) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ApplicationTable("app")).Where(squirrel.Eq{s.preprocessColumn("app.id", ""): s.preprocessValue(res.ID, "")})) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveApplicationByID removes row from the sys_application table +func (s Store) RemoveApplicationByID(ctx context.Context, ID uint64) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ApplicationTable("app")).Where(squirrel.Eq{s.preprocessColumn("app.id", ""): s.preprocessValue(ID, "")})) +} + +// TruncateApplications removes all rows from the sys_application table +func (s Store) TruncateApplications(ctx context.Context) error { + return Truncate(ctx, s.DB(), s.ApplicationTable()) +} + +// ExecUpdateApplications updates all matched (by cnd) rows in sys_application with given data +func (s Store) ExecUpdateApplications(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ApplicationTable("app")).Where(cnd).SetMap(set)) +} + +// ApplicationLookup prepares Application query and executes it, +// returning types.Application (or error) +func (s Store) ApplicationLookup(ctx context.Context, cnd squirrel.Sqlizer) (*types.Application, error) { + return s.internalApplicationRowScanner(s.QueryRow(ctx, s.QueryApplications().Where(cnd))) +} + +func (s Store) internalApplicationRowScanner(row rowScanner, err error) (*types.Application, error) { + if err != nil { + return nil, err + } + + var res = &types.Application{} + if _, has := s.config.RowScanners["application"]; has { + scanner := s.config.RowScanners["application"].(func(rowScanner, *types.Application) error) + err = scanner(row, res) + } else { + err = row.Scan( + &res.ID, + &res.Name, + &res.OwnerID, + &res.Enabled, + &res.Unify, + &res.CreatedAt, + &res.UpdatedAt, + &res.DeletedAt, + ) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for Application: %w", err) + } else { + return res, nil + } +} + +// QueryApplications returns squirrel.SelectBuilder with set table and all columns +func (s Store) QueryApplications() squirrel.SelectBuilder { + return s.Select(s.ApplicationTable("app"), s.ApplicationColumns("app")...) +} + +// ApplicationTable name of the db table +func (Store) ApplicationTable(aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "sys_application" + alias +} + +// ApplicationColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) ApplicationColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "id", + alias + "name", + alias + "rel_owner", + alias + "enabled", + alias + "unify", + alias + "created_at", + alias + "updated_at", + alias + "deleted_at", + } +} + +// internalApplicationEncoder encodes fields from types.Application to store.Payload (map) +// +// Encoding is done by using generic approach or by calling encodeApplication +// func when rdbms.customEncoder=true +func (s Store) internalApplicationEncoder(res *types.Application) store.Payload { + return store.Payload{ + "id": res.ID, + "name": res.Name, + "rel_owner": res.OwnerID, + "enabled": res.Enabled, + "unify": res.Unify, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + } +} diff --git a/store/rdbms/applications.go b/store/rdbms/applications.go new file mode 100644 index 000000000..5c77c1245 --- /dev/null +++ b/store/rdbms/applications.go @@ -0,0 +1,41 @@ +package rdbms + +import ( + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/pkg/rh" + "github.com/cortezaproject/corteza-server/system/types" +) + +func (s Store) convertApplicationFilter(f types.ApplicationFilter) (query squirrel.SelectBuilder, err error) { + if f.Sort == "" { + f.Sort = "id" + } + + query = s.QueryApplications() + + query = rh.FilterNullByState(query, "app.deleted_at", f.Deleted) + + if f.Query != "" { + qs := f.Query + "%" + query = query.Where(squirrel.Or{ + squirrel.Like{"app.name": qs}, + }) + } + + if f.Name != "" { + query = query.Where(squirrel.Eq{"app.name": f.Name}) + } + + if f.IsReadable != nil { + query = query.Where(f.IsReadable) + } + + var orderBy []string + if orderBy, err = rh.ParseOrder(f.Sort, s.ApplicationColumns()...); err != nil { + return + } else { + query = query.OrderBy(orderBy...) + } + + return +} diff --git a/store/rdbms/compose_charts.gen.go b/store/rdbms/compose_charts.gen.go new file mode 100644 index 000000000..3cc89166c --- /dev/null +++ b/store/rdbms/compose_charts.gen.go @@ -0,0 +1,253 @@ +package rdbms + +// This file is an auto-generated file +// +// Template: pkg/codegen/assets/store_rdbms.gen.go.tpl +// Definitions: store/compose_charts.yaml +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/store" + "github.com/jmoiron/sqlx" +) + +// SearchComposeCharts returns all matching rows +// +// This function calls convertComposeChartFilter with the given +// types.ChartFilter and expects to receive a working squirrel.SelectBuilder +func (s Store) SearchComposeCharts(ctx context.Context, f types.ChartFilter) (types.ChartSet, types.ChartFilter, error) { + q, err := s.convertComposeChartFilter(f) + if err != nil { + return nil, f, err + } + + q = ApplyPaging(q, f.PageFilter) + + scap := f.PerPage + if scap == 0 { + scap = DefaultSliceCapacity + } + + var ( + set = make([]*types.Chart, 0, scap) + res *types.Chart + ) + + return set, f, func() error { + if f.Count, err = Count(ctx, s.db, q); err != nil || f.Count == 0 { + return err + } + rows, err := s.Query(ctx, q) + if err != nil { + return err + } + + for rows.Next() { + if res, err = s.internalComposeChartRowScanner(rows, rows.Err()); err != nil { + if cerr := rows.Close(); cerr != nil { + return fmt.Errorf("could not close rows (%v) after scan error: %w", cerr, err) + } + + return err + } + + set = append(set, res) + } + + return rows.Close() + }() +} + +// LookupComposeChartByID searches for compose chart by ID +// +// It returns compose chart even if deleted +func (s Store) LookupComposeChartByID(ctx context.Context, id uint64) (*types.Chart, error) { + return s.ComposeChartLookup(ctx, squirrel.Eq{ + "cch.id": id, + }) +} + +// LookupComposeChartByHandle searches for compose chart by handle (case-insensitive) +func (s Store) LookupComposeChartByHandle(ctx context.Context, handle string) (*types.Chart, error) { + return s.ComposeChartLookup(ctx, squirrel.Eq{ + "cch.handle": handle, + }) +} + +// CreateComposeChart creates one or more rows in compose_chart table +func (s Store) CreateComposeChart(ctx context.Context, rr ...*types.Chart) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ComposeChartTable()).SetMap(s.internalComposeChartEncoder(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// UpdateComposeChart updates one or more existing rows in compose_chart +func (s Store) UpdateComposeChart(ctx context.Context, rr ...*types.Chart) error { + return s.PartialUpdateComposeChart(ctx, nil, rr...) +} + +// PartialUpdateComposeChart updates one or more existing rows in compose_chart +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +func (s Store) PartialUpdateComposeChart(ctx context.Context, onlyColumns []string, rr ...*types.Chart) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateComposeCharts( + ctx, + squirrel.Eq{s.preprocessColumn("cch.id", ""): s.preprocessValue(res.ID, "")}, + s.internalComposeChartEncoder(res).Skip("id").Only(onlyColumns...)) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveComposeChart removes one or more rows from compose_chart table +func (s Store) RemoveComposeChart(ctx context.Context, rr ...*types.Chart) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeChartTable("cch")).Where(squirrel.Eq{s.preprocessColumn("cch.id", ""): s.preprocessValue(res.ID, "")})) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveComposeChartByID removes row from the compose_chart table +func (s Store) RemoveComposeChartByID(ctx context.Context, ID uint64) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeChartTable("cch")).Where(squirrel.Eq{s.preprocessColumn("cch.id", ""): s.preprocessValue(ID, "")})) +} + +// TruncateComposeCharts removes all rows from the compose_chart table +func (s Store) TruncateComposeCharts(ctx context.Context) error { + return Truncate(ctx, s.DB(), s.ComposeChartTable()) +} + +// ExecUpdateComposeCharts updates all matched (by cnd) rows in compose_chart with given data +func (s Store) ExecUpdateComposeCharts(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposeChartTable("cch")).Where(cnd).SetMap(set)) +} + +// ComposeChartLookup prepares ComposeChart query and executes it, +// returning types.Chart (or error) +func (s Store) ComposeChartLookup(ctx context.Context, cnd squirrel.Sqlizer) (*types.Chart, error) { + return s.internalComposeChartRowScanner(s.QueryRow(ctx, s.QueryComposeCharts().Where(cnd))) +} + +func (s Store) internalComposeChartRowScanner(row rowScanner, err error) (*types.Chart, error) { + if err != nil { + return nil, err + } + + var res = &types.Chart{} + if _, has := s.config.RowScanners["composeChart"]; has { + scanner := s.config.RowScanners["composeChart"].(func(rowScanner, *types.Chart) error) + err = scanner(row, res) + } else { + err = row.Scan( + &res.ID, + &res.Handle, + &res.Name, + &res.Config, + &res.NamespaceID, + &res.CreatedAt, + &res.UpdatedAt, + &res.DeletedAt, + ) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for ComposeChart: %w", err) + } else { + return res, nil + } +} + +// QueryComposeCharts returns squirrel.SelectBuilder with set table and all columns +func (s Store) QueryComposeCharts() squirrel.SelectBuilder { + return s.Select(s.ComposeChartTable("cch"), s.ComposeChartColumns("cch")...) +} + +// ComposeChartTable name of the db table +func (Store) ComposeChartTable(aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "compose_chart" + alias +} + +// ComposeChartColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) ComposeChartColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "id", + alias + "handle", + alias + "name", + alias + "config", + alias + "rel_namespace", + alias + "created_at", + alias + "updated_at", + alias + "deleted_at", + } +} + +// internalComposeChartEncoder encodes fields from types.Chart to store.Payload (map) +// +// Encoding is done by using generic approach or by calling encodeComposeChart +// func when rdbms.customEncoder=true +func (s Store) internalComposeChartEncoder(res *types.Chart) store.Payload { + return store.Payload{ + "id": res.ID, + "handle": res.Handle, + "name": res.Name, + "config": res.Config, + "rel_namespace": res.NamespaceID, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + } +} diff --git a/store/rdbms/compose_charts.go b/store/rdbms/compose_charts.go new file mode 100644 index 000000000..85f678438 --- /dev/null +++ b/store/rdbms/compose_charts.go @@ -0,0 +1,47 @@ +package rdbms + +import ( + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/pkg/rh" + "strings" +) + +func (s Store) convertComposeChartFilter(f types.ChartFilter) (query squirrel.SelectBuilder, err error) { + if f.Sort == "" { + f.Sort = "id ASC" + } + + query = s.QueryComposeCharts() + + query = rh.FilterNullByState(query, "cch.deleted_at", f.Deleted) + + if f.NamespaceID > 0 { + query = query.Where("cch.rel_namespace = ?", f.NamespaceID) + } + + if f.Query != "" { + q := "%" + strings.ToLower(f.Query) + "%" + query = query.Where(squirrel.Or{ + squirrel.Like{"LOWER(cch.handle)": q}, + squirrel.Like{"LOWER(cch.name)": q}, + }) + } + + if f.Handle != "" { + query = query.Where(squirrel.Eq{"LOWER(cch.handle)": strings.ToLower(f.Handle)}) + } + + if f.IsReadable != nil { + query = query.Where(f.IsReadable) + } + + var orderBy []string + if orderBy, err = rh.ParseOrder(f.Sort, s.ComposeChartColumns()...); err != nil { + return + } else { + query = query.OrderBy(orderBy...) + } + + return +} diff --git a/store/rdbms/compose_module_fields.gen.go b/store/rdbms/compose_module_fields.gen.go new file mode 100644 index 000000000..78714587f --- /dev/null +++ b/store/rdbms/compose_module_fields.gen.go @@ -0,0 +1,211 @@ +package rdbms + +// This file is an auto-generated file +// +// Template: pkg/codegen/assets/store_rdbms.gen.go.tpl +// Definitions: store/compose_module_fields.yaml +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/store" + "github.com/jmoiron/sqlx" +) + +// CreateComposeModuleField creates one or more rows in compose_module_field table +func (s Store) CreateComposeModuleField(ctx context.Context, rr ...*types.ModuleField) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ComposeModuleFieldTable()).SetMap(s.internalComposeModuleFieldEncoder(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// UpdateComposeModuleField updates one or more existing rows in compose_module_field +func (s Store) UpdateComposeModuleField(ctx context.Context, rr ...*types.ModuleField) error { + return s.PartialUpdateComposeModuleField(ctx, nil, rr...) +} + +// PartialUpdateComposeModuleField updates one or more existing rows in compose_module_field +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +func (s Store) PartialUpdateComposeModuleField(ctx context.Context, onlyColumns []string, rr ...*types.ModuleField) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateComposeModuleFields( + ctx, + squirrel.Eq{s.preprocessColumn("cmf.id", ""): s.preprocessValue(res.ID, "")}, + s.internalComposeModuleFieldEncoder(res).Skip("id").Only(onlyColumns...)) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveComposeModuleField removes one or more rows from compose_module_field table +func (s Store) RemoveComposeModuleField(ctx context.Context, rr ...*types.ModuleField) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeModuleFieldTable("cmf")).Where(squirrel.Eq{s.preprocessColumn("cmf.id", ""): s.preprocessValue(res.ID, "")})) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveComposeModuleFieldByID removes row from the compose_module_field table +func (s Store) RemoveComposeModuleFieldByID(ctx context.Context, ID uint64) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeModuleFieldTable("cmf")).Where(squirrel.Eq{s.preprocessColumn("cmf.id", ""): s.preprocessValue(ID, "")})) +} + +// TruncateComposeModuleFields removes all rows from the compose_module_field table +func (s Store) TruncateComposeModuleFields(ctx context.Context) error { + return Truncate(ctx, s.DB(), s.ComposeModuleFieldTable()) +} + +// ExecUpdateComposeModuleFields updates all matched (by cnd) rows in compose_module_field with given data +func (s Store) ExecUpdateComposeModuleFields(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposeModuleFieldTable("cmf")).Where(cnd).SetMap(set)) +} + +// ComposeModuleFieldLookup prepares ComposeModuleField query and executes it, +// returning types.ModuleField (or error) +func (s Store) ComposeModuleFieldLookup(ctx context.Context, cnd squirrel.Sqlizer) (*types.ModuleField, error) { + return s.internalComposeModuleFieldRowScanner(s.QueryRow(ctx, s.QueryComposeModuleFields().Where(cnd))) +} + +func (s Store) internalComposeModuleFieldRowScanner(row rowScanner, err error) (*types.ModuleField, error) { + if err != nil { + return nil, err + } + + var res = &types.ModuleField{} + if _, has := s.config.RowScanners["composeModuleField"]; has { + scanner := s.config.RowScanners["composeModuleField"].(func(rowScanner, *types.ModuleField) error) + err = scanner(row, res) + } else { + err = row.Scan( + &res.ID, + &res.Name, + &res.ModuleID, + &res.Place, + &res.Kind, + &res.Label, + &res.Options, + &res.Private, + &res.Required, + &res.Visible, + &res.Multi, + &res.DefaultValue, + &res.CreatedAt, + &res.UpdatedAt, + &res.DeletedAt, + ) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for ComposeModuleField: %w", err) + } else { + return res, nil + } +} + +// QueryComposeModuleFields returns squirrel.SelectBuilder with set table and all columns +func (s Store) QueryComposeModuleFields() squirrel.SelectBuilder { + return s.Select(s.ComposeModuleFieldTable("cmf"), s.ComposeModuleFieldColumns("cmf")...) +} + +// ComposeModuleFieldTable name of the db table +func (Store) ComposeModuleFieldTable(aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "compose_module_field" + alias +} + +// ComposeModuleFieldColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) ComposeModuleFieldColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "id", + alias + "name", + alias + "rel_module", + alias + "place", + alias + "kind", + alias + "label", + alias + "options", + alias + "is_private", + alias + "is_required", + alias + "is_visible", + alias + "is_multi", + alias + "default_value", + alias + "created_at", + alias + "updated_at", + alias + "deleted_at", + } +} + +// internalComposeModuleFieldEncoder encodes fields from types.ModuleField to store.Payload (map) +// +// Encoding is done by using generic approach or by calling encodeComposeModuleField +// func when rdbms.customEncoder=true +func (s Store) internalComposeModuleFieldEncoder(res *types.ModuleField) store.Payload { + return store.Payload{ + "id": res.ID, + "name": res.Name, + "rel_module": res.ModuleID, + "place": res.Place, + "kind": res.Kind, + "label": res.Label, + "options": res.Options, + "is_private": res.Private, + "is_required": res.Required, + "is_visible": res.Visible, + "is_multi": res.Multi, + "default_value": res.DefaultValue, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + } +} diff --git a/store/rdbms/compose_modules.gen.go b/store/rdbms/compose_modules.gen.go new file mode 100644 index 000000000..6e00a7ea2 --- /dev/null +++ b/store/rdbms/compose_modules.gen.go @@ -0,0 +1,253 @@ +package rdbms + +// This file is an auto-generated file +// +// Template: pkg/codegen/assets/store_rdbms.gen.go.tpl +// Definitions: store/compose_modules.yaml +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/store" + "github.com/jmoiron/sqlx" +) + +// SearchComposeModules returns all matching rows +// +// This function calls convertComposeModuleFilter with the given +// types.ModuleFilter and expects to receive a working squirrel.SelectBuilder +func (s Store) SearchComposeModules(ctx context.Context, f types.ModuleFilter) (types.ModuleSet, types.ModuleFilter, error) { + q, err := s.convertComposeModuleFilter(f) + if err != nil { + return nil, f, err + } + + q = ApplyPaging(q, f.PageFilter) + + scap := f.PerPage + if scap == 0 { + scap = DefaultSliceCapacity + } + + var ( + set = make([]*types.Module, 0, scap) + res *types.Module + ) + + return set, f, func() error { + if f.Count, err = Count(ctx, s.db, q); err != nil || f.Count == 0 { + return err + } + rows, err := s.Query(ctx, q) + if err != nil { + return err + } + + for rows.Next() { + if res, err = s.internalComposeModuleRowScanner(rows, rows.Err()); err != nil { + if cerr := rows.Close(); cerr != nil { + return fmt.Errorf("could not close rows (%v) after scan error: %w", cerr, err) + } + + return err + } + + set = append(set, res) + } + + return rows.Close() + }() +} + +// LookupComposeModuleByHandle searches for compose module by handle (case-insensitive) +func (s Store) LookupComposeModuleByHandle(ctx context.Context, handle string) (*types.Module, error) { + return s.ComposeModuleLookup(ctx, squirrel.Eq{ + "cmd.handle": handle, + }) +} + +// LookupComposeModuleByID searches for compose module by ID +// +// It returns compose module even if deleted +func (s Store) LookupComposeModuleByID(ctx context.Context, id uint64) (*types.Module, error) { + return s.ComposeModuleLookup(ctx, squirrel.Eq{ + "cmd.id": id, + }) +} + +// CreateComposeModule creates one or more rows in compose_module table +func (s Store) CreateComposeModule(ctx context.Context, rr ...*types.Module) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ComposeModuleTable()).SetMap(s.internalComposeModuleEncoder(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// UpdateComposeModule updates one or more existing rows in compose_module +func (s Store) UpdateComposeModule(ctx context.Context, rr ...*types.Module) error { + return s.PartialUpdateComposeModule(ctx, nil, rr...) +} + +// PartialUpdateComposeModule updates one or more existing rows in compose_module +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +func (s Store) PartialUpdateComposeModule(ctx context.Context, onlyColumns []string, rr ...*types.Module) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateComposeModules( + ctx, + squirrel.Eq{s.preprocessColumn("cmd.id", ""): s.preprocessValue(res.ID, "")}, + s.internalComposeModuleEncoder(res).Skip("id").Only(onlyColumns...)) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveComposeModule removes one or more rows from compose_module table +func (s Store) RemoveComposeModule(ctx context.Context, rr ...*types.Module) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeModuleTable("cmd")).Where(squirrel.Eq{s.preprocessColumn("cmd.id", ""): s.preprocessValue(res.ID, "")})) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveComposeModuleByID removes row from the compose_module table +func (s Store) RemoveComposeModuleByID(ctx context.Context, ID uint64) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeModuleTable("cmd")).Where(squirrel.Eq{s.preprocessColumn("cmd.id", ""): s.preprocessValue(ID, "")})) +} + +// TruncateComposeModules removes all rows from the compose_module table +func (s Store) TruncateComposeModules(ctx context.Context) error { + return Truncate(ctx, s.DB(), s.ComposeModuleTable()) +} + +// ExecUpdateComposeModules updates all matched (by cnd) rows in compose_module with given data +func (s Store) ExecUpdateComposeModules(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposeModuleTable("cmd")).Where(cnd).SetMap(set)) +} + +// ComposeModuleLookup prepares ComposeModule query and executes it, +// returning types.Module (or error) +func (s Store) ComposeModuleLookup(ctx context.Context, cnd squirrel.Sqlizer) (*types.Module, error) { + return s.internalComposeModuleRowScanner(s.QueryRow(ctx, s.QueryComposeModules().Where(cnd))) +} + +func (s Store) internalComposeModuleRowScanner(row rowScanner, err error) (*types.Module, error) { + if err != nil { + return nil, err + } + + var res = &types.Module{} + if _, has := s.config.RowScanners["composeModule"]; has { + scanner := s.config.RowScanners["composeModule"].(func(rowScanner, *types.Module) error) + err = scanner(row, res) + } else { + err = row.Scan( + &res.ID, + &res.Handle, + &res.Name, + &res.Meta, + &res.NamespaceID, + &res.CreatedAt, + &res.UpdatedAt, + &res.DeletedAt, + ) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for ComposeModule: %w", err) + } else { + return res, nil + } +} + +// QueryComposeModules returns squirrel.SelectBuilder with set table and all columns +func (s Store) QueryComposeModules() squirrel.SelectBuilder { + return s.Select(s.ComposeModuleTable("cmd"), s.ComposeModuleColumns("cmd")...) +} + +// ComposeModuleTable name of the db table +func (Store) ComposeModuleTable(aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "compose_module" + alias +} + +// ComposeModuleColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) ComposeModuleColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "id", + alias + "handle", + alias + "name", + alias + "meta", + alias + "rel_namespace", + alias + "created_at", + alias + "updated_at", + alias + "deleted_at", + } +} + +// internalComposeModuleEncoder encodes fields from types.Module to store.Payload (map) +// +// Encoding is done by using generic approach or by calling encodeComposeModule +// func when rdbms.customEncoder=true +func (s Store) internalComposeModuleEncoder(res *types.Module) store.Payload { + return store.Payload{ + "id": res.ID, + "handle": res.Handle, + "name": res.Name, + "meta": res.Meta, + "rel_namespace": res.NamespaceID, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + } +} diff --git a/store/rdbms/compose_modules.go b/store/rdbms/compose_modules.go new file mode 100644 index 000000000..c03840bee --- /dev/null +++ b/store/rdbms/compose_modules.go @@ -0,0 +1,51 @@ +package rdbms + +import ( + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/pkg/rh" + "strings" +) + +func (s Store) convertComposeModuleFilter(f types.ModuleFilter) (query squirrel.SelectBuilder, err error) { + if f.Sort == "" { + f.Sort = "id ASC" + } + + query = s.QueryComposeModules() + + query = rh.FilterNullByState(query, "cmd.deleted_at", f.Deleted) + + if f.NamespaceID > 0 { + query = query.Where("cmd.rel_namespace = ?", f.NamespaceID) + } + + if f.Query != "" { + q := "%" + strings.ToLower(f.Query) + "%" + query = query.Where(squirrel.Or{ + squirrel.Like{"LOWER(cmd.name)": q}, + squirrel.Like{"LOWER(cmd.handle)": q}, + }) + } + + if f.Name != "" { + query = query.Where(squirrel.Eq{"LOWER(cmd.name)": strings.ToLower(f.Name)}) + } + + if f.Handle != "" { + query = query.Where(squirrel.Eq{"LOWER(cmd.handle)": strings.ToLower(f.Handle)}) + } + + if f.IsReadable != nil { + query = query.Where(f.IsReadable) + } + + var orderBy []string + if orderBy, err = rh.ParseOrder(f.Sort, s.ComposeModuleColumns()...); err != nil { + return + } else { + query = query.OrderBy(orderBy...) + } + + return +} diff --git a/store/rdbms/compose_namespaces.gen.go b/store/rdbms/compose_namespaces.gen.go new file mode 100644 index 000000000..0f67a9099 --- /dev/null +++ b/store/rdbms/compose_namespaces.gen.go @@ -0,0 +1,253 @@ +package rdbms + +// This file is an auto-generated file +// +// Template: pkg/codegen/assets/store_rdbms.gen.go.tpl +// Definitions: store/compose_namespaces.yaml +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/store" + "github.com/jmoiron/sqlx" +) + +// SearchComposeNamespaces returns all matching rows +// +// This function calls convertComposeNamespaceFilter with the given +// types.NamespaceFilter and expects to receive a working squirrel.SelectBuilder +func (s Store) SearchComposeNamespaces(ctx context.Context, f types.NamespaceFilter) (types.NamespaceSet, types.NamespaceFilter, error) { + q, err := s.convertComposeNamespaceFilter(f) + if err != nil { + return nil, f, err + } + + q = ApplyPaging(q, f.PageFilter) + + scap := f.PerPage + if scap == 0 { + scap = DefaultSliceCapacity + } + + var ( + set = make([]*types.Namespace, 0, scap) + res *types.Namespace + ) + + return set, f, func() error { + if f.Count, err = Count(ctx, s.db, q); err != nil || f.Count == 0 { + return err + } + rows, err := s.Query(ctx, q) + if err != nil { + return err + } + + for rows.Next() { + if res, err = s.internalComposeNamespaceRowScanner(rows, rows.Err()); err != nil { + if cerr := rows.Close(); cerr != nil { + return fmt.Errorf("could not close rows (%v) after scan error: %w", cerr, err) + } + + return err + } + + set = append(set, res) + } + + return rows.Close() + }() +} + +// LookupComposeNamespaceBySlug searches for namespace by slug (case-insensitive) +func (s Store) LookupComposeNamespaceBySlug(ctx context.Context, slug string) (*types.Namespace, error) { + return s.ComposeNamespaceLookup(ctx, squirrel.Eq{ + "cns.slug": slug, + }) +} + +// LookupComposeNamespaceByID searches for compose namespace by ID +// +// It returns compose namespace even if deleted +func (s Store) LookupComposeNamespaceByID(ctx context.Context, id uint64) (*types.Namespace, error) { + return s.ComposeNamespaceLookup(ctx, squirrel.Eq{ + "cns.id": id, + }) +} + +// CreateComposeNamespace creates one or more rows in compose_namespace table +func (s Store) CreateComposeNamespace(ctx context.Context, rr ...*types.Namespace) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ComposeNamespaceTable()).SetMap(s.internalComposeNamespaceEncoder(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// UpdateComposeNamespace updates one or more existing rows in compose_namespace +func (s Store) UpdateComposeNamespace(ctx context.Context, rr ...*types.Namespace) error { + return s.PartialUpdateComposeNamespace(ctx, nil, rr...) +} + +// PartialUpdateComposeNamespace updates one or more existing rows in compose_namespace +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +func (s Store) PartialUpdateComposeNamespace(ctx context.Context, onlyColumns []string, rr ...*types.Namespace) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateComposeNamespaces( + ctx, + squirrel.Eq{s.preprocessColumn("cns.id", ""): s.preprocessValue(res.ID, "")}, + s.internalComposeNamespaceEncoder(res).Skip("id").Only(onlyColumns...)) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveComposeNamespace removes one or more rows from compose_namespace table +func (s Store) RemoveComposeNamespace(ctx context.Context, rr ...*types.Namespace) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeNamespaceTable("cns")).Where(squirrel.Eq{s.preprocessColumn("cns.id", ""): s.preprocessValue(res.ID, "")})) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveComposeNamespaceByID removes row from the compose_namespace table +func (s Store) RemoveComposeNamespaceByID(ctx context.Context, ID uint64) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeNamespaceTable("cns")).Where(squirrel.Eq{s.preprocessColumn("cns.id", ""): s.preprocessValue(ID, "")})) +} + +// TruncateComposeNamespaces removes all rows from the compose_namespace table +func (s Store) TruncateComposeNamespaces(ctx context.Context) error { + return Truncate(ctx, s.DB(), s.ComposeNamespaceTable()) +} + +// ExecUpdateComposeNamespaces updates all matched (by cnd) rows in compose_namespace with given data +func (s Store) ExecUpdateComposeNamespaces(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposeNamespaceTable("cns")).Where(cnd).SetMap(set)) +} + +// ComposeNamespaceLookup prepares ComposeNamespace query and executes it, +// returning types.Namespace (or error) +func (s Store) ComposeNamespaceLookup(ctx context.Context, cnd squirrel.Sqlizer) (*types.Namespace, error) { + return s.internalComposeNamespaceRowScanner(s.QueryRow(ctx, s.QueryComposeNamespaces().Where(cnd))) +} + +func (s Store) internalComposeNamespaceRowScanner(row rowScanner, err error) (*types.Namespace, error) { + if err != nil { + return nil, err + } + + var res = &types.Namespace{} + if _, has := s.config.RowScanners["composeNamespace"]; has { + scanner := s.config.RowScanners["composeNamespace"].(func(rowScanner, *types.Namespace) error) + err = scanner(row, res) + } else { + err = row.Scan( + &res.ID, + &res.Name, + &res.Slug, + &res.Enabled, + &res.Meta, + &res.CreatedAt, + &res.UpdatedAt, + &res.DeletedAt, + ) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for ComposeNamespace: %w", err) + } else { + return res, nil + } +} + +// QueryComposeNamespaces returns squirrel.SelectBuilder with set table and all columns +func (s Store) QueryComposeNamespaces() squirrel.SelectBuilder { + return s.Select(s.ComposeNamespaceTable("cns"), s.ComposeNamespaceColumns("cns")...) +} + +// ComposeNamespaceTable name of the db table +func (Store) ComposeNamespaceTable(aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "compose_namespace" + alias +} + +// ComposeNamespaceColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) ComposeNamespaceColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "id", + alias + "name", + alias + "slug", + alias + "enabled", + alias + "meta", + alias + "created_at", + alias + "updated_at", + alias + "deleted_at", + } +} + +// internalComposeNamespaceEncoder encodes fields from types.Namespace to store.Payload (map) +// +// Encoding is done by using generic approach or by calling encodeComposeNamespace +// func when rdbms.customEncoder=true +func (s Store) internalComposeNamespaceEncoder(res *types.Namespace) store.Payload { + return store.Payload{ + "id": res.ID, + "name": res.Name, + "slug": res.Slug, + "enabled": res.Enabled, + "meta": res.Meta, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + } +} diff --git a/store/rdbms/compose_namespaces.go b/store/rdbms/compose_namespaces.go new file mode 100644 index 000000000..a600dbee6 --- /dev/null +++ b/store/rdbms/compose_namespaces.go @@ -0,0 +1,47 @@ +package rdbms + +import ( + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/pkg/rh" + "strings" +) + +func (s Store) convertComposeNamespaceFilter(f types.NamespaceFilter) (query squirrel.SelectBuilder, err error) { + if f.Sort == "" { + f.Sort = "id ASC" + } + + query = s.QueryComposeNamespaces() + + query = rh.FilterNullByState(query, "cns.deleted_at", f.Deleted) + + if f.Query != "" { + q := "%" + strings.ToLower(f.Query) + "%" + query = query.Where(squirrel.Or{ + squirrel.Like{"LOWER(cns.name)": q}, + squirrel.Like{"LOWER(cns.slug)": q}, + }) + } + + if f.Name != "" { + query = query.Where(squirrel.Eq{"LOWER(cns.name)": strings.ToLower(f.Name)}) + } + + if f.Slug != "" { + query = query.Where(squirrel.Eq{"LOWER(cns.slug)": strings.ToLower(f.Slug)}) + } + + if f.IsReadable != nil { + query = query.Where(f.IsReadable) + } + + var orderBy []string + if orderBy, err = rh.ParseOrder(f.Sort, s.ComposeModuleColumns()...); err != nil { + return + } else { + query = query.OrderBy(orderBy...) + } + + return +} diff --git a/store/rdbms/compose_pages.gen.go b/store/rdbms/compose_pages.gen.go new file mode 100644 index 000000000..49785d744 --- /dev/null +++ b/store/rdbms/compose_pages.gen.go @@ -0,0 +1,268 @@ +package rdbms + +// This file is an auto-generated file +// +// Template: pkg/codegen/assets/store_rdbms.gen.go.tpl +// Definitions: store/compose_pages.yaml +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/store" + "github.com/jmoiron/sqlx" +) + +// SearchComposePages returns all matching rows +// +// This function calls convertComposePageFilter with the given +// types.PageFilter and expects to receive a working squirrel.SelectBuilder +func (s Store) SearchComposePages(ctx context.Context, f types.PageFilter) (types.PageSet, types.PageFilter, error) { + q, err := s.convertComposePageFilter(f) + if err != nil { + return nil, f, err + } + + q = ApplyPaging(q, f.PageFilter) + + scap := f.PerPage + if scap == 0 { + scap = DefaultSliceCapacity + } + + var ( + set = make([]*types.Page, 0, scap) + res *types.Page + ) + + return set, f, func() error { + if f.Count, err = Count(ctx, s.db, q); err != nil || f.Count == 0 { + return err + } + rows, err := s.Query(ctx, q) + if err != nil { + return err + } + + for rows.Next() { + if res, err = s.internalComposePageRowScanner(rows, rows.Err()); err != nil { + if cerr := rows.Close(); cerr != nil { + return fmt.Errorf("could not close rows (%v) after scan error: %w", cerr, err) + } + + return err + } + + set = append(set, res) + } + + return rows.Close() + }() +} + +// LookupComposePageByHandle searches for page chart by handle (case-insensitive) +func (s Store) LookupComposePageByHandle(ctx context.Context, handle string) (*types.Page, error) { + return s.ComposePageLookup(ctx, squirrel.Eq{ + "cpg.handle": handle, + }) +} + +// LookupComposePageByID searches for compose page by ID +// +// It returns compose page even if deleted +func (s Store) LookupComposePageByID(ctx context.Context, id uint64) (*types.Page, error) { + return s.ComposePageLookup(ctx, squirrel.Eq{ + "cpg.id": id, + }) +} + +// CreateComposePage creates one or more rows in compose_page table +func (s Store) CreateComposePage(ctx context.Context, rr ...*types.Page) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ComposePageTable()).SetMap(s.internalComposePageEncoder(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// UpdateComposePage updates one or more existing rows in compose_page +func (s Store) UpdateComposePage(ctx context.Context, rr ...*types.Page) error { + return s.PartialUpdateComposePage(ctx, nil, rr...) +} + +// PartialUpdateComposePage updates one or more existing rows in compose_page +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +func (s Store) PartialUpdateComposePage(ctx context.Context, onlyColumns []string, rr ...*types.Page) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateComposePages( + ctx, + squirrel.Eq{s.preprocessColumn("cpg.id", ""): s.preprocessValue(res.ID, "")}, + s.internalComposePageEncoder(res).Skip("id").Only(onlyColumns...)) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveComposePage removes one or more rows from compose_page table +func (s Store) RemoveComposePage(ctx context.Context, rr ...*types.Page) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposePageTable("cpg")).Where(squirrel.Eq{s.preprocessColumn("cpg.id", ""): s.preprocessValue(res.ID, "")})) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveComposePageByID removes row from the compose_page table +func (s Store) RemoveComposePageByID(ctx context.Context, ID uint64) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposePageTable("cpg")).Where(squirrel.Eq{s.preprocessColumn("cpg.id", ""): s.preprocessValue(ID, "")})) +} + +// TruncateComposePages removes all rows from the compose_page table +func (s Store) TruncateComposePages(ctx context.Context) error { + return Truncate(ctx, s.DB(), s.ComposePageTable()) +} + +// ExecUpdateComposePages updates all matched (by cnd) rows in compose_page with given data +func (s Store) ExecUpdateComposePages(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposePageTable("cpg")).Where(cnd).SetMap(set)) +} + +// ComposePageLookup prepares ComposePage query and executes it, +// returning types.Page (or error) +func (s Store) ComposePageLookup(ctx context.Context, cnd squirrel.Sqlizer) (*types.Page, error) { + return s.internalComposePageRowScanner(s.QueryRow(ctx, s.QueryComposePages().Where(cnd))) +} + +func (s Store) internalComposePageRowScanner(row rowScanner, err error) (*types.Page, error) { + if err != nil { + return nil, err + } + + var res = &types.Page{} + if _, has := s.config.RowScanners["composePage"]; has { + scanner := s.config.RowScanners["composePage"].(func(rowScanner, *types.Page) error) + err = scanner(row, res) + } else { + err = row.Scan( + &res.ID, + &res.SelfID, + &res.NamespaceID, + &res.ModuleID, + &res.Handle, + &res.Title, + &res.Description, + &res.Blocks, + &res.Visible, + &res.Weight, + &res.CreatedAt, + &res.UpdatedAt, + &res.DeletedAt, + ) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for ComposePage: %w", err) + } else { + return res, nil + } +} + +// QueryComposePages returns squirrel.SelectBuilder with set table and all columns +func (s Store) QueryComposePages() squirrel.SelectBuilder { + return s.Select(s.ComposePageTable("cpg"), s.ComposePageColumns("cpg")...) +} + +// ComposePageTable name of the db table +func (Store) ComposePageTable(aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "compose_page" + alias +} + +// ComposePageColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) ComposePageColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "id", + alias + "self_id", + alias + "rel_namespace", + alias + "rel_module", + alias + "handle", + alias + "title", + alias + "description", + alias + "blocks", + alias + "visible", + alias + "weight", + alias + "created_at", + alias + "updated_at", + alias + "deleted_at", + } +} + +// internalComposePageEncoder encodes fields from types.Page to store.Payload (map) +// +// Encoding is done by using generic approach or by calling encodeComposePage +// func when rdbms.customEncoder=true +func (s Store) internalComposePageEncoder(res *types.Page) store.Payload { + return store.Payload{ + "id": res.ID, + "self_id": res.SelfID, + "rel_namespace": res.NamespaceID, + "rel_module": res.ModuleID, + "handle": res.Handle, + "title": res.Title, + "description": res.Description, + "blocks": res.Blocks, + "visible": res.Visible, + "weight": res.Weight, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + } +} diff --git a/store/rdbms/compose_pages.go b/store/rdbms/compose_pages.go new file mode 100644 index 000000000..31fb26154 --- /dev/null +++ b/store/rdbms/compose_pages.go @@ -0,0 +1,54 @@ +package rdbms + +import ( + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/pkg/rh" + "strings" +) + +func (s Store) convertComposePageFilter(f types.PageFilter) (query squirrel.SelectBuilder, err error) { + if f.Sort == "" { + f.Sort = "id ASC" + } + + query = s.QueryComposePages() + + query = rh.FilterNullByState(query, "cpg.deleted_at", f.Deleted) + + if f.NamespaceID > 0 { + query = query.Where("cpg.rel_namespace = ?", f.NamespaceID) + } + + if f.ParentID > 0 { + query = query.Where("self_id = ?", f.ParentID) + } else if f.Root { + query = query.Where("self_id = 0") + } + + if f.Query != "" { + q := "%" + strings.ToLower(f.Query) + "%" + query = query.Where(squirrel.Or{ + squirrel.Like{"LOWER(cpg.handle)": q}, + squirrel.Like{"LOWER(cpg.title)": q}, + squirrel.Like{"LOWER(cpg.description)": q}, + }) + } + + if f.Handle != "" { + query = query.Where(squirrel.Eq{"LOWER(cpg.handle)": strings.ToLower(f.Handle)}) + } + + if f.IsReadable != nil { + query = query.Where(f.IsReadable) + } + + var orderBy []string + if orderBy, err = rh.ParseOrder(f.Sort, s.ComposePageColumns()...); err != nil { + return + } else { + query = query.OrderBy(orderBy...) + } + + return +} diff --git a/store/rdbms/compose_records.go b/store/rdbms/compose_records.go new file mode 100644 index 000000000..943d8a5e3 --- /dev/null +++ b/store/rdbms/compose_records.go @@ -0,0 +1,566 @@ +package rdbms + +// Handles record values +// +// This file IS NOT autogenerated like most of other store handlers +// because of the specificities that are required for compose record (value) store handling +// +// Main difference is record (value) searching and storage is based on record module settings. + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/pkg/ql" + "github.com/cortezaproject/corteza-server/pkg/rh" + "github.com/cortezaproject/corteza-server/store" + "github.com/jmoiron/sqlx" + "strings" +) + +// SearchComposeRecords returns all matching rows +// +// This function calls convertComposeRecordFilter with the given +// types.RecordFilter and expects to receive a working squirrel.SelectBuilder +func (s Store) SearchComposeRecords(ctx context.Context, m *types.Module, f types.RecordFilter) (types.RecordSet, types.RecordFilter, error) { + q, err := s.convertComposeRecordFilter(m, f) + if err != nil { + return nil, f, err + } + + q = ApplyPaging(q, f.PageFilter) + + cap := f.PerPage + if cap == 0 { + cap = DefaultSliceCapacity + } + + var ( + set = make([]*types.Record, 0, cap) + res *types.Record + ) + + return set, f, func() error { + if f.Count, err = Count(ctx, s.db, q); err != nil || f.Count == 0 { + return err + } + rows, err := s.Query(ctx, q) + if err != nil { + return err + } + + defer rows.Close() + for rows.Next() { + if res, err = s.scanComposeRecord(rows, rows.Err()); err != nil { + return err + } + + set = append(set, res) + } + + return nil + }() +} + +func (s Store) convertComposeRecordFilter(m *types.Module, f types.RecordFilter) (query squirrel.SelectBuilder, err error) { + var ( + joinedFields = []string{} + alreadyJoined = func(f string) bool { + for _, a := range joinedFields { + if a == f { + return true + } + } + + joinedFields = append(joinedFields, f) + return false + } + + identResolver = func(i ql.Ident) (ql.Ident, error) { + var is bool + if i.Value, is = isRealRecordCol(i.Value); is { + i.Value += " " + return i, nil + } + + if !m.Fields.HasName(i.Value) { + return i, fmt.Errorf("unknown field %q", i.Value) + } + + if !alreadyJoined(i.Value) { + query = query.LeftJoin(fmt.Sprintf( + "compose_record_value AS rv_%s ON (rv_%s.record_id = crc.id AND rv_%s.name = ? AND rv_%s.deleted_at IS NULL)", + i.Value, i.Value, i.Value, i.Value, + ), i.Value) + } + + field := m.Fields.FindByName(i.Value) + + switch true { + case field.IsBoolean(): + i.Value = fmt.Sprintf("(rv_%s.value NOT IN ('', '0', 'false', 'f', 'FALSE', 'F', false))", i.Value) + case field.IsNumeric(): + i.Value = fmt.Sprintf("CAST(rv_%s.value AS SIGNED)", i.Value) + case field.IsDateTime(): + i.Value = fmt.Sprintf("CAST(rv_%s.value AS DATETIME)", i.Value) + case field.IsRef(): + i.Value = fmt.Sprintf("rv_%s.ref ", i.Value) + default: + i.Value = fmt.Sprintf("rv_%s.value ", i.Value) + } + + return i, nil + } + ) + + // Create query for fetching and counting records. + query = s.QueryComposeRecords(m). + Where("crc.module_id = ?", m.ID). + Where("crc.rel_namespace = ?", m.NamespaceID) + + // Inc/exclude deleted records according to filter settings + query = rh.FilterNullByState(query, "crc.deleted_at", f.Deleted) + + // Parse filters. + if f.Query != "" { + var ( + // Filter parser + fp = ql.NewParser() + + // Filter node + fn ql.ASTNode + ) + + // Resolve all identifiers found in the query + // into their table/column counterparts + fp.OnIdent = identResolver + + if fn, err = fp.ParseExpression(f.Query); err != nil { + return + } else if filterSql, filterArgs, err := fn.ToSql(); err != nil { + return query, err + } else { + query = query.Where("("+filterSql+")", filterArgs...) + } + } + + if f.Sort != "" { + var ( + // Sort parser + sp = ql.NewParser() + + // Sort columns + sc ql.Columns + ) + + // Resolve all identifiers found in sort + // into their table/column counterparts + sp.OnIdent = identResolver + + if sc, err = sp.ParseColumns(f.Sort); err != nil { + return + } + + query = query.OrderBy(sc.Strings()...) + } + + return +} + +// LookupComposeRecordByID searches for compose page by ID +// +// It returns compose page even if deleted +func (s Store) LookupComposeRecordByID(ctx context.Context, m *types.Module, id uint64) (*types.Record, error) { + return s.ComposeRecordLookup(ctx, m, squirrel.Eq{ + "crc.id": id, + }) +} + +// CreateComposeRecord creates one or more rows in compose_record table +func (s Store) CreateComposeRecord(ctx context.Context, m *types.Module, rr ...*types.Record) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ComposeRecordTable(m)).SetMap(s.ComposeRecordEnc(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// CreateComposeRecordValue creates one or more rows in compose_record_value table +// +// @this can probbably be merged with CreateComposeRecord +func (s Store) CreateComposeRecordValue(ctx context.Context, m *types.Module, rr ...*types.RecordValue) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ComposeRecordValueTable(m)).SetMap(s.ComposeRecordValueEnc(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// UpdateComposeRecord updates one or more existing rows in compose_record +func (s Store) UpdateComposeRecord(ctx context.Context, m *types.Module, rr ...*types.Record) error { + return s.PartialUpdateComposeRecord(ctx, m, nil, rr...) +} + +// UpdateComposeRecordValue updates one or more existing rows in compose_record_value +// +// @todo this can probably be merged with UpdateComposeRecord +func (s Store) UpdateComposeRecordValue(ctx context.Context, m *types.Module, rr ...*types.RecordValue) error { + return s.PartialUpdateComposeRecordValue(ctx, m, rr...) +} + +// PartialUpdateComposeRecord updates one or more existing rows in compose_record +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +func (s Store) PartialUpdateComposeRecord(ctx context.Context, m *types.Module, onlyColumns []string, rr ...*types.Record) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateComposeRecords( + ctx, m, + squirrel.Eq{s.preprocessColumn("crc.id", ""): s.preprocessValue(res.ID, "")}, + s.ComposeRecordEnc(res).Skip("id").Only(onlyColumns...)) + if err != nil { + return err + } + } + + return nil + }) +} + +// PartialUpdateComposeRecordValue updates one or more existing rows in compose_record_value +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +// +// @todo this can probably be merged with PartialUpdateComposeRecord +func (s Store) PartialUpdateComposeRecordValue(ctx context.Context, m *types.Module, rr ...*types.RecordValue) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateComposeRecordValues( + ctx, m, + squirrel.Eq{s.preprocessColumn("crv.record_id", ""): s.preprocessValue(res.RecordID, ""), + s.preprocessColumn("crv.place", ""): s.preprocessValue(res.Place, ""), + s.preprocessColumn("crv.name", ""): s.preprocessValue(res.Name, ""), + }, + s.ComposeRecordValueEnc(res).Skip("record_id", "place", "name")) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveComposeRecord removes one or more rows from compose_record table +func (s Store) RemoveComposeRecord(ctx context.Context, m *types.Module, rr ...*types.Record) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeRecordTable(m, "crc")).Where(squirrel.Eq{s.preprocessColumn("crc.id", ""): s.preprocessValue(res.ID, "")})) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveComposeRecordValue removes one or more rows from compose_record_value table +// +// @todo this can probably be merged with RemoveComposeRecord +func (s Store) RemoveComposeRecordValue(ctx context.Context, m *types.Module, rr ...*types.RecordValue) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeRecordValueTable(m, "crv")).Where(squirrel.Eq{s.preprocessColumn("crv.record_id", ""): s.preprocessValue(res.RecordID, ""), + s.preprocessColumn("crv.place", ""): s.preprocessValue(res.Place, ""), + s.preprocessColumn("crv.name", ""): s.preprocessValue(res.Name, ""), + })) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveComposeRecordByID removes row from the compose_record table +func (s Store) RemoveComposeRecordByID(ctx context.Context, m *types.Module, ID uint64) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeRecordTable(m)).Where(squirrel.Eq{s.preprocessColumn("crc.id", ""): s.preprocessValue(ID, "")})) +} + +// RemoveComposeRecordValueByRecordIDPlaceName removes row from the compose_record_value table +// +// @todo this can probably be merged with RemoveComposeRecordByID +func (s Store) RemoveComposeRecordValueByRecordID(ctx context.Context, m *types.Module, recordID uint64, place int, name string) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ComposeRecordValueTable(m)).Where(squirrel.Eq{s.preprocessColumn("crv.record_id", ""): s.preprocessValue(recordID, "")})) +} + +// TruncateComposeRecords removes all rows from the compose_record table +func (s Store) TruncateComposeRecords(ctx context.Context, m *types.Module) error { + return Truncate(ctx, s.DB(), s.ComposeRecordTable(m)) +} + +// TruncateComposeRecordValues removes all rows from the compose_record_value table +// +// @todo this can probably be merged with TruncateComposeRecords +func (s Store) TruncateComposeRecordValues(ctx context.Context, m *types.Module) error { + return Truncate(ctx, s.DB(), s.ComposeRecordValueTable(m)) +} + +// ExecUpdateComposeRecords updates all matchhed (cnd) rows in compose_record with given data +func (s Store) ExecUpdateComposeRecords(ctx context.Context, m *types.Module, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposeRecordTable(m, "crc")).Where(cnd).SetMap(set)) +} + +// ExecUpdateComposeRecordValues updates all matchhed (cnd) rows in compose_record_value with given data +func (s Store) ExecUpdateComposeRecordValues(ctx context.Context, m *types.Module, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ComposeRecordValueTable(m, "crv")).Where(cnd).SetMap(set)) +} + +// ComposeRecordLookup prepares ComposeRecord query and executes it, +// returning types.Record (or error) +func (s Store) ComposeRecordLookup(ctx context.Context, m *types.Module, cnd squirrel.Sqlizer) (*types.Record, error) { + return s.scanComposeRecord(s.QueryRow(ctx, s.QueryComposeRecords(m).Where(cnd))) +} + +// ComposeRecordValueLookup prepares ComposeRecordValue query and executes it, +// returning types.RecordValue (or error) +func (s Store) ComposeRecordValueLookup(ctx context.Context, m *types.Module, cnd squirrel.Sqlizer) (*types.RecordValue, error) { + return s.scanComposeRecordValue(s.QueryRow(ctx, s.QueryComposeRecordValues(m).Where(cnd))) +} + +func (s Store) scanComposeRecord(row rowScanner, err error) (*types.Record, error) { + if err != nil { + return nil, err + } + + var res = &types.Record{} + if _, has := s.config.RowScanners["ComposeRecord"]; has { + scanner := s.config.RowScanners["ComposeRecord"].(func(rowScanner, *types.Record) error) + err = scanner(row, res) + } else { + err = row.Scan( + &res.ID, + &res.ModuleID, + &res.NamespaceID, + &res.OwnedBy, + &res.CreatedAt, + &res.CreatedBy, + &res.UpdatedAt, + &res.UpdatedBy, + &res.DeletedAt, + &res.DeletedBy, + ) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for ComposeRecord: %w", err) + } else { + return res, nil + } +} + +func (s Store) scanComposeRecordValue(row rowScanner, err error) (*types.RecordValue, error) { + if err != nil { + return nil, err + } + + var res = &types.RecordValue{} + if _, has := s.config.RowScanners["ComposeRecordValue"]; has { + scanner := s.config.RowScanners["ComposeRecordValue"].(func(rowScanner, *types.RecordValue) error) + err = scanner(row, res) + } else { + err = row.Scan( + &res.RecordID, + &res.Place, + &res.Name, + &res.Ref, + &res.Value, + &res.DeletedAt, + ) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for ComposeRecordValue: %w", err) + } else { + return res, nil + } +} + +// QueryComposeRecords returns squirrel.SelectBuilder with set table and all columns +func (s Store) QueryComposeRecords(m *types.Module) squirrel.SelectBuilder { + return s.Select(s.ComposeRecordTable(m, "crc"), s.ComposeRecordColumns("crc")...) +} + +// ComposeRecordTable name of the db table +func (Store) ComposeRecordTable(m *types.Module, aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "compose_record" + alias +} + +// ComposeRecordColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) ComposeRecordColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "id", + alias + "module_id", + alias + "rel_namespace", + alias + "owned_by", + alias + "created_at", + alias + "created_by", + alias + "updated_at", + alias + "updated_by", + alias + "deleted_at", + alias + "deleted_by", + } +} + +// ComposeRecordEnc encodes fields from types.Record to store.Payload (map) +func (Store) ComposeRecordEnc(res *types.Record) store.Payload { + return store.Payload{ + "id": res.ID, + "module_id": res.ModuleID, + "rel_namespace": res.NamespaceID, + "owned_by": res.OwnedBy, + "created_at": res.CreatedAt, + "created_by": res.CreatedBy, + "updated_at": res.UpdatedAt, + "updated_by": res.UpdatedBy, + "deleted_at": res.DeletedAt, + "deleted_by": res.DeletedBy, + } +} + +// QueryComposeRecordValues returns squirrel.SelectBuilder with set table and all columns +func (s Store) QueryComposeRecordValues(m *types.Module) squirrel.SelectBuilder { + return s.Select(s.ComposeRecordValueTable(m, "crv"), s.ComposeRecordValueColumns("crv")...) +} + +// ComposeRecordValueTable name of the db table +func (Store) ComposeRecordValueTable(m *types.Module, aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "compose_record_value" + alias +} + +// ComposeRecordValueColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) ComposeRecordValueColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "record_id", + alias + "place", + alias + "name", + alias + "ref", + alias + "value", + alias + "deleted_at", + } +} + +// ComposeRecordValueEnc encodes fields from types.RecordValue to store.Payload (map) +func (Store) ComposeRecordValueEnc(res *types.RecordValue) store.Payload { + return store.Payload{ + "record_id": res.RecordID, + "place": res.Place, + "name": res.Name, + "ref": res.Ref, + "value": res.Value, + "deleted_at": res.DeletedAt, + } +} + +// Checks if field name is "real column", reformats it and returns +func isRealRecordCol(name string) (string, bool) { + switch name { + case + "recordID", + "id": + return "crc.id", true + case + "module_id", + "owned_by", + "created_by", + "created_at", + "updated_by", + "updated_at", + "deleted_by", + "deleted_at": + return "crc." + name, true + + case + "moduleID", + "ownedBy", + "createdBy", + "createdAt", + "updatedBy", + "updatedAt", + "deletedBy", + "deletedAt": + return "crc." + name[0:len(name)-2] + "_" + strings.ToLower(name[len(name)-2:]), true + } + + return name, false +} diff --git a/store/rdbms/credentials.gen.go b/store/rdbms/credentials.gen.go new file mode 100644 index 000000000..e053ec445 --- /dev/null +++ b/store/rdbms/credentials.gen.go @@ -0,0 +1,247 @@ +package rdbms + +// This file is an auto-generated file +// +// Template: pkg/codegen/assets/store_rdbms.gen.go.tpl +// Definitions: store/credentials.yaml +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/store" + "github.com/cortezaproject/corteza-server/system/types" + "github.com/jmoiron/sqlx" +) + +// SearchCredentials returns all matching rows +// +// This function calls convertCredentialsFilter with the given +// types.CredentialsFilter and expects to receive a working squirrel.SelectBuilder +func (s Store) SearchCredentials(ctx context.Context, f types.CredentialsFilter) (types.CredentialsSet, types.CredentialsFilter, error) { + q, err := s.convertCredentialsFilter(f) + if err != nil { + return nil, f, err + } + + scap := DefaultSliceCapacity + + var ( + set = make([]*types.Credentials, 0, scap) + res *types.Credentials + ) + + return set, f, func() error { + rows, err := s.Query(ctx, q) + if err != nil { + return err + } + + for rows.Next() { + if res, err = s.internalCredentialsRowScanner(rows, rows.Err()); err != nil { + if cerr := rows.Close(); cerr != nil { + return fmt.Errorf("could not close rows (%v) after scan error: %w", cerr, err) + } + + return err + } + + set = append(set, res) + } + + return rows.Close() + }() +} + +// LookupCredentialsByID searches for credentials by ID +// +// It returns credentials even if deleted +func (s Store) LookupCredentialsByID(ctx context.Context, id uint64) (*types.Credentials, error) { + return s.CredentialsLookup(ctx, squirrel.Eq{ + "crd.id": id, + }) +} + +// CreateCredentials creates one or more rows in sys_credentials table +func (s Store) CreateCredentials(ctx context.Context, rr ...*types.Credentials) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.CredentialsTable()).SetMap(s.internalCredentialsEncoder(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// UpdateCredentials updates one or more existing rows in sys_credentials +func (s Store) UpdateCredentials(ctx context.Context, rr ...*types.Credentials) error { + return s.PartialUpdateCredentials(ctx, nil, rr...) +} + +// PartialUpdateCredentials updates one or more existing rows in sys_credentials +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +func (s Store) PartialUpdateCredentials(ctx context.Context, onlyColumns []string, rr ...*types.Credentials) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateCredentials( + ctx, + squirrel.Eq{s.preprocessColumn("crd.id", ""): s.preprocessValue(res.ID, "")}, + s.internalCredentialsEncoder(res).Skip("id").Only(onlyColumns...)) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveCredentials removes one or more rows from sys_credentials table +func (s Store) RemoveCredentials(ctx context.Context, rr ...*types.Credentials) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.CredentialsTable("crd")).Where(squirrel.Eq{s.preprocessColumn("crd.id", ""): s.preprocessValue(res.ID, "")})) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveCredentialsByID removes row from the sys_credentials table +func (s Store) RemoveCredentialsByID(ctx context.Context, ID uint64) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.CredentialsTable("crd")).Where(squirrel.Eq{s.preprocessColumn("crd.id", ""): s.preprocessValue(ID, "")})) +} + +// TruncateCredentials removes all rows from the sys_credentials table +func (s Store) TruncateCredentials(ctx context.Context) error { + return Truncate(ctx, s.DB(), s.CredentialsTable()) +} + +// ExecUpdateCredentials updates all matched (by cnd) rows in sys_credentials with given data +func (s Store) ExecUpdateCredentials(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.CredentialsTable("crd")).Where(cnd).SetMap(set)) +} + +// CredentialsLookup prepares Credentials query and executes it, +// returning types.Credentials (or error) +func (s Store) CredentialsLookup(ctx context.Context, cnd squirrel.Sqlizer) (*types.Credentials, error) { + return s.internalCredentialsRowScanner(s.QueryRow(ctx, s.QueryCredentials().Where(cnd))) +} + +func (s Store) internalCredentialsRowScanner(row rowScanner, err error) (*types.Credentials, error) { + if err != nil { + return nil, err + } + + var res = &types.Credentials{} + if _, has := s.config.RowScanners["credentials"]; has { + scanner := s.config.RowScanners["credentials"].(func(rowScanner, *types.Credentials) error) + err = scanner(row, res) + } else { + err = row.Scan( + &res.ID, + &res.OwnerID, + &res.Kind, + &res.Label, + &res.Credentials, + &res.Meta, + &res.LastUsedAt, + &res.ExpiresAt, + &res.CreatedAt, + &res.UpdatedAt, + &res.DeletedAt, + ) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for Credentials: %w", err) + } else { + return res, nil + } +} + +// QueryCredentials returns squirrel.SelectBuilder with set table and all columns +func (s Store) QueryCredentials() squirrel.SelectBuilder { + return s.Select(s.CredentialsTable("crd"), s.CredentialsColumns("crd")...) +} + +// CredentialsTable name of the db table +func (Store) CredentialsTable(aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "sys_credentials" + alias +} + +// CredentialsColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) CredentialsColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "id", + alias + "rel_owner", + alias + "kind", + alias + "label", + alias + "credentials", + alias + "meta", + alias + "last_used_at", + alias + "expires_at", + alias + "created_at", + alias + "updated_at", + alias + "deleted_at", + } +} + +// internalCredentialsEncoder encodes fields from types.Credentials to store.Payload (map) +// +// Encoding is done by using generic approach or by calling encodeCredentials +// func when rdbms.customEncoder=true +func (s Store) internalCredentialsEncoder(res *types.Credentials) store.Payload { + return store.Payload{ + "id": res.ID, + "rel_owner": res.OwnerID, + "kind": res.Kind, + "label": res.Label, + "credentials": res.Credentials, + "meta": res.Meta, + "last_used_at": res.LastUsedAt, + "expires_at": res.ExpiresAt, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + } +} diff --git a/store/rdbms/credentials.go b/store/rdbms/credentials.go new file mode 100644 index 000000000..f66b2da2e --- /dev/null +++ b/store/rdbms/credentials.go @@ -0,0 +1,16 @@ +package rdbms + +import ( + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/system/types" +) + +func (s Store) convertCredentialsFilter(f types.CredentialsFilter) (query squirrel.SelectBuilder, err error) { + query = s.QueryCredentials() + + if f.Kind != "" { + query = query.Where(squirrel.Eq{"crd.kind": f.Kind}) + } + + return +} diff --git a/store/rdbms/ddl/def.go b/store/rdbms/ddl/def.go new file mode 100644 index 000000000..db6b583b1 --- /dev/null +++ b/store/rdbms/ddl/def.go @@ -0,0 +1,219 @@ +package ddl + +import ( + "fmt" + "strings" +) + +type ( + tableManipulator func(*Table) + indexManipulator func(*Index) + columnManipulator func(*Column) + + Table struct { + Name string + Columns []*Column + Indexes []*Index + PrimaryKey *Index + } + + Index struct { + Name string + Table string + Fields []*IField + Unique bool + Condition string + + // someday maybe index type + } + + IField struct { + // Expression or a single column + Field string + + // Wrap part in parenthesis + Expr bool + + // Ascending or descending + Desc bool + } + + columnType uint + ColumnType struct { + Type columnType + Length int + + // implementation variations + Flags map[string]interface{} + } + + Column struct { + Name string + Type ColumnType + IsNull bool + DefaultValue string + Comment string + } +) + +const ( + // Subset of SQL types + // + // Just the ones we use in Corteza + // Each type should have it's own formatter inside + + ColumnTypeIdentifier columnType = iota + ColumnTypeVarchar + ColumnTypeText + ColumnTypeTimestamp + ColumnTypeInteger + ColumnTypeJson + ColumnTypeBoolean +) + +func TableDef(name string, mm ...tableManipulator) *Table { + var t = &Table{Name: name} + return t.Apply(mm...) +} + +func (t *Table) Apply(mm ...tableManipulator) *Table { + for _, m := range mm { + m(t) + } + + return t +} + +// Adds ID column and sets primary key +func ID(t *Table) { + t.Columns = append(t.Columns, &Column{ + Name: "id", + Type: ColumnType{Type: ColumnTypeIdentifier}, + Comment: fmt.Sprintf("Unique ID for %s", t.Name), + }) + + PrimaryKey(IColumn("id"))(t) +} + +// Adds created_at/updated_at/deleted-at columns +func CUDTimestamps(t *Table) { + t.Apply( + ColumnDef("created_at", ColumnTypeTimestamp), + ColumnDef("updated_at", ColumnTypeTimestamp, Null), + ColumnDef("deleted_at", ColumnTypeTimestamp, Null), + ) +} + +// Adds created_at/updated_at/deleted-by columns +func CUDUsers(t *Table) { + t.Apply( + ColumnDef("created_by", ColumnTypeIdentifier), + ColumnDef("updated_by", ColumnTypeIdentifier, DefaultValue("0")), + ColumnDef("deleted_by", ColumnTypeIdentifier, DefaultValue("0")), + ) +} + +func ColumnDef(name string, cType columnType, mm ...columnManipulator) tableManipulator { + return func(t *Table) { + typ := ColumnType{ + Type: cType, + Flags: make(map[string]interface{}), + + // Setting length to -1 + // + // This way we'll know if it was actually set to 0 + Length: -1, + } + col := &Column{Name: name, Type: typ} + + for _, m := range mm { + m(col) + } + + t.Columns = append(t.Columns, col) + } +} + +// AddIndex adds index to table +// If name has unique_ prefix it unique flag to true +func AddIndex(name string, mm ...indexManipulator) tableManipulator { + return func(t *Table) { + i := &Index{ + Name: name, + Table: t.Name, + Unique: strings.HasPrefix(name, "unique_"), + } + + for _, m := range mm { + m(i) + } + + t.Indexes = append(t.Indexes, i) + } +} + +func Null(c *Column) { + c.IsNull = true +} + +func ColumnTypeLength(l int) columnManipulator { + return func(c *Column) { + c.Type.Length = l + } +} + +func ColumnTypeFlag(n string, v interface{}) columnManipulator { + return func(c *Column) { + c.Type.Flags[n] = v + } +} + +// DefaultValue sets default value on column +// +// Note: avoid using NOW(), CURRENT_TIMESTAMP or other (volatile) function +// service layer should take care of this +func DefaultValue(v string) columnManipulator { + return func(c *Column) { + c.DefaultValue = v + } +} + +func PrimaryKey(mm ...indexManipulator) tableManipulator { + return func(t *Table) { + if t.PrimaryKey == nil { + t.PrimaryKey = &Index{} + } + + for _, m := range mm { + m(t.PrimaryKey) + } + } +} + +func Unique(i *Index) { + i.Unique = true +} + +// IColumn adds one or more keys as columns +func IColumn(cc ...string) indexManipulator { + return func(i *Index) { + for _, c := range cc { + i.Fields = append(i.Fields, &IField{Field: c}) + } + } +} + +// IExpr adds one or more keys as expressions +func IExpr(ee ...string) indexManipulator { + return func(i *Index) { + for _, e := range ee { + i.Fields = append(i.Fields, &IField{Field: e, Expr: true}) + } + } +} + +func IWhere(cnd string) indexManipulator { + return func(i *Index) { + i.Condition = cnd + } +} diff --git a/store/rdbms/ddl/gen.go b/store/rdbms/ddl/gen.go new file mode 100644 index 000000000..37ea57796 --- /dev/null +++ b/store/rdbms/ddl/gen.go @@ -0,0 +1,142 @@ +package ddl + +import ( + "bytes" + "fmt" + "go.uber.org/zap" + "strings" + "text/template" +) + +type ( + Generator struct { + log *zap.Logger + tpl *template.Template + } +) + +const ( + // table creation + genericCreateTable = ` +CREATE TABLE {{ .Name }} ( +{{ range $n, $c := .Columns -}} +{{ if $n }}, {{ else }} {{ end }}{{ template "create-table-column" . }} +{{ end -}} +{{- if .PrimaryKey }} +, PRIMARY KEY {{ template "index-fields" .PrimaryKey.Fields }} +{{- end }} +) {{- template "create-table-suffix" . -}} +` + genericCreateTableSuffix = `` + + genericCreateTableColumn = ` + {{- .Name }} {{ columnType .Type }} + {{- if not .IsNull }} NOT NULL{{end}} + {{- if .DefaultValue }} DEFAULT {{ .DefaultValue }} {{end}} +` + + genericAddColumn = `ALTER TABLE {{ .Table }} ADD {{ template "create-table-column" .Column }}` + genericAddPrimaryKey = `ALTER TABLE {{ .Table }} ADD CONSTRAINT PRIMARY KEY {{ template "index-fields" .PrimaryKey.Fields }}` + + // index creation + genericCreateIndex = `CREATE {{ if .Unique }}UNIQUE {{ end }}INDEX {{ template "index-name" . }} ON {{ .Table }} {{ template "index-fields" .Fields }}{{ template "index-condition" . }}` + + genericIndexName = `{{ .Table }}_{{ .Name }}` + genericIndexCondition = `{{- if .Condition }} WHERE ({{ .Condition }}){{ end }}` + + // index creation + genericIndexFields = ` +({{ range $n, $f := . -}} + {{ if $n }}, {{ end }} + {{- if .Expr}}({{ end }} + {{- .Field }} + {{- if .Expr}}){{ end }} + {{- if .Desc }} DESC{{ end }} +{{- end }}) +` +) + +func NewGenerator(log *zap.Logger) *Generator { + g := &Generator{log: log, tpl: template.New("")} + g.AddTemplateFunc("columnType", GenColumnType) + g.AddTemplate("create-table", genericCreateTable) + g.AddTemplate("create-table-suffix", genericCreateTableSuffix) + g.AddTemplate("create-table-column", genericCreateTableColumn) + g.AddTemplate("add-column", genericAddColumn) + g.AddTemplate("add-primary-key", genericAddPrimaryKey) + g.AddTemplate("create-index", genericCreateIndex) + g.AddTemplate("index-condition", genericIndexCondition) + g.AddTemplate("index-name", genericIndexName) + g.AddTemplate("index-fields", genericIndexFields) + + return g +} + +func (g *Generator) executeTemplate(name string, data interface{}) string { + buf := &bytes.Buffer{} + if err := g.tpl.ExecuteTemplate(buf, name, data); err != nil { + panic(err) + } + + return buf.String() +} + +func (g *Generator) AddTemplateFunc(name string, fn interface{}) { + g.tpl.Funcs(template.FuncMap{name: fn}) +} + +func (g *Generator) AddTemplate(name, tpl string) { + template.Must(g.tpl.New(name).Parse(strings.TrimSpace(tpl))) +} + +func (g *Generator) CreateTable(t *Table) string { + return g.executeTemplate("create-table", t) +} + +func (g *Generator) CreateIndex(i *Index) string { + return g.executeTemplate("create-index", i) +} + +func (g *Generator) AddColumn(table string, c *Column) string { + return g.executeTemplate("add-column", map[string]interface{}{ + "Table": table, + "Column": c, + }) +} + +func (g *Generator) AddPrimaryKey(table string, pk *Index) string { + return g.executeTemplate("add-primary-key", map[string]interface{}{ + "Table": table, + "PrimaryKey": pk, + }) +} + +func GenColumnType(ct *ColumnType) string { + switch ct.Type { + case ColumnTypeIdentifier: + return "BIGINT" + case ColumnTypeVarchar: + if ct.Length > 0 { + // VARCHAR(0) is useless + return fmt.Sprintf("VARCHAR(%d)", ct.Length) + } + return "VARCHAR" + case ColumnTypeText: + return "TEXT" + case ColumnTypeJson: + return "JSON" + case ColumnTypeTimestamp: + if ct.Length > -1 { + // TIMESTAMPTZ(0) strips out milliseconds + return fmt.Sprintf("TIMESTAMPTZ(%d)", ct.Length) + } + + return "TIMESTAMPTZ" + case ColumnTypeInteger: + return "INTEGER" + case ColumnTypeBoolean: + return "BOOLEAN" + default: + panic(fmt.Sprintf("unhandled column type: %d ", ct.Type)) + } +} diff --git a/store/rdbms/ddl/gen_test.go b/store/rdbms/ddl/gen_test.go new file mode 100644 index 000000000..971df8e47 --- /dev/null +++ b/store/rdbms/ddl/gen_test.go @@ -0,0 +1,88 @@ +package ddl + +import ( + "github.com/stretchr/testify/require" + "go.uber.org/zap" + "strings" + "testing" +) + +func Test_generator_CreateTable(t *testing.T) { + var ( + tests = []struct { + name string + in *Table + out string + }{ + { + name: "2col", + in: TableDef("tbl", + ColumnDef("col1", ColumnTypeInteger, Null), + ColumnDef("col2", ColumnTypeVarchar, ColumnTypeLength(2)), + ), + out: ` +CREATE TABLE tbl ( + col1 INTEGER +, col2 VARCHAR(2) NOT NULL + +)`, + }, + { + name: "primary key", + in: TableDef("tbl", + ID, + ), + out: ` +CREATE TABLE tbl ( + id BIGINT NOT NULL + +, PRIMARY KEY (id) +)`, + }, + } + ) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.New(t).Equal(strings.TrimSpace(tt.out), NewGenerator(zap.NewNop()).CreateTable(tt.in)) + }) + } +} + +func Test_generator_CreateIndex(t *testing.T) { + var ( + tests = []struct { + name string + in *Table + out string + }{ + { + name: "columns", + in: TableDef("tbl", + AddIndex("mix", IColumn("c1", "c2")), + ), + out: "CREATE INDEX tbl_mix ON tbl (c1, c2)", + }, + { + name: "expression", + in: TableDef("tbl", + AddIndex("mix", IExpr("LOWER(exp1)")), + ), + out: "CREATE INDEX tbl_mix ON tbl ((LOWER(exp1)))", + }, + { + name: "conditional", + in: TableDef("tbl", + AddIndex("mix", IColumn("c1"), IWhere("cnd IS NULL")), + ), + out: "CREATE INDEX tbl_mix ON tbl (c1) WHERE (cnd IS NULL)", + }, + } + ) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.New(t).Equal(tt.out, NewGenerator(zap.NewNop()).CreateIndex(tt.in.Indexes[0])) + }) + } +} diff --git a/store/rdbms/generic_selectors.go b/store/rdbms/generic_selectors.go new file mode 100644 index 000000000..30e2b4f50 --- /dev/null +++ b/store/rdbms/generic_selectors.go @@ -0,0 +1,95 @@ +package rdbms + +import ( + "context" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/pkg/rh" + "github.com/jmoiron/sqlx" + "github.com/lann/builder" +) + +// Count counts all rows that match conditions from given query builder +func Count(ctx context.Context, db *sqlx.DB, q squirrel.SelectBuilder) (count uint, err error) { + // Remove order-bys for counting + q = builder.Delete(q, "OrderByParts").(squirrel.SelectBuilder) + + // Replace columns with count(*) + q = builder.Delete(q, "Columns").(squirrel.SelectBuilder).Column("COUNT(*)") + + if sqlSelect, argsSelect, err := q.ToSql(); err != nil { + return 0, err + } else { + if err := db.GetContext(ctx, &count, sqlSelect, argsSelect...); err != nil { + return 0, err + } + } + + return count, nil +} + +// FetchPaged fetches paged rows +func ApplyPaging(q squirrel.SelectBuilder, p rh.PageFilter) squirrel.SelectBuilder { + if p.Limit+p.Offset == 0 { + // When both, offset & limit are 0, + // calculate both values from page/perPage params + if p.PerPage > 0 { + p.Limit = p.PerPage + } + + if p.Page < 1 { + p.Page = 1 + } + + p.Offset = (p.Page - 1) * p.PerPage + } + + if p.Limit > 0 { + q = q.Limit(uint64(p.Limit)) + } + + if p.Offset > 0 { + q = q.Offset(uint64(p.Offset)) + } + + return q +} + +// FetchPaged fetches paged rows +// +// Deprecated +func FetchPaged(ctx context.Context, db *sqlx.DB, q squirrel.SelectBuilder, p rh.PageFilter, set interface{}) error { + if p.Limit+p.Offset == 0 { + // When both, offset & limit are 0, + // calculate both values from page/perPage params + if p.PerPage > 0 { + p.Limit = p.PerPage + } + + if p.Page < 1 { + p.Page = 1 + } + + p.Offset = (p.Page - 1) * p.PerPage + } + + if p.Limit > 0 { + q = q.Limit(uint64(p.Limit)) + } + + if p.Offset > 0 { + q = q.Offset(uint64(p.Offset)) + } + + return FetchAll(ctx, db, q, set) +} + +// FetchPaged fetches paged rows +// +// Deprecated +func FetchAll(ctx context.Context, db *sqlx.DB, q squirrel.Sqlizer, set interface{}) error { + if sqlSelect, argsSelect, err := q.ToSql(); err != nil { + return err + } else { + return db.SelectContext(ctx, set, sqlSelect, argsSelect...) + } +} diff --git a/store/rdbms/generic_upgrades.go b/store/rdbms/generic_upgrades.go new file mode 100644 index 000000000..79a20183d --- /dev/null +++ b/store/rdbms/generic_upgrades.go @@ -0,0 +1,223 @@ +package rdbms + +import ( + "context" + "fmt" + "github.com/cortezaproject/corteza-server/store/rdbms/ddl" + "go.uber.org/zap" +) + +type ( + genericUpgrades struct { + log *zap.Logger + u upgrader + } + + upgrader interface { + TableExists(context.Context, string) (bool, error) + AddColumn(context.Context, string, *ddl.Column) (bool, error) + AddPrimaryKey(context.Context, string, *ddl.Index) (bool, error) + Exec(context.Context, string, ...interface{}) error + } +) + +func GenericUpgrades(log *zap.Logger, u upgrader) *genericUpgrades { + return &genericUpgrades{log, u} +} + +func (g genericUpgrades) Before(ctx context.Context) error { + return g.all(ctx, + g.RenameActionlog, + g.RenameReminders, + ) +} + +func (g genericUpgrades) After(ctx context.Context) error { + return nil +} + +func (g genericUpgrades) Upgrade(ctx context.Context, t *ddl.Table) error { + switch t.Name { + case "settings": + return g.all(ctx, + g.MergeSettingsTables, + ) + case "rbac_rules": + return g.all(ctx, + g.MergePermissionRulesTables, + ) + case "actionlog": + return g.all(ctx, + g.AlterActionlogAddID, + ) + } + + return nil +} + +func (genericUpgrades) all(ctx context.Context, ffn ...func(context.Context) error) (err error) { + for _, fn := range ffn { + if err = fn(ctx); err != nil { + return err + } + } + + return nil +} + +// MergeSettingsTables merges "*_settings" tables into one single "settings" +func (g genericUpgrades) MergeSettingsTables(ctx context.Context) error { + var ( + err error + tt = []struct { + tbl string + applyNamePrefix string + }{ + {tbl: "sys_settings", applyNamePrefix: ""}, + {tbl: "compose_settings", applyNamePrefix: "compose."}, + {tbl: "messaging_settings", applyNamePrefix: "messaging."}, + } + + // CONCAT does not work in sqlite but we'Ll ignore this since sqlite should + // not even get execute this query (*_settings tables do not exist) + merge = ` + INSERT INTO settings (rel_owner, name, value, updated_by, updated_at) + SELECT rel_owner, CONCAT('%s', name), value, updated_by, updated_at + FROM %s` + + drop = `DROP TABLE %s` + ) + + for _, t := range tt { + if exists, err := g.u.TableExists(ctx, t.tbl); err != nil { + return err + } else if !exists { + g.log.Debug(fmt.Sprintf("skipping settings merge, table %s already removed", t.tbl)) + continue + } + + err = g.u.Exec(ctx, fmt.Sprintf(merge, t.applyNamePrefix, t.tbl)) + if err != nil { + return fmt.Errorf("could not merge %s: %w", t.tbl, err) + } + + err = g.u.Exec(ctx, fmt.Sprintf(drop, t.tbl)) + if err != nil { + return fmt.Errorf("could not drop %s: %w", t.tbl, err) + } + + g.log.Debug(fmt.Sprintf("table %s merged into settings and removed", t.tbl)) + } + + return nil +} + +// MergeSettingsTables merges "*_settings" tables into one single "settings" +func (g genericUpgrades) MergePermissionRulesTables(ctx context.Context) error { + var ( + err error + tt = []struct { + tbl string + }{ + {tbl: "sys_permission_rules"}, + {tbl: "compose_permission_rules"}, + {tbl: "messaging_permission_rules"}, + } + + // CONCAT does not work in sqlite but we'Ll ignore this since sqlite should + // not even get execute this query (*_permissions tables do not exist) + merge = ` + INSERT INTO rbac_rules (rel_role, resource, operation, access) + SELECT rel_role, resource, operation, access + FROM %s` + + drop = `DROP TABLE %s` + ) + + for _, t := range tt { + if exists, err := g.u.TableExists(ctx, t.tbl); err != nil { + return err + } else if !exists { + g.log.Debug(fmt.Sprintf("skipping rbac rules merge, table %s already removed", t.tbl)) + continue + } + + err = g.u.Exec(ctx, fmt.Sprintf(merge, t.tbl)) + if err != nil { + return fmt.Errorf("could not merge %s: %w", t.tbl, err) + } + + err = g.u.Exec(ctx, fmt.Sprintf(drop, t.tbl)) + if err != nil { + return fmt.Errorf("could not drop %s: %w", t.tbl, err) + } + + g.log.Debug(fmt.Sprintf("table %s merged into rbac_rules and removed", t.tbl)) + } + + return nil +} + +func (g genericUpgrades) RenameActionlog(ctx context.Context) error { + return g.RenameTable(ctx, "sys_actionlog", "actionlog") + +} + +// AlterActionlogAddID adds ID column, fills it with values and adds PK on it +// +// This is MySQL only; other implementations were never in state with actionlog table +// without ID column. +func (g genericUpgrades) AlterActionlogAddID(ctx context.Context) (err error) { + var ( + added bool + col = &ddl.Column{Name: "id", Type: ddl.ColumnType{Type: ddl.ColumnTypeIdentifier}, IsNull: false} + ind = &ddl.Index{Fields: []*ddl.IField{{Field: col.Name}}} + upd = `UPDATE actionlog SET id = @v := COALESCE(@v, 0) + 1 WHERE id = 0` + ) + if added, err = g.u.AddColumn(ctx, "actionlog", col); err != nil { + return err + } else if !added { + // not added, no need to continue + return + } + + // Now prefill with generated IDs in any case -- if col was added or not + g.log.Debug(fmt.Sprintf("prefilling missing values for actionlog ID field, might take a while")) + if err = g.u.Exec(ctx, upd); err != nil { + return fmt.Errorf("could not prefill actionlog ID field: %w", err) + } + + if added, err = g.u.AddPrimaryKey(ctx, "actionlog", ind); err != nil { + return err + } + + return nil +} + +func (g genericUpgrades) RenameReminders(ctx context.Context) error { + return g.RenameTable(ctx, "sys_reminder", "reminders") +} + +func (g genericUpgrades) RenameTable(ctx context.Context, old, new string) error { + if exists, err := g.u.TableExists(ctx, old); err != nil { + return err + } else if !exists { + g.log.Debug(fmt.Sprintf("skipping %s table rename, old table does not exist", old)) + return nil + } + + if exists, err := g.u.TableExists(ctx, new); err != nil { + return err + } else if exists { + g.log.Debug(fmt.Sprintf("skipping %s table rename, new table already exist", new)) + return nil + } + + if err := g.u.Exec(ctx, fmt.Sprintf("ALTER TABLE %s RENAME TO %s", old, new)); err != nil { + return err + } + + g.log.Debug(fmt.Sprintf("table %s renamed to %s", old, new)) + + return nil +} diff --git a/store/rdbms/rbac_rules.gen.go b/store/rdbms/rbac_rules.gen.go new file mode 100644 index 000000000..b1131691e --- /dev/null +++ b/store/rdbms/rbac_rules.gen.go @@ -0,0 +1,225 @@ +package rdbms + +// This file is an auto-generated file +// +// Template: pkg/codegen/assets/store_rdbms.gen.go.tpl +// Definitions: store/rbac_rules.yaml +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/pkg/permissions" + "github.com/cortezaproject/corteza-server/store" + "github.com/jmoiron/sqlx" +) + +// SearchRbacRules returns all matching rows +// +// This function calls convertRbacRuleFilter with the given +// permissions.RuleFilter and expects to receive a working squirrel.SelectBuilder +func (s Store) SearchRbacRules(ctx context.Context, f permissions.RuleFilter) (permissions.RuleSet, permissions.RuleFilter, error) { + q := s.QueryRbacRules() + + scap := DefaultSliceCapacity + + var ( + set = make([]*permissions.Rule, 0, scap) + res *permissions.Rule + ) + + return set, f, func() error { + rows, err := s.Query(ctx, q) + if err != nil { + return err + } + + for rows.Next() { + if res, err = s.internalRbacRuleRowScanner(rows, rows.Err()); err != nil { + if cerr := rows.Close(); cerr != nil { + return fmt.Errorf("could not close rows (%v) after scan error: %w", cerr, err) + } + + return err + } + + set = append(set, res) + } + + return rows.Close() + }() +} + +// CreateRbacRule creates one or more rows in rbac_rules table +func (s Store) CreateRbacRule(ctx context.Context, rr ...*permissions.Rule) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.RbacRuleTable()).SetMap(s.internalRbacRuleEncoder(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// UpdateRbacRule updates one or more existing rows in rbac_rules +func (s Store) UpdateRbacRule(ctx context.Context, rr ...*permissions.Rule) error { + return s.PartialUpdateRbacRule(ctx, nil, rr...) +} + +// PartialUpdateRbacRule updates one or more existing rows in rbac_rules +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +func (s Store) PartialUpdateRbacRule(ctx context.Context, onlyColumns []string, rr ...*permissions.Rule) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateRbacRules( + ctx, + squirrel.Eq{s.preprocessColumn("rls.rel_role", ""): s.preprocessValue(res.RoleID, ""), + s.preprocessColumn("rls.resource", ""): s.preprocessValue(res.Resource, ""), + s.preprocessColumn("rls.operation", ""): s.preprocessValue(res.Operation, ""), + }, + s.internalRbacRuleEncoder(res).Skip("rel_role", "resource", "operation").Only(onlyColumns...)) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveRbacRule removes one or more rows from rbac_rules table +func (s Store) RemoveRbacRule(ctx context.Context, rr ...*permissions.Rule) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.RbacRuleTable("rls")).Where(squirrel.Eq{s.preprocessColumn("rls.rel_role", ""): s.preprocessValue(res.RoleID, ""), + s.preprocessColumn("rls.resource", ""): s.preprocessValue(res.Resource, ""), + s.preprocessColumn("rls.operation", ""): s.preprocessValue(res.Operation, ""), + })) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveRbacRuleByRoleIDResourceOperation removes row from the rbac_rules table +func (s Store) RemoveRbacRuleByRoleIDResourceOperation(ctx context.Context, roleID uint64, resource string, operation string) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.RbacRuleTable("rls")).Where(squirrel.Eq{s.preprocessColumn("rls.rel_role", ""): s.preprocessValue(roleID, ""), + + s.preprocessColumn("rls.resource", ""): s.preprocessValue(resource, ""), + + s.preprocessColumn("rls.operation", ""): s.preprocessValue(operation, ""), + })) +} + +// TruncateRbacRules removes all rows from the rbac_rules table +func (s Store) TruncateRbacRules(ctx context.Context) error { + return Truncate(ctx, s.DB(), s.RbacRuleTable()) +} + +// ExecUpdateRbacRules updates all matched (by cnd) rows in rbac_rules with given data +func (s Store) ExecUpdateRbacRules(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.RbacRuleTable("rls")).Where(cnd).SetMap(set)) +} + +// RbacRuleLookup prepares RbacRule query and executes it, +// returning permissions.Rule (or error) +func (s Store) RbacRuleLookup(ctx context.Context, cnd squirrel.Sqlizer) (*permissions.Rule, error) { + return s.internalRbacRuleRowScanner(s.QueryRow(ctx, s.QueryRbacRules().Where(cnd))) +} + +func (s Store) internalRbacRuleRowScanner(row rowScanner, err error) (*permissions.Rule, error) { + if err != nil { + return nil, err + } + + var res = &permissions.Rule{} + if _, has := s.config.RowScanners["rbacRule"]; has { + scanner := s.config.RowScanners["rbacRule"].(func(rowScanner, *permissions.Rule) error) + err = scanner(row, res) + } else { + err = row.Scan( + &res.RoleID, + &res.Resource, + &res.Operation, + &res.Access, + ) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for RbacRule: %w", err) + } else { + return res, nil + } +} + +// QueryRbacRules returns squirrel.SelectBuilder with set table and all columns +func (s Store) QueryRbacRules() squirrel.SelectBuilder { + return s.Select(s.RbacRuleTable("rls"), s.RbacRuleColumns("rls")...) +} + +// RbacRuleTable name of the db table +func (Store) RbacRuleTable(aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "rbac_rules" + alias +} + +// RbacRuleColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) RbacRuleColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "rel_role", + alias + "resource", + alias + "operation", + alias + "access", + } +} + +// internalRbacRuleEncoder encodes fields from permissions.Rule to store.Payload (map) +// +// Encoding is done by using generic approach or by calling encodeRbacRule +// func when rdbms.customEncoder=true +func (s Store) internalRbacRuleEncoder(res *permissions.Rule) store.Payload { + return store.Payload{ + "rel_role": res.RoleID, + "resource": res.Resource, + "operation": res.Operation, + "access": res.Access, + } +} diff --git a/store/rdbms/rdbms.go b/store/rdbms/rdbms.go new file mode 100644 index 000000000..14e8f4999 --- /dev/null +++ b/store/rdbms/rdbms.go @@ -0,0 +1,335 @@ +package rdbms + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/store/bulk" + "github.com/cortezaproject/corteza-server/store/rdbms/ddl" + "github.com/jmoiron/sqlx" + "strings" + "time" +) + +// persistance layer +// +// all functions go under one struct +// why? because it will be easier to initialize and pass around +// +// each domain will be in it's own file +// +// connection logic will be built in the persistence layer (making pkg/db obsolete) +// + +type ( + txRetryOnErrHandler func(int, error) bool + columnPreprocFn func(string, string) string + valuePreprocFn func(interface{}, string) interface{} + + schemaUpgradeGenerator interface { + TableExists(string) bool + CreateTable(t *ddl.Table) string + CreateIndexes(ii ...*ddl.Index) []string + } + + rowScanner interface { + Scan(...interface{}) error + } + + Config struct { + DriverName string + DataSourceName string + DBName string + + PlaceholderFormat squirrel.PlaceholderFormat + + // How many times should we retry failed transaction? + TxMaxRetries int + + // TxRetryErrHandler should return true if transaction should be retried + // + // Because retry algorithm varies between concrete rdbms implementations + // + // Handler must return true if failed transaction should be replied + // and false if we're safe to terminate it + TxRetryErrHandler txRetryOnErrHandler + + ColumnPreprocessors map[string]columnPreprocFn + ValuePreprocessors map[string]valuePreprocFn + + // Implementations can override internal RDBMS row scanners + RowScanners map[string]interface{} + } + + Store struct { + config *Config + + // Schema upgrade generator converts internal upgrade config + // to implementation specific SQL + sug schemaUpgradeGenerator + + db *sqlx.DB + } +) + +const ( + // This is the absolute maximum retries we'll allow + TxRetryHardLimit = 100 + + DefaultSliceCapacity = 1000 +) + +var ( + now = func() time.Time { + return time.Now() + } +) + +//func Instrumentation(log *zap.Logger) { +// logger := instrumentedsql.LoggerFunc(func(ctx context.Context, msg string, keyvals ...interface{}) { +// //spew.Dump(msg, keyvals) +// log.With(zap.Any("kv", keyvals)).Info(msg) +// }) +// +// sql.Register( +// "mysql+instrumented", +// instrumentedsql.WrapDriver(&mysql.MySQLDriver{}, instrumentedsql.WithLogger(logger))) +// +// sql.Register( +// "postgres+instrumented", +// instrumentedsql.WrapDriver(&pq.Driver{}, instrumentedsql.WithLogger(logger))) +//} + +func New(ctx context.Context, cfg *Config) (*Store, error) { + var s = &Store{ + config: cfg, + } + + if s.config.PlaceholderFormat == nil { + s.config.PlaceholderFormat = squirrel.Question + } + + if s.config.TxMaxRetries == 0 { + s.config.TxMaxRetries = TxRetryHardLimit + } + + if s.config.TxRetryErrHandler == nil { + // Default transaction retry handler + s.config.TxRetryErrHandler = TxNoRetry + } + + if err := s.Connect(ctx); err != nil { + return nil, err + } + + return s, nil +} + +func (s *Store) Connect(ctx context.Context) (err error) { + s.db, err = sqlx.ConnectContext(ctx, s.config.DriverName, s.config.DataSourceName) + return err +} + +// Select is a shorthand for squirrel.SelectBuilder +// +// Sets passed table & columns and configured placeholder format +func (s Store) Select(table string, cc ...string) squirrel.SelectBuilder { + return squirrel.Select(cc...).From(table).PlaceholderFormat(s.config.PlaceholderFormat) +} + +func (s Store) Query(ctx context.Context, q squirrel.SelectBuilder) (*sql.Rows, error) { + query, args, err := q.ToSql() + if err != nil { + return nil, fmt.Errorf("could not build query: %w", err) + } + + return s.db.QueryContext(ctx, query, args...) +} + +// QueryRow returns row instead of filling in the passed struct +func (s Store) QueryRow(ctx context.Context, q squirrel.SelectBuilder) (*sql.Row, error) { + query, args, err := q.ToSql() + if err != nil { + return nil, fmt.Errorf("could not build query: %w", err) + } + + return s.db.QueryRowContext(ctx, query, args...), nil +} + +// Insert is a shorthand for squirrel.InsertBuilder +// +// Sets passed table and configured placeholder format +func (s Store) Insert(table string) squirrel.InsertBuilder { + return squirrel.Insert(table).PlaceholderFormat(s.config.PlaceholderFormat) +} + +// Update is a shorthand for squirrel.UpdateBuilder +// +// Sets passed table and configured placeholder format +func (s Store) Update(table string) squirrel.UpdateBuilder { + return squirrel.Update(table).PlaceholderFormat(s.config.PlaceholderFormat) +} + +// Delete is a shorthand for squirrel.DeleteBuilder +// +// Sets passed table and configured placeholder format +func (s Store) Delete(table string) squirrel.DeleteBuilder { + return squirrel.Delete(table).PlaceholderFormat(s.config.PlaceholderFormat) +} + +func (s Store) DB() *sqlx.DB { + return s.db +} + +func (s Store) Config() *Config { + return s.config +} + +// Bulk returns channel that accepts jobs and executes them inside a transaction +// +// Note: This is experimental function! +// Final version might not return channel directly +// +func (s Store) Bulk(ctx context.Context) chan bulk.Job { + jc := make(chan bulk.Job) + + go Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + var job bulk.Job + + for { + select { + case <-ctx.Done(): + return ctx.Err() + + case job = <-jc: + if err = job.Do(ctx, s); err != nil { + return + } + } + } + }) + + return jc +} + +// column preprocessor logic to modify db value before using it in condition filter +// +// It checks registered ColumnPreprocessors from config +// and then the standard set +// +// No preprocessor ("") is intentionally checked after checking registered list of preprocessors +func (s Store) preprocessColumn(col string, p string) string { + if fn, has := s.config.ColumnPreprocessors[p]; has { + return fn(col, p) + } + + switch p { + case "": + return col + case "lower": + return fmt.Sprintf("LOWER(%s)", col) + default: + panic(fmt.Sprintf("unknown preprocessor %q used for column %q", p, col)) + } +} + +// value preprocessor logic to modify input value before using it in condition filters +// +// It checks registered ValuePreprocessors from config +// and then the standard set +// +// No preprocessor ("") is intentionally checked after checking registered list of preprocessors +func (s Store) preprocessValue(val interface{}, p string) interface{} { + if fn, has := s.config.ValuePreprocessors[p]; has { + return fn(val, p) + } + + switch p { + case "": + return val + case "lower": + if str, ok := val.(string); ok { + return strings.ToLower(str) + } + panic(fmt.Sprintf("preprocessor %q not compatible with type %T (value: %v)", p, val, val)) + + default: + panic(fmt.Sprintf("unknown preprocessor %q used for value %v", p, val)) + } +} + +func ExecuteSqlizer(ctx context.Context, db sqlx.ExecerContext, sqlizer squirrel.Sqlizer) error { + query, args, err := sqlizer.ToSql() + + if err != nil { + return err + } + + _, err = db.ExecContext(ctx, query, args...) + + return err +} + +func Truncate(ctx context.Context, db sqlx.ExecerContext, table string) error { + _, err := db.ExecContext(ctx, "DELETE FROM "+table) + return err +} + +// Tx begins a new db transaction and handles it's retries when possible +// +// It utilizes configured transaction error handlers and max-retry limits +// to determine if and how many times transaction should be retried +func Tx(ctx context.Context, db *sqlx.DB, cfg *Config, txOpt *sql.TxOptions, task func(*sqlx.Tx) error) error { + var ( + lastTaskErr error + err error + tx *sqlx.Tx + try = 1 + ) + + for { + try++ + + // Start transaction + tx, err = db.BeginTxx(ctx, txOpt) + if err != nil { + return nil + } + + if lastTaskErr = task(tx); lastTaskErr == nil { + // Task completed successfully + return tx.Commit() + } + + // No matter the cause of the error, rollback the transaction + if rollbackErr := tx.Rollback(); rollbackErr != nil { + return fmt.Errorf("failed to rollback transaction (tries: %d) on error %v: %w", try, lastTaskErr, rollbackErr) + } + + // Call the the configured transaction retry error handler + // if this particular error should be retried or not + // + // We can not generalize here because different store implementation have + // different errors and we need to act accordingly + if !cfg.TxRetryErrHandler(try, lastTaskErr) { + return fmt.Errorf("failed to complete transaction: %w", lastTaskErr) + } + + // Tx error handlers can take current number of tries into account and + // break the retry-loop earlier, but that might not be always the case + // + // We'll check the configured and hard-limit maximums + if try >= cfg.TxMaxRetries || try >= TxRetryHardLimit { + return fmt.Errorf("failed to perform transaction (tries: %d), last error: %w", try, lastTaskErr) + } + + // Sleep (with a bit of kickback) before doing next retry + time.Sleep(50 * time.Duration(try*50)) + } +} + +// TxNoRetry - Transaction retry handler +// +// Only returns false so transactions will never retry +func TxNoRetry(int, error) bool { return false } diff --git a/store/rdbms/rdbms_schema.go b/store/rdbms/rdbms_schema.go new file mode 100644 index 000000000..c27755866 --- /dev/null +++ b/store/rdbms/rdbms_schema.go @@ -0,0 +1,448 @@ +package rdbms + +import ( + "context" + "fmt" + . "github.com/cortezaproject/corteza-server/store/rdbms/ddl" +) + +type ( + Schema struct{} + + // schemaUpgrader provides procedures to upgrade rdbms store tables + schemaUpgrader interface { + Before(context.Context) error + CreateTable(context.Context, *Table) error + After(context.Context) error + } +) + +const ( + handleLength = 64 + resourceLength = 512 + + // https://www.rfc-editor.org/errata/eid1690 + emailLength = 254 +) + +// Upgrades schema +func (s *Schema) Upgrade(ctx context.Context, g schemaUpgrader) (err error) { + if err = g.Before(ctx); err != nil { + return fmt.Errorf("could not run \"before\" upgrade procedures: %w", err) + } + + for _, t := range s.Tables() { + if err = g.CreateTable(ctx, t); err != nil { + return fmt.Errorf("could not create table %s: %w", t.Name, err) + } + } + + if err = g.After(ctx); err != nil { + return fmt.Errorf("could not run \"after\" upgrade procedures: %w", err) + } + + return nil +} + +func (s Schema) Tables() []*Table { + return []*Table{ + s.Users(), + s.Credentials(), + s.Roles(), + s.RoleMembers(), + s.Applications(), + s.Reminders(), + s.Attachments(), + s.ActionLog(), + s.RbacRules(), + s.Settings(), + s.ComposeAttachment(), + s.ComposeChart(), + s.ComposeModule(), + s.ComposeModuleField(), + s.ComposeNamespace(), + s.ComposePage(), + s.ComposeRecord(), + s.ComposeRecordValue(), + s.MessagingAttachment(), + s.MessagingChannel(), + s.MessagingChannelMember(), + s.MessagingMention(), + s.MessagingMessage(), + s.MessagingMessageAttachment(), + s.MessagingMessageFlag(), + s.MessagingUnread(), + } +} + +func (Schema) Users() *Table { + return TableDef("sys_user", + ID, + ColumnDef("email", ColumnTypeVarchar, ColumnTypeLength(emailLength)), + ColumnDef("email_confirmed", ColumnTypeBoolean, DefaultValue("false")), + ColumnDef("username", ColumnTypeText), + ColumnDef("name", ColumnTypeText), + ColumnDef("handle", ColumnTypeVarchar, ColumnTypeLength(handleLength)), + ColumnDef("kind", ColumnTypeVarchar, ColumnTypeLength(8)), + ColumnDef("meta", ColumnTypeJson), + ColumnDef("suspended_at", ColumnTypeTimestamp, Null), + CUDTimestamps, + + AddIndex("unique_email", IExpr("LOWER(email)"), IWhere("LENGTH(email) > 0 AND deleted_at IS NULL AND suspended_at IS NULL")), + AddIndex("unique_handle", IExpr("LOWER(handle)"), IWhere("LENGTH(handle) > 0 AND deleted_at IS NULL AND suspended_at IS NULL")), + ) +} + +func (Schema) Credentials() *Table { + return TableDef(`sys_credentials`, + ID, + ColumnDef("rel_owner", ColumnTypeIdentifier), + ColumnDef("label", ColumnTypeText), + ColumnDef("kind", ColumnTypeVarchar, ColumnTypeLength(128)), + ColumnDef("credentials", ColumnTypeText), + ColumnDef("meta", ColumnTypeJson), + ColumnDef("expires_at", ColumnTypeTimestamp, Null), + ColumnDef("last_used_at", ColumnTypeTimestamp, Null), + CUDTimestamps, + + AddIndex("owner_kind", IColumn("rel_owner", "kind"), IWhere("deleted_at IS NULL")), + ) +} + +func (Schema) Roles() *Table { + return TableDef(`sys_role`, + ID, + ColumnDef("name", ColumnTypeText), + ColumnDef("handle", ColumnTypeVarchar, ColumnTypeLength(handleLength)), + ColumnDef("archived_at", ColumnTypeTimestamp, Null), + CUDTimestamps, + + AddIndex("unique_handle", IExpr("LOWER(handle)"), IWhere("LENGTH(handle) > 0 AND deleted_at IS NULL AND archived_at IS NULL")), + ) +} + +func (Schema) RoleMembers() *Table { + return TableDef(`sys_role_member`, + ColumnDef("rel_role", ColumnTypeIdentifier), + ColumnDef("rel_user", ColumnTypeIdentifier), + + AddIndex("unique_membership", IColumn("rel_role", "rel_user")), + ) +} + +func (Schema) Applications() *Table { + return TableDef("sys_application", + ID, + ColumnDef("name", ColumnTypeText), + ColumnDef("enabled", ColumnTypeBoolean, DefaultValue("true")), + ColumnDef("unify", ColumnTypeJson), + ColumnDef("rel_owner", ColumnTypeIdentifier), + CUDTimestamps, + ) +} + +func (Schema) Reminders() *Table { + return TableDef("reminders", + ID, + ColumnDef("resource", ColumnTypeVarchar, ColumnTypeLength(resourceLength)), + ColumnDef("payload", ColumnTypeJson), + ColumnDef("snooze_count", ColumnTypeInteger, DefaultValue("0")), + ColumnDef("assigned_to", ColumnTypeIdentifier, DefaultValue("0")), + ColumnDef("assigned_by", ColumnTypeIdentifier, DefaultValue("0")), + ColumnDef("assigned_at", ColumnTypeTimestamp), + ColumnDef("remind_at", ColumnTypeTimestamp, Null), + ColumnDef("dismissed_at", ColumnTypeTimestamp, Null), + ColumnDef("dismissed_by", ColumnTypeIdentifier, DefaultValue("0")), + CUDTimestamps, + + AddIndex("resource", IColumn("resource")), + AddIndex("assignee", IColumn("assigned_to")), + ) +} + +func (Schema) Attachments() *Table { + return TableDef("sys_attachment", + ID, + ColumnDef("rel_owner", ColumnTypeIdentifier), + ColumnDef("kind", ColumnTypeText), + ColumnDef("url", ColumnTypeText), + ColumnDef("preview_url", ColumnTypeText), + ColumnDef("name", ColumnTypeText), + ColumnDef("meta", ColumnTypeJson), + CUDTimestamps, + ) +} + +func (Schema) ActionLog() *Table { + return TableDef("actionlog", + ID, + ColumnDef("ts", ColumnTypeTimestamp), + ColumnDef("actor_ip_addr", ColumnTypeVarchar, ColumnTypeLength(15)), + ColumnDef("actor_id", ColumnTypeIdentifier), + ColumnDef("request_origin", ColumnTypeVarchar, ColumnTypeLength(32)), + ColumnDef("request_id", ColumnTypeVarchar, ColumnTypeLength(256)), + ColumnDef("resource", ColumnTypeVarchar, ColumnTypeLength(resourceLength)), + ColumnDef("action", ColumnTypeVarchar, ColumnTypeLength(64)), + ColumnDef("error", ColumnTypeText), + ColumnDef("severity", ColumnTypeInteger), + ColumnDef("description", ColumnTypeText), + ColumnDef("meta", ColumnTypeJson), + + AddIndex("ts", IColumn("ts")), + AddIndex("request_origin", IColumn("request_origin")), + AddIndex("actor_id", IColumn("actor_id")), + AddIndex("resource", IColumn("resource")), + AddIndex("action", IColumn("action")), + ) +} + +func (Schema) RbacRules() *Table { + return TableDef("rbac_rules", + ColumnDef("rel_role", ColumnTypeIdentifier), + ColumnDef("resource", ColumnTypeVarchar, ColumnTypeLength(resourceLength)), + ColumnDef("operation", ColumnTypeVarchar, ColumnTypeLength(50)), + ColumnDef("access", ColumnTypeInteger), + + PrimaryKey(IColumn("rel_role", "resource", "operation", "access")), + ) +} + +func (Schema) Settings() *Table { + return TableDef("settings", + ColumnDef("rel_owner", ColumnTypeIdentifier), + ColumnDef("name", ColumnTypeVarchar, ColumnTypeLength(resourceLength)), + ColumnDef("value", ColumnTypeJson), + ColumnDef("updated_by", ColumnTypeIdentifier), + ColumnDef("updated_at", ColumnTypeTimestamp), + + AddIndex("unique_name", IExpr("LOWER(name)"), IColumn("rel_owner")), + ) +} + +func (Schema) ComposeAttachment() *Table { + // @todo merge with general attachment table + + return TableDef("compose_attachment", + ID, + ColumnDef("rel_namespace", ColumnTypeIdentifier), + ColumnDef("rel_owner", ColumnTypeIdentifier), + ColumnDef("kind", ColumnTypeText), + ColumnDef("url", ColumnTypeText), + ColumnDef("preview_url", ColumnTypeText), + ColumnDef("name", ColumnTypeText), + ColumnDef("meta", ColumnTypeJson), + CUDTimestamps, + + AddIndex("namespace", IColumn("rel_namespace")), + ) +} + +func (Schema) ComposeChart() *Table { + return TableDef("compose_chart", + ID, + ColumnDef("handle", ColumnTypeVarchar, ColumnTypeLength(handleLength)), + ColumnDef("rel_namespace", ColumnTypeIdentifier), + ColumnDef("name", ColumnTypeText), + ColumnDef("config", ColumnTypeJson), + CUDTimestamps, + + AddIndex("namespace", IColumn("rel_namespace")), + AddIndex("unique_handle", IColumn("rel_namespace"), IExpr("LOWER(handle)"), IWhere("LENGTH(handle) > 0 AND deleted_at IS NULL")), + ) +} + +func (Schema) ComposeModule() *Table { + return TableDef("compose_module", + ID, + ColumnDef("rel_namespace", ColumnTypeIdentifier), + ColumnDef("handle", ColumnTypeVarchar, ColumnTypeLength(handleLength)), + ColumnDef("name", ColumnTypeText), + ColumnDef("meta", ColumnTypeJson), + CUDTimestamps, + + AddIndex("namespace", IColumn("rel_namespace")), + AddIndex("unique_handle", IColumn("rel_namespace"), IExpr("LOWER(handle)"), IWhere("LENGTH(handle) > 0 AND deleted_at IS NULL")), + ) +} + +func (Schema) ComposeModuleField() *Table { + return TableDef("compose_module_field", + ID, + + ColumnDef("rel_module", ColumnTypeIdentifier), + ColumnDef("place", ColumnTypeInteger), + ColumnDef("kind", ColumnTypeText), + ColumnDef("options", ColumnTypeJson), + ColumnDef("default_value", ColumnTypeJson), + ColumnDef("name", ColumnTypeVarchar, ColumnTypeLength(handleLength)), + ColumnDef("label", ColumnTypeText), + ColumnDef("is_private", ColumnTypeBoolean), + ColumnDef("is_required", ColumnTypeBoolean), + ColumnDef("is_visible", ColumnTypeBoolean), + ColumnDef("is_multi", ColumnTypeBoolean), + + CUDTimestamps, + + AddIndex("unique_name", IColumn("rel_module"), IExpr("LOWER(name)"), IWhere("LENGTH(name) > 0 AND deleted_at IS NULL")), + AddIndex("module", IColumn("rel_module")), + ) +} + +func (Schema) ComposeNamespace() *Table { + return TableDef("compose_namespace", + ID, + ColumnDef("name", ColumnTypeText), + ColumnDef("slug", ColumnTypeVarchar, ColumnTypeLength(handleLength)), + ColumnDef("enabled", ColumnTypeBoolean), + ColumnDef("meta", ColumnTypeJson), + CUDTimestamps, + + AddIndex("unique_slug", IExpr("LOWER(slug)"), IWhere("LENGTH(slug) > 0 AND deleted_at IS NULL")), + ) +} + +func (Schema) ComposePage() *Table { + return TableDef("compose_page", + ID, + ColumnDef("title", ColumnTypeText), + ColumnDef("handle", ColumnTypeVarchar, ColumnTypeLength(handleLength)), + ColumnDef("description", ColumnTypeText), + ColumnDef("rel_namespace", ColumnTypeIdentifier), + ColumnDef("rel_module", ColumnTypeIdentifier), + ColumnDef("self_id", ColumnTypeIdentifier), + ColumnDef("blocks", ColumnTypeJson), + ColumnDef("visible", ColumnTypeBoolean), + ColumnDef("weight", ColumnTypeInteger), + CUDTimestamps, + + AddIndex("self", IColumn("self_id")), + AddIndex("namespace", IColumn("rel_namespace")), + AddIndex("module", IColumn("rel_module")), + AddIndex("unique_handle", IColumn("rel_namespace"), IExpr("LOWER(handle)"), IWhere("LENGTH(handle) > 0 AND deleted_at IS NULL")), + ) +} + +func (Schema) ComposeRecord() *Table { + return TableDef("compose_record", + ID, + ColumnDef("rel_namespace", ColumnTypeIdentifier), + ColumnDef("module_id", ColumnTypeIdentifier), + ColumnDef("owned_by", ColumnTypeIdentifier), + CUDTimestamps, + CUDUsers, + + AddIndex("namespace", IColumn("rel_namespace")), + AddIndex("module", IColumn("module_id")), + AddIndex("owner", IColumn("owned_by")), + ) +} + +func (Schema) ComposeRecordValue() *Table { + return TableDef("compose_record_value", + ColumnDef("record_id", ColumnTypeIdentifier), + ColumnDef("name", ColumnTypeVarchar, ColumnTypeLength(64)), + ColumnDef("value", ColumnTypeText, ColumnTypeFlag("mysqlLongText", true)), + ColumnDef("ref", ColumnTypeIdentifier), + ColumnDef("place", ColumnTypeInteger), + ColumnDef("deleted_at", ColumnTypeTimestamp, Null), + + PrimaryKey(IColumn("record_id", "name", "place")), + AddIndex("ref", IColumn("ref"), IWhere("ref > 0")), + ) +} + +func (Schema) MessagingAttachment() *Table { + // @todo merge with general attachment table + return TableDef("messaging_attachment", + ID, + ColumnDef("rel_user", ColumnTypeIdentifier), // @todo rename => rel_owner + ColumnDef("url", ColumnTypeText), + ColumnDef("preview_url", ColumnTypeText), + ColumnDef("name", ColumnTypeText), + ColumnDef("meta", ColumnTypeJson), + CUDTimestamps, + ) +} + +func (Schema) MessagingChannel() *Table { + return TableDef("messaging_channel", + ID, + ColumnDef("name", ColumnTypeText), + ColumnDef("topic", ColumnTypeText), + ColumnDef("meta", ColumnTypeJson), + ColumnDef("type", ColumnTypeText), + ColumnDef("membership_policy", ColumnTypeText), + ColumnDef("rel_creator", ColumnTypeIdentifier), // @todo rename => created_by + ColumnDef("rel_organisation", ColumnTypeIdentifier), + ColumnDef("archived_at", ColumnTypeTimestamp, Null), + ColumnDef("rel_last_message", ColumnTypeIdentifier), + CUDTimestamps, + ) +} + +func (Schema) MessagingChannelMember() *Table { + return TableDef("messaging_channel_member", + ColumnDef("rel_channel", ColumnTypeIdentifier), + ColumnDef("rel_user", ColumnTypeIdentifier), + ColumnDef("type", ColumnTypeText), + ColumnDef("flag", ColumnTypeText), + CUDTimestamps, + PrimaryKey(IColumn("rel_channel", "rel_user")), + ) +} + +func (Schema) MessagingMention() *Table { + return TableDef("messaging_mention", + ColumnDef("rel_channel", ColumnTypeIdentifier), + ColumnDef("rel_message", ColumnTypeIdentifier), + ColumnDef("rel_user", ColumnTypeIdentifier), + ColumnDef("rel_mentioned_by", ColumnTypeIdentifier), + ColumnDef("created_at", ColumnTypeTimestamp), + ) +} + +func (Schema) MessagingMessage() *Table { + return TableDef("messaging_message", + ID, + ColumnDef("type", ColumnTypeText), + ColumnDef("message", ColumnTypeText), + ColumnDef("meta", ColumnTypeJson), + ColumnDef("rel_channel", ColumnTypeIdentifier), + ColumnDef("rel_user", ColumnTypeIdentifier), + ColumnDef("reply_to", ColumnTypeIdentifier, DefaultValue("0")), + ColumnDef("replies", ColumnTypeInteger, DefaultValue("0")), + + CUDTimestamps, + ) +} + +func (Schema) MessagingMessageAttachment() *Table { + return TableDef("messaging_message_attachment", + ColumnDef("rel_message", ColumnTypeIdentifier), + ColumnDef("rel_attachment", ColumnTypeIdentifier), + PrimaryKey(IColumn("rel_message")), + ) + +} + +func (Schema) MessagingMessageFlag() *Table { + return TableDef("messaging_message_flag", + ID, + ColumnDef("rel_channel", ColumnTypeIdentifier), + ColumnDef("rel_message", ColumnTypeIdentifier), + ColumnDef("rel_user", ColumnTypeIdentifier), + ColumnDef("flag", ColumnTypeText), + ColumnDef("created_at", ColumnTypeTimestamp), + ) +} + +func (Schema) MessagingUnread() *Table { + return TableDef("messaging_unread", + ColumnDef("rel_channel", ColumnTypeIdentifier), + ColumnDef("rel_reply_to", ColumnTypeIdentifier), + ColumnDef("rel_user", ColumnTypeIdentifier), + ColumnDef("count", ColumnTypeInteger), + ColumnDef("rel_last_message", ColumnTypeIdentifier), + PrimaryKey(IColumn("rel_channel", "rel_reply_to", "rel_user")), + ) +} diff --git a/store/rdbms/reminder.go b/store/rdbms/reminder.go new file mode 100644 index 000000000..fd5359933 --- /dev/null +++ b/store/rdbms/reminder.go @@ -0,0 +1,52 @@ +package rdbms + +import ( + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/pkg/rh" + "github.com/cortezaproject/corteza-server/system/types" + "time" +) + +func (s Store) convertReminderFilter(f types.ReminderFilter) (query squirrel.SelectBuilder, err error) { + if f.Sort == "" { + f.Sort = "remind_at" + } + + query = s.QueryReminders() + + if len(f.ReminderID) > 0 { + query = query.Where(squirrel.Eq{"rmd.ID": f.ReminderID}) + } + + if f.ExcludeDismissed { + query = query.Where("rmd.dismissed_at IS NULL") + } + + if f.ScheduledOnly { + query = query.Where("rmd.remind_at IS NOT NULL") + } + + if f.AssignedTo != 0 { + query = query.Where("rmd.assigned_to = ?", f.AssignedTo) + } + + if f.Resource != "" { + query = query.Where("rmd.resource LIKE ?", f.Resource+"%") + } + + if f.ScheduledFrom != nil { + query = query.Where("rmd.remind_at >= ?", f.ScheduledFrom.Format(time.RFC3339)) + } + if f.ScheduledUntil != nil { + query = query.Where("rmd.remind_at <= ?", f.ScheduledUntil.Format(time.RFC3339)) + } + + var orderBy []string + if orderBy, err = rh.ParseOrder(f.Sort, s.ReminderColumns()...); err != nil { + return + } else { + query = query.OrderBy(orderBy...) + } + + return +} diff --git a/store/rdbms/reminders.gen.go b/store/rdbms/reminders.gen.go new file mode 100644 index 000000000..d232dd879 --- /dev/null +++ b/store/rdbms/reminders.gen.go @@ -0,0 +1,261 @@ +package rdbms + +// This file is an auto-generated file +// +// Template: pkg/codegen/assets/store_rdbms.gen.go.tpl +// Definitions: store/reminders.yaml +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/store" + "github.com/cortezaproject/corteza-server/system/types" + "github.com/jmoiron/sqlx" +) + +// SearchReminders returns all matching rows +// +// This function calls convertReminderFilter with the given +// types.ReminderFilter and expects to receive a working squirrel.SelectBuilder +func (s Store) SearchReminders(ctx context.Context, f types.ReminderFilter) (types.ReminderSet, types.ReminderFilter, error) { + q, err := s.convertReminderFilter(f) + if err != nil { + return nil, f, err + } + + q = ApplyPaging(q, f.PageFilter) + + scap := f.PerPage + if scap == 0 { + scap = DefaultSliceCapacity + } + + var ( + set = make([]*types.Reminder, 0, scap) + res *types.Reminder + ) + + return set, f, func() error { + if f.Count, err = Count(ctx, s.db, q); err != nil || f.Count == 0 { + return err + } + rows, err := s.Query(ctx, q) + if err != nil { + return err + } + + for rows.Next() { + if res, err = s.internalReminderRowScanner(rows, rows.Err()); err != nil { + if cerr := rows.Close(); cerr != nil { + return fmt.Errorf("could not close rows (%v) after scan error: %w", cerr, err) + } + + return err + } + + set = append(set, res) + } + + return rows.Close() + }() +} + +// LookupReminderByID searches for reminder by its ID +// +// It returns reminder even if deleted or suspended +func (s Store) LookupReminderByID(ctx context.Context, id uint64) (*types.Reminder, error) { + return s.ReminderLookup(ctx, squirrel.Eq{ + "rmd.id": id, + }) +} + +// CreateReminder creates one or more rows in reminders table +func (s Store) CreateReminder(ctx context.Context, rr ...*types.Reminder) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.ReminderTable()).SetMap(s.internalReminderEncoder(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// UpdateReminder updates one or more existing rows in reminders +func (s Store) UpdateReminder(ctx context.Context, rr ...*types.Reminder) error { + return s.PartialUpdateReminder(ctx, nil, rr...) +} + +// PartialUpdateReminder updates one or more existing rows in reminders +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +func (s Store) PartialUpdateReminder(ctx context.Context, onlyColumns []string, rr ...*types.Reminder) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateReminders( + ctx, + squirrel.Eq{s.preprocessColumn("rmd.id", ""): s.preprocessValue(res.ID, "")}, + s.internalReminderEncoder(res).Skip("id").Only(onlyColumns...)) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveReminder removes one or more rows from reminders table +func (s Store) RemoveReminder(ctx context.Context, rr ...*types.Reminder) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ReminderTable("rmd")).Where(squirrel.Eq{s.preprocessColumn("rmd.id", ""): s.preprocessValue(res.ID, "")})) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveReminderByID removes row from the reminders table +func (s Store) RemoveReminderByID(ctx context.Context, ID uint64) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.ReminderTable("rmd")).Where(squirrel.Eq{s.preprocessColumn("rmd.id", ""): s.preprocessValue(ID, "")})) +} + +// TruncateReminders removes all rows from the reminders table +func (s Store) TruncateReminders(ctx context.Context) error { + return Truncate(ctx, s.DB(), s.ReminderTable()) +} + +// ExecUpdateReminders updates all matched (by cnd) rows in reminders with given data +func (s Store) ExecUpdateReminders(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.ReminderTable("rmd")).Where(cnd).SetMap(set)) +} + +// ReminderLookup prepares Reminder query and executes it, +// returning types.Reminder (or error) +func (s Store) ReminderLookup(ctx context.Context, cnd squirrel.Sqlizer) (*types.Reminder, error) { + return s.internalReminderRowScanner(s.QueryRow(ctx, s.QueryReminders().Where(cnd))) +} + +func (s Store) internalReminderRowScanner(row rowScanner, err error) (*types.Reminder, error) { + if err != nil { + return nil, err + } + + var res = &types.Reminder{} + if _, has := s.config.RowScanners["reminder"]; has { + scanner := s.config.RowScanners["reminder"].(func(rowScanner, *types.Reminder) error) + err = scanner(row, res) + } else { + err = row.Scan( + &res.ID, + &res.Resource, + &res.Payload, + &res.SnoozeCount, + &res.AssignedTo, + &res.AssignedBy, + &res.AssignedAt, + &res.DismissedBy, + &res.DismissedAt, + &res.RemindAt, + &res.CreatedAt, + &res.UpdatedAt, + &res.DeletedAt, + ) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for Reminder: %w", err) + } else { + return res, nil + } +} + +// QueryReminders returns squirrel.SelectBuilder with set table and all columns +func (s Store) QueryReminders() squirrel.SelectBuilder { + return s.Select(s.ReminderTable("rmd"), s.ReminderColumns("rmd")...) +} + +// ReminderTable name of the db table +func (Store) ReminderTable(aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "reminders" + alias +} + +// ReminderColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) ReminderColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "id", + alias + "resource", + alias + "payload", + alias + "snooze_count", + alias + "assigned_to", + alias + "assigned_by", + alias + "assigned_at", + alias + "dismissed_by", + alias + "dismissed_at", + alias + "remind_at", + alias + "created_at", + alias + "updated_at", + alias + "deleted_at", + } +} + +// internalReminderEncoder encodes fields from types.Reminder to store.Payload (map) +// +// Encoding is done by using generic approach or by calling encodeReminder +// func when rdbms.customEncoder=true +func (s Store) internalReminderEncoder(res *types.Reminder) store.Payload { + return store.Payload{ + "id": res.ID, + "resource": res.Resource, + "payload": res.Payload, + "snooze_count": res.SnoozeCount, + "assigned_to": res.AssignedTo, + "assigned_by": res.AssignedBy, + "assigned_at": res.AssignedAt, + "dismissed_by": res.DismissedBy, + "dismissed_at": res.DismissedAt, + "remind_at": res.RemindAt, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + } +} diff --git a/store/rdbms/roles.gen.go b/store/rdbms/roles.gen.go new file mode 100644 index 000000000..4be7df7e8 --- /dev/null +++ b/store/rdbms/roles.gen.go @@ -0,0 +1,265 @@ +package rdbms + +// This file is an auto-generated file +// +// Template: pkg/codegen/assets/store_rdbms.gen.go.tpl +// Definitions: store/roles.yaml +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/store" + "github.com/cortezaproject/corteza-server/system/types" + "github.com/jmoiron/sqlx" +) + +// SearchRoles returns all matching rows +// +// This function calls convertRoleFilter with the given +// types.RoleFilter and expects to receive a working squirrel.SelectBuilder +func (s Store) SearchRoles(ctx context.Context, f types.RoleFilter) (types.RoleSet, types.RoleFilter, error) { + q, err := s.convertRoleFilter(f) + if err != nil { + return nil, f, err + } + + q = ApplyPaging(q, f.PageFilter) + + scap := f.PerPage + if scap == 0 { + scap = DefaultSliceCapacity + } + + var ( + set = make([]*types.Role, 0, scap) + res *types.Role + ) + + return set, f, func() error { + if f.Count, err = Count(ctx, s.db, q); err != nil || f.Count == 0 { + return err + } + rows, err := s.Query(ctx, q) + if err != nil { + return err + } + + for rows.Next() { + if res, err = s.internalRoleRowScanner(rows, rows.Err()); err != nil { + if cerr := rows.Close(); cerr != nil { + return fmt.Errorf("could not close rows (%v) after scan error: %w", cerr, err) + } + + return err + } + + set = append(set, res) + } + + return rows.Close() + }() +} + +// LookupRoleByID searches for role by ID +// +// It returns role even if deleted or suspended +func (s Store) LookupRoleByID(ctx context.Context, id uint64) (*types.Role, error) { + return s.RoleLookup(ctx, squirrel.Eq{ + "rl.id": id, + }) +} + +// LookupRoleByHandle searches for role by its handle +// +// It returns only valid roles (not deleted, not archived) +func (s Store) LookupRoleByHandle(ctx context.Context, handle string) (*types.Role, error) { + return s.RoleLookup(ctx, squirrel.Eq{ + "rl.handle": handle, + "rl.archived_at": nil, + "rl.deleted_at": nil, + }) +} + +// LookupRoleByName searches for role by its name +// +// It returns only valid roles (not deleted, not archived) +func (s Store) LookupRoleByName(ctx context.Context, name string) (*types.Role, error) { + return s.RoleLookup(ctx, squirrel.Eq{ + "rl.name": name, + "rl.archived_at": nil, + "rl.deleted_at": nil, + }) +} + +// CreateRole creates one or more rows in sys_role table +func (s Store) CreateRole(ctx context.Context, rr ...*types.Role) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.RoleTable()).SetMap(s.internalRoleEncoder(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// UpdateRole updates one or more existing rows in sys_role +func (s Store) UpdateRole(ctx context.Context, rr ...*types.Role) error { + return s.PartialUpdateRole(ctx, nil, rr...) +} + +// PartialUpdateRole updates one or more existing rows in sys_role +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +func (s Store) PartialUpdateRole(ctx context.Context, onlyColumns []string, rr ...*types.Role) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateRoles( + ctx, + squirrel.Eq{s.preprocessColumn("rl.id", ""): s.preprocessValue(res.ID, "")}, + s.internalRoleEncoder(res).Skip("id").Only(onlyColumns...)) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveRole removes one or more rows from sys_role table +func (s Store) RemoveRole(ctx context.Context, rr ...*types.Role) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.RoleTable("rl")).Where(squirrel.Eq{s.preprocessColumn("rl.id", ""): s.preprocessValue(res.ID, "")})) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveRoleByID removes row from the sys_role table +func (s Store) RemoveRoleByID(ctx context.Context, ID uint64) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.RoleTable("rl")).Where(squirrel.Eq{s.preprocessColumn("rl.id", ""): s.preprocessValue(ID, "")})) +} + +// TruncateRoles removes all rows from the sys_role table +func (s Store) TruncateRoles(ctx context.Context) error { + return Truncate(ctx, s.DB(), s.RoleTable()) +} + +// ExecUpdateRoles updates all matched (by cnd) rows in sys_role with given data +func (s Store) ExecUpdateRoles(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.RoleTable("rl")).Where(cnd).SetMap(set)) +} + +// RoleLookup prepares Role query and executes it, +// returning types.Role (or error) +func (s Store) RoleLookup(ctx context.Context, cnd squirrel.Sqlizer) (*types.Role, error) { + return s.internalRoleRowScanner(s.QueryRow(ctx, s.QueryRoles().Where(cnd))) +} + +func (s Store) internalRoleRowScanner(row rowScanner, err error) (*types.Role, error) { + if err != nil { + return nil, err + } + + var res = &types.Role{} + if _, has := s.config.RowScanners["role"]; has { + scanner := s.config.RowScanners["role"].(func(rowScanner, *types.Role) error) + err = scanner(row, res) + } else { + err = row.Scan( + &res.ID, + &res.Name, + &res.Handle, + &res.ArchivedAt, + &res.CreatedAt, + &res.UpdatedAt, + &res.DeletedAt, + ) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for Role: %w", err) + } else { + return res, nil + } +} + +// QueryRoles returns squirrel.SelectBuilder with set table and all columns +func (s Store) QueryRoles() squirrel.SelectBuilder { + return s.Select(s.RoleTable("rl"), s.RoleColumns("rl")...) +} + +// RoleTable name of the db table +func (Store) RoleTable(aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "sys_role" + alias +} + +// RoleColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) RoleColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "id", + alias + "name", + alias + "handle", + alias + "archived_at", + alias + "created_at", + alias + "updated_at", + alias + "deleted_at", + } +} + +// internalRoleEncoder encodes fields from types.Role to store.Payload (map) +// +// Encoding is done by using generic approach or by calling encodeRole +// func when rdbms.customEncoder=true +func (s Store) internalRoleEncoder(res *types.Role) store.Payload { + return store.Payload{ + "id": res.ID, + "name": res.Name, + "handle": res.Handle, + "archived_at": res.ArchivedAt, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + } +} diff --git a/store/rdbms/roles.go b/store/rdbms/roles.go new file mode 100644 index 000000000..4148c733a --- /dev/null +++ b/store/rdbms/roles.go @@ -0,0 +1,129 @@ +package rdbms + +import ( + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/pkg/rh" + "github.com/cortezaproject/corteza-server/system/types" +) + +func (s Store) convertRoleFilter(f types.RoleFilter) (query squirrel.SelectBuilder, err error) { + if f.Sort == "" { + f.Sort = "id" + } + + query = s.QueryRoles() + + query = rh.FilterNullByState(query, "rl.deleted_at", f.Deleted) + query = rh.FilterNullByState(query, "rl.archived_at", f.Archived) + + if len(f.RoleID) > 0 { + query = query.Where(squirrel.Eq{"rl.ID": f.RoleID}) + } + + if f.MemberID > 0 { + query = query.Where(squirrel.Expr("rl.ID IN (SELECT rel_role FROM sys_role_member AS m WHERE m.rel_user = ?)", f.MemberID)) + } + + if f.Query != "" { + qs := f.Query + "%" + query = query.Where(squirrel.Or{ + squirrel.Like{"rl.name": qs}, + squirrel.Like{"rl.handle": qs}, + }) + } + + if f.Name != "" { + query = query.Where(squirrel.Eq{"rl.name": f.Name}) + } + + if f.Handle != "" { + query = query.Where(squirrel.Eq{"rl.handle": f.Handle}) + } + + if f.IsReadable != nil { + query = query.Where(f.IsReadable) + } + + var orderBy []string + if orderBy, err = rh.ParseOrder(f.Sort, s.RoleColumns()...); err != nil { + return + } else { + query = query.OrderBy(orderBy...) + } + + return +} + +func (s Store) roleMemberTable() string { + return "sys_role_member" +} + +//func (s *Store) MembershipsFindByUserID(roleID uint64) (mm []*types.RoleMember, err error) { +// rval := make([]*types.RoleMember, 0) +// sql := "SELECT * FROM " + rl.tableMember() + " WHERE rel_user = ?" +// return rval, rl.db().Select(&rval, sql, roleID) +//} +// +//func (s *Store) MemberFindByRoleID(roleID uint64) (mm []*types.RoleMember, err error) { +// rval := make([]*types.RoleMember, 0) +// sql := "SELECT * FROM " + rl.tableMember() + " WHERE rel_role = ?" +// return rval, rl.db().Select(&rval, sql, roleID) +//} +// +//func (s *Store) MemberAddByID(roleID, userID uint64) error { +// mod := &types.RoleMember{ +// RoleID: roleID, +// UserID: userID, +// } +// return rl.db().Replace(rl.tableMember(), mod) +//} +// +//func (s *Store) MemberRemoveByID(roleID, userID uint64) error { +// mod := &types.RoleMember{ +// RoleID: roleID, +// UserID: userID, +// } +// return rl.db().Delete(rl.tableMember(), mod, "rel_role", "rel_user") +//} + +//// Metrics collects and returns user metrics +//func (s *Store) Metrics() (rval *types.RoleMetrics, err error) { +// var ( +// counters = squirrel. +// Select( +// "COUNT(*) as total", +// "SUM(IF(deleted_at IS NULL, 0, 1)) as deleted", +// "SUM(IF(archived_at IS NULL, 0, 1)) as archived", +// "SUM(IF(deleted_at IS NULL AND archived_at IS NULL, 1, 0)) as valid", +// ). +// From(s.roleTable() + " AS u") +// ) +// +// rval = &types.RoleMetrics{} +// +// if err = rh.FetchOne(s.db(), counters, rval); err != nil { +// return +// } +// +// // Fetch daily metrics for created, updated, deleted and archived roles +// err = rh.MultiDailyMetrics( +// s.db(), +// squirrel.Select().From(s.roleTable()+" AS u"), +// []string{ +// "created_at", +// "updated_at", +// "deleted_at", +// "archived_at", +// }, +// &rval.DailyCreated, +// &rval.DailyUpdated, +// &rval.DailyDeleted, +// &rval.DailyArchived, +// ) +// +// if err != nil { +// return +// } +// +// return +//} diff --git a/store/rdbms/settings.gen.go b/store/rdbms/settings.gen.go new file mode 100644 index 000000000..f76d3f6bf --- /dev/null +++ b/store/rdbms/settings.gen.go @@ -0,0 +1,243 @@ +package rdbms + +// This file is an auto-generated file +// +// Template: pkg/codegen/assets/store_rdbms.gen.go.tpl +// Definitions: store/settings.yaml +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/store" + "github.com/cortezaproject/corteza-server/system/types" + "github.com/jmoiron/sqlx" +) + +// SearchSettings returns all matching rows +// +// This function calls convertSettingFilter with the given +// types.SettingsFilter and expects to receive a working squirrel.SelectBuilder +func (s Store) SearchSettings(ctx context.Context, f types.SettingsFilter) (types.SettingValueSet, types.SettingsFilter, error) { + q, err := s.convertSettingFilter(f) + if err != nil { + return nil, f, err + } + + q = ApplyPaging(q, f.PageFilter) + + scap := f.PerPage + if scap == 0 { + scap = DefaultSliceCapacity + } + + var ( + set = make([]*types.SettingValue, 0, scap) + res *types.SettingValue + ) + + return set, f, func() error { + if f.Count, err = Count(ctx, s.db, q); err != nil || f.Count == 0 { + return err + } + rows, err := s.Query(ctx, q) + if err != nil { + return err + } + + for rows.Next() { + if res, err = s.internalSettingRowScanner(rows, rows.Err()); err != nil { + if cerr := rows.Close(); cerr != nil { + return fmt.Errorf("could not close rows (%v) after scan error: %w", cerr, err) + } + + return err + } + + set = append(set, res) + } + + return rows.Close() + }() +} + +// LookupSettingByNameOwnedBy searches for settings by name and owner +func (s Store) LookupSettingByNameOwnedBy(ctx context.Context, name string, owned_by uint64) (*types.SettingValue, error) { + return s.SettingLookup(ctx, squirrel.Eq{ + "st.name": name, + "st.rel_owner": owned_by, + }) +} + +// CreateSetting creates one or more rows in settings table +func (s Store) CreateSetting(ctx context.Context, rr ...*types.SettingValue) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.SettingTable()).SetMap(s.internalSettingEncoder(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// UpdateSetting updates one or more existing rows in settings +func (s Store) UpdateSetting(ctx context.Context, rr ...*types.SettingValue) error { + return s.PartialUpdateSetting(ctx, nil, rr...) +} + +// PartialUpdateSetting updates one or more existing rows in settings +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +func (s Store) PartialUpdateSetting(ctx context.Context, onlyColumns []string, rr ...*types.SettingValue) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateSettings( + ctx, + squirrel.Eq{s.preprocessColumn("st.name", ""): s.preprocessValue(res.Name, ""), + s.preprocessColumn("st.rel_owner", ""): s.preprocessValue(res.OwnedBy, ""), + }, + s.internalSettingEncoder(res).Skip("name", "rel_owner").Only(onlyColumns...)) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveSetting removes one or more rows from settings table +func (s Store) RemoveSetting(ctx context.Context, rr ...*types.SettingValue) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.SettingTable("st")).Where(squirrel.Eq{s.preprocessColumn("st.name", ""): s.preprocessValue(res.Name, ""), + s.preprocessColumn("st.rel_owner", ""): s.preprocessValue(res.OwnedBy, ""), + })) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveSettingByNameOwnedBy removes row from the settings table +func (s Store) RemoveSettingByNameOwnedBy(ctx context.Context, name string, ownedBy uint64) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.SettingTable("st")).Where(squirrel.Eq{s.preprocessColumn("st.name", ""): s.preprocessValue(name, ""), + + s.preprocessColumn("st.rel_owner", ""): s.preprocessValue(ownedBy, ""), + })) +} + +// TruncateSettings removes all rows from the settings table +func (s Store) TruncateSettings(ctx context.Context) error { + return Truncate(ctx, s.DB(), s.SettingTable()) +} + +// ExecUpdateSettings updates all matched (by cnd) rows in settings with given data +func (s Store) ExecUpdateSettings(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.SettingTable("st")).Where(cnd).SetMap(set)) +} + +// SettingLookup prepares Setting query and executes it, +// returning types.SettingValue (or error) +func (s Store) SettingLookup(ctx context.Context, cnd squirrel.Sqlizer) (*types.SettingValue, error) { + return s.internalSettingRowScanner(s.QueryRow(ctx, s.QuerySettings().Where(cnd))) +} + +func (s Store) internalSettingRowScanner(row rowScanner, err error) (*types.SettingValue, error) { + if err != nil { + return nil, err + } + + var res = &types.SettingValue{} + if _, has := s.config.RowScanners["setting"]; has { + scanner := s.config.RowScanners["setting"].(func(rowScanner, *types.SettingValue) error) + err = scanner(row, res) + } else { + err = row.Scan( + &res.Name, + &res.Value, + &res.OwnedBy, + &res.UpdatedBy, + &res.UpdatedAt, + ) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for Setting: %w", err) + } else { + return res, nil + } +} + +// QuerySettings returns squirrel.SelectBuilder with set table and all columns +func (s Store) QuerySettings() squirrel.SelectBuilder { + return s.Select(s.SettingTable("st"), s.SettingColumns("st")...) +} + +// SettingTable name of the db table +func (Store) SettingTable(aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "settings" + alias +} + +// SettingColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) SettingColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "name", + alias + "value", + alias + "rel_owner", + alias + "updated_by", + alias + "updated_at", + } +} + +// internalSettingEncoder encodes fields from types.SettingValue to store.Payload (map) +// +// Encoding is done by using generic approach or by calling encodeSetting +// func when rdbms.customEncoder=true +func (s Store) internalSettingEncoder(res *types.SettingValue) store.Payload { + return store.Payload{ + "name": res.Name, + "value": res.Value, + "rel_owner": res.OwnedBy, + "updated_by": res.UpdatedBy, + "updated_at": res.UpdatedAt, + } +} diff --git a/store/rdbms/settings.go b/store/rdbms/settings.go new file mode 100644 index 000000000..7a0fcc208 --- /dev/null +++ b/store/rdbms/settings.go @@ -0,0 +1,82 @@ +package rdbms + +import ( + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/system/types" +) + +func (s Store) columns() []string { + return []string{ + "name", + "value", + "rel_owner", + "updated_at", + "updated_by", + } +} + +func (s Store) convertSettingFilter(f types.SettingsFilter) (query squirrel.SelectBuilder, err error) { + query = s.QuerySettings().Where(squirrel.Eq{"rel_owner": f.OwnedBy}) + + if len(f.Prefix) > 0 { + query = query.Where("name LIKE ?", f.Prefix+"%") + } + + return +} + +//func (s Store) BulkSet(ctx context.Context, vv ValueSet) error { +// // Save all inside a db transaction +// return r.db().Transaction(func() (err error) { +// return vv.Walk(func(v *SettingValue) error { +// return r.Set(v) +// }) +// }) +//} +// +//func (s Store) UpdateSettings(ctx context.Context, value *SettingValue) error { +// return s.DB().Replace(s.dbTable, value) +//} +// +//func (s Store) DeleteSettings(name string, ownedBy uint64) error { +// _, err := s.db().Exec( +// fmt.Sprintf("DELETE FROM %s WHERE name = ? AND rel_owner = ? ", s.dbTable), +// name, +// ownedBy, +// ) +// return err +//} +// +//func (s Store) SettingsLookupByName(ctx context.Context, name string, ownedBy uint64) (*settings.SettingValue, error) { +// var ( +// v = &settings.SettingValue{} +// cnd = squirrel.Eq{"rel_owner": ownedBy, "name": name} +// err = s.Lookup(ctx, v, s.QuerySettings(), cnd) +// ) +// +// if err != nil { +// return +// } +// +// return v, err +//} +// +//// Returns squirrel.SelectBuilder +//func (s Store) QuerySettings() squirrel.SelectBuilder { +// return s.Select(s.SettingsTable()+" AS stngs", s.SettingsColumns()...) +//} +// +//// Name of the db table +//func (Store) SettingsTable() string { +// return "sys_settings" +//} +// +//func (Store) SettingsColumns() []string { +// return []string{ +// "stngs.name", +// "stngs.value", +// "stngs.rel_owner", +// "stngs.created_by", +// "stngs.updated_at", +// } +//} diff --git a/store/rdbms/system_attachments.gen.go b/store/rdbms/system_attachments.gen.go new file mode 100644 index 000000000..a13f4f059 --- /dev/null +++ b/store/rdbms/system_attachments.gen.go @@ -0,0 +1,252 @@ +package rdbms + +// This file is an auto-generated file +// +// Template: pkg/codegen/assets/store_rdbms.gen.go.tpl +// Definitions: store/system_attachments.yaml +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/store" + "github.com/cortezaproject/corteza-server/system/types" + "github.com/jmoiron/sqlx" +) + +// SearchAttachments returns all matching rows +// +// This function calls convertAttachmentFilter with the given +// types.AttachmentFilter and expects to receive a working squirrel.SelectBuilder +func (s Store) SearchAttachments(ctx context.Context, f types.AttachmentFilter) (types.AttachmentSet, types.AttachmentFilter, error) { + q, err := s.convertAttachmentFilter(f) + if err != nil { + return nil, f, err + } + + q = ApplyPaging(q, f.PageFilter) + + scap := f.PerPage + if scap == 0 { + scap = DefaultSliceCapacity + } + + var ( + set = make([]*types.Attachment, 0, scap) + res *types.Attachment + ) + + return set, f, func() error { + if f.Count, err = Count(ctx, s.db, q); err != nil || f.Count == 0 { + return err + } + rows, err := s.Query(ctx, q) + if err != nil { + return err + } + + for rows.Next() { + if res, err = s.internalAttachmentRowScanner(rows, rows.Err()); err != nil { + if cerr := rows.Close(); cerr != nil { + return fmt.Errorf("could not close rows (%v) after scan error: %w", cerr, err) + } + + return err + } + + set = append(set, res) + } + + return rows.Close() + }() +} + +// LookupAttachmentByID searches for attachment by its ID +// +// It returns attachment even if deleted +func (s Store) LookupAttachmentByID(ctx context.Context, id uint64) (*types.Attachment, error) { + return s.AttachmentLookup(ctx, squirrel.Eq{ + "att.id": id, + }) +} + +// CreateAttachment creates one or more rows in sys_attachment table +func (s Store) CreateAttachment(ctx context.Context, rr ...*types.Attachment) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.AttachmentTable()).SetMap(s.internalAttachmentEncoder(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// UpdateAttachment updates one or more existing rows in sys_attachment +func (s Store) UpdateAttachment(ctx context.Context, rr ...*types.Attachment) error { + return s.PartialUpdateAttachment(ctx, nil, rr...) +} + +// PartialUpdateAttachment updates one or more existing rows in sys_attachment +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +func (s Store) PartialUpdateAttachment(ctx context.Context, onlyColumns []string, rr ...*types.Attachment) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateAttachments( + ctx, + squirrel.Eq{s.preprocessColumn("att.id", ""): s.preprocessValue(res.ID, "")}, + s.internalAttachmentEncoder(res).Skip("id").Only(onlyColumns...)) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveAttachment removes one or more rows from sys_attachment table +func (s Store) RemoveAttachment(ctx context.Context, rr ...*types.Attachment) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.AttachmentTable("att")).Where(squirrel.Eq{s.preprocessColumn("att.id", ""): s.preprocessValue(res.ID, "")})) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveAttachmentByID removes row from the sys_attachment table +func (s Store) RemoveAttachmentByID(ctx context.Context, ID uint64) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.AttachmentTable("att")).Where(squirrel.Eq{s.preprocessColumn("att.id", ""): s.preprocessValue(ID, "")})) +} + +// TruncateAttachments removes all rows from the sys_attachment table +func (s Store) TruncateAttachments(ctx context.Context) error { + return Truncate(ctx, s.DB(), s.AttachmentTable()) +} + +// ExecUpdateAttachments updates all matched (by cnd) rows in sys_attachment with given data +func (s Store) ExecUpdateAttachments(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.AttachmentTable("att")).Where(cnd).SetMap(set)) +} + +// AttachmentLookup prepares Attachment query and executes it, +// returning types.Attachment (or error) +func (s Store) AttachmentLookup(ctx context.Context, cnd squirrel.Sqlizer) (*types.Attachment, error) { + return s.internalAttachmentRowScanner(s.QueryRow(ctx, s.QueryAttachments().Where(cnd))) +} + +func (s Store) internalAttachmentRowScanner(row rowScanner, err error) (*types.Attachment, error) { + if err != nil { + return nil, err + } + + var res = &types.Attachment{} + if _, has := s.config.RowScanners["attachment"]; has { + scanner := s.config.RowScanners["attachment"].(func(rowScanner, *types.Attachment) error) + err = scanner(row, res) + } else { + err = row.Scan( + &res.ID, + &res.OwnerID, + &res.Kind, + &res.Url, + &res.PreviewUrl, + &res.Name, + &res.Meta, + &res.CreatedAt, + &res.UpdatedAt, + &res.DeletedAt, + ) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for Attachment: %w", err) + } else { + return res, nil + } +} + +// QueryAttachments returns squirrel.SelectBuilder with set table and all columns +func (s Store) QueryAttachments() squirrel.SelectBuilder { + return s.Select(s.AttachmentTable("att"), s.AttachmentColumns("att")...) +} + +// AttachmentTable name of the db table +func (Store) AttachmentTable(aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "sys_attachment" + alias +} + +// AttachmentColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) AttachmentColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "id", + alias + "rel_owner", + alias + "kind", + alias + "url", + alias + "preview_url", + alias + "name", + alias + "meta", + alias + "created_at", + alias + "updated_at", + alias + "deleted_at", + } +} + +// internalAttachmentEncoder encodes fields from types.Attachment to store.Payload (map) +// +// Encoding is done by using generic approach or by calling encodeAttachment +// func when rdbms.customEncoder=true +func (s Store) internalAttachmentEncoder(res *types.Attachment) store.Payload { + return store.Payload{ + "id": res.ID, + "rel_owner": res.OwnerID, + "kind": res.Kind, + "url": res.Url, + "preview_url": res.PreviewUrl, + "name": res.Name, + "meta": res.Meta, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + } +} diff --git a/store/rdbms/system_attachments.go b/store/rdbms/system_attachments.go new file mode 100644 index 000000000..c3bb7def1 --- /dev/null +++ b/store/rdbms/system_attachments.go @@ -0,0 +1,28 @@ +package rdbms + +import ( + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/pkg/rh" + "github.com/cortezaproject/corteza-server/system/types" +) + +func (s Store) convertAttachmentFilter(f types.AttachmentFilter) (query squirrel.SelectBuilder, err error) { + if f.Sort == "" { + f.Sort = "id" + } + + query = s.QueryAttachments() + + if f.Kind != "" { + query = query.Where(squirrel.Eq{"att.kind": f.Kind}) + } + + var orderBy []string + if orderBy, err = rh.ParseOrder(f.Sort, s.AttachmentColumns()...); err != nil { + return + } else { + query = query.OrderBy(orderBy...) + } + + return +} diff --git a/store/rdbms/users.gen.go b/store/rdbms/users.gen.go new file mode 100644 index 000000000..465ed7bc1 --- /dev/null +++ b/store/rdbms/users.gen.go @@ -0,0 +1,291 @@ +package rdbms + +// This file is an auto-generated file +// +// Template: pkg/codegen/assets/store_rdbms.gen.go.tpl +// Definitions: store/users.yaml +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. + +import ( + "context" + "database/sql" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/store" + "github.com/cortezaproject/corteza-server/system/types" + "github.com/jmoiron/sqlx" +) + +// SearchUsers returns all matching rows +// +// This function calls convertUserFilter with the given +// types.UserFilter and expects to receive a working squirrel.SelectBuilder +func (s Store) SearchUsers(ctx context.Context, f types.UserFilter) (types.UserSet, types.UserFilter, error) { + q, err := s.convertUserFilter(f) + if err != nil { + return nil, f, err + } + + q = ApplyPaging(q, f.PageFilter) + + scap := f.PerPage + if scap == 0 { + scap = DefaultSliceCapacity + } + + var ( + set = make([]*types.User, 0, scap) + res *types.User + ) + + return set, f, func() error { + if f.Count, err = Count(ctx, s.db, q); err != nil || f.Count == 0 { + return err + } + rows, err := s.Query(ctx, q) + if err != nil { + return err + } + + for rows.Next() { + if res, err = s.internalUserRowScanner(rows, rows.Err()); err != nil { + if cerr := rows.Close(); cerr != nil { + return fmt.Errorf("could not close rows (%v) after scan error: %w", cerr, err) + } + + return err + } + + set = append(set, res) + } + + return rows.Close() + }() +} + +// LookupUserByID searches for user by ID +// +// It returns user even if deleted or suspended +func (s Store) LookupUserByID(ctx context.Context, id uint64) (*types.User, error) { + return s.UserLookup(ctx, squirrel.Eq{ + "usr.id": id, + }) +} + +// LookupUserByEmail searches for user by their email +// +// It returns only valid users (not deleted, not suspended) +func (s Store) LookupUserByEmail(ctx context.Context, email string) (*types.User, error) { + return s.UserLookup(ctx, squirrel.Eq{ + "usr.email": email, + "usr.deleted_at": nil, + "usr.suspended_at": nil, + }) +} + +// LookupUserByHandle searches for user by their email +// +// It returns only valid users (not deleted, not suspended) +func (s Store) LookupUserByHandle(ctx context.Context, handle string) (*types.User, error) { + return s.UserLookup(ctx, squirrel.Eq{ + "usr.handle": handle, + "usr.deleted_at": nil, + "usr.suspended_at": nil, + }) +} + +// LookupUserByUsername searches for user by their username +// +// It returns only valid users (not deleted, not suspended) +func (s Store) LookupUserByUsername(ctx context.Context, username string) (*types.User, error) { + return s.UserLookup(ctx, squirrel.Eq{ + "usr.username": username, + "usr.deleted_at": nil, + "usr.suspended_at": nil, + }) +} + +// CreateUser creates one or more rows in sys_user table +func (s Store) CreateUser(ctx context.Context, rr ...*types.User) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Insert(s.UserTable()).SetMap(s.internalUserEncoder(res))) + if err != nil { + return err + } + } + + return nil + }) +} + +// UpdateUser updates one or more existing rows in sys_user +func (s Store) UpdateUser(ctx context.Context, rr ...*types.User) error { + return s.PartialUpdateUser(ctx, nil, rr...) +} + +// PartialUpdateUser updates one or more existing rows in sys_user +// +// It wraps the update into transaction and can perform partial update by providing list of updatable columns +func (s Store) PartialUpdateUser(ctx context.Context, onlyColumns []string, rr ...*types.User) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = s.ExecUpdateUsers( + ctx, + squirrel.Eq{s.preprocessColumn("usr.id", ""): s.preprocessValue(res.ID, "")}, + s.internalUserEncoder(res).Skip("id").Only(onlyColumns...)) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveUser removes one or more rows from sys_user table +func (s Store) RemoveUser(ctx context.Context, rr ...*types.User) error { + if len(rr) == 0 { + return nil + } + + return Tx(ctx, s.db, s.config, nil, func(db *sqlx.Tx) (err error) { + for _, res := range rr { + err = ExecuteSqlizer(ctx, s.DB(), s.Delete(s.UserTable("usr")).Where(squirrel.Eq{s.preprocessColumn("usr.id", ""): s.preprocessValue(res.ID, "")})) + if err != nil { + return err + } + } + + return nil + }) +} + +// RemoveUserByID removes row from the sys_user table +func (s Store) RemoveUserByID(ctx context.Context, ID uint64) error { + return ExecuteSqlizer(ctx, s.DB(), s.Delete(s.UserTable("usr")).Where(squirrel.Eq{s.preprocessColumn("usr.id", ""): s.preprocessValue(ID, "")})) +} + +// TruncateUsers removes all rows from the sys_user table +func (s Store) TruncateUsers(ctx context.Context) error { + return Truncate(ctx, s.DB(), s.UserTable()) +} + +// ExecUpdateUsers updates all matched (by cnd) rows in sys_user with given data +func (s Store) ExecUpdateUsers(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error { + return ExecuteSqlizer(ctx, s.DB(), s.Update(s.UserTable("usr")).Where(cnd).SetMap(set)) +} + +// UserLookup prepares User query and executes it, +// returning types.User (or error) +func (s Store) UserLookup(ctx context.Context, cnd squirrel.Sqlizer) (*types.User, error) { + return s.internalUserRowScanner(s.QueryRow(ctx, s.QueryUsers().Where(cnd))) +} + +func (s Store) internalUserRowScanner(row rowScanner, err error) (*types.User, error) { + if err != nil { + return nil, err + } + + var res = &types.User{} + if _, has := s.config.RowScanners["user"]; has { + scanner := s.config.RowScanners["user"].(func(rowScanner, *types.User) error) + err = scanner(row, res) + } else { + err = row.Scan( + &res.ID, + &res.Email, + &res.EmailConfirmed, + &res.Username, + &res.Name, + &res.Handle, + &res.Meta, + &res.Kind, + &res.CreatedAt, + &res.UpdatedAt, + &res.SuspendedAt, + &res.DeletedAt, + ) + } + + if err == sql.ErrNoRows { + return nil, store.ErrNotFound + } + + if err != nil { + return nil, fmt.Errorf("could not scan db row for User: %w", err) + } else { + return res, nil + } +} + +// QueryUsers returns squirrel.SelectBuilder with set table and all columns +func (s Store) QueryUsers() squirrel.SelectBuilder { + return s.Select(s.UserTable("usr"), s.UserColumns("usr")...) +} + +// UserTable name of the db table +func (Store) UserTable(aa ...string) string { + var alias string + if len(aa) > 0 { + alias = " AS " + aa[0] + } + + return "sys_user" + alias +} + +// UserColumns returns all defined table columns +// +// With optional string arg, all columns are returned aliased +func (Store) UserColumns(aa ...string) []string { + var alias string + if len(aa) > 0 { + alias = aa[0] + "." + } + + return []string{ + alias + "id", + alias + "email", + alias + "email_confirmed", + alias + "username", + alias + "name", + alias + "handle", + alias + "meta", + alias + "kind", + alias + "created_at", + alias + "updated_at", + alias + "suspended_at", + alias + "deleted_at", + } +} + +// internalUserEncoder encodes fields from types.User to store.Payload (map) +// +// Encoding is done by using generic approach or by calling encodeUser +// func when rdbms.customEncoder=true +func (s Store) internalUserEncoder(res *types.User) store.Payload { + return store.Payload{ + "id": res.ID, + "email": res.Email, + "email_confirmed": res.EmailConfirmed, + "username": res.Username, + "name": res.Name, + "handle": res.Handle, + "meta": res.Meta, + "kind": res.Kind, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "suspended_at": res.SuspendedAt, + "deleted_at": res.DeletedAt, + } +} diff --git a/store/rdbms/users.go b/store/rdbms/users.go new file mode 100644 index 000000000..1067bcc71 --- /dev/null +++ b/store/rdbms/users.go @@ -0,0 +1,81 @@ +package rdbms + +import ( + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/pkg/permissions" + "github.com/cortezaproject/corteza-server/pkg/rh" + "github.com/cortezaproject/corteza-server/system/types" +) + +func (s Store) convertUserFilter(f types.UserFilter) (query squirrel.SelectBuilder, err error) { + if f.Sort == "" { + f.Sort = "id" + } + + query = s.QueryUsers() + + // Returns user filter (flt) wrapped in IF() function with cnd as condition (when cnd != nil) + whereMasked := func(cnd *permissions.ResourceFilter, flt squirrel.Sqlizer) squirrel.Sqlizer { + if cnd != nil { + return rh.SquirrelFunction("IF", cnd, flt, squirrel.Expr("false")) + } else { + return flt + } + } + + query = rh.FilterNullByState(query, "usr.deleted_at", f.Deleted) + query = rh.FilterNullByState(query, "usr.suspended_at", f.Suspended) + + if len(f.UserID) > 0 { + query = query.Where(squirrel.Eq{"usr.ID": f.UserID}) + } + + if len(f.RoleID) > 0 { + or := squirrel.Or{} + // Due to lack of support for more exotic expressions (slice of values inside subquery) + // we'll use set of OR expressions as a workaround + for _, roleID := range f.RoleID { + or = append(or, squirrel.Expr("usr.ID IN (SELECT rel_user FROM sys_role_member WHERE rel_role = ?)", roleID)) + } + + query = query.Where(or) + } + + if f.Query != "" { + qs := f.Query + "%" + query = query.Where(squirrel.Or{ + squirrel.Like{"usr.username": qs}, + squirrel.Like{"usr.handle": qs}, + whereMasked(f.IsEmailUnmaskable, squirrel.Like{"usr.email": qs}), + whereMasked(f.IsNameUnmaskable, squirrel.Like{"usr.name": qs}), + }) + } + + if f.Email != "" { + query = query.Where(whereMasked(f.IsEmailUnmaskable, squirrel.Eq{"usr.email": f.Email})) + } + + if f.Username != "" { + query = query.Where(squirrel.Eq{"usr.username": f.Username}) + } + + if f.Handle != "" { + query = query.Where(squirrel.Eq{"usr.handle": f.Handle}) + } + + if f.Kind != "" { + query = query.Where(squirrel.Eq{"usr.kind": f.Kind}) + } + + if f.IsReadable != nil { + query = query.Where(f.IsReadable) + } + + var orderBy []string + if orderBy, err = rh.ParseOrder(f.Sort, s.UserColumns()...); err != nil { + return + } + + query = query.OrderBy(orderBy...) + return +} diff --git a/store/reminders.yaml b/store/reminders.yaml new file mode 100644 index 000000000..86fcf4a36 --- /dev/null +++ b/store/reminders.yaml @@ -0,0 +1,32 @@ +import: + - github.com/cortezaproject/corteza-server/system/types + +interface: + - system/service + +fields: + - { field: ID } + - { field: Resource } + - { field: Payload } + - { field: SnoozeCount } + - { field: AssignedTo } + - { field: AssignedBy } + - { field: AssignedAt } + - { field: DismissedBy } + - { field: DismissedAt } + - { field: RemindAt } + - { field: CreatedAt } + - { field: UpdatedAt } + - { field: DeletedAt } + +lookups: + - fields: [ ID ] + description: |- + searches for reminder by its ID + + It returns reminder even if deleted or suspended + +rdbms: + alias: rmd + table: reminders + customFilterConverter: true diff --git a/store/roles.yaml b/store/roles.yaml new file mode 100644 index 000000000..0836cb3ed --- /dev/null +++ b/store/roles.yaml @@ -0,0 +1,38 @@ +import: + - github.com/cortezaproject/corteza-server/system/types + +interface: + - system/service + +fields: + - { field: ID } + - { field: Name } + - { field: Handle } + - { field: ArchivedAt } + - { field: CreatedAt } + - { field: UpdatedAt } + - { field: DeletedAt } + +lookups: + - fields: [ ID ] + description: |- + searches for role by ID + + It returns role even if deleted or suspended + - fields: [ Handle ] + filter: { DeletedAt: nil, ArchivedAt: nil } + description: |- + searches for role by its handle + + It returns only valid roles (not deleted, not archived) + - fields: [ Name ] + filter: { DeletedAt: nil, ArchivedAt: nil } + description: |- + searches for role by its name + + It returns only valid roles (not deleted, not archived) + +rdbms: + alias: rl + table: sys_role + customFilterConverter: true diff --git a/store/settings.yaml b/store/settings.yaml new file mode 100644 index 000000000..95a400b13 --- /dev/null +++ b/store/settings.yaml @@ -0,0 +1,27 @@ +import: + - github.com/cortezaproject/corteza-server/system/types + +interface: + - system/service + +types: + type: types.SettingValue + filterType: types.SettingsFilter + +fields: + - { field: Name, isPrimaryKey: true } + - { field: Value } + - { field: OwnedBy, isPrimaryKey: true, column: rel_owner } + - { field: UpdatedBy } + - { field: UpdatedAt } + +lookups: + - fields: [ Name, OwnedBy ] + description: |- + searches for settings by name and owner + +rdbms: + alias: st + table: settings + customFilterConverter: true + diff --git a/store/sqlite/sqlite.go b/store/sqlite/sqlite.go new file mode 100644 index 000000000..aa4069221 --- /dev/null +++ b/store/sqlite/sqlite.go @@ -0,0 +1,65 @@ +package sqlite + +import ( + "context" + "fmt" + "github.com/Masterminds/squirrel" + "github.com/cortezaproject/corteza-server/store/rdbms" + _ "github.com/mattn/go-sqlite3" + "go.uber.org/zap" + "strings" +) + +type ( + Store struct { + *rdbms.Store + } +) + +func New(ctx context.Context, dsn string) (s *Store, err error) { + var cfg *rdbms.Config + + if cfg, err = ProcDataSourceName(dsn); err != nil { + return nil, err + } + + cfg.PlaceholderFormat = squirrel.Dollar + + s = new(Store) + if s.Store, err = rdbms.New(ctx, cfg); err != nil { + return nil, err + } + + return s, nil +} + +func (s *Store) Upgrade(ctx context.Context, log *zap.Logger) (err error) { + if err = (&rdbms.Schema{}).Upgrade(ctx, NewUpgrader(log, s)); err != nil { + return fmt.Errorf("can not upgrade sqlite schema: %w", err) + } + + return nil +} + +// ProcDataSourceName validates given DSN and ensures +// params are present and correct +func ProcDataSourceName(in string) (*rdbms.Config, error) { + const ( + schemeDel = "://" + validScheme = "sqlite3" + ) + + var ( + endOfSchema = strings.Index(in, schemeDel) + c = &rdbms.Config{} + ) + + if endOfSchema > 0 && (in[:endOfSchema] == validScheme || strings.HasPrefix(in[:endOfSchema], validScheme+"+")) { + c.DriverName = in[:endOfSchema] + c.DataSourceName = in[endOfSchema+len(schemeDel):] + } else { + return nil, fmt.Errorf("expecting valid schema (sqlite3://) at the beginning of the DSN (%s)", in) + } + + return c, nil +} diff --git a/store/sqlite/upgrade.go b/store/sqlite/upgrade.go new file mode 100644 index 000000000..ae3641e1e --- /dev/null +++ b/store/sqlite/upgrade.go @@ -0,0 +1,110 @@ +package sqlite + +// PostgreSQL specific prefixes, sql +// templates, functions and other helpers + +import ( + "context" + "fmt" + "github.com/cortezaproject/corteza-server/store/rdbms" + "github.com/cortezaproject/corteza-server/store/rdbms/ddl" + "go.uber.org/zap" +) + +type ( + upgrader struct { + s *Store + log *zap.Logger + ddl *ddl.Generator + } +) + +// NewUpgrader returns SQLite schema upgrader +func NewUpgrader(log *zap.Logger, store *Store) *upgrader { + var g = &upgrader{store, log, ddl.NewGenerator(log)} + // All modifications we need for the DDL generator + // to properly support SQLite dialect + + // Cover mysql exceptions + g.ddl.AddTemplateFunc("columnType", func(ct *ddl.ColumnType) string { + switch ct.Type { + case ddl.ColumnTypeTimestamp: + return "TIMESTAMP" + default: + return ddl.GenColumnType(ct) + } + }) + + return g +} + +// Before runs before all tables are upgraded +func (u upgrader) Before(ctx context.Context) error { + return rdbms.GenericUpgrades(u.log, u).Before(ctx) +} + +// After runs after all tables are upgraded +func (u upgrader) After(ctx context.Context) error { + return rdbms.GenericUpgrades(u.log, u).After(ctx) +} + +// CreateTable is triggered for every table defined in the rdbms package +// +// It checks if table is missing and creates it, otherwise +// it runs +func (u upgrader) CreateTable(ctx context.Context, t *ddl.Table) (err error) { + var exists bool + if exists, err = u.TableExists(ctx, t.Name); err != nil { + return + } + + if !exists { + if err = u.Exec(ctx, u.ddl.CreateTable(t)); err != nil { + println(u.ddl.CreateTable(t)) + return err + } + + for _, i := range t.Indexes { + if err = u.Exec(ctx, u.ddl.CreateIndex(i)); err != nil { + return fmt.Errorf("could not create index %s on table %s: %w", i.Name, i.Table, err) + } + } + } else { + return u.upgradeTable(ctx, t) + } + + return nil +} + +func (u upgrader) Exec(ctx context.Context, sql string, aa ...interface{}) error { + _, err := u.s.DB().ExecContext(ctx, sql, aa...) + return err +} + +// upgradeTable applies any necessary changes connected to that specific table +func (u upgrader) upgradeTable(ctx context.Context, t *ddl.Table) error { + g := rdbms.GenericUpgrades(u.log, u) + + switch t.Name { + default: + return g.Upgrade(ctx, t) + } +} + +func (u upgrader) TableExists(ctx context.Context, table string) (bool, error) { + var exists bool + + if err := u.s.DB().GetContext(ctx, &exists, "SELECT COUNT(*) > 0 FROM sqlite_master WHERE type = 'table' AND name = ?", table); err != nil { + return false, fmt.Errorf("could not check if table exists: %w", err) + } + + return exists, nil +} + +func (u upgrader) AddColumn(ctx context.Context, table string, col *ddl.Column) (added bool, err error) { + return false, fmt.Errorf("adding column on sqlite tables is not implemented") +} + +func (u upgrader) AddPrimaryKey(ctx context.Context, table string, ind *ddl.Index) (added bool, err error) { + return false, fmt.Errorf("adding primary keys on sqlite tables is not implemented") +} diff --git a/store/system_attachments.yaml b/store/system_attachments.yaml new file mode 100644 index 000000000..1ff5d2b97 --- /dev/null +++ b/store/system_attachments.yaml @@ -0,0 +1,38 @@ +import: + - github.com/cortezaproject/corteza-server/system/types + +interface: + - system/service + +types: + base: Attachment + +fields: + - { field: ID } + - { field: OwnerID } + - { field: Kind } + - { field: Url } + - { field: PreviewUrl } + - { field: Name } + - { field: Meta } + - { field: CreatedAt } + - { field: UpdatedAt } + - { field: DeletedAt } + +lookups: + - fields: [ ID ] + description: |- + searches for attachment by its ID + + It returns attachment even if deleted + +partialUpdates: + - name: delete + set: { DeletedAt: now() } + - name: undelete + set: { DeletedAt: nil } + +rdbms: + alias: att + table: sys_attachment + customFilterConverter: true diff --git a/store/tests/actionlog_test.go b/store/tests/actionlog_test.go new file mode 100644 index 000000000..f5c75cc42 --- /dev/null +++ b/store/tests/actionlog_test.go @@ -0,0 +1,43 @@ +package tests + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/actionlog" + _ "github.com/joho/godotenv/autoload" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +func testActionlog(t *testing.T, s actionlogsStore) { + var ( + ctx = context.Background() + req = require.New(t) + + //err error + action *actionlog.Action + ) + + t.Run("create", func(t *testing.T) { + action = &actionlog.Action{ + ID: 42, + Timestamp: time.Now(), + Resource: "resource", + Action: "action", + } + req.NoError(s.CreateActionlog(ctx, action)) + }) + + t.Run("search by resource", func(t *testing.T) { + set, _, err := s.SearchActionlogs(ctx, actionlog.Filter{Resource: action.Resource}) + req.NoError(err) + req.Len(set, 1) + }) + + t.Run("search by action", func(t *testing.T) { + set, _, err := s.SearchActionlogs(ctx, actionlog.Filter{Action: action.Action}) + req.NoError(err) + req.Len(set, 1) + }) + +} diff --git a/store/tests/applications_test.go b/store/tests/applications_test.go new file mode 100644 index 000000000..4cacc8301 --- /dev/null +++ b/store/tests/applications_test.go @@ -0,0 +1,117 @@ +package tests + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/id" + "github.com/cortezaproject/corteza-server/pkg/rh" + "github.com/cortezaproject/corteza-server/system/types" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +func testApplications(t *testing.T, s applicationsStore) { + var ( + ctx = context.Background() + req = require.New(t) + + makeNew = func(name string) *types.Application { + // minimum data set for new application + return &types.Application{ + ID: id.Next(), + CreatedAt: time.Now(), + Name: name, + Unify: &types.ApplicationUnify{}, + } + } + ) + + t.Run("create", func(t *testing.T) { + application := makeNew("ApplicationCRUD") + req.NoError(s.CreateApplication(ctx, application)) + }) + + t.Run("lookup by ID", func(t *testing.T) { + application := makeNew("look up by id") + req.NoError(s.CreateApplication(ctx, application)) + fetched, err := s.LookupApplicationByID(ctx, application.ID) + req.NoError(err) + req.Equal(application.Name, fetched.Name) + req.Equal(application.ID, fetched.ID) + req.NotNil(fetched.CreatedAt) + req.Nil(fetched.UpdatedAt) + req.Nil(fetched.DeletedAt) + }) + + t.Run("remove", func(t *testing.T) { + application := makeNew("remove") + req.NoError(s.CreateApplication(ctx, application)) + req.NoError(s.RemoveApplication(ctx)) + }) + + t.Run("remove by ID", func(t *testing.T) { + application := makeNew("remove by id") + req.NoError(s.CreateApplication(ctx, application)) + req.NoError(s.RemoveApplication(ctx)) + }) + + t.Run("update", func(t *testing.T) { + application := makeNew("update me") + req.NoError(s.CreateApplication(ctx, application)) + + application = &types.Application{ + ID: application.ID, + CreatedAt: application.CreatedAt, + Name: "ApplicationCRUD+2", + Unify: application.Unify, + } + req.NoError(s.UpdateApplication(ctx, application)) + + updated, err := s.LookupApplicationByID(ctx, application.ID) + req.NoError(err) + req.Equal(application.Name, updated.Name) + }) + + t.Run("search", func(t *testing.T) { + prefill := []*types.Application{ + makeNew("/one-one"), + makeNew("/one-two"), + makeNew("/two-one"), + makeNew("/two-two"), + makeNew("/two-deleted"), + } + + count := len(prefill) + + prefill[4].DeletedAt = &prefill[4].CreatedAt + valid := count - 1 + + req.NoError(s.TruncateApplications(ctx)) + req.NoError(s.CreateApplication(ctx, prefill...)) + + // search for all valid + set, f, err := s.SearchApplications(ctx, types.ApplicationFilter{}) + req.NoError(err) + req.Len(set, valid) // we've deleted one + req.Equal(valid, int(f.Count)) + + // search for ALL + set, f, err = s.SearchApplications(ctx, types.ApplicationFilter{Deleted: rh.FilterStateInclusive}) + req.NoError(err) + req.Len(set, count) // we've deleted one + + // search for deleted only + set, f, err = s.SearchApplications(ctx, types.ApplicationFilter{Deleted: rh.FilterStateExclusive}) + req.NoError(err) + req.Len(set, 1) // we've deleted one + + set, f, err = s.SearchApplications(ctx, types.ApplicationFilter{Name: "/two-one"}) + req.NoError(err) + req.Len(set, 1) + + // find all prefixed + set, f, err = s.SearchApplications(ctx, types.ApplicationFilter{Query: "/two"}) + req.NoError(err) + req.Len(set, 2) + }) +} diff --git a/store/tests/compose_charts_test.go b/store/tests/compose_charts_test.go new file mode 100644 index 000000000..7f1e58d25 --- /dev/null +++ b/store/tests/compose_charts_test.go @@ -0,0 +1,127 @@ +package tests + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/pkg/id" + "github.com/cortezaproject/corteza-server/pkg/rh" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +func testComposeCharts(t *testing.T, s composeChartsStore) { + var ( + ctx = context.Background() + req = require.New(t) + + namespaceID = id.Next() + + makeNew = func(name, handle string) *types.Chart { + // minimum data set for new composeChart + return &types.Chart{ + ID: id.Next(), + NamespaceID: namespaceID, + CreatedAt: time.Now(), + Name: name, + Handle: handle, + } + } + ) + + t.Run("create", func(t *testing.T) { + composeChart := makeNew("ComposeChartCRUD", "compose-chart-crud") + req.NoError(s.CreateComposeChart(ctx, composeChart)) + }) + + t.Run("create with duplicate handle", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("lookup by ID", func(t *testing.T) { + composeChart := makeNew("look up by id", "look-up-by-id") + req.NoError(s.CreateComposeChart(ctx, composeChart)) + fetched, err := s.LookupComposeChartByID(ctx, composeChart.ID) + req.NoError(err) + req.Equal(composeChart.Name, fetched.Name) + req.Equal(composeChart.ID, fetched.ID) + req.NotNil(fetched.CreatedAt) + req.Nil(fetched.UpdatedAt) + req.Nil(fetched.DeletedAt) + }) + + t.Run("remove", func(t *testing.T) { + composeChart := makeNew("remove", "remove") + req.NoError(s.CreateComposeChart(ctx, composeChart)) + req.NoError(s.RemoveComposeChart(ctx)) + }) + + t.Run("remove by ID", func(t *testing.T) { + composeChart := makeNew("remove by id", "remove-by-id") + req.NoError(s.CreateComposeChart(ctx, composeChart)) + req.NoError(s.RemoveComposeChart(ctx)) + }) + + t.Run("update", func(t *testing.T) { + composeChart := makeNew("update me", "update-me") + req.NoError(s.CreateComposeChart(ctx, composeChart)) + + composeChart = &types.Chart{ + ID: composeChart.ID, + CreatedAt: composeChart.CreatedAt, + Name: "ComposeChartCRUD+2", + } + req.NoError(s.UpdateComposeChart(ctx, composeChart)) + + updated, err := s.LookupComposeChartByID(ctx, composeChart.ID) + req.NoError(err) + req.Equal(composeChart.Name, updated.Name) + }) + + t.Run("update with duplicate handle", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("search", func(t *testing.T) { + prefill := []*types.Chart{ + makeNew("/one-one", "chart-1-1"), + makeNew("/one-two", "chart-1-2"), + makeNew("/two-one", "chart-2-1"), + makeNew("/two-two", "chart-2-2"), + makeNew("/two-deleted", "chart-2-d"), + } + + count := len(prefill) + + prefill[4].DeletedAt = &prefill[4].CreatedAt + valid := count - 1 + + req.NoError(s.TruncateComposeCharts(ctx)) + req.NoError(s.CreateComposeChart(ctx, prefill...)) + + // search for all valid + set, f, err := s.SearchComposeCharts(ctx, types.ChartFilter{}) + req.NoError(err) + req.Len(set, valid) // we've deleted one + req.Equal(valid, int(f.Count)) + + // search for ALL + set, f, err = s.SearchComposeCharts(ctx, types.ChartFilter{Deleted: rh.FilterStateInclusive}) + req.NoError(err) + req.Len(set, count) // we've deleted one + + // search for deleted only + set, f, err = s.SearchComposeCharts(ctx, types.ChartFilter{Deleted: rh.FilterStateExclusive}) + req.NoError(err) + req.Len(set, 1) // we've deleted one + + set, f, err = s.SearchComposeCharts(ctx, types.ChartFilter{Handle: "chart-2-1"}) + req.NoError(err) + req.Len(set, 1) + + // find all prefixed + set, f, err = s.SearchComposeCharts(ctx, types.ChartFilter{Query: "/two-"}) + req.NoError(err) + req.Len(set, 2) + }) +} diff --git a/store/tests/compose_module_fields_test.go b/store/tests/compose_module_fields_test.go new file mode 100644 index 000000000..6e0aab639 --- /dev/null +++ b/store/tests/compose_module_fields_test.go @@ -0,0 +1,66 @@ +package tests + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/pkg/id" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +func testComposeModuleFields(t *testing.T, s composeModuleFieldsStore) { + var ( + ctx = context.Background() + req = require.New(t) + + moduleID = id.Next() + + makeNew = func(name, handle string) *types.ModuleField { + // minimum data set for new composeModuleField + return &types.ModuleField{ + ID: id.Next(), + ModuleID: moduleID, + CreatedAt: time.Now(), + Name: name, + } + } + ) + + t.Run("create", func(t *testing.T) { + composeModuleField := makeNew("ComposeModuleFieldCRUD", "compose-moduleField-crud") + req.NoError(s.CreateComposeModuleField(ctx, composeModuleField)) + }) + + t.Run("create with duplicate handle", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("remove", func(t *testing.T) { + composeModuleField := makeNew("remove", "remove") + req.NoError(s.CreateComposeModuleField(ctx, composeModuleField)) + req.NoError(s.RemoveComposeModuleField(ctx)) + }) + + t.Run("remove by ID", func(t *testing.T) { + composeModuleField := makeNew("remove by id", "remove-by-id") + req.NoError(s.CreateComposeModuleField(ctx, composeModuleField)) + req.NoError(s.RemoveComposeModuleField(ctx)) + }) + + t.Run("update", func(t *testing.T) { + composeModuleField := makeNew("update me", "update-me") + req.NoError(s.CreateComposeModuleField(ctx, composeModuleField)) + + composeModuleField = &types.ModuleField{ + ID: composeModuleField.ID, + CreatedAt: composeModuleField.CreatedAt, + Name: "ComposeModuleFieldCRUD+2", + } + req.NoError(s.UpdateComposeModuleField(ctx, composeModuleField)) + }) + + t.Run("update with duplicate handle", func(t *testing.T) { + t.Skip("not implemented") + }) +} diff --git a/store/tests/compose_modules_test.go b/store/tests/compose_modules_test.go new file mode 100644 index 000000000..5d32231ec --- /dev/null +++ b/store/tests/compose_modules_test.go @@ -0,0 +1,127 @@ +package tests + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/pkg/id" + "github.com/cortezaproject/corteza-server/pkg/rh" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +func testComposeModules(t *testing.T, s composeModulesStore) { + var ( + ctx = context.Background() + req = require.New(t) + + namespaceID = id.Next() + + makeNew = func(name, handle string) *types.Module { + // minimum data set for new composeModule + return &types.Module{ + ID: id.Next(), + NamespaceID: namespaceID, + CreatedAt: time.Now(), + Name: name, + Handle: handle, + } + } + ) + + t.Run("create", func(t *testing.T) { + composeModule := makeNew("ComposeModuleCRUD", "compose-module-crud") + req.NoError(s.CreateComposeModule(ctx, composeModule)) + }) + + t.Run("create with duplicate handle", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("lookup by ID", func(t *testing.T) { + composeModule := makeNew("look up by id", "look-up-by-id") + req.NoError(s.CreateComposeModule(ctx, composeModule)) + fetched, err := s.LookupComposeModuleByID(ctx, composeModule.ID) + req.NoError(err) + req.Equal(composeModule.Name, fetched.Name) + req.Equal(composeModule.ID, fetched.ID) + req.NotNil(fetched.CreatedAt) + req.Nil(fetched.UpdatedAt) + req.Nil(fetched.DeletedAt) + }) + + t.Run("remove", func(t *testing.T) { + composeModule := makeNew("remove", "remove") + req.NoError(s.CreateComposeModule(ctx, composeModule)) + req.NoError(s.RemoveComposeModule(ctx)) + }) + + t.Run("remove by ID", func(t *testing.T) { + composeModule := makeNew("remove by id", "remove-by-id") + req.NoError(s.CreateComposeModule(ctx, composeModule)) + req.NoError(s.RemoveComposeModule(ctx)) + }) + + t.Run("update", func(t *testing.T) { + composeModule := makeNew("update me", "update-me") + req.NoError(s.CreateComposeModule(ctx, composeModule)) + + composeModule = &types.Module{ + ID: composeModule.ID, + CreatedAt: composeModule.CreatedAt, + Name: "ComposeModuleCRUD+2", + } + req.NoError(s.UpdateComposeModule(ctx, composeModule)) + + updated, err := s.LookupComposeModuleByID(ctx, composeModule.ID) + req.NoError(err) + req.Equal(composeModule.Name, updated.Name) + }) + + t.Run("update with duplicate handle", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("search", func(t *testing.T) { + prefill := []*types.Module{ + makeNew("/one-one", "module-1-1"), + makeNew("/one-two", "module-1-2"), + makeNew("/two-one", "module-2-1"), + makeNew("/two-two", "module-2-2"), + makeNew("/two-deleted", "module-2-d"), + } + + count := len(prefill) + + prefill[4].DeletedAt = &prefill[4].CreatedAt + valid := count - 1 + + req.NoError(s.TruncateComposeModules(ctx)) + req.NoError(s.CreateComposeModule(ctx, prefill...)) + + // search for all valid + set, f, err := s.SearchComposeModules(ctx, types.ModuleFilter{}) + req.NoError(err) + req.Len(set, valid) // we've deleted one + req.Equal(valid, int(f.Count)) + + // search for ALL + set, f, err = s.SearchComposeModules(ctx, types.ModuleFilter{Deleted: rh.FilterStateInclusive}) + req.NoError(err) + req.Len(set, count) // we've deleted one + + // search for deleted only + set, f, err = s.SearchComposeModules(ctx, types.ModuleFilter{Deleted: rh.FilterStateExclusive}) + req.NoError(err) + req.Len(set, 1) // we've deleted one + + set, f, err = s.SearchComposeModules(ctx, types.ModuleFilter{Handle: "module-2-1"}) + req.NoError(err) + req.Len(set, 1) + + // find all prefixed + set, f, err = s.SearchComposeModules(ctx, types.ModuleFilter{Query: "/two-"}) + req.NoError(err) + req.Len(set, 2) + }) +} diff --git a/store/tests/compose_namespaces_test.go b/store/tests/compose_namespaces_test.go new file mode 100644 index 000000000..4f9153c57 --- /dev/null +++ b/store/tests/compose_namespaces_test.go @@ -0,0 +1,124 @@ +package tests + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/pkg/id" + "github.com/cortezaproject/corteza-server/pkg/rh" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +func testComposeNamespaces(t *testing.T, s composeNamespacesStore) { + var ( + ctx = context.Background() + req = require.New(t) + + makeNew = func(name, slug string) *types.Namespace { + // minimum data set for new composeNamespace + return &types.Namespace{ + ID: id.Next(), + CreatedAt: time.Now(), + Name: name, + Slug: slug, + } + } + ) + + t.Run("create", func(t *testing.T) { + composeNamespace := makeNew("ComposeNamespaceCRUD", "compose-namespace-crud") + req.NoError(s.CreateComposeNamespace(ctx, composeNamespace)) + }) + + t.Run("create with duplicate slug", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("lookup by ID", func(t *testing.T) { + composeNamespace := makeNew("look up by id", "look-up-by-id") + req.NoError(s.CreateComposeNamespace(ctx, composeNamespace)) + fetched, err := s.LookupComposeNamespaceByID(ctx, composeNamespace.ID) + req.NoError(err) + req.Equal(composeNamespace.Name, fetched.Name) + req.Equal(composeNamespace.ID, fetched.ID) + req.NotNil(fetched.CreatedAt) + req.Nil(fetched.UpdatedAt) + req.Nil(fetched.DeletedAt) + }) + + t.Run("remove", func(t *testing.T) { + composeNamespace := makeNew("remove", "remove") + req.NoError(s.CreateComposeNamespace(ctx, composeNamespace)) + req.NoError(s.RemoveComposeNamespace(ctx)) + }) + + t.Run("remove by ID", func(t *testing.T) { + composeNamespace := makeNew("remove by id", "remove-by-id") + req.NoError(s.CreateComposeNamespace(ctx, composeNamespace)) + req.NoError(s.RemoveComposeNamespace(ctx)) + }) + + t.Run("update", func(t *testing.T) { + composeNamespace := makeNew("update me", "update-me") + req.NoError(s.CreateComposeNamespace(ctx, composeNamespace)) + + composeNamespace = &types.Namespace{ + ID: composeNamespace.ID, + CreatedAt: composeNamespace.CreatedAt, + Name: "ComposeNamespaceCRUD+2", + } + req.NoError(s.UpdateComposeNamespace(ctx, composeNamespace)) + + updated, err := s.LookupComposeNamespaceByID(ctx, composeNamespace.ID) + req.NoError(err) + req.Equal(composeNamespace.Name, updated.Name) + }) + + t.Run("update with duplicate slug", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("search", func(t *testing.T) { + prefill := []*types.Namespace{ + makeNew("/one-one", "namespace-1-1"), + makeNew("/one-two", "namespace-1-2"), + makeNew("/two-one", "namespace-2-1"), + makeNew("/two-two", "namespace-2-2"), + makeNew("/two-deleted", "namespace-2-d"), + } + + count := len(prefill) + + prefill[4].DeletedAt = &prefill[4].CreatedAt + valid := count - 1 + + req.NoError(s.TruncateComposeNamespaces(ctx)) + req.NoError(s.CreateComposeNamespace(ctx, prefill...)) + + // search for all valid + set, f, err := s.SearchComposeNamespaces(ctx, types.NamespaceFilter{}) + req.NoError(err) + req.Len(set, valid) // we've deleted one + req.Equal(valid, int(f.Count)) + + // search for ALL + set, f, err = s.SearchComposeNamespaces(ctx, types.NamespaceFilter{Deleted: rh.FilterStateInclusive}) + req.NoError(err) + req.Len(set, count) // we've deleted one + + // search for deleted only + set, f, err = s.SearchComposeNamespaces(ctx, types.NamespaceFilter{Deleted: rh.FilterStateExclusive}) + req.NoError(err) + req.Len(set, 1) // we've deleted one + + set, f, err = s.SearchComposeNamespaces(ctx, types.NamespaceFilter{Slug: "namespace-2-1"}) + req.NoError(err) + req.Len(set, 1) + + // find all prefixed + set, f, err = s.SearchComposeNamespaces(ctx, types.NamespaceFilter{Query: "/two-"}) + req.NoError(err) + req.Len(set, 2) + }) +} diff --git a/store/tests/compose_pages_test.go b/store/tests/compose_pages_test.go new file mode 100644 index 000000000..0a3b39565 --- /dev/null +++ b/store/tests/compose_pages_test.go @@ -0,0 +1,127 @@ +package tests + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/pkg/id" + "github.com/cortezaproject/corteza-server/pkg/rh" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +func testComposePages(t *testing.T, s composePagesStore) { + var ( + ctx = context.Background() + req = require.New(t) + + namespaceID = id.Next() + + makeNew = func(title, handle string) *types.Page { + // minimum data set for new composePage + return &types.Page{ + ID: id.Next(), + NamespaceID: namespaceID, + CreatedAt: time.Now(), + Title: title, + Handle: handle, + } + } + ) + + t.Run("create", func(t *testing.T) { + composePage := makeNew("ComposePageCRUD", "compose-page-crud") + req.NoError(s.CreateComposePage(ctx, composePage)) + }) + + t.Run("create with duplicate handle", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("lookup by ID", func(t *testing.T) { + composePage := makeNew("look up by id", "look-up-by-id") + req.NoError(s.CreateComposePage(ctx, composePage)) + fetched, err := s.LookupComposePageByID(ctx, composePage.ID) + req.NoError(err) + req.Equal(composePage.Title, fetched.Title) + req.Equal(composePage.ID, fetched.ID) + req.NotNil(fetched.CreatedAt) + req.Nil(fetched.UpdatedAt) + req.Nil(fetched.DeletedAt) + }) + + t.Run("remove", func(t *testing.T) { + composePage := makeNew("remove", "remove") + req.NoError(s.CreateComposePage(ctx, composePage)) + req.NoError(s.RemoveComposePage(ctx)) + }) + + t.Run("remove by ID", func(t *testing.T) { + composePage := makeNew("remove by id", "remove-by-id") + req.NoError(s.CreateComposePage(ctx, composePage)) + req.NoError(s.RemoveComposePage(ctx)) + }) + + t.Run("update", func(t *testing.T) { + composePage := makeNew("update me", "update-me") + req.NoError(s.CreateComposePage(ctx, composePage)) + + composePage = &types.Page{ + ID: composePage.ID, + CreatedAt: composePage.CreatedAt, + Title: "ComposePageCRUD+2", + } + req.NoError(s.UpdateComposePage(ctx, composePage)) + + updated, err := s.LookupComposePageByID(ctx, composePage.ID) + req.NoError(err) + req.Equal(composePage.Title, updated.Title) + }) + + t.Run("update with duplicate handle", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("search", func(t *testing.T) { + prefill := []*types.Page{ + makeNew("/one-one", "page-1-1"), + makeNew("/one-two", "page-1-2"), + makeNew("/two-one", "page-2-1"), + makeNew("/two-two", "page-2-2"), + makeNew("/two-deleted", "page-2-d"), + } + + count := len(prefill) + + prefill[4].DeletedAt = &prefill[4].CreatedAt + valid := count - 1 + + req.NoError(s.TruncateComposePages(ctx)) + req.NoError(s.CreateComposePage(ctx, prefill...)) + + // search for all valid + set, f, err := s.SearchComposePages(ctx, types.PageFilter{}) + req.NoError(err) + req.Len(set, valid) // we've deleted one + req.Equal(valid, int(f.Count)) + + // search for ALL + set, f, err = s.SearchComposePages(ctx, types.PageFilter{Deleted: rh.FilterStateInclusive}) + req.NoError(err) + req.Len(set, count) // we've deleted one + + // search for deleted only + set, f, err = s.SearchComposePages(ctx, types.PageFilter{Deleted: rh.FilterStateExclusive}) + req.NoError(err) + req.Len(set, 1) // we've deleted one + + set, f, err = s.SearchComposePages(ctx, types.PageFilter{Handle: "page-2-1"}) + req.NoError(err) + req.Len(set, 1) + + // find all prefixed + set, f, err = s.SearchComposePages(ctx, types.PageFilter{Query: "/two-"}) + req.NoError(err) + req.Len(set, 2) + }) +} diff --git a/store/tests/compose_records_test.go b/store/tests/compose_records_test.go new file mode 100644 index 000000000..4f8195065 --- /dev/null +++ b/store/tests/compose_records_test.go @@ -0,0 +1,249 @@ +package tests + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/pkg/id" + "github.com/cortezaproject/corteza-server/pkg/rh" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +type ( + // For + composeRecordsStore interface { + SearchComposeRecords(ctx context.Context, m *types.Module, f types.RecordFilter) (types.RecordSet, types.RecordFilter, error) + LookupComposeRecordByID(ctx context.Context, m *types.Module, id uint64) (*types.Record, error) + CreateComposeRecord(ctx context.Context, m *types.Module, rr ...*types.Record) error + //CreateComposeRecordValue(ctx context.Context, m *types.Module, rr ...*types.RecordValue) error + UpdateComposeRecord(ctx context.Context, m *types.Module, rr ...*types.Record) error + //UpdateComposeRecordValue(ctx context.Context, m *types.Module, rr ...*types.RecordValue) error + //PartialUpdateComposeRecord(ctx context.Context, m *types.Module, onlyColumns []string, rr ...*types.Record) error + //PartialUpdateComposeRecordValue(ctx context.Context, m *types.Module, rr ...*types.RecordValue) error + RemoveComposeRecord(ctx context.Context, m *types.Module, rr ...*types.Record) error + //RemoveComposeRecordValue(ctx context.Context, m *types.Module, rr ...*types.RecordValue) error + //RemoveComposeRecordByID(ctx context.Context, m *types.Module, ID uint64) error + //RemoveComposeRecordValueByRecordID(ctx context.Context, m *types.Module, recordID uint64, place int, name string) error + TruncateComposeRecords(ctx context.Context, m *types.Module) error + //TruncateComposeRecordValues(ctx context.Context, m *types.Module) error + //ExecUpdateComposeRecords(ctx context.Context, m *types.Module, cnd squirrel.Sqlizer, set store.Payload) error + //ExecUpdateComposeRecordValues(ctx context.Context, m *types.Module, cnd squirrel.Sqlizer, set store.Payload) error + //ComposeRecordLookup(ctx context.Context, m *types.Module, cnd squirrel.Sqlizer) (*types.Record, error) + //ComposeRecordValueLookup(ctx context.Context, m *types.Module, cnd squirrel.Sqlizer) (*types.RecordValue, error) + //QueryComposeRecords(m *types.Module) squirrel.SelectBuilder + //QueryComposeRecordValues(m *types.Module) squirrel.SelectBuilder + } +) + +func testComposeRecords(t *testing.T, s composeRecordsStore) { + var ( + ctx = context.Background() + req = require.New(t) + + mod = &types.Module{ + ID: id.Next(), + NamespaceID: id.Next(), + Handle: "", + Name: "testComposeRecords", + CreatedAt: time.Now(), + } + + makeNew = func() *types.Record { + // minimum data set for new composeRecord + return &types.Record{ + ID: id.Next(), + NamespaceID: mod.NamespaceID, + ModuleID: mod.ID, + CreatedAt: time.Now(), + } + } + ) + + t.Run("create", func(t *testing.T) { + composeRecord := makeNew() + req.NoError(s.CreateComposeRecord(ctx, mod, composeRecord)) + }) + + t.Run("create with duplicate handle", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("lookup by ID", func(t *testing.T) { + composeRecord := makeNew() + req.NoError(s.CreateComposeRecord(ctx, mod, composeRecord)) + fetched, err := s.LookupComposeRecordByID(ctx, mod, composeRecord.ID) + req.NoError(err) + req.Equal(composeRecord.ID, fetched.ID) + req.NotNil(fetched.CreatedAt) + req.Nil(fetched.UpdatedAt) + req.Nil(fetched.DeletedAt) + }) + + t.Run("remove", func(t *testing.T) { + composeRecord := makeNew() + req.NoError(s.CreateComposeRecord(ctx, mod, composeRecord)) + req.NoError(s.RemoveComposeRecord(ctx, mod)) + }) + + t.Run("remove by ID", func(t *testing.T) { + composeRecord := makeNew() + req.NoError(s.CreateComposeRecord(ctx, mod, composeRecord)) + req.NoError(s.RemoveComposeRecord(ctx, mod)) + }) + + t.Run("update", func(t *testing.T) { + composeRecord := makeNew() + req.NoError(s.CreateComposeRecord(ctx, mod, composeRecord)) + + composeRecord = &types.Record{ + ID: composeRecord.ID, + CreatedAt: composeRecord.CreatedAt, + OwnedBy: 1, + } + req.NoError(s.UpdateComposeRecord(ctx, mod, composeRecord)) + + updated, err := s.LookupComposeRecordByID(ctx, mod, composeRecord.ID) + req.NoError(err) + req.Equal(composeRecord.OwnedBy, updated.OwnedBy) + }) + + t.Run("search", func(t *testing.T) { + prefill := []*types.Record{ + makeNew(), + makeNew(), + makeNew(), + makeNew(), + makeNew(), + } + + count := len(prefill) + + prefill[4].DeletedAt = &prefill[4].CreatedAt + valid := count - 1 + + req.NoError(s.TruncateComposeRecords(ctx, mod)) + req.NoError(s.CreateComposeRecord(ctx, mod, prefill...)) + + // search for all valid + set, f, err := s.SearchComposeRecords(ctx, mod, types.RecordFilter{}) + req.NoError(err) + req.Len(set, valid) // we've deleted one + req.Equal(valid, int(f.Count)) + + // search for ALL + set, f, err = s.SearchComposeRecords(ctx, mod, types.RecordFilter{Deleted: rh.FilterStateInclusive}) + req.NoError(err) + req.Len(set, count) // we've deleted one + + // search for deleted only + set, f, err = s.SearchComposeRecords(ctx, mod, types.RecordFilter{Deleted: rh.FilterStateExclusive}) + req.NoError(err) + req.Len(set, 1) // we've deleted one + }) + + t.Run("filtered search", func(t *testing.T) { + // testComposeRecordsSearch(t, s) + }) +} + +//func testComposeRecordsSearch(t *testing.T, s store.ComposeRecords) { +// m := &types.Module{ +// ID: 123, +// NamespaceID: 456, +// Fields: types.ModuleFieldSet{ +// &types.ModuleField{Name: "foo"}, +// &types.ModuleField{Name: "bar"}, +// &types.ModuleField{Name: "booly", Kind: "Bool"}, +// }, +// } +// +// ttc := []struct { +// name string +// f types.RecordFilter +// match []string +// noMatch []string +// args []interface{} +// err string +// }{ +// { +// name: "default filter", +// match: []string{ +// "SELECT r.id, r.module_id, r.rel_namespace, r.owned_by, r.created_at, " + +// "r.created_by, r.updated_at, r.updated_by, r.deleted_at, r.deleted_by " + +// "FROM compose_record AS r " + +// "WHERE r.module_id = ? AND r.rel_namespace = ? AND r.deleted_at IS NULL", +// }, +// }, +// { +// name: "simple query", +// f: types.RecordFilter{Query: "id = 5 AND foo = 7"}, +// match: []string{ +// "r.id = 5", +// "rv_foo.value = 7"}, +// args: []interface{}{"foo"}, +// }, +// { +// name: "sorting", +// f: types.RecordFilter{Sort: "id ASC, bar DESC"}, +// match: []string{ +// " r.id ASC", +// " rv_bar.value DESC", +// }, +// args: []interface{}{"bar"}, +// }, +// { +// name: "exclude deleted records (def. behaviour)", +// f: types.RecordFilter{Deleted: rh.FilterStateExcluded}, +// match: []string{" r.deleted_at IS "}, +// }, +// { +// name: "include deleted records", +// f: types.RecordFilter{Deleted: rh.FilterStateInclusive}, +// noMatch: []string{" r.deleted_at IS NULL "}, +// }, +// { +// name: "only deleted record", +// f: types.RecordFilter{Deleted: rh.FilterStateExclusive}, +// match: []string{" r.deleted_at IS NOT NULL"}, +// }, +// { +// name: "boolean", +// f: types.RecordFilter{Query: "booly"}, +// match: []string{"(rv_booly.value NOT IN ("}, +// args: []interface{}{"booly"}, +// }, +// } +// +// for _, tc := range ttc { +// t.Run(tc.name, func(t *testing.T) { +// req := require.New(t) +// sb, err := s.query(m, tc.f) +// +// if tc.err != nil { +// req.Error(err, tc.err, "buildQuery(%+v) did not return an expected error %q but %q", tc.f, tc.err, err) +// } else { +// req.NoError(err,"buildQuery(%+v) returned an unexpected error: %v", tc.f, err) +// } +// +// sql, args, err := sb.ToSql() +// +// for _, m := range tc.match { +// require.True(t, strings.Contains(sql, m), +// "assertion failed; query %q \n "+ +// " did not contain %q", sql, m) +// } +// +// for _, m := range tc.noMatch { +// require.False(t, strings.Contains(sql, m), +// "assertion failed; query %q \n "+ +// " must not contain %q", sql, m) +// } +// +// tc.args = append(tc.args, m.ID, m.NamespaceID) +// require.True(t, fmt.Sprintf("%+v", args) == fmt.Sprintf("%+v", tc.args), +// "assertion failed; args %+v \n "+ +// " do not match expected %+v", args, tc.args) +// }) +// } +//} diff --git a/store/tests/credentials_test.go b/store/tests/credentials_test.go new file mode 100644 index 000000000..e81009c70 --- /dev/null +++ b/store/tests/credentials_test.go @@ -0,0 +1,67 @@ +package tests + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" + _ "github.com/joho/godotenv/autoload" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +func testCredentials(t *testing.T, s credentialsStore) { + var ( + ctx = context.Background() + req = require.New(t) + credentials *types.Credentials + //err error + ) + + t.Run("create", func(t *testing.T) { + credentials = &types.Credentials{ + ID: 42, + CreatedAt: time.Now(), + Label: "CredentialsCRUD", + } + req.NoError(s.CreateCredentials(ctx, credentials)) + }) + + t.Run("lookup by ID", func(t *testing.T) { + fetched, err := s.LookupCredentialsByID(ctx, credentials.ID) + req.NoError(err) + req.Equal(credentials.ID, fetched.ID) + req.NotNil(fetched.CreatedAt) + req.Nil(fetched.UpdatedAt) + req.Nil(fetched.DeletedAt) + }) + + t.Run("update", func(t *testing.T) { + + credentials = &types.Credentials{ + ID: 42, + CreatedAt: time.Now(), + Label: "CredentialsCRUD+2", + } + req.NoError(s.UpdateCredentials(ctx, credentials)) + }) + + //t.Run("delete/undelete", func(t *testing.T) { + // ID := credentials.ID + // credentials, err = s.LookupCredentialsByID(ctx, ID) + // req.NoError(err) + // + // req.NoError(s.DeleteCredentialsByID(ctx, ID)) + // credentials, err = s.LookupCredentialsByID(ctx, ID) + // req.NoError(err) + // req.NotNil(credentials.DeletedAt) + // + // req.NoError(s.UndeleteCredentialsByID(ctx, ID)) + // credentials, err = s.LookupCredentialsByID(ctx, ID) + // req.NoError(err) + // req.Nil(credentials.DeletedAt) + //}) + + t.Run("search by *", func(t *testing.T) { + t.Skip("not implemented") + }) +} diff --git a/store/tests/gen_test.go b/store/tests/gen_test.go new file mode 100644 index 000000000..0b4190cf6 --- /dev/null +++ b/store/tests/gen_test.go @@ -0,0 +1,115 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// + +import ( + "context" + "github.com/stretchr/testify/require" + "testing" +) + +func testAllGenerated(t *testing.T, all interface{}) { + + // Run generated tests for Actionlog + t.Run("Actionlog", func(t *testing.T) { + var s = all.(actionlogsStore) + require.New(t).NoError(s.TruncateActionlogs(context.Background())) + testActionlog(t, s) + }) + + // Run generated tests for Applications + t.Run("Applications", func(t *testing.T) { + var s = all.(applicationsStore) + require.New(t).NoError(s.TruncateApplications(context.Background())) + testApplications(t, s) + }) + + // Run generated tests for ComposeCharts + t.Run("ComposeCharts", func(t *testing.T) { + var s = all.(composeChartsStore) + require.New(t).NoError(s.TruncateComposeCharts(context.Background())) + testComposeCharts(t, s) + }) + + // Run generated tests for ComposeModuleFields + t.Run("ComposeModuleFields", func(t *testing.T) { + var s = all.(composeModuleFieldsStore) + require.New(t).NoError(s.TruncateComposeModuleFields(context.Background())) + testComposeModuleFields(t, s) + }) + + // Run generated tests for ComposeModules + t.Run("ComposeModules", func(t *testing.T) { + var s = all.(composeModulesStore) + require.New(t).NoError(s.TruncateComposeModules(context.Background())) + testComposeModules(t, s) + }) + + // Run generated tests for ComposeNamespaces + t.Run("ComposeNamespaces", func(t *testing.T) { + var s = all.(composeNamespacesStore) + require.New(t).NoError(s.TruncateComposeNamespaces(context.Background())) + testComposeNamespaces(t, s) + }) + + // Run generated tests for ComposePages + t.Run("ComposePages", func(t *testing.T) { + var s = all.(composePagesStore) + require.New(t).NoError(s.TruncateComposePages(context.Background())) + testComposePages(t, s) + }) + + // Run generated tests for Credentials + t.Run("Credentials", func(t *testing.T) { + var s = all.(credentialsStore) + require.New(t).NoError(s.TruncateCredentials(context.Background())) + testCredentials(t, s) + }) + + // Run generated tests for RbacRules + t.Run("RbacRules", func(t *testing.T) { + var s = all.(rbacRulesStore) + require.New(t).NoError(s.TruncateRbacRules(context.Background())) + testRbacRules(t, s) + }) + + // Run generated tests for Reminders + t.Run("Reminders", func(t *testing.T) { + var s = all.(remindersStore) + require.New(t).NoError(s.TruncateReminders(context.Background())) + testReminders(t, s) + }) + + // Run generated tests for Roles + t.Run("Roles", func(t *testing.T) { + var s = all.(rolesStore) + require.New(t).NoError(s.TruncateRoles(context.Background())) + testRoles(t, s) + }) + + // Run generated tests for Settings + t.Run("Settings", func(t *testing.T) { + var s = all.(settingsStore) + require.New(t).NoError(s.TruncateSettings(context.Background())) + testSettings(t, s) + }) + + // Run generated tests for Attachment + t.Run("Attachment", func(t *testing.T) { + var s = all.(attachmentsStore) + require.New(t).NoError(s.TruncateAttachments(context.Background())) + testAttachment(t, s) + }) + + // Run generated tests for Users + t.Run("Users", func(t *testing.T) { + var s = all.(usersStore) + require.New(t).NoError(s.TruncateUsers(context.Background())) + testUsers(t, s) + }) + +} diff --git a/store/tests/main_test.go b/store/tests/main_test.go new file mode 100644 index 000000000..2588b38d8 --- /dev/null +++ b/store/tests/main_test.go @@ -0,0 +1,107 @@ +package tests + +import ( + "context" + "github.com/cortezaproject/corteza-server/store/mysql" + "github.com/cortezaproject/corteza-server/store/pgsql" + "github.com/cortezaproject/corteza-server/store/sqlite" + "github.com/cortezaproject/corteza-server/tests/helpers" + _ "github.com/joho/godotenv/autoload" + "go.uber.org/zap" + "os" + "testing" +) + +func init() { + helpers.RecursiveDotEnvLoad() +} + +func Test_Store(t *testing.T) { + type ( + suite struct { + name string + dsnEnvKey string + init func(ctx context.Context, dsn string) (storeInterface, error) + } + + upgrader interface { + Upgrade(context.Context, *zap.Logger) error + } + ) + + var ( + ctx = context.Background() + + ss = []suite{ + { + name: "MySQL", + dsnEnvKey: "RDBMS_MYSQL_DSN", + init: func(ctx context.Context, dsn string) (storeInterface, error) { return mysql.New(ctx, dsn) }, + }, + { + name: "PostgreSQL", + dsnEnvKey: "RDBMS_PGSQL_DSN", + init: func(ctx context.Context, dsn string) (storeInterface, error) { return pgsql.New(ctx, dsn) }, + }, + { + name: "CockroachDB", + dsnEnvKey: "RDBMS_COCKROACHDB_DSN", + init: nil, + }, + { + name: "SQLite", + dsnEnvKey: "RDBMS_SQLITE_DSN", + init: func(ctx context.Context, dsn string) (storeInterface, error) { return sqlite.New(ctx, dsn) }, + }, + { + name: "InMemory", + dsnEnvKey: "MEMORY_DSN", + init: nil, + }, + { + name: "MongoDB", + dsnEnvKey: "MONGODB_DSN", + init: nil, + }, + { + name: "ElasticSearch", + dsnEnvKey: "ELASTICSEARCH_DSN", + init: nil, + }, + } + ) + + for _, s := range ss { + t.Run(s.name, func(t *testing.T) { + dsn, has := os.LookupEnv(s.dsnEnvKey) + if !has { + t.Skipf("no %s found, skipping %s store tests", s.dsnEnvKey, s.name) + return + } + + t.Logf("connecting to %s with %s", s.name, dsn) + + genericStore, err := s.init(ctx, dsn) + if err != nil { + t.Errorf("failed to initialize %s store: %s", s.name, err.Error()) + return + } + + if up, ok := genericStore.(upgrader); ok { + err = up.Upgrade(ctx, zap.NewNop()) + if err != nil { + t.Errorf("failed to upgrade %s store: %s", s.name, err.Error()) + return + } + } + + testAllGenerated(t, genericStore) + + t.Run("ComposeRecords", func(t *testing.T) { + var s = genericStore.(composeRecordsStore) + testComposeRecords(t, s) + }) + }) + } + +} diff --git a/store/tests/rbac_rules_test.go b/store/tests/rbac_rules_test.go new file mode 100644 index 000000000..c0cdf3b34 --- /dev/null +++ b/store/tests/rbac_rules_test.go @@ -0,0 +1,44 @@ +package tests + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/permissions" + _ "github.com/joho/godotenv/autoload" + "github.com/stretchr/testify/require" + "testing" +) + +func testRbacRules(t *testing.T, s rbacRulesStore) { + var ( + ctx = context.Background() + req = require.New(t) + + rule *permissions.Rule + ) + + t.Run("create", func(t *testing.T) { + rule = &permissions.Rule{ + RoleID: 42, + Resource: permissions.Resource("res"), + Operation: permissions.Operation("op"), + Access: permissions.Allow, + } + req.NoError(s.CreateRbacRule(ctx, rule)) + }) + + t.Run("update", func(t *testing.T) { + rule = &permissions.Rule{ + RoleID: 42, + Resource: permissions.Resource("res"), + Operation: permissions.Operation("op"), + Access: permissions.Allow, + } + req.NoError(s.UpdateRbacRule(ctx, rule)) + }) + + t.Run("search", func(t *testing.T) { + set, _, err := s.SearchRbacRules(ctx, permissions.RuleFilter{}) + req.NoError(err) + req.Len(set, 1) + }) +} diff --git a/store/tests/reminders_test.go b/store/tests/reminders_test.go new file mode 100644 index 000000000..d18bccbca --- /dev/null +++ b/store/tests/reminders_test.go @@ -0,0 +1,78 @@ +package tests + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" + _ "github.com/joho/godotenv/autoload" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +func testReminders(t *testing.T, s remindersStore) { + var ( + ctx = context.Background() + req = require.New(t) + + //err error + reminder *types.Reminder + ) + + t.Run("create", func(t *testing.T) { + reminder = &types.Reminder{ + ID: 42, + CreatedAt: time.Now(), + AssignedAt: time.Now(), + } + req.NoError(s.CreateReminder(ctx, reminder)) + }) + + t.Run("lookup by ID", func(t *testing.T) { + fetched, err := s.LookupReminderByID(ctx, reminder.ID) + req.NoError(err) + req.Equal(reminder.ID, fetched.ID) + req.NotNil(fetched.CreatedAt) + req.Nil(fetched.UpdatedAt) + req.Nil(fetched.DeletedAt) + }) + + t.Run("update", func(t *testing.T) { + reminder = &types.Reminder{ + ID: 42, + CreatedAt: time.Now(), + AssignedAt: time.Now(), + } + req.NoError(s.UpdateReminder(ctx, reminder)) + }) + + //t.Run("delete/undelete", func(t *testing.T) { + // ID := reminder.ID + // reminder, err = s.LookupReminderByID(ctx, ID) + // req.NoError(err) + // + // req.NoError(s.DeleteReminderByID(ctx, ID)) + // reminder, err = s.LookupReminderByID(ctx, ID) + // req.NoError(err) + // req.NotNil(reminder.DeletedAt) + // + // req.NoError(s.UndeleteReminderByID(ctx, ID)) + // reminder, err = s.LookupReminderByID(ctx, ID) + // req.NoError(err) + // req.Nil(reminder.DeletedAt) + //}) + + t.Run("search", func(t *testing.T) { + set, f, err := s.SearchReminders(ctx, types.ReminderFilter{}) + req.NoError(err) + req.Len(set, 1) + req.Equal(uint(1), f.Count) + }) + + t.Run("search by *", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("ordered search", func(t *testing.T) { + t.Skip("not implemented") + }) +} diff --git a/store/tests/roles_test.go b/store/tests/roles_test.go new file mode 100644 index 000000000..9baffeb44 --- /dev/null +++ b/store/tests/roles_test.go @@ -0,0 +1,112 @@ +package tests + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" + _ "github.com/joho/godotenv/autoload" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +func testRoles(t *testing.T, s rolesStore) { + var ( + ctx = context.Background() + req = require.New(t) + + //err error + role *types.Role + ) + + t.Run("create", func(t *testing.T) { + role = &types.Role{ + ID: 42, + CreatedAt: time.Now(), + Name: "RoleCRUD", + Handle: "rolecrud", + } + role.ArchivedAt = &role.CreatedAt + req.NoError(s.CreateRole(ctx, role)) + }) + + t.Run("lookup by ID", func(t *testing.T) { + fetched, err := s.LookupRoleByID(ctx, role.ID) + req.NoError(err) + req.Equal(role.Name, fetched.Name) + req.Equal(role.Handle, fetched.Handle) + req.Equal(role.ID, fetched.ID) + req.NotNil(fetched.ArchivedAt) + req.NotNil(fetched.CreatedAt) + req.Nil(fetched.UpdatedAt) + req.Nil(fetched.DeletedAt) + }) + + t.Run("update", func(t *testing.T) { + role = &types.Role{ + ID: 42, + CreatedAt: time.Now(), + Name: "RoleCRUD+2", + Handle: "rolecrud+2", + } + req.NoError(s.UpdateRole(ctx, role)) + }) + + //t.Run("delete/undelete", func(t *testing.T) { + // ID := role.ID + // role, err = s.LookupRoleByID(ctx, ID) + // req.NoError(err) + // + // req.NoError(s.DeleteRoleByID(ctx, ID)) + // role, err = s.LookupRoleByID(ctx, ID) + // req.NoError(err) + // req.NotNil(role.DeletedAt) + // + // req.NoError(s.UndeleteRoleByID(ctx, ID)) + // role, err = s.LookupRoleByID(ctx, ID) + // req.NoError(err) + // req.Nil(role.DeletedAt) + //}) + // + //t.Run("archive/unarchive", func(t *testing.T) { + // ID := role.ID + // req.NoError(s.ArchiveRoleByID(ctx, ID)) + // role, err = s.LookupRoleByID(ctx, ID) + // req.NoError(err) + // req.NotNil(role.ArchivedAt) + // + // req.NoError(s.UnarchiveRoleByID(ctx, ID)) + // role, err = s.LookupRoleByID(ctx, ID) + // req.NoError(err) + // req.Nil(role.ArchivedAt) + //}) + + t.Run("lookup by handle", func(t *testing.T) { + fetched, err := s.LookupRoleByHandle(ctx, role.Handle) + req.NoError(err) + req.Equal(role.ID, fetched.ID) + }) + + t.Run("search", func(t *testing.T) { + set, f, err := s.SearchRoles(ctx, types.RoleFilter{RoleID: []uint64{role.ID}}) + req.NoError(err) + req.Equal([]uint64{role.ID}, f.RoleID) + req.Len(set, 1) + req.Equal(uint(1), f.Count) + //req.Equal(set[0].ID, role.ID) + }) + + t.Run("search", func(t *testing.T) { + set, f, err := s.SearchRoles(ctx, types.RoleFilter{Name: role.Name}) + req.NoError(err) + req.Len(set, 1) + req.Equal(uint(1), f.Count) + }) + + t.Run("search by *", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("ordered search", func(t *testing.T) { + t.Skip("not implemented") + }) +} diff --git a/store/tests/settings_test.go b/store/tests/settings_test.go new file mode 100644 index 000000000..11453bb50 --- /dev/null +++ b/store/tests/settings_test.go @@ -0,0 +1,35 @@ +package tests + +import ( + "testing" +) + +func testSettings(t *testing.T, s settingsStore) { + t.Run("create", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("lookup by ID", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("update", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("delete/undelete", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("search", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("search by *", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("ordered search", func(t *testing.T) { + t.Skip("not implemented") + }) +} diff --git a/store/tests/store_interface.gen.go b/store/tests/store_interface.gen.go new file mode 100644 index 000000000..43500f927 --- /dev/null +++ b/store/tests/store_interface.gen.go @@ -0,0 +1,42 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/actionlog.yaml +// - store/applications.yaml +// - store/compose_charts.yaml +// - store/compose_module_fields.yaml +// - store/compose_modules.yaml +// - store/compose_namespaces.yaml +// - store/compose_pages.yaml +// - store/credentials.yaml +// - store/rbac_rules.yaml +// - store/reminders.yaml +// - store/roles.yaml +// - store/settings.yaml +// - store/system_attachments.yaml +// - store/users.yaml + +type ( + // Interface combines interfaces of all supported store interfaces + storeInterface interface { + actionlogsStore + applicationsStore + composeChartsStore + composeModuleFieldsStore + composeModulesStore + composeNamespacesStore + composePagesStore + credentialsStore + rbacRulesStore + remindersStore + rolesStore + settingsStore + attachmentsStore + usersStore + } +) diff --git a/store/tests/store_interface_actionlog.gen.go b/store/tests/store_interface_actionlog.gen.go new file mode 100644 index 000000000..eac543af7 --- /dev/null +++ b/store/tests/store_interface_actionlog.gen.go @@ -0,0 +1,27 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/actionlog.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/actionlog" +) + +type ( + actionlogsStore interface { + SearchActionlogs(ctx context.Context, f actionlog.Filter) (actionlog.ActionSet, actionlog.Filter, error) + CreateActionlog(ctx context.Context, rr ...*actionlog.Action) error + UpdateActionlog(ctx context.Context, rr ...*actionlog.Action) error + PartialUpdateActionlog(ctx context.Context, onlyColumns []string, rr ...*actionlog.Action) error + RemoveActionlog(ctx context.Context, rr ...*actionlog.Action) error + RemoveActionlogByID(ctx context.Context, ID uint64) error + + TruncateActionlogs(ctx context.Context) error + } +) diff --git a/store/tests/store_interface_applications.gen.go b/store/tests/store_interface_applications.gen.go new file mode 100644 index 000000000..c01efe25d --- /dev/null +++ b/store/tests/store_interface_applications.gen.go @@ -0,0 +1,28 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/applications.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + applicationsStore interface { + SearchApplications(ctx context.Context, f types.ApplicationFilter) (types.ApplicationSet, types.ApplicationFilter, error) + LookupApplicationByID(ctx context.Context, id uint64) (*types.Application, error) + CreateApplication(ctx context.Context, rr ...*types.Application) error + UpdateApplication(ctx context.Context, rr ...*types.Application) error + PartialUpdateApplication(ctx context.Context, onlyColumns []string, rr ...*types.Application) error + RemoveApplication(ctx context.Context, rr ...*types.Application) error + RemoveApplicationByID(ctx context.Context, ID uint64) error + + TruncateApplications(ctx context.Context) error + } +) diff --git a/store/tests/store_interface_compose_charts.gen.go b/store/tests/store_interface_compose_charts.gen.go new file mode 100644 index 000000000..70477d342 --- /dev/null +++ b/store/tests/store_interface_compose_charts.gen.go @@ -0,0 +1,29 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/compose_charts.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeChartsStore interface { + SearchComposeCharts(ctx context.Context, f types.ChartFilter) (types.ChartSet, types.ChartFilter, error) + LookupComposeChartByID(ctx context.Context, id uint64) (*types.Chart, error) + LookupComposeChartByHandle(ctx context.Context, handle string) (*types.Chart, error) + CreateComposeChart(ctx context.Context, rr ...*types.Chart) error + UpdateComposeChart(ctx context.Context, rr ...*types.Chart) error + PartialUpdateComposeChart(ctx context.Context, onlyColumns []string, rr ...*types.Chart) error + RemoveComposeChart(ctx context.Context, rr ...*types.Chart) error + RemoveComposeChartByID(ctx context.Context, ID uint64) error + + TruncateComposeCharts(ctx context.Context) error + } +) diff --git a/store/tests/store_interface_compose_module_fields.gen.go b/store/tests/store_interface_compose_module_fields.gen.go new file mode 100644 index 000000000..d7b646758 --- /dev/null +++ b/store/tests/store_interface_compose_module_fields.gen.go @@ -0,0 +1,26 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/compose_module_fields.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeModuleFieldsStore interface { + CreateComposeModuleField(ctx context.Context, rr ...*types.ModuleField) error + UpdateComposeModuleField(ctx context.Context, rr ...*types.ModuleField) error + PartialUpdateComposeModuleField(ctx context.Context, onlyColumns []string, rr ...*types.ModuleField) error + RemoveComposeModuleField(ctx context.Context, rr ...*types.ModuleField) error + RemoveComposeModuleFieldByID(ctx context.Context, ID uint64) error + + TruncateComposeModuleFields(ctx context.Context) error + } +) diff --git a/store/tests/store_interface_compose_modules.gen.go b/store/tests/store_interface_compose_modules.gen.go new file mode 100644 index 000000000..87e1a880b --- /dev/null +++ b/store/tests/store_interface_compose_modules.gen.go @@ -0,0 +1,29 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/compose_modules.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeModulesStore interface { + SearchComposeModules(ctx context.Context, f types.ModuleFilter) (types.ModuleSet, types.ModuleFilter, error) + LookupComposeModuleByHandle(ctx context.Context, handle string) (*types.Module, error) + LookupComposeModuleByID(ctx context.Context, id uint64) (*types.Module, error) + CreateComposeModule(ctx context.Context, rr ...*types.Module) error + UpdateComposeModule(ctx context.Context, rr ...*types.Module) error + PartialUpdateComposeModule(ctx context.Context, onlyColumns []string, rr ...*types.Module) error + RemoveComposeModule(ctx context.Context, rr ...*types.Module) error + RemoveComposeModuleByID(ctx context.Context, ID uint64) error + + TruncateComposeModules(ctx context.Context) error + } +) diff --git a/store/tests/store_interface_compose_namespaces.gen.go b/store/tests/store_interface_compose_namespaces.gen.go new file mode 100644 index 000000000..e200dc0ca --- /dev/null +++ b/store/tests/store_interface_compose_namespaces.gen.go @@ -0,0 +1,29 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/compose_namespaces.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composeNamespacesStore interface { + SearchComposeNamespaces(ctx context.Context, f types.NamespaceFilter) (types.NamespaceSet, types.NamespaceFilter, error) + LookupComposeNamespaceBySlug(ctx context.Context, slug string) (*types.Namespace, error) + LookupComposeNamespaceByID(ctx context.Context, id uint64) (*types.Namespace, error) + CreateComposeNamespace(ctx context.Context, rr ...*types.Namespace) error + UpdateComposeNamespace(ctx context.Context, rr ...*types.Namespace) error + PartialUpdateComposeNamespace(ctx context.Context, onlyColumns []string, rr ...*types.Namespace) error + RemoveComposeNamespace(ctx context.Context, rr ...*types.Namespace) error + RemoveComposeNamespaceByID(ctx context.Context, ID uint64) error + + TruncateComposeNamespaces(ctx context.Context) error + } +) diff --git a/store/tests/store_interface_compose_pages.gen.go b/store/tests/store_interface_compose_pages.gen.go new file mode 100644 index 000000000..bbd1b2475 --- /dev/null +++ b/store/tests/store_interface_compose_pages.gen.go @@ -0,0 +1,29 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/compose_pages.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/compose/types" +) + +type ( + composePagesStore interface { + SearchComposePages(ctx context.Context, f types.PageFilter) (types.PageSet, types.PageFilter, error) + LookupComposePageByHandle(ctx context.Context, handle string) (*types.Page, error) + LookupComposePageByID(ctx context.Context, id uint64) (*types.Page, error) + CreateComposePage(ctx context.Context, rr ...*types.Page) error + UpdateComposePage(ctx context.Context, rr ...*types.Page) error + PartialUpdateComposePage(ctx context.Context, onlyColumns []string, rr ...*types.Page) error + RemoveComposePage(ctx context.Context, rr ...*types.Page) error + RemoveComposePageByID(ctx context.Context, ID uint64) error + + TruncateComposePages(ctx context.Context) error + } +) diff --git a/store/tests/store_interface_credentials.gen.go b/store/tests/store_interface_credentials.gen.go new file mode 100644 index 000000000..d59e7d881 --- /dev/null +++ b/store/tests/store_interface_credentials.gen.go @@ -0,0 +1,28 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/credentials.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + credentialsStore interface { + SearchCredentials(ctx context.Context, f types.CredentialsFilter) (types.CredentialsSet, types.CredentialsFilter, error) + LookupCredentialsByID(ctx context.Context, id uint64) (*types.Credentials, error) + CreateCredentials(ctx context.Context, rr ...*types.Credentials) error + UpdateCredentials(ctx context.Context, rr ...*types.Credentials) error + PartialUpdateCredentials(ctx context.Context, onlyColumns []string, rr ...*types.Credentials) error + RemoveCredentials(ctx context.Context, rr ...*types.Credentials) error + RemoveCredentialsByID(ctx context.Context, ID uint64) error + + TruncateCredentials(ctx context.Context) error + } +) diff --git a/store/tests/store_interface_rbac_rules.gen.go b/store/tests/store_interface_rbac_rules.gen.go new file mode 100644 index 000000000..fad961e13 --- /dev/null +++ b/store/tests/store_interface_rbac_rules.gen.go @@ -0,0 +1,27 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/rbac_rules.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/permissions" +) + +type ( + rbacRulesStore interface { + SearchRbacRules(ctx context.Context, f permissions.RuleFilter) (permissions.RuleSet, permissions.RuleFilter, error) + CreateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + UpdateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + PartialUpdateRbacRule(ctx context.Context, onlyColumns []string, rr ...*permissions.Rule) error + RemoveRbacRule(ctx context.Context, rr ...*permissions.Rule) error + RemoveRbacRuleByRoleIDResourceOperation(ctx context.Context, roleID uint64, resource string, operation string) error + + TruncateRbacRules(ctx context.Context) error + } +) diff --git a/store/tests/store_interface_reminders.gen.go b/store/tests/store_interface_reminders.gen.go new file mode 100644 index 000000000..2eec909d7 --- /dev/null +++ b/store/tests/store_interface_reminders.gen.go @@ -0,0 +1,28 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/reminders.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + remindersStore interface { + SearchReminders(ctx context.Context, f types.ReminderFilter) (types.ReminderSet, types.ReminderFilter, error) + LookupReminderByID(ctx context.Context, id uint64) (*types.Reminder, error) + CreateReminder(ctx context.Context, rr ...*types.Reminder) error + UpdateReminder(ctx context.Context, rr ...*types.Reminder) error + PartialUpdateReminder(ctx context.Context, onlyColumns []string, rr ...*types.Reminder) error + RemoveReminder(ctx context.Context, rr ...*types.Reminder) error + RemoveReminderByID(ctx context.Context, ID uint64) error + + TruncateReminders(ctx context.Context) error + } +) diff --git a/store/tests/store_interface_roles.gen.go b/store/tests/store_interface_roles.gen.go new file mode 100644 index 000000000..2607796d1 --- /dev/null +++ b/store/tests/store_interface_roles.gen.go @@ -0,0 +1,30 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/roles.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + rolesStore interface { + SearchRoles(ctx context.Context, f types.RoleFilter) (types.RoleSet, types.RoleFilter, error) + LookupRoleByID(ctx context.Context, id uint64) (*types.Role, error) + LookupRoleByHandle(ctx context.Context, handle string) (*types.Role, error) + LookupRoleByName(ctx context.Context, name string) (*types.Role, error) + CreateRole(ctx context.Context, rr ...*types.Role) error + UpdateRole(ctx context.Context, rr ...*types.Role) error + PartialUpdateRole(ctx context.Context, onlyColumns []string, rr ...*types.Role) error + RemoveRole(ctx context.Context, rr ...*types.Role) error + RemoveRoleByID(ctx context.Context, ID uint64) error + + TruncateRoles(ctx context.Context) error + } +) diff --git a/store/tests/store_interface_settings.gen.go b/store/tests/store_interface_settings.gen.go new file mode 100644 index 000000000..03de17e86 --- /dev/null +++ b/store/tests/store_interface_settings.gen.go @@ -0,0 +1,28 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/settings.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + settingsStore interface { + SearchSettings(ctx context.Context, f types.SettingsFilter) (types.SettingValueSet, types.SettingsFilter, error) + LookupSettingByNameOwnedBy(ctx context.Context, name string, owned_by uint64) (*types.SettingValue, error) + CreateSetting(ctx context.Context, rr ...*types.SettingValue) error + UpdateSetting(ctx context.Context, rr ...*types.SettingValue) error + PartialUpdateSetting(ctx context.Context, onlyColumns []string, rr ...*types.SettingValue) error + RemoveSetting(ctx context.Context, rr ...*types.SettingValue) error + RemoveSettingByNameOwnedBy(ctx context.Context, name string, ownedBy uint64) error + + TruncateSettings(ctx context.Context) error + } +) diff --git a/store/tests/store_interface_system_attachments.gen.go b/store/tests/store_interface_system_attachments.gen.go new file mode 100644 index 000000000..f570ad993 --- /dev/null +++ b/store/tests/store_interface_system_attachments.gen.go @@ -0,0 +1,28 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/system_attachments.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + attachmentsStore interface { + SearchAttachments(ctx context.Context, f types.AttachmentFilter) (types.AttachmentSet, types.AttachmentFilter, error) + LookupAttachmentByID(ctx context.Context, id uint64) (*types.Attachment, error) + CreateAttachment(ctx context.Context, rr ...*types.Attachment) error + UpdateAttachment(ctx context.Context, rr ...*types.Attachment) error + PartialUpdateAttachment(ctx context.Context, onlyColumns []string, rr ...*types.Attachment) error + RemoveAttachment(ctx context.Context, rr ...*types.Attachment) error + RemoveAttachmentByID(ctx context.Context, ID uint64) error + + TruncateAttachments(ctx context.Context) error + } +) diff --git a/store/tests/store_interface_users.gen.go b/store/tests/store_interface_users.gen.go new file mode 100644 index 000000000..12d871810 --- /dev/null +++ b/store/tests/store_interface_users.gen.go @@ -0,0 +1,31 @@ +package tests + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/users.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + usersStore interface { + SearchUsers(ctx context.Context, f types.UserFilter) (types.UserSet, types.UserFilter, error) + LookupUserByID(ctx context.Context, id uint64) (*types.User, error) + LookupUserByEmail(ctx context.Context, email string) (*types.User, error) + LookupUserByHandle(ctx context.Context, handle string) (*types.User, error) + LookupUserByUsername(ctx context.Context, username string) (*types.User, error) + CreateUser(ctx context.Context, rr ...*types.User) error + UpdateUser(ctx context.Context, rr ...*types.User) error + PartialUpdateUser(ctx context.Context, onlyColumns []string, rr ...*types.User) error + RemoveUser(ctx context.Context, rr ...*types.User) error + RemoveUserByID(ctx context.Context, ID uint64) error + + TruncateUsers(ctx context.Context) error + } +) diff --git a/store/tests/system_attachments_test.go b/store/tests/system_attachments_test.go new file mode 100644 index 000000000..5eaca0d45 --- /dev/null +++ b/store/tests/system_attachments_test.go @@ -0,0 +1,60 @@ +package tests + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" + _ "github.com/joho/godotenv/autoload" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +func testAttachment(t *testing.T, s attachmentsStore) { + var ( + ctx = context.Background() + req = require.New(t) + + attachment *types.Attachment + ) + + t.Run("create", func(t *testing.T) { + attachment = &types.Attachment{ + ID: 42, + CreatedAt: time.Now(), + } + req.NoError(s.CreateAttachment(ctx, attachment)) + }) + + t.Run("lookup by ID", func(t *testing.T) { + fetched, err := s.LookupAttachmentByID(ctx, attachment.ID) + req.NoError(err) + req.Equal(attachment.ID, fetched.ID) + req.NotNil(fetched.CreatedAt) + req.Nil(fetched.UpdatedAt) + req.Nil(fetched.DeletedAt) + }) + + t.Run("update", func(t *testing.T) { + attachment = &types.Attachment{ + ID: 42, + CreatedAt: time.Now(), + } + req.NoError(s.UpdateAttachment(ctx, attachment)) + }) + + t.Run("search", func(t *testing.T) { + t.Skip("not implemented") + //set, f, err := s.SearchAttachments(ctx, types.AttachmentFilter{}) + //req.NoError(err) + //req.Len(set, 1) + //req.Equal(uint(1), f.Count) + }) + + t.Run("search by *", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("ordered search", func(t *testing.T) { + t.Skip("not implemented") + }) +} diff --git a/store/tests/users_test.go b/store/tests/users_test.go new file mode 100644 index 000000000..d2bbccec3 --- /dev/null +++ b/store/tests/users_test.go @@ -0,0 +1,157 @@ +package tests + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" + _ "github.com/joho/godotenv/autoload" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +func testUsers(t *testing.T, s usersStore) { + var ( + ctx = context.Background() + req = require.New(t) + + //err error + user *types.User + ) + + t.Run("create", func(t *testing.T) { + user = &types.User{ + ID: 42, + CreatedAt: time.Now(), + Email: "user-crud@crust.test", + Username: "UserCRUD", + Handle: "usercrud", + } + req.NoError(s.CreateUser(ctx, user)) + }) + + t.Run("lookup by ID", func(t *testing.T) { + fetched, err := s.LookupUserByID(ctx, user.ID) + req.NoError(err) + req.Equal(user.Email, fetched.Email) + req.Equal(user.Username, fetched.Username) + req.Equal(user.Handle, fetched.Handle) + req.Equal(user.ID, fetched.ID) + req.NotNil(fetched.CreatedAt) + req.Nil(fetched.UpdatedAt) + req.Nil(fetched.DeletedAt) + req.Nil(fetched.SuspendedAt) + }) + + t.Run("update", func(t *testing.T) { + user = &types.User{ + ID: 42, + CreatedAt: time.Now(), + Email: "user-crud+2@crust.test", + Username: "UserCRUD+2", + Handle: "usercrud+2", + } + req.NoError(s.UpdateUser(ctx, user)) + }) + + //t.Run("delete/undelete", func(t *testing.T) { + // ID := user.ID + // user, err = s.LookupUserByID(ctx, ID) + // req.NoError(err) + // + // req.NoError(s.DeleteUserByID(ctx, ID)) + // user, err = s.LookupUserByID(ctx, ID) + // req.NoError(err) + // req.NotNil(user.DeletedAt) + // + // req.NoError(s.UndeleteUserByID(ctx, ID)) + // user, err = s.LookupUserByID(ctx, ID) + // req.NoError(err) + // req.Nil(user.DeletedAt) + //}) + // + //t.Run("suspend/suspend", func(t *testing.T) { + // ID := user.ID + // req.NoError(s.SuspendUserByID(ctx, ID)) + // user, err = s.LookupUserByID(ctx, ID) + // req.NoError(err) + // req.NotNil(user.SuspendedAt) + // + // req.NoError(s.UnsuspendUserByID(ctx, ID)) + // user, err = s.LookupUserByID(ctx, ID) + // req.NoError(err) + // req.Nil(user.SuspendedAt) + //}) + + t.Run("lookup by email", func(t *testing.T) { + fetched, err := s.LookupUserByEmail(ctx, user.Email) + req.NoError(err) + req.Equal(user.Email, fetched.Email) + }) + + t.Run("lookup by handle", func(t *testing.T) { + fetched, err := s.LookupUserByHandle(ctx, user.Handle) + req.NoError(err) + req.Equal(user.ID, fetched.ID) + }) + + t.Run("lookup by nonexisting handle", func(t *testing.T) { + fetched, err := s.LookupUserByHandle(ctx, "no such handle") + req.EqualError(err, "not found") + req.Nil(fetched) + }) + + t.Run("lookup by username", func(t *testing.T) { + fetched, err := s.LookupUserByUsername(ctx, user.Username) + req.NoError(err) + req.Equal(user.ID, fetched.ID) + }) + + t.Run("search by ID", func(t *testing.T) { + set, f, err := s.SearchUsers(ctx, types.UserFilter{UserID: []uint64{user.ID}}) + req.NoError(err) + req.Equal([]uint64{user.ID}, f.UserID) + req.Len(set, 1) + req.Equal(uint(1), f.Count) + //req.Equal(set[0].ID, user.ID) + }) + + t.Run("search by email", func(t *testing.T) { + set, f, err := s.SearchUsers(ctx, types.UserFilter{Email: user.Email}) + req.NoError(err) + req.Len(set, 1) + req.Equal(uint(1), f.Count) + }) + + t.Run("search by username", func(t *testing.T) { + set, f, err := s.SearchUsers(ctx, types.UserFilter{Username: user.Username}) + req.NoError(err) + req.Len(set, 1) + req.Equal(uint(1), f.Count) + }) + + t.Run("search by query", func(t *testing.T) { + set, f, err := s.SearchUsers(ctx, types.UserFilter{Query: user.Handle}) + req.NoError(err) + req.Len(set, 1) + req.Equal(uint(1), f.Count) + }) + + t.Run("search by username", func(t *testing.T) { + set, f, err := s.SearchUsers(ctx, types.UserFilter{Username: "no such username"}) + req.NoError(err) + req.Len(set, 0) + req.Equal(uint(0), f.Count) + }) + + t.Run("search with masked details", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("search by role", func(t *testing.T) { + t.Skip("not implemented") + }) + + t.Run("ordered search", func(t *testing.T) { + t.Skip("not implemented") + }) +} diff --git a/store/users.yaml b/store/users.yaml new file mode 100644 index 000000000..33bce6c6f --- /dev/null +++ b/store/users.yaml @@ -0,0 +1,67 @@ +import: + - github.com/cortezaproject/corteza-server/system/types + +interface: + - system/service + +fields: + - { field: ID } + - { field: Email } + - { field: EmailConfirmed } + - { field: Username } + - { field: Name } + - { field: Handle } + - { field: Meta, type: "*types.UserMeta" } + - { field: Kind } + - { field: CreatedAt } + - { field: UpdatedAt } + - { field: SuspendedAt } + - { field: DeletedAt } + +lookups: + - fields: [ ID ] + description: |- + searches for user by ID + + It returns user even if deleted or suspended + - fields: [ Email ] + filter: { DeletedAt: nil, SuspendedAt: nil } + description: |- + searches for user by their email + + It returns only valid users (not deleted, not suspended) + - fields: [ Handle ] + filter: { DeletedAt: nil, SuspendedAt: nil } + description: |- + searches for user by their email + + It returns only valid users (not deleted, not suspended) + - fields: [ Username ] + filter: { DeletedAt: nil, SuspendedAt: nil } + description: |- + searches for user by their username + + It returns only valid users (not deleted, not suspended) + +partialUpdates: + - name: delete + set: { DeletedAt: now() } + description: |- + deletes user + - name: undelete + set: { DeletedAt: nil } + description: |- + undeletes user + - name: suspend + set: { SuspendedAt: now() } + description: |- + suspends user + - name: unsuspend + set: { SuspendedAt: nil } + description: |- + unsuspends user + +rdbms: + alias: usr + table: sys_user + customFilterConverter: true diff --git a/system/auth/external/external.go b/system/auth/external/external.go index 51ef8815d..c2438e70d 100644 --- a/system/auth/external/external.go +++ b/system/auth/external/external.go @@ -12,7 +12,16 @@ const ( ) func Init() { - setupGoth(service.CurrentSettings) + ase := service.CurrentSettings.Auth.External + + if !ase.Enabled { + log().Info("external authentication disabled") + return + } + + setupGoth(ase.SessionStoreSecure, []byte(ase.SessionStoreSecret)) + setupGothProviders(ase.Providers, ase.RedirectUrl) + } func log() *zap.Logger { diff --git a/system/auth/external/goth.go b/system/auth/external/goth.go index a6e493510..46bb921b8 100644 --- a/system/auth/external/goth.go +++ b/system/auth/external/goth.go @@ -2,6 +2,7 @@ package external import ( "fmt" + "github.com/cortezaproject/corteza-server/system/types" "strings" "github.com/gorilla/sessions" @@ -13,8 +14,6 @@ import ( "github.com/markbates/goth/providers/linkedin" "github.com/markbates/goth/providers/openidConnect" "go.uber.org/zap" - - "github.com/cortezaproject/corteza-server/system/types" ) // We're expecting that our users will be able to complete @@ -25,16 +24,11 @@ const ( WellKnown = "/.well-known/openid-configuration" ) -func setupGoth(s *types.Settings) { - if !s.Auth.External.Enabled { - log().Info("external authentication disabled") - return - } - - store := sessions.NewCookieStore([]byte(s.Auth.External.SessionStoreSecret)) +func setupGoth(secure bool, secret []byte) { + store := sessions.NewCookieStore(secret) store.MaxAge(gothMaxSessionStoreAge) store.Options.HttpOnly = true - store.Options.Secure = s.Auth.External.SessionStoreSecure + store.Options.Secure = secure gothic.Store = store log().Debug("registering cookie session store") @@ -44,11 +38,9 @@ func setupGoth(s *types.Settings) { } - setupGothProviders(s) - } -func setupGothProviders(s *types.Settings) { +func setupGothProviders(ep types.ExternalAuthProviderSet, redirectUrl string) { var ( err error ) @@ -60,7 +52,7 @@ func setupGothProviders(s *types.Settings) { } var enabled = 0 - for _, pc := range s.Auth.External.Providers { + for _, pc := range ep { if pc.Enabled { enabled++ } @@ -68,7 +60,7 @@ func setupGothProviders(s *types.Settings) { log().Debug("initializing enabled external authentication providers", zap.Int("count", enabled)) - for _, pc := range s.Auth.External.Providers { + for _, pc := range ep { var provider goth.Provider log := log().With(zap.String("provider", pc.Handle)) @@ -81,7 +73,7 @@ func setupGothProviders(s *types.Settings) { if redirect == "" { // If redirect URL is not explicitly set for this provider, // generate one from template string - redirect = fmt.Sprintf(s.Auth.External.RedirectUrl, pc.Handle) + redirect = fmt.Sprintf(redirectUrl, pc.Handle) } if strings.Index(pc.Handle, OIDC_PROVIDER_PREFIX) == 0 { diff --git a/system/auth/external/register.go b/system/auth/external/register.go index 396a0c15f..828975750 100644 --- a/system/auth/external/register.go +++ b/system/auth/external/register.go @@ -3,6 +3,7 @@ package external import ( "context" "fmt" + "github.com/cortezaproject/corteza-server/system/types" "io/ioutil" "net/http" "net/url" @@ -12,9 +13,7 @@ import ( "github.com/pkg/errors" "go.uber.org/zap" - "github.com/cortezaproject/corteza-server/pkg/settings" "github.com/cortezaproject/corteza-server/system/service" - "github.com/cortezaproject/corteza-server/system/types" ) func AddProvider(ctx context.Context, eap *types.ExternalAuthProvider, force bool) error { @@ -53,7 +52,7 @@ func AddProvider(ctx context.Context, eap *types.ExternalAuthProvider, force boo // @todo remove dependency on github.com/crusttech/go-oidc (and github.com/coreos/go-oidc) // and move client registration to corteza codebase -func DiscoverOidcProvider(ctx context.Context, s *types.Settings, name, url string) (eap *types.ExternalAuthProvider, err error) { +func DiscoverOidcProvider(ctx context.Context, s *types.AppSettings, name, url string) (eap *types.ExternalAuthProvider, err error) { var ( provider *oidc.Provider client *oidc.Client @@ -138,7 +137,7 @@ func RegisterOidcProvider(ctx context.Context, name, providerUrl string, force, } if enable { - err = vv.Walk(func(value *settings.Value) error { + err = vv.Walk(func(value *types.SettingValue) error { if strings.HasSuffix(value.Name, ".enabled") { return value.SetValue(true) } @@ -150,7 +149,7 @@ func RegisterOidcProvider(ctx context.Context, name, providerUrl string, force, return } - v := &settings.Value{Name: "auth.external.enabled"} + v := &types.SettingValue{Name: "auth.external.enabled"} err = v.SetValue(true) if err != nil { return @@ -186,7 +185,7 @@ func parseExternalProviderUrl(in string) (p *url.URL, err error) { // StaticValidateExternal // // Simple checks of external auth settings -func staticValidateExternal(s *types.Settings) error { +func staticValidateExternal(s *types.AppSettings) error { if s.Auth.External.RedirectUrl == "" { return errors.New("redirect URL is empty") } @@ -217,7 +216,7 @@ func staticValidateExternal(s *types.Settings) error { // ValidateExternalRedirectURL // // Validates external redirect URL -func validateExternalRedirectURL(s *types.Settings) error { +func validateExternalRedirectURL(s *types.AppSettings) error { const tpt = "test-provider-test" const cb = "/callback" diff --git a/system/grpc/roles_service.go b/system/grpc/roles_service.go deleted file mode 100644 index 3b40c2a24..000000000 --- a/system/grpc/roles_service.go +++ /dev/null @@ -1,45 +0,0 @@ -package grpc - -import ( - "context" - - "github.com/cortezaproject/corteza-server/system/proto" - "github.com/cortezaproject/corteza-server/system/service" - "github.com/cortezaproject/corteza-server/system/types" -) - -type ( - roleService struct { - roles service.RoleService - } -) - -func NewRoleService(roles service.RoleService) *roleService { - return &roleService{ - roles: roles, - } -} - -func (gs roleService) Find(ctx context.Context, req *proto.FindRoleRequest) (rsp *proto.FindRoleResponse, err error) { - var ( - rr types.RoleSet - ) - - if rr, _, err = gs.roles.Find(types.RoleFilter{}); err != nil { - return - } - - rsp = &proto.FindRoleResponse{ - Roles: make([]*proto.Role, len(rr)), - } - - for i := range rr { - rsp.Roles[i] = &proto.Role{ - ID: rr[i].ID, - Handle: rr[i].Handle, - Name: rr[i].Name, - } - } - - return -} diff --git a/system/grpc/users_service.go b/system/grpc/users_service.go deleted file mode 100644 index 7f6153e83..000000000 --- a/system/grpc/users_service.go +++ /dev/null @@ -1,81 +0,0 @@ -package grpc - -import ( - "context" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "github.com/cortezaproject/corteza-server/pkg/auth" - "github.com/cortezaproject/corteza-server/system/proto" - "github.com/cortezaproject/corteza-server/system/service" - "github.com/cortezaproject/corteza-server/system/types" -) - -type ( - userService struct { - ac userServiceAccessControl - users service.UserService - auth service.AuthService - jwt auth.TokenEncoder - } - - userServiceAccessControl interface { - CanGrant(ctx context.Context) bool - } -) - -func NewUserService(users service.UserService, auth service.AuthService, jwt auth.TokenEncoder, ac userServiceAccessControl) *userService { - return &userService{ - ac: ac, - users: users, - auth: auth, - jwt: jwt, - } -} - -func (gs userService) MakeJWT(ctx context.Context, req *proto.MakeJWTUserRequest) (rsp *proto.MakeJWTUserResponse, err error) { - var ( - u *types.User - ) - - if !gs.ac.CanGrant(ctx) { - return nil, status.Error(codes.PermissionDenied, "no permissions to issue jwt for other users") - } - - if u, err = gs.users.FindByID(req.UserID); err != nil { - return - } - - if err = gs.auth.LoadRoleMemberships(u); err != nil { - return - } - - rsp = &proto.MakeJWTUserResponse{ - JWT: gs.jwt.Encode(u), - } - - return -} - -func (gs userService) FindByID(ctx context.Context, req *proto.FindByIDUserRequest) (rsp *proto.FindByIDUserResponse, err error) { - var ( - u *types.User - ) - - if u, err = gs.users.FindByID(req.UserID); err != nil { - return - } - - rsp = &proto.FindByIDUserResponse{ - User: &proto.User{ - ID: u.ID, - Email: u.Email, - Handle: u.Handle, - Name: u.Name, - Kind: string(u.Kind), - }, - } - - return -} diff --git a/system/importer/default.go b/system/importer/default.go index 90a7b8369..0d167c140 100644 --- a/system/importer/default.go +++ b/system/importer/default.go @@ -2,14 +2,13 @@ package importer import ( "context" - "io" - - "gopkg.in/yaml.v2" - + "errors" "github.com/cortezaproject/corteza-server/pkg/permissions" "github.com/cortezaproject/corteza-server/pkg/settings" "github.com/cortezaproject/corteza-server/system/service" "github.com/cortezaproject/corteza-server/system/types" + "gopkg.in/yaml.v2" + "io" ) // Import performs standard import procedure with default services @@ -20,6 +19,11 @@ func Import(ctx context.Context, ff ...io.Reader) (err error) { ) roles, _, err = service.DefaultRole.With(ctx).Find(types.RoleFilter{}) + + for errors.Unwrap(err) != nil { + err = errors.Unwrap(err) + } + if err != nil { return err } diff --git a/system/importer/importer.go b/system/importer/importer.go index d73ff984c..508d7ec14 100644 --- a/system/importer/importer.go +++ b/system/importer/importer.go @@ -2,14 +2,13 @@ package importer import ( "context" + "errors" "fmt" - "github.com/cortezaproject/corteza-server/pkg/deinterfacer" "github.com/cortezaproject/corteza-server/pkg/importer" "github.com/cortezaproject/corteza-server/pkg/permissions" "github.com/cortezaproject/corteza-server/pkg/settings" "github.com/cortezaproject/corteza-server/system/types" - "github.com/pkg/errors" ) type ( @@ -81,10 +80,9 @@ func (imp *Importer) Store( if err != nil { return } - if imp.permissions != nil { // Make sure we properly replace role handles with IDs - roles.Walk(func(role *types.Role) error { + _ = roles.Walk(func(role *types.Role) error { imp.permissions.UpdateRoles(role.Handle, role.ID) return nil }) @@ -92,15 +90,26 @@ func (imp *Importer) Store( if imp.permissions != nil { err = imp.permissions.Store(ctx, pk) + + for errors.Unwrap(err) != nil { + err = errors.Unwrap(err) + } + if err != nil { return } + } if imp.settings != nil { err = imp.settings.Store(ctx, sk) + + for errors.Unwrap(err) != nil { + err = errors.Unwrap(err) + } + if err != nil { - return errors.Wrap(err, "could not import settings") + return fmt.Errorf("could not import settings: %w", err) } } diff --git a/system/importer/role.go b/system/importer/role.go index ebc7fcf08..0f8838f8f 100644 --- a/system/importer/role.go +++ b/system/importer/role.go @@ -2,10 +2,8 @@ package importer import ( "context" + "errors" "fmt" - - "github.com/pkg/errors" - "github.com/cortezaproject/corteza-server/pkg/deinterfacer" "github.com/cortezaproject/corteza-server/pkg/importer" "github.com/cortezaproject/corteza-server/system/types" @@ -53,7 +51,7 @@ func (rImp *Role) Cast(handle string, def interface{}) (err error) { var role *types.Role if !importer.IsValidHandle(handle) { - return errors.New("invalid role handle") + return fmt.Errorf("invalid role handle") } handle = importer.NormalizeHandle(handle) @@ -66,7 +64,7 @@ func (rImp *Role) Cast(handle string, def interface{}) (err error) { rImp.set = append(rImp.set, role) } else if role.ID == 0 { - return errors.Errorf("role handle %q already defined in this import session", role.Handle) + return fmt.Errorf("role handle %q already defined in this import session", role.Handle) } else { rImp.dirty[role.ID] = true } @@ -99,7 +97,7 @@ func (rImp *Role) Get(handle string) (*types.Role, error) { handle = importer.NormalizeHandle(handle) if !importer.IsValidHandle(handle) { - return nil, errors.New("invalid role handle") + return nil, fmt.Errorf("invalid role handle") } return rImp.set.FindByHandle(handle), nil @@ -115,6 +113,10 @@ func (rImp *Role) Store(ctx context.Context, k roleKeeper) error { role, err = k.Update(role) } + for errors.Unwrap(err) != nil { + err = errors.Unwrap(err) + } + if err != nil { return } diff --git a/system/proto/role.pb.go b/system/proto/role.pb.go deleted file mode 100644 index c1263a319..000000000 --- a/system/proto/role.pb.go +++ /dev/null @@ -1,254 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: role.proto - -package proto - -import ( - context "context" - fmt "fmt" - proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - math "math" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package - -type FindRoleRequest struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *FindRoleRequest) Reset() { *m = FindRoleRequest{} } -func (m *FindRoleRequest) String() string { return proto.CompactTextString(m) } -func (*FindRoleRequest) ProtoMessage() {} -func (*FindRoleRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_48a3ff9f7c9032f8, []int{0} -} - -func (m *FindRoleRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_FindRoleRequest.Unmarshal(m, b) -} -func (m *FindRoleRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_FindRoleRequest.Marshal(b, m, deterministic) -} -func (m *FindRoleRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_FindRoleRequest.Merge(m, src) -} -func (m *FindRoleRequest) XXX_Size() int { - return xxx_messageInfo_FindRoleRequest.Size(m) -} -func (m *FindRoleRequest) XXX_DiscardUnknown() { - xxx_messageInfo_FindRoleRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_FindRoleRequest proto.InternalMessageInfo - -type FindRoleResponse struct { - Roles []*Role `protobuf:"bytes,1,rep,name=roles,proto3" json:"roles,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *FindRoleResponse) Reset() { *m = FindRoleResponse{} } -func (m *FindRoleResponse) String() string { return proto.CompactTextString(m) } -func (*FindRoleResponse) ProtoMessage() {} -func (*FindRoleResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_48a3ff9f7c9032f8, []int{1} -} - -func (m *FindRoleResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_FindRoleResponse.Unmarshal(m, b) -} -func (m *FindRoleResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_FindRoleResponse.Marshal(b, m, deterministic) -} -func (m *FindRoleResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_FindRoleResponse.Merge(m, src) -} -func (m *FindRoleResponse) XXX_Size() int { - return xxx_messageInfo_FindRoleResponse.Size(m) -} -func (m *FindRoleResponse) XXX_DiscardUnknown() { - xxx_messageInfo_FindRoleResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_FindRoleResponse proto.InternalMessageInfo - -func (m *FindRoleResponse) GetRoles() []*Role { - if m != nil { - return m.Roles - } - return nil -} - -type Role struct { - ID uint64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"` - Handle string `protobuf:"bytes,2,opt,name=handle,proto3" json:"handle,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Role) Reset() { *m = Role{} } -func (m *Role) String() string { return proto.CompactTextString(m) } -func (*Role) ProtoMessage() {} -func (*Role) Descriptor() ([]byte, []int) { - return fileDescriptor_48a3ff9f7c9032f8, []int{2} -} - -func (m *Role) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Role.Unmarshal(m, b) -} -func (m *Role) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Role.Marshal(b, m, deterministic) -} -func (m *Role) XXX_Merge(src proto.Message) { - xxx_messageInfo_Role.Merge(m, src) -} -func (m *Role) XXX_Size() int { - return xxx_messageInfo_Role.Size(m) -} -func (m *Role) XXX_DiscardUnknown() { - xxx_messageInfo_Role.DiscardUnknown(m) -} - -var xxx_messageInfo_Role proto.InternalMessageInfo - -func (m *Role) GetID() uint64 { - if m != nil { - return m.ID - } - return 0 -} - -func (m *Role) GetHandle() string { - if m != nil { - return m.Handle - } - return "" -} - -func (m *Role) GetName() string { - if m != nil { - return m.Name - } - return "" -} - -func init() { - proto.RegisterType((*FindRoleRequest)(nil), "system.FindRoleRequest") - proto.RegisterType((*FindRoleResponse)(nil), "system.FindRoleResponse") - proto.RegisterType((*Role)(nil), "system.Role") -} - -func init() { proto.RegisterFile("role.proto", fileDescriptor_48a3ff9f7c9032f8) } - -var fileDescriptor_48a3ff9f7c9032f8 = []byte{ - // 189 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0xca, 0xcf, 0x49, - 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2b, 0xae, 0x2c, 0x2e, 0x49, 0xcd, 0x55, 0x12, - 0xe4, 0xe2, 0x77, 0xcb, 0xcc, 0x4b, 0x09, 0xca, 0xcf, 0x49, 0x0d, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, - 0x2e, 0x51, 0x32, 0xe3, 0x12, 0x40, 0x08, 0x15, 0x17, 0xe4, 0xe7, 0x15, 0xa7, 0x0a, 0x29, 0x71, - 0xb1, 0x82, 0x34, 0x17, 0x4b, 0x30, 0x2a, 0x30, 0x6b, 0x70, 0x1b, 0xf1, 0xe8, 0x41, 0xb4, 0xeb, - 0x81, 0x15, 0x41, 0xa4, 0x94, 0x9c, 0xb8, 0x58, 0x40, 0x5c, 0x21, 0x3e, 0x2e, 0x26, 0x4f, 0x17, - 0x09, 0x46, 0x05, 0x46, 0x0d, 0x96, 0x20, 0x26, 0x4f, 0x17, 0x21, 0x31, 0x2e, 0xb6, 0x8c, 0xc4, - 0xbc, 0x94, 0x9c, 0x54, 0x09, 0x26, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x28, 0x4f, 0x48, 0x88, 0x8b, - 0x25, 0x2f, 0x31, 0x37, 0x55, 0x82, 0x19, 0x2c, 0x0a, 0x66, 0x1b, 0x39, 0x71, 0xb1, 0x82, 0xcc, - 0x28, 0x16, 0xb2, 0xe4, 0x62, 0x01, 0x39, 0x42, 0x48, 0x1c, 0x66, 0x13, 0x9a, 0x2b, 0xa5, 0x24, - 0x30, 0x25, 0x20, 0x6e, 0x75, 0x62, 0x8f, 0x62, 0x05, 0xfb, 0x31, 0x89, 0x0d, 0x4c, 0x19, 0x03, - 0x02, 0x00, 0x00, 0xff, 0xff, 0x80, 0x25, 0xf0, 0xe7, 0xf8, 0x00, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// RolesClient is the client API for Roles service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type RolesClient interface { - Find(ctx context.Context, in *FindRoleRequest, opts ...grpc.CallOption) (*FindRoleResponse, error) -} - -type rolesClient struct { - cc *grpc.ClientConn -} - -func NewRolesClient(cc *grpc.ClientConn) RolesClient { - return &rolesClient{cc} -} - -func (c *rolesClient) Find(ctx context.Context, in *FindRoleRequest, opts ...grpc.CallOption) (*FindRoleResponse, error) { - out := new(FindRoleResponse) - err := c.cc.Invoke(ctx, "/system.Roles/Find", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// RolesServer is the server API for Roles service. -type RolesServer interface { - Find(context.Context, *FindRoleRequest) (*FindRoleResponse, error) -} - -// UnimplementedRolesServer can be embedded to have forward compatible implementations. -type UnimplementedRolesServer struct { -} - -func (*UnimplementedRolesServer) Find(ctx context.Context, req *FindRoleRequest) (*FindRoleResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Find not implemented") -} - -func RegisterRolesServer(s *grpc.Server, srv RolesServer) { - s.RegisterService(&_Roles_serviceDesc, srv) -} - -func _Roles_Find_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(FindRoleRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(RolesServer).Find(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/system.Roles/Find", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RolesServer).Find(ctx, req.(*FindRoleRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Roles_serviceDesc = grpc.ServiceDesc{ - ServiceName: "system.Roles", - HandlerType: (*RolesServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Find", - Handler: _Roles_Find_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "role.proto", -} diff --git a/system/proto/user.pb.go b/system/proto/user.pb.go deleted file mode 100644 index 565eb60c7..000000000 --- a/system/proto/user.pb.go +++ /dev/null @@ -1,399 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: user.proto - -package proto - -import ( - context "context" - fmt "fmt" - proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - math "math" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package - -type MakeJWTUserRequest struct { - UserID uint64 `protobuf:"varint,1,opt,name=userID,proto3" json:"userID,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *MakeJWTUserRequest) Reset() { *m = MakeJWTUserRequest{} } -func (m *MakeJWTUserRequest) String() string { return proto.CompactTextString(m) } -func (*MakeJWTUserRequest) ProtoMessage() {} -func (*MakeJWTUserRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_116e343673f7ffaf, []int{0} -} - -func (m *MakeJWTUserRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_MakeJWTUserRequest.Unmarshal(m, b) -} -func (m *MakeJWTUserRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_MakeJWTUserRequest.Marshal(b, m, deterministic) -} -func (m *MakeJWTUserRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_MakeJWTUserRequest.Merge(m, src) -} -func (m *MakeJWTUserRequest) XXX_Size() int { - return xxx_messageInfo_MakeJWTUserRequest.Size(m) -} -func (m *MakeJWTUserRequest) XXX_DiscardUnknown() { - xxx_messageInfo_MakeJWTUserRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_MakeJWTUserRequest proto.InternalMessageInfo - -func (m *MakeJWTUserRequest) GetUserID() uint64 { - if m != nil { - return m.UserID - } - return 0 -} - -type MakeJWTUserResponse struct { - JWT string `protobuf:"bytes,1,opt,name=JWT,proto3" json:"JWT,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *MakeJWTUserResponse) Reset() { *m = MakeJWTUserResponse{} } -func (m *MakeJWTUserResponse) String() string { return proto.CompactTextString(m) } -func (*MakeJWTUserResponse) ProtoMessage() {} -func (*MakeJWTUserResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_116e343673f7ffaf, []int{1} -} - -func (m *MakeJWTUserResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_MakeJWTUserResponse.Unmarshal(m, b) -} -func (m *MakeJWTUserResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_MakeJWTUserResponse.Marshal(b, m, deterministic) -} -func (m *MakeJWTUserResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MakeJWTUserResponse.Merge(m, src) -} -func (m *MakeJWTUserResponse) XXX_Size() int { - return xxx_messageInfo_MakeJWTUserResponse.Size(m) -} -func (m *MakeJWTUserResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MakeJWTUserResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MakeJWTUserResponse proto.InternalMessageInfo - -func (m *MakeJWTUserResponse) GetJWT() string { - if m != nil { - return m.JWT - } - return "" -} - -type FindByIDUserRequest struct { - UserID uint64 `protobuf:"varint,1,opt,name=userID,proto3" json:"userID,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *FindByIDUserRequest) Reset() { *m = FindByIDUserRequest{} } -func (m *FindByIDUserRequest) String() string { return proto.CompactTextString(m) } -func (*FindByIDUserRequest) ProtoMessage() {} -func (*FindByIDUserRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_116e343673f7ffaf, []int{2} -} - -func (m *FindByIDUserRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_FindByIDUserRequest.Unmarshal(m, b) -} -func (m *FindByIDUserRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_FindByIDUserRequest.Marshal(b, m, deterministic) -} -func (m *FindByIDUserRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_FindByIDUserRequest.Merge(m, src) -} -func (m *FindByIDUserRequest) XXX_Size() int { - return xxx_messageInfo_FindByIDUserRequest.Size(m) -} -func (m *FindByIDUserRequest) XXX_DiscardUnknown() { - xxx_messageInfo_FindByIDUserRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_FindByIDUserRequest proto.InternalMessageInfo - -func (m *FindByIDUserRequest) GetUserID() uint64 { - if m != nil { - return m.UserID - } - return 0 -} - -type FindByIDUserResponse struct { - User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *FindByIDUserResponse) Reset() { *m = FindByIDUserResponse{} } -func (m *FindByIDUserResponse) String() string { return proto.CompactTextString(m) } -func (*FindByIDUserResponse) ProtoMessage() {} -func (*FindByIDUserResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_116e343673f7ffaf, []int{3} -} - -func (m *FindByIDUserResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_FindByIDUserResponse.Unmarshal(m, b) -} -func (m *FindByIDUserResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_FindByIDUserResponse.Marshal(b, m, deterministic) -} -func (m *FindByIDUserResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_FindByIDUserResponse.Merge(m, src) -} -func (m *FindByIDUserResponse) XXX_Size() int { - return xxx_messageInfo_FindByIDUserResponse.Size(m) -} -func (m *FindByIDUserResponse) XXX_DiscardUnknown() { - xxx_messageInfo_FindByIDUserResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_FindByIDUserResponse proto.InternalMessageInfo - -func (m *FindByIDUserResponse) GetUser() *User { - if m != nil { - return m.User - } - return nil -} - -type User struct { - ID uint64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"` - Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` - Handle string `protobuf:"bytes,3,opt,name=handle,proto3" json:"handle,omitempty"` - Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` - Kind string `protobuf:"bytes,5,opt,name=kind,proto3" json:"kind,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *User) Reset() { *m = User{} } -func (m *User) String() string { return proto.CompactTextString(m) } -func (*User) ProtoMessage() {} -func (*User) Descriptor() ([]byte, []int) { - return fileDescriptor_116e343673f7ffaf, []int{4} -} - -func (m *User) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_User.Unmarshal(m, b) -} -func (m *User) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_User.Marshal(b, m, deterministic) -} -func (m *User) XXX_Merge(src proto.Message) { - xxx_messageInfo_User.Merge(m, src) -} -func (m *User) XXX_Size() int { - return xxx_messageInfo_User.Size(m) -} -func (m *User) XXX_DiscardUnknown() { - xxx_messageInfo_User.DiscardUnknown(m) -} - -var xxx_messageInfo_User proto.InternalMessageInfo - -func (m *User) GetID() uint64 { - if m != nil { - return m.ID - } - return 0 -} - -func (m *User) GetEmail() string { - if m != nil { - return m.Email - } - return "" -} - -func (m *User) GetHandle() string { - if m != nil { - return m.Handle - } - return "" -} - -func (m *User) GetName() string { - if m != nil { - return m.Name - } - return "" -} - -func (m *User) GetKind() string { - if m != nil { - return m.Kind - } - return "" -} - -func init() { - proto.RegisterType((*MakeJWTUserRequest)(nil), "system.MakeJWTUserRequest") - proto.RegisterType((*MakeJWTUserResponse)(nil), "system.MakeJWTUserResponse") - proto.RegisterType((*FindByIDUserRequest)(nil), "system.FindByIDUserRequest") - proto.RegisterType((*FindByIDUserResponse)(nil), "system.FindByIDUserResponse") - proto.RegisterType((*User)(nil), "system.User") -} - -func init() { proto.RegisterFile("user.proto", fileDescriptor_116e343673f7ffaf) } - -var fileDescriptor_116e343673f7ffaf = []byte{ - // 271 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0x41, 0x4b, 0xc3, 0x40, - 0x10, 0x85, 0x49, 0xba, 0x49, 0x75, 0x14, 0x91, 0x69, 0x91, 0x25, 0x7a, 0x28, 0xb9, 0xe8, 0x41, - 0x73, 0xa8, 0x17, 0xcf, 0x21, 0x0a, 0x29, 0x78, 0x09, 0x95, 0x82, 0xb7, 0x48, 0x06, 0x0c, 0x4d, - 0x36, 0x35, 0x9b, 0x1e, 0xfa, 0x37, 0xfc, 0xc5, 0xb2, 0x93, 0x6d, 0xa1, 0x98, 0x43, 0x4f, 0x99, - 0xf7, 0xe6, 0xe3, 0xed, 0xcc, 0x04, 0x60, 0xab, 0xa9, 0x8d, 0x36, 0x6d, 0xd3, 0x35, 0xe8, 0xeb, - 0x9d, 0xee, 0xa8, 0x0e, 0x1f, 0x01, 0xdf, 0xf3, 0x35, 0x2d, 0x56, 0xcb, 0x0f, 0x4d, 0x6d, 0x46, - 0x3f, 0x5b, 0xd2, 0x1d, 0xde, 0x80, 0x6f, 0xd8, 0x34, 0x91, 0xce, 0xcc, 0x79, 0x10, 0x99, 0x55, - 0xe1, 0x3d, 0x4c, 0x8e, 0x68, 0xbd, 0x69, 0x94, 0x26, 0xbc, 0x86, 0xd1, 0x62, 0xb5, 0x64, 0xf6, - 0x3c, 0x33, 0x65, 0xf8, 0x04, 0x93, 0xb7, 0x52, 0x15, 0xf1, 0x2e, 0x4d, 0x4e, 0xc9, 0x7d, 0x81, - 0xe9, 0x31, 0x6e, 0x83, 0x67, 0x20, 0x0c, 0xc1, 0xf4, 0xc5, 0xfc, 0x32, 0xea, 0x87, 0x8e, 0x98, - 0xe1, 0x4e, 0x58, 0x81, 0x30, 0x0a, 0xaf, 0xc0, 0x3d, 0xa4, 0xba, 0x69, 0x82, 0x53, 0xf0, 0xa8, - 0xce, 0xcb, 0x4a, 0xba, 0x3c, 0x54, 0x2f, 0xcc, 0xfb, 0xdf, 0xb9, 0x2a, 0x2a, 0x92, 0x23, 0xb6, - 0xad, 0x42, 0x04, 0xa1, 0xf2, 0x9a, 0xa4, 0x60, 0x97, 0x6b, 0xe3, 0xad, 0x4b, 0x55, 0x48, 0xaf, - 0xf7, 0x4c, 0x3d, 0xff, 0x75, 0xc0, 0x33, 0xcf, 0x69, 0x8c, 0x61, 0x6c, 0x2f, 0x81, 0xc1, 0x7e, - 0xac, 0xff, 0x87, 0x0c, 0x6e, 0x07, 0x7b, 0x76, 0xbb, 0x57, 0x38, 0xdb, 0x6f, 0x8d, 0x07, 0x70, - 0xe0, 0x6c, 0xc1, 0xdd, 0x70, 0xb3, 0x8f, 0x89, 0xc7, 0x9f, 0x1e, 0xff, 0xd3, 0x2f, 0x9f, 0x3f, - 0xcf, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x0e, 0x54, 0x3b, 0x6a, 0xe8, 0x01, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// UsersClient is the client API for Users service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type UsersClient interface { - MakeJWT(ctx context.Context, in *MakeJWTUserRequest, opts ...grpc.CallOption) (*MakeJWTUserResponse, error) - FindByID(ctx context.Context, in *FindByIDUserRequest, opts ...grpc.CallOption) (*FindByIDUserResponse, error) -} - -type usersClient struct { - cc *grpc.ClientConn -} - -func NewUsersClient(cc *grpc.ClientConn) UsersClient { - return &usersClient{cc} -} - -func (c *usersClient) MakeJWT(ctx context.Context, in *MakeJWTUserRequest, opts ...grpc.CallOption) (*MakeJWTUserResponse, error) { - out := new(MakeJWTUserResponse) - err := c.cc.Invoke(ctx, "/system.Users/MakeJWT", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *usersClient) FindByID(ctx context.Context, in *FindByIDUserRequest, opts ...grpc.CallOption) (*FindByIDUserResponse, error) { - out := new(FindByIDUserResponse) - err := c.cc.Invoke(ctx, "/system.Users/FindByID", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// UsersServer is the server API for Users service. -type UsersServer interface { - MakeJWT(context.Context, *MakeJWTUserRequest) (*MakeJWTUserResponse, error) - FindByID(context.Context, *FindByIDUserRequest) (*FindByIDUserResponse, error) -} - -// UnimplementedUsersServer can be embedded to have forward compatible implementations. -type UnimplementedUsersServer struct { -} - -func (*UnimplementedUsersServer) MakeJWT(ctx context.Context, req *MakeJWTUserRequest) (*MakeJWTUserResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method MakeJWT not implemented") -} -func (*UnimplementedUsersServer) FindByID(ctx context.Context, req *FindByIDUserRequest) (*FindByIDUserResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method FindByID not implemented") -} - -func RegisterUsersServer(s *grpc.Server, srv UsersServer) { - s.RegisterService(&_Users_serviceDesc, srv) -} - -func _Users_MakeJWT_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MakeJWTUserRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(UsersServer).MakeJWT(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/system.Users/MakeJWT", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(UsersServer).MakeJWT(ctx, req.(*MakeJWTUserRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Users_FindByID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(FindByIDUserRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(UsersServer).FindByID(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/system.Users/FindByID", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(UsersServer).FindByID(ctx, req.(*FindByIDUserRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Users_serviceDesc = grpc.ServiceDesc{ - ServiceName: "system.Users", - HandlerType: (*UsersServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "MakeJWT", - Handler: _Users_MakeJWT_Handler, - }, - { - MethodName: "FindByID", - Handler: _Users_FindByID_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "user.proto", -} diff --git a/system/service/access_control.go b/system/service/access_control.go index efda19445..a4b53544b 100644 --- a/system/service/access_control.go +++ b/system/service/access_control.go @@ -17,10 +17,10 @@ type ( } accessControlPermissionServicer interface { - Can(context.Context, permissions.Resource, permissions.Operation, ...permissions.CheckAccessFunc) bool + Can([]uint64, permissions.Resource, permissions.Operation, ...permissions.CheckAccessFunc) bool Grant(context.Context, permissions.Whitelist, ...*permissions.Rule) error FindRulesByRoleID(roleID uint64) (rr permissions.RuleSet) - ResourceFilter(context.Context, permissions.Resource, permissions.Operation, permissions.Access) *permissions.ResourceFilter + ResourceFilter([]uint64, permissions.Resource, permissions.Operation, permissions.Access) *permissions.ResourceFilter } permissionResource interface { @@ -87,11 +87,11 @@ func (svc accessControl) CanAssignReminder(ctx context.Context) bool { } func (svc accessControl) CanReadRole(ctx context.Context, rl *types.Role) bool { - return svc.can(ctx, rl, "read", permissions.Allowed) + return svc.can(ctx, rl.PermissionResource(), "read", permissions.Allowed) } func (svc accessControl) FilterReadableRoles(ctx context.Context) *permissions.ResourceFilter { - return svc.permissions.ResourceFilter(ctx, types.RolePermissionResource, "read", permissions.Allow) + return svc.filter(ctx, types.RolePermissionResource, "read", permissions.Allow) } func (svc accessControl) CanUpdateRole(ctx context.Context, rl *types.Role) bool { @@ -99,7 +99,7 @@ func (svc accessControl) CanUpdateRole(ctx context.Context, rl *types.Role) bool return false } - return svc.can(ctx, rl, "update") + return svc.can(ctx, rl.PermissionResource(), "update") } func (svc accessControl) CanDeleteRole(ctx context.Context, rl *types.Role) bool { @@ -107,62 +107,62 @@ func (svc accessControl) CanDeleteRole(ctx context.Context, rl *types.Role) bool return false } - return svc.can(ctx, rl, "delete") + return svc.can(ctx, rl.PermissionResource(), "delete") } func (svc accessControl) CanManageRoleMembers(ctx context.Context, rl *types.Role) bool { if rl.ID == permissions.EveryoneRoleID { return false } - return svc.can(ctx, rl, "members.manage") + return svc.can(ctx, rl.PermissionResource(), "members.manage") } func (svc accessControl) CanReadApplication(ctx context.Context, app *types.Application) bool { - return svc.can(ctx, app, "read", permissions.Allowed) + return svc.can(ctx, app.PermissionResource(), "read", permissions.Allowed) } func (svc accessControl) FilterReadableApplications(ctx context.Context) *permissions.ResourceFilter { - return svc.permissions.ResourceFilter(ctx, types.ApplicationPermissionResource, "read", permissions.Deny) + return svc.filter(ctx, types.ApplicationPermissionResource, "read", permissions.Deny) } func (svc accessControl) CanUpdateApplication(ctx context.Context, app *types.Application) bool { - return svc.can(ctx, app, "update") + return svc.can(ctx, app.PermissionResource(), "update") } func (svc accessControl) CanDeleteApplication(ctx context.Context, app *types.Application) bool { - return svc.can(ctx, app, "delete") + return svc.can(ctx, app.PermissionResource(), "delete") } func (svc accessControl) FilterReadableUsers(ctx context.Context) *permissions.ResourceFilter { - return svc.permissions.ResourceFilter(ctx, types.UserPermissionResource, "read", permissions.Deny) + return svc.filter(ctx, types.UserPermissionResource, "read", permissions.Deny) } func (svc accessControl) FilterUsersWithUnmaskableEmail(ctx context.Context) *permissions.ResourceFilter { - return svc.permissions.ResourceFilter(ctx, types.UserPermissionResource, "unmask.email", permissions.Deny) + return svc.filter(ctx, types.UserPermissionResource, "unmask.email", permissions.Deny) } func (svc accessControl) FilterUsersWithUnmaskableName(ctx context.Context) *permissions.ResourceFilter { - return svc.permissions.ResourceFilter(ctx, types.UserPermissionResource, "unmask.name", permissions.Deny) + return svc.filter(ctx, types.UserPermissionResource, "unmask.name", permissions.Deny) } func (svc accessControl) CanUpdateUser(ctx context.Context, u *types.User) bool { - return svc.can(ctx, u, "update") + return svc.can(ctx, u.PermissionResource(), "update") } func (svc accessControl) CanSuspendUser(ctx context.Context, u *types.User) bool { - return svc.can(ctx, u, "suspend") + return svc.can(ctx, u.PermissionResource(), "suspend") } func (svc accessControl) CanUnsuspendUser(ctx context.Context, u *types.User) bool { - return svc.can(ctx, u, "unsuspend") + return svc.can(ctx, u.PermissionResource(), "unsuspend") } func (svc accessControl) CanDeleteUser(ctx context.Context, u *types.User) bool { - return svc.can(ctx, u, "delete") + return svc.can(ctx, u.PermissionResource(), "delete") } func (svc accessControl) CanImpersonateUser(ctx context.Context, u *types.User) bool { - return svc.can(ctx, u, "impersonate", permissions.Denied) + return svc.can(ctx, u.PermissionResource(), "impersonate", permissions.Denied) } func (svc accessControl) CanUnmaskEmail(ctx context.Context, u *types.User) bool { @@ -171,7 +171,7 @@ func (svc accessControl) CanUnmaskEmail(ctx context.Context, u *types.User) bool return true } - return svc.can(ctx, u, "unmask.email") + return svc.can(ctx, u.PermissionResource(), "unmask.email") } func (svc accessControl) CanUnmaskName(ctx context.Context, u *types.User) bool { @@ -180,11 +180,39 @@ func (svc accessControl) CanUnmaskName(ctx context.Context, u *types.User) bool return true } - return svc.can(ctx, u, "unmask.name") + return svc.can(ctx, u.PermissionResource(), "unmask.name") } -func (svc accessControl) can(ctx context.Context, res permissionResource, op permissions.Operation, ff ...permissions.CheckAccessFunc) bool { - return svc.permissions.Can(ctx, res.PermissionResource(), op, ff...) +func (svc accessControl) can(ctx context.Context, res permissions.Resource, op permissions.Operation, ff ...permissions.CheckAccessFunc) bool { + var ( + u = internalAuth.GetIdentityFromContext(ctx) + roles = u.Roles() + ) + + if internalAuth.IsSuperUser(u) { + // Temp solution to allow migration from passing context to ResourceFilter + // and checking "superuser" privileges there to more sustainable solution + // (eg: creating super-role with allow-all) + return true + } + + return svc.permissions.Can(roles, res.PermissionResource(), op, ff...) +} + +func (svc accessControl) filter(ctx context.Context, res permissions.Resource, op permissions.Operation, a permissions.Access) *permissions.ResourceFilter { + var ( + u = internalAuth.GetIdentityFromContext(ctx) + roles = u.Roles() + ) + + if internalAuth.IsSuperUser(u) { + // Temp solution to allow migration from passing context to ResourceFilter + //and checking "superuser" privileges there + // to more sustainable solution (eg: creating super-role with allow-all) + return permissions.NewSuperuserFilter() + } + + return svc.permissions.ResourceFilter(roles, res, op, a) } func (svc accessControl) Grant(ctx context.Context, rr ...*permissions.Rule) error { diff --git a/system/service/access_control_actions.gen.go b/system/service/access_control_actions.gen.go index 93c27f45c..435336503 100644 --- a/system/service/access_control_actions.gen.go +++ b/system/service/access_control_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from system/service/access_control_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// system/service/access_control_actions.yaml import ( "context" diff --git a/system/service/application.go b/system/service/application.go index ae9581e83..4ec32272d 100644 --- a/system/service/application.go +++ b/system/service/application.go @@ -2,29 +2,19 @@ package service import ( "context" - - "github.com/titpetric/factory" - "github.com/cortezaproject/corteza-server/pkg/actionlog" - "github.com/cortezaproject/corteza-server/pkg/eventbus" "github.com/cortezaproject/corteza-server/pkg/permissions" "github.com/cortezaproject/corteza-server/pkg/rh" - "github.com/cortezaproject/corteza-server/system/repository" "github.com/cortezaproject/corteza-server/system/service/event" "github.com/cortezaproject/corteza-server/system/types" ) type ( application struct { - db *factory.DB - ctx context.Context - - ac applicationAccessController - eventbus eventDispatcher - + ac applicationAccessController + eventbus eventDispatcher actionlog actionlog.Recorder - - application repository.ApplicationRepository + store applicationsStore } applicationAccessController interface { @@ -36,44 +26,14 @@ type ( FilterReadableApplications(ctx context.Context) *permissions.ResourceFilter } - - ApplicationService interface { - With(ctx context.Context) ApplicationService - - FindByID(applicationID uint64) (*types.Application, error) - Find(types.ApplicationFilter) (types.ApplicationSet, types.ApplicationFilter, error) - - Create(application *types.Application) (*types.Application, error) - Update(application *types.Application) (*types.Application, error) - Delete(uint64) error - Undelete(uint64) error - } ) -func Application(ctx context.Context) ApplicationService { - return (&application{ - ac: DefaultAccessControl, - eventbus: eventbus.Service(), - }).With(ctx) - +// Application is a default application service initializer +func Application(s applicationsStore, ac applicationAccessController, al actionlog.Recorder, eb eventDispatcher) *application { + return &application{store: s, ac: ac, actionlog: al, eventbus: eb} } -func (svc *application) With(ctx context.Context) ApplicationService { - db := repository.DB(ctx) - return &application{ - db: db, - ctx: ctx, - - ac: svc.ac, - eventbus: svc.eventbus, - - actionlog: DefaultActionlog, - - application: repository.Application(ctx, db), - } -} - -func (svc *application) FindByID(ID uint64) (app *types.Application, err error) { +func (svc *application) LookupByID(ctx context.Context, ID uint64) (app *types.Application, err error) { var ( aaProps = &applicationActionProps{application: &types.Application{ID: ID}} ) @@ -83,29 +43,29 @@ func (svc *application) FindByID(ID uint64) (app *types.Application, err error) return ApplicationErrInvalidID() } - if app, err = svc.application.FindByID(ID); err != nil { + if app, err = svc.store.LookupApplicationByID(ctx, ID); err != nil { return ApplicationErrInvalidID().Wrap(err) } aaProps.setApplication(app) - if !svc.ac.CanReadApplication(svc.ctx, app) { + if !svc.ac.CanReadApplication(ctx, app) { return ApplicationErrNotAllowedToRead() } return nil }() - return app, svc.recordAction(svc.ctx, aaProps, ApplicationActionLookup, err) + return app, svc.recordAction(ctx, aaProps, ApplicationActionLookup, err) } -func (svc *application) Find(filter types.ApplicationFilter) (aa types.ApplicationSet, f types.ApplicationFilter, err error) { +func (svc *application) Search(ctx context.Context, filter types.ApplicationFilter) (aa types.ApplicationSet, f types.ApplicationFilter, err error) { var ( aaProps = &applicationActionProps{filter: &filter} ) err = func() error { - filter.IsReadable = svc.ac.FilterReadableApplications(svc.ctx) + filter.IsReadable = svc.ac.FilterReadableApplications(ctx) if filter.Deleted > rh.FilterStateExcluded { // If list with deleted applications is requested @@ -113,46 +73,49 @@ func (svc *application) Find(filter types.ApplicationFilter) (aa types.Applicati // // not the best solution but ATM it allows us to have at least // some kind of control over who can see deleted applications - if !svc.ac.CanAccess(svc.ctx) { + if !svc.ac.CanAccess(ctx) { return ApplicationErrNotAllowedToListApplications() } } - aa, f, err = svc.application.Find(filter) + aa, f, err = svc.store.SearchApplications(ctx, filter) return err }() - return aa, f, svc.recordAction(svc.ctx, aaProps, ApplicationActionSearch, err) + return aa, f, svc.recordAction(ctx, aaProps, ApplicationActionSearch, err) } -func (svc *application) Create(new *types.Application) (app *types.Application, err error) { +func (svc *application) Create(ctx context.Context, new *types.Application) (app *types.Application, err error) { var ( aaProps = &applicationActionProps{new: new} ) err = func() (err error) { - if !svc.ac.CanCreateApplication(svc.ctx) { + if !svc.ac.CanCreateApplication(ctx) { return ApplicationErrNotAllowedToCreate() } - if err = svc.eventbus.WaitFor(svc.ctx, event.ApplicationBeforeCreate(new, nil)); err != nil { + if err = svc.eventbus.WaitFor(ctx, event.ApplicationBeforeCreate(new, nil)); err != nil { return } - if app, err = svc.application.Create(new); err != nil { + // Set new values after beforeCreate events are emitted + new.ID = nextID() + new.CreatedAt = now() + if err = svc.store.CreateApplication(ctx, new); err != nil { return } aaProps.setApplication(app) - _ = svc.eventbus.WaitFor(svc.ctx, event.ApplicationAfterCreate(new, nil)) + _ = svc.eventbus.WaitFor(ctx, event.ApplicationAfterCreate(new, nil)) return nil }() - return app, svc.recordAction(svc.ctx, aaProps, ApplicationActionCreate, err) + return app, svc.recordAction(ctx, aaProps, ApplicationActionCreate, err) } -func (svc *application) Update(upd *types.Application) (app *types.Application, err error) { +func (svc *application) Update(ctx context.Context, upd *types.Application) (app *types.Application, err error) { var ( aaProps = &applicationActionProps{update: upd} ) @@ -162,37 +125,38 @@ func (svc *application) Update(upd *types.Application) (app *types.Application, return ApplicationErrInvalidID() } - if app, err = svc.application.FindByID(upd.ID); err != nil { + if app, err = svc.store.LookupApplicationByID(ctx, upd.ID); err != nil { return } aaProps.setApplication(app) - if !svc.ac.CanUpdateApplication(svc.ctx, app) { + if !svc.ac.CanUpdateApplication(ctx, app) { return ApplicationErrNotAllowedToUpdate() } - if err = svc.eventbus.WaitFor(svc.ctx, event.ApplicationBeforeUpdate(upd, app)); err != nil { + if err = svc.eventbus.WaitFor(ctx, event.ApplicationBeforeUpdate(upd, app)); err != nil { return } - // Assign changed values + // Assign changed values after afterUpdate events are emitted app.Name = upd.Name app.Enabled = upd.Enabled app.Unify = upd.Unify + app.UpdatedAt = nowPtr() - if app, err = svc.application.Update(app); err != nil { + if err = svc.store.UpdateApplication(ctx, app); err != nil { return err } - _ = svc.eventbus.WaitFor(svc.ctx, event.ApplicationAfterUpdate(upd, app)) + _ = svc.eventbus.WaitFor(ctx, event.ApplicationAfterUpdate(upd, app)) return nil }() - return app, svc.recordAction(svc.ctx, aaProps, ApplicationActionUpdate, err) + return app, svc.recordAction(ctx, aaProps, ApplicationActionUpdate, err) } -func (svc *application) Delete(ID uint64) (err error) { +func (svc *application) Delete(ctx context.Context, ID uint64) (err error) { var ( aaProps = &applicationActionProps{} app *types.Application @@ -203,30 +167,33 @@ func (svc *application) Delete(ID uint64) (err error) { return ApplicationErrInvalidID() } - if app, err = svc.application.FindByID(ID); err != nil { + if app, err = svc.store.LookupApplicationByID(ctx, ID); err != nil { return } - if !svc.ac.CanDeleteApplication(svc.ctx, app) { + aaProps.setApplication(app) + + if !svc.ac.CanDeleteApplication(ctx, app) { return ApplicationErrNotAllowedToDelete() } - if err = svc.eventbus.WaitFor(svc.ctx, event.ApplicationBeforeDelete(nil, app)); err != nil { + if err = svc.eventbus.WaitFor(ctx, event.ApplicationBeforeDelete(nil, app)); err != nil { return } - if err = svc.application.DeleteByID(ID); err != nil { + app.DeletedAt = nowPtr() + if err = svc.store.PartialUpdateApplication(ctx, []string{"UpdatedAt"}, app); err != nil { return } - _ = svc.eventbus.WaitFor(svc.ctx, event.ApplicationAfterDelete(nil, app)) + _ = svc.eventbus.WaitFor(ctx, event.ApplicationAfterDelete(nil, app)) return nil }() - return svc.recordAction(svc.ctx, aaProps, ApplicationActionDelete, err) + return svc.recordAction(ctx, aaProps, ApplicationActionDelete, err) } -func (svc *application) Undelete(ID uint64) (err error) { +func (svc *application) Undelete(ctx context.Context, ID uint64) (err error) { var ( aaProps = &applicationActionProps{} app *types.Application @@ -237,27 +204,30 @@ func (svc *application) Undelete(ID uint64) (err error) { return ApplicationErrInvalidID() } - if app, err = svc.application.FindByID(ID); err != nil { + if app, err = svc.store.LookupApplicationByID(ctx, ID); err != nil { return } - if !svc.ac.CanDeleteApplication(svc.ctx, app) { + aaProps.setApplication(app) + + if !svc.ac.CanDeleteApplication(ctx, app) { return ApplicationErrNotAllowedToUndelete() } // @todo add event - // if err = svc.eventbus.WaitFor(svc.ctx, event.ApplicationBeforeUndelete(nil, app)); err != nil { + // if err = svc.eventbus.WaitFor(ctx, event.ApplicationBeforeUndelete(nil, app)); err != nil { // return // } - if err = svc.application.UndeleteByID(ID); err != nil { + app.DeletedAt = nil + if err = svc.store.PartialUpdateApplication(ctx, []string{"UpdatedAt"}, app); err != nil { return } // @todo add event - // _ = svc.eventbus.WaitFor(svc.ctx, event.ApplicationAfterUndelete(nil, app)) + // _ = svc.eventbus.WaitFor(ctx, event.ApplicationAfterUndelete(nil, app)) return nil }() - return svc.recordAction(svc.ctx, aaProps, ApplicationActionDelete, err) + return svc.recordAction(ctx, aaProps, ApplicationActionUndelete, err) } diff --git a/system/service/application_actions.gen.go b/system/service/application_actions.gen.go index 1b767e3ad..353b06171 100644 --- a/system/service/application_actions.gen.go +++ b/system/service/application_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from system/service/application_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// system/service/application_actions.yaml import ( "context" diff --git a/system/service/attachment.go b/system/service/attachment.go index bf5d62774..84ff4cba9 100644 --- a/system/service/attachment.go +++ b/system/service/attachment.go @@ -11,8 +11,6 @@ import ( "strings" "github.com/cortezaproject/corteza-server/pkg/actionlog" - "github.com/cortezaproject/corteza-server/pkg/settings" - "github.com/disintegration/imaging" "github.com/edwvee/exiffix" "github.com/pkg/errors" @@ -40,8 +38,6 @@ type ( ac attachmentAccessController - settingsSvc settings.Service - attachment repository.AttachmentRepository } @@ -67,8 +63,6 @@ func Attachment(store store.Store) AttachmentService { actionlog: DefaultActionlog, ac: DefaultAccessControl, - - settingsSvc: DefaultSettings, }).With(context.Background()) } @@ -81,8 +75,6 @@ func (svc attachment) With(ctx context.Context) AttachmentService { actionlog: svc.actionlog, ac: svc.ac, - settingsSvc: svc.settingsSvc, - store: svc.store, attachment: repository.Attachment(ctx, db), diff --git a/system/service/attachment_actions.gen.go b/system/service/attachment_actions.gen.go index fcd5fe424..5601a7604 100644 --- a/system/service/attachment_actions.gen.go +++ b/system/service/attachment_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from system/service/attachment_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// system/service/attachment_actions.yaml import ( "context" diff --git a/system/service/auth.go b/system/service/auth.go index 94f60cf70..47f0d9a1e 100644 --- a/system/service/auth.go +++ b/system/service/auth.go @@ -34,7 +34,7 @@ type ( credentials repository.CredentialsRepository users repository.UserRepository roles repository.RoleRepository - settings *types.Settings + settings *types.AppSettings notifications AuthNotificationService providerValidator func(string) error diff --git a/system/service/auth_actions.gen.go b/system/service/auth_actions.gen.go index 7cb810b0f..97d37a28e 100644 --- a/system/service/auth_actions.gen.go +++ b/system/service/auth_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from system/service/auth_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// system/service/auth_actions.yaml import ( "context" diff --git a/system/service/auth_notification.go b/system/service/auth_notification.go index de56dc170..65393a665 100644 --- a/system/service/auth_notification.go +++ b/system/service/auth_notification.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "github.com/cortezaproject/corteza-server/system/types" "html/template" "go.uber.org/zap" @@ -12,14 +13,13 @@ import ( "github.com/cortezaproject/corteza-server/pkg/logger" "github.com/cortezaproject/corteza-server/pkg/mail" - "github.com/cortezaproject/corteza-server/system/types" ) type ( authNotification struct { ctx context.Context logger *zap.Logger - settings *types.Settings + settings *types.AppSettings } AuthNotificationService interface { diff --git a/system/service/current_settings.go b/system/service/current_settings.go new file mode 100644 index 000000000..6d43c3366 --- /dev/null +++ b/system/service/current_settings.go @@ -0,0 +1 @@ +package service diff --git a/system/service/event/application.gen.go b/system/service/event/application.gen.go deleted file mode 100644 index 9e1ffd33e..000000000 --- a/system/service/event/application.gen.go +++ /dev/null @@ -1,461 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// system/service/event/events.yaml -// -// Regenerate with: -// go run ./codegen/v2/events --service system -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/system/types" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // applicationBase - // - // This type is auto-generated. - applicationBase struct { - immutable bool - application *types.Application - oldApplication *types.Application - invoker auth.Identifiable - } - - // applicationOnManual - // - // This type is auto-generated. - applicationOnManual struct { - *applicationBase - } - - // applicationBeforeCreate - // - // This type is auto-generated. - applicationBeforeCreate struct { - *applicationBase - } - - // applicationBeforeUpdate - // - // This type is auto-generated. - applicationBeforeUpdate struct { - *applicationBase - } - - // applicationBeforeDelete - // - // This type is auto-generated. - applicationBeforeDelete struct { - *applicationBase - } - - // applicationAfterCreate - // - // This type is auto-generated. - applicationAfterCreate struct { - *applicationBase - } - - // applicationAfterUpdate - // - // This type is auto-generated. - applicationAfterUpdate struct { - *applicationBase - } - - // applicationAfterDelete - // - // This type is auto-generated. - applicationAfterDelete struct { - *applicationBase - } -) - -// ResourceType returns "system:application" -// -// This function is auto-generated. -func (applicationBase) ResourceType() string { - return "system:application" -} - -// EventType on applicationOnManual returns "onManual" -// -// This function is auto-generated. -func (applicationOnManual) EventType() string { - return "onManual" -} - -// EventType on applicationBeforeCreate returns "beforeCreate" -// -// This function is auto-generated. -func (applicationBeforeCreate) EventType() string { - return "beforeCreate" -} - -// EventType on applicationBeforeUpdate returns "beforeUpdate" -// -// This function is auto-generated. -func (applicationBeforeUpdate) EventType() string { - return "beforeUpdate" -} - -// EventType on applicationBeforeDelete returns "beforeDelete" -// -// This function is auto-generated. -func (applicationBeforeDelete) EventType() string { - return "beforeDelete" -} - -// EventType on applicationAfterCreate returns "afterCreate" -// -// This function is auto-generated. -func (applicationAfterCreate) EventType() string { - return "afterCreate" -} - -// EventType on applicationAfterUpdate returns "afterUpdate" -// -// This function is auto-generated. -func (applicationAfterUpdate) EventType() string { - return "afterUpdate" -} - -// EventType on applicationAfterDelete returns "afterDelete" -// -// This function is auto-generated. -func (applicationAfterDelete) EventType() string { - return "afterDelete" -} - -// ApplicationOnManual creates onManual for system:application resource -// -// This function is auto-generated. -func ApplicationOnManual( - argApplication *types.Application, - argOldApplication *types.Application, -) *applicationOnManual { - return &applicationOnManual{ - applicationBase: &applicationBase{ - immutable: false, - application: argApplication, - oldApplication: argOldApplication, - }, - } -} - -// ApplicationOnManualImmutable creates onManual for system:application resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ApplicationOnManualImmutable( - argApplication *types.Application, - argOldApplication *types.Application, -) *applicationOnManual { - return &applicationOnManual{ - applicationBase: &applicationBase{ - immutable: true, - application: argApplication, - oldApplication: argOldApplication, - }, - } -} - -// ApplicationBeforeCreate creates beforeCreate for system:application resource -// -// This function is auto-generated. -func ApplicationBeforeCreate( - argApplication *types.Application, - argOldApplication *types.Application, -) *applicationBeforeCreate { - return &applicationBeforeCreate{ - applicationBase: &applicationBase{ - immutable: false, - application: argApplication, - oldApplication: argOldApplication, - }, - } -} - -// ApplicationBeforeCreateImmutable creates beforeCreate for system:application resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ApplicationBeforeCreateImmutable( - argApplication *types.Application, - argOldApplication *types.Application, -) *applicationBeforeCreate { - return &applicationBeforeCreate{ - applicationBase: &applicationBase{ - immutable: true, - application: argApplication, - oldApplication: argOldApplication, - }, - } -} - -// ApplicationBeforeUpdate creates beforeUpdate for system:application resource -// -// This function is auto-generated. -func ApplicationBeforeUpdate( - argApplication *types.Application, - argOldApplication *types.Application, -) *applicationBeforeUpdate { - return &applicationBeforeUpdate{ - applicationBase: &applicationBase{ - immutable: false, - application: argApplication, - oldApplication: argOldApplication, - }, - } -} - -// ApplicationBeforeUpdateImmutable creates beforeUpdate for system:application resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ApplicationBeforeUpdateImmutable( - argApplication *types.Application, - argOldApplication *types.Application, -) *applicationBeforeUpdate { - return &applicationBeforeUpdate{ - applicationBase: &applicationBase{ - immutable: true, - application: argApplication, - oldApplication: argOldApplication, - }, - } -} - -// ApplicationBeforeDelete creates beforeDelete for system:application resource -// -// This function is auto-generated. -func ApplicationBeforeDelete( - argApplication *types.Application, - argOldApplication *types.Application, -) *applicationBeforeDelete { - return &applicationBeforeDelete{ - applicationBase: &applicationBase{ - immutable: false, - application: argApplication, - oldApplication: argOldApplication, - }, - } -} - -// ApplicationBeforeDeleteImmutable creates beforeDelete for system:application resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ApplicationBeforeDeleteImmutable( - argApplication *types.Application, - argOldApplication *types.Application, -) *applicationBeforeDelete { - return &applicationBeforeDelete{ - applicationBase: &applicationBase{ - immutable: true, - application: argApplication, - oldApplication: argOldApplication, - }, - } -} - -// ApplicationAfterCreate creates afterCreate for system:application resource -// -// This function is auto-generated. -func ApplicationAfterCreate( - argApplication *types.Application, - argOldApplication *types.Application, -) *applicationAfterCreate { - return &applicationAfterCreate{ - applicationBase: &applicationBase{ - immutable: false, - application: argApplication, - oldApplication: argOldApplication, - }, - } -} - -// ApplicationAfterCreateImmutable creates afterCreate for system:application resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ApplicationAfterCreateImmutable( - argApplication *types.Application, - argOldApplication *types.Application, -) *applicationAfterCreate { - return &applicationAfterCreate{ - applicationBase: &applicationBase{ - immutable: true, - application: argApplication, - oldApplication: argOldApplication, - }, - } -} - -// ApplicationAfterUpdate creates afterUpdate for system:application resource -// -// This function is auto-generated. -func ApplicationAfterUpdate( - argApplication *types.Application, - argOldApplication *types.Application, -) *applicationAfterUpdate { - return &applicationAfterUpdate{ - applicationBase: &applicationBase{ - immutable: false, - application: argApplication, - oldApplication: argOldApplication, - }, - } -} - -// ApplicationAfterUpdateImmutable creates afterUpdate for system:application resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ApplicationAfterUpdateImmutable( - argApplication *types.Application, - argOldApplication *types.Application, -) *applicationAfterUpdate { - return &applicationAfterUpdate{ - applicationBase: &applicationBase{ - immutable: true, - application: argApplication, - oldApplication: argOldApplication, - }, - } -} - -// ApplicationAfterDelete creates afterDelete for system:application resource -// -// This function is auto-generated. -func ApplicationAfterDelete( - argApplication *types.Application, - argOldApplication *types.Application, -) *applicationAfterDelete { - return &applicationAfterDelete{ - applicationBase: &applicationBase{ - immutable: false, - application: argApplication, - oldApplication: argOldApplication, - }, - } -} - -// ApplicationAfterDeleteImmutable creates afterDelete for system:application resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func ApplicationAfterDeleteImmutable( - argApplication *types.Application, - argOldApplication *types.Application, -) *applicationAfterDelete { - return &applicationAfterDelete{ - applicationBase: &applicationBase{ - immutable: true, - application: argApplication, - oldApplication: argOldApplication, - }, - } -} - -// SetApplication sets new application value -// -// This function is auto-generated. -func (res *applicationBase) SetApplication(argApplication *types.Application) { - res.application = argApplication -} - -// Application returns application -// -// This function is auto-generated. -func (res applicationBase) Application() *types.Application { - return res.application -} - -// OldApplication returns oldApplication -// -// This function is auto-generated. -func (res applicationBase) OldApplication() *types.Application { - return res.oldApplication -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *applicationBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res applicationBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res applicationBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["application"], err = json.Marshal(res.application); err != nil { - return nil, err - } - - if args["oldApplication"], err = json.Marshal(res.oldApplication); err != nil { - return nil, err - } - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *applicationBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.application != nil { - if r, ok := results["result"]; ok && len(results) == 1 { - if err = json.Unmarshal(r, res.application); err != nil { - return - } - } - } - - if res.application != nil { - if r, ok := results["application"]; ok { - if err = json.Unmarshal(r, res.application); err != nil { - return - } - } - } - - // Do not decode oldApplication; marked as immutable - - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/system/service/event/auth.gen.go b/system/service/event/auth.gen.go deleted file mode 100644 index 4729bcfec..000000000 --- a/system/service/event/auth.gen.go +++ /dev/null @@ -1,330 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// system/service/event/events.yaml -// -// Regenerate with: -// go run ./codegen/v2/events --service system -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/system/types" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // authBase - // - // This type is auto-generated. - authBase struct { - immutable bool - user *types.User - provider *types.AuthProvider - invoker auth.Identifiable - } - - // authBeforeLogin - // - // This type is auto-generated. - authBeforeLogin struct { - *authBase - } - - // authBeforeSignup - // - // This type is auto-generated. - authBeforeSignup struct { - *authBase - } - - // authAfterLogin - // - // This type is auto-generated. - authAfterLogin struct { - *authBase - } - - // authAfterSignup - // - // This type is auto-generated. - authAfterSignup struct { - *authBase - } -) - -// ResourceType returns "system:auth" -// -// This function is auto-generated. -func (authBase) ResourceType() string { - return "system:auth" -} - -// EventType on authBeforeLogin returns "beforeLogin" -// -// This function is auto-generated. -func (authBeforeLogin) EventType() string { - return "beforeLogin" -} - -// EventType on authBeforeSignup returns "beforeSignup" -// -// This function is auto-generated. -func (authBeforeSignup) EventType() string { - return "beforeSignup" -} - -// EventType on authAfterLogin returns "afterLogin" -// -// This function is auto-generated. -func (authAfterLogin) EventType() string { - return "afterLogin" -} - -// EventType on authAfterSignup returns "afterSignup" -// -// This function is auto-generated. -func (authAfterSignup) EventType() string { - return "afterSignup" -} - -// AuthBeforeLogin creates beforeLogin for system:auth resource -// -// This function is auto-generated. -func AuthBeforeLogin( - argUser *types.User, - argProvider *types.AuthProvider, -) *authBeforeLogin { - return &authBeforeLogin{ - authBase: &authBase{ - immutable: false, - user: argUser, - provider: argProvider, - }, - } -} - -// AuthBeforeLoginImmutable creates beforeLogin for system:auth resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func AuthBeforeLoginImmutable( - argUser *types.User, - argProvider *types.AuthProvider, -) *authBeforeLogin { - return &authBeforeLogin{ - authBase: &authBase{ - immutable: true, - user: argUser, - provider: argProvider, - }, - } -} - -// AuthBeforeSignup creates beforeSignup for system:auth resource -// -// This function is auto-generated. -func AuthBeforeSignup( - argUser *types.User, - argProvider *types.AuthProvider, -) *authBeforeSignup { - return &authBeforeSignup{ - authBase: &authBase{ - immutable: false, - user: argUser, - provider: argProvider, - }, - } -} - -// AuthBeforeSignupImmutable creates beforeSignup for system:auth resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func AuthBeforeSignupImmutable( - argUser *types.User, - argProvider *types.AuthProvider, -) *authBeforeSignup { - return &authBeforeSignup{ - authBase: &authBase{ - immutable: true, - user: argUser, - provider: argProvider, - }, - } -} - -// AuthAfterLogin creates afterLogin for system:auth resource -// -// This function is auto-generated. -func AuthAfterLogin( - argUser *types.User, - argProvider *types.AuthProvider, -) *authAfterLogin { - return &authAfterLogin{ - authBase: &authBase{ - immutable: false, - user: argUser, - provider: argProvider, - }, - } -} - -// AuthAfterLoginImmutable creates afterLogin for system:auth resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func AuthAfterLoginImmutable( - argUser *types.User, - argProvider *types.AuthProvider, -) *authAfterLogin { - return &authAfterLogin{ - authBase: &authBase{ - immutable: true, - user: argUser, - provider: argProvider, - }, - } -} - -// AuthAfterSignup creates afterSignup for system:auth resource -// -// This function is auto-generated. -func AuthAfterSignup( - argUser *types.User, - argProvider *types.AuthProvider, -) *authAfterSignup { - return &authAfterSignup{ - authBase: &authBase{ - immutable: false, - user: argUser, - provider: argProvider, - }, - } -} - -// AuthAfterSignupImmutable creates afterSignup for system:auth resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func AuthAfterSignupImmutable( - argUser *types.User, - argProvider *types.AuthProvider, -) *authAfterSignup { - return &authAfterSignup{ - authBase: &authBase{ - immutable: true, - user: argUser, - provider: argProvider, - }, - } -} - -// SetUser sets new user value -// -// This function is auto-generated. -func (res *authBase) SetUser(argUser *types.User) { - res.user = argUser -} - -// User returns user -// -// This function is auto-generated. -func (res authBase) User() *types.User { - return res.user -} - -// SetProvider sets new provider value -// -// This function is auto-generated. -func (res *authBase) SetProvider(argProvider *types.AuthProvider) { - res.provider = argProvider -} - -// Provider returns provider -// -// This function is auto-generated. -func (res authBase) Provider() *types.AuthProvider { - return res.provider -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *authBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res authBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res authBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["user"], err = json.Marshal(res.user); err != nil { - return nil, err - } - - if args["provider"], err = json.Marshal(res.provider); err != nil { - return nil, err - } - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *authBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.user != nil { - if r, ok := results["result"]; ok && len(results) == 1 { - if err = json.Unmarshal(r, res.user); err != nil { - return - } - } - } - - if res.user != nil { - if r, ok := results["user"]; ok { - if err = json.Unmarshal(r, res.user); err != nil { - return - } - } - } - - if res.provider != nil { - if r, ok := results["provider"]; ok { - if err = json.Unmarshal(r, res.provider); err != nil { - return - } - } - } - - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/system/service/event/events.gen.go b/system/service/event/events.gen.go new file mode 100644 index 000000000..f79106d5e --- /dev/null +++ b/system/service/event/events.gen.go @@ -0,0 +1,2510 @@ +package event + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// system/service/event/events.yaml + +import ( + "encoding/json" + "github.com/cortezaproject/corteza-server/pkg/auth" + "github.com/cortezaproject/corteza-server/system/types" +) + +// dummy placing to simplify import generation logic +var _ = json.NewEncoder + +type ( + + // systemBase + // + // This type is auto-generated. + systemBase struct { + immutable bool + invoker auth.Identifiable + } + + // systemOnManual + // + // This type is auto-generated. + systemOnManual struct { + *systemBase + } + + // systemOnInterval + // + // This type is auto-generated. + systemOnInterval struct { + *systemBase + } + + // systemOnTimestamp + // + // This type is auto-generated. + systemOnTimestamp struct { + *systemBase + } + + // applicationBase + // + // This type is auto-generated. + applicationBase struct { + immutable bool + application *types.Application + oldApplication *types.Application + invoker auth.Identifiable + } + + // applicationOnManual + // + // This type is auto-generated. + applicationOnManual struct { + *applicationBase + } + + // applicationBeforeCreate + // + // This type is auto-generated. + applicationBeforeCreate struct { + *applicationBase + } + + // applicationBeforeUpdate + // + // This type is auto-generated. + applicationBeforeUpdate struct { + *applicationBase + } + + // applicationBeforeDelete + // + // This type is auto-generated. + applicationBeforeDelete struct { + *applicationBase + } + + // applicationAfterCreate + // + // This type is auto-generated. + applicationAfterCreate struct { + *applicationBase + } + + // applicationAfterUpdate + // + // This type is auto-generated. + applicationAfterUpdate struct { + *applicationBase + } + + // applicationAfterDelete + // + // This type is auto-generated. + applicationAfterDelete struct { + *applicationBase + } + + // authBase + // + // This type is auto-generated. + authBase struct { + immutable bool + user *types.User + provider *types.AuthProvider + invoker auth.Identifiable + } + + // authBeforeLogin + // + // This type is auto-generated. + authBeforeLogin struct { + *authBase + } + + // authBeforeSignup + // + // This type is auto-generated. + authBeforeSignup struct { + *authBase + } + + // authAfterLogin + // + // This type is auto-generated. + authAfterLogin struct { + *authBase + } + + // authAfterSignup + // + // This type is auto-generated. + authAfterSignup struct { + *authBase + } + + // mailBase + // + // This type is auto-generated. + mailBase struct { + immutable bool + message *types.MailMessage + invoker auth.Identifiable + } + + // mailOnManual + // + // This type is auto-generated. + mailOnManual struct { + *mailBase + } + + // mailOnReceive + // + // This type is auto-generated. + mailOnReceive struct { + *mailBase + } + + // mailOnSend + // + // This type is auto-generated. + mailOnSend struct { + *mailBase + } + + // roleBase + // + // This type is auto-generated. + roleBase struct { + immutable bool + role *types.Role + oldRole *types.Role + invoker auth.Identifiable + } + + // roleOnManual + // + // This type is auto-generated. + roleOnManual struct { + *roleBase + } + + // roleBeforeCreate + // + // This type is auto-generated. + roleBeforeCreate struct { + *roleBase + } + + // roleBeforeUpdate + // + // This type is auto-generated. + roleBeforeUpdate struct { + *roleBase + } + + // roleBeforeDelete + // + // This type is auto-generated. + roleBeforeDelete struct { + *roleBase + } + + // roleAfterCreate + // + // This type is auto-generated. + roleAfterCreate struct { + *roleBase + } + + // roleAfterUpdate + // + // This type is auto-generated. + roleAfterUpdate struct { + *roleBase + } + + // roleAfterDelete + // + // This type is auto-generated. + roleAfterDelete struct { + *roleBase + } + + // roleMemberBase + // + // This type is auto-generated. + roleMemberBase struct { + immutable bool + user *types.User + role *types.Role + invoker auth.Identifiable + } + + // roleMemberBeforeAdd + // + // This type is auto-generated. + roleMemberBeforeAdd struct { + *roleMemberBase + } + + // roleMemberBeforeRemove + // + // This type is auto-generated. + roleMemberBeforeRemove struct { + *roleMemberBase + } + + // roleMemberAfterAdd + // + // This type is auto-generated. + roleMemberAfterAdd struct { + *roleMemberBase + } + + // roleMemberAfterRemove + // + // This type is auto-generated. + roleMemberAfterRemove struct { + *roleMemberBase + } + + // sinkBase + // + // This type is auto-generated. + sinkBase struct { + immutable bool + response *types.SinkResponse + request *types.SinkRequest + invoker auth.Identifiable + } + + // sinkOnRequest + // + // This type is auto-generated. + sinkOnRequest struct { + *sinkBase + } + + // userBase + // + // This type is auto-generated. + userBase struct { + immutable bool + user *types.User + oldUser *types.User + invoker auth.Identifiable + } + + // userOnManual + // + // This type is auto-generated. + userOnManual struct { + *userBase + } + + // userBeforeCreate + // + // This type is auto-generated. + userBeforeCreate struct { + *userBase + } + + // userBeforeUpdate + // + // This type is auto-generated. + userBeforeUpdate struct { + *userBase + } + + // userBeforeDelete + // + // This type is auto-generated. + userBeforeDelete struct { + *userBase + } + + // userAfterCreate + // + // This type is auto-generated. + userAfterCreate struct { + *userBase + } + + // userAfterUpdate + // + // This type is auto-generated. + userAfterUpdate struct { + *userBase + } + + // userAfterDelete + // + // This type is auto-generated. + userAfterDelete struct { + *userBase + } +) + +// ResourceType returns "system" +// +// This function is auto-generated. +func (systemBase) ResourceType() string { + return "system" +} + +// EventType on systemOnManual returns "onManual" +// +// This function is auto-generated. +func (systemOnManual) EventType() string { + return "onManual" +} + +// EventType on systemOnInterval returns "onInterval" +// +// This function is auto-generated. +func (systemOnInterval) EventType() string { + return "onInterval" +} + +// EventType on systemOnTimestamp returns "onTimestamp" +// +// This function is auto-generated. +func (systemOnTimestamp) EventType() string { + return "onTimestamp" +} + +// SystemOnManual creates onManual for system resource +// +// This function is auto-generated. +func SystemOnManual() *systemOnManual { + return &systemOnManual{ + systemBase: &systemBase{ + immutable: false, + }, + } +} + +// SystemOnManualImmutable creates onManual for system resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func SystemOnManualImmutable() *systemOnManual { + return &systemOnManual{ + systemBase: &systemBase{ + immutable: true, + }, + } +} + +// SystemOnInterval creates onInterval for system resource +// +// This function is auto-generated. +func SystemOnInterval() *systemOnInterval { + return &systemOnInterval{ + systemBase: &systemBase{ + immutable: false, + }, + } +} + +// SystemOnIntervalImmutable creates onInterval for system resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func SystemOnIntervalImmutable() *systemOnInterval { + return &systemOnInterval{ + systemBase: &systemBase{ + immutable: true, + }, + } +} + +// SystemOnTimestamp creates onTimestamp for system resource +// +// This function is auto-generated. +func SystemOnTimestamp() *systemOnTimestamp { + return &systemOnTimestamp{ + systemBase: &systemBase{ + immutable: false, + }, + } +} + +// SystemOnTimestampImmutable creates onTimestamp for system resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func SystemOnTimestampImmutable() *systemOnTimestamp { + return &systemOnTimestamp{ + systemBase: &systemBase{ + immutable: true, + }, + } +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *systemBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res systemBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res systemBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *systemBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} + +// ResourceType returns "system:application" +// +// This function is auto-generated. +func (applicationBase) ResourceType() string { + return "system:application" +} + +// EventType on applicationOnManual returns "onManual" +// +// This function is auto-generated. +func (applicationOnManual) EventType() string { + return "onManual" +} + +// EventType on applicationBeforeCreate returns "beforeCreate" +// +// This function is auto-generated. +func (applicationBeforeCreate) EventType() string { + return "beforeCreate" +} + +// EventType on applicationBeforeUpdate returns "beforeUpdate" +// +// This function is auto-generated. +func (applicationBeforeUpdate) EventType() string { + return "beforeUpdate" +} + +// EventType on applicationBeforeDelete returns "beforeDelete" +// +// This function is auto-generated. +func (applicationBeforeDelete) EventType() string { + return "beforeDelete" +} + +// EventType on applicationAfterCreate returns "afterCreate" +// +// This function is auto-generated. +func (applicationAfterCreate) EventType() string { + return "afterCreate" +} + +// EventType on applicationAfterUpdate returns "afterUpdate" +// +// This function is auto-generated. +func (applicationAfterUpdate) EventType() string { + return "afterUpdate" +} + +// EventType on applicationAfterDelete returns "afterDelete" +// +// This function is auto-generated. +func (applicationAfterDelete) EventType() string { + return "afterDelete" +} + +// ApplicationOnManual creates onManual for system:application resource +// +// This function is auto-generated. +func ApplicationOnManual( + argApplication *types.Application, + argOldApplication *types.Application, +) *applicationOnManual { + return &applicationOnManual{ + applicationBase: &applicationBase{ + immutable: false, + application: argApplication, + oldApplication: argOldApplication, + }, + } +} + +// ApplicationOnManualImmutable creates onManual for system:application resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ApplicationOnManualImmutable( + argApplication *types.Application, + argOldApplication *types.Application, +) *applicationOnManual { + return &applicationOnManual{ + applicationBase: &applicationBase{ + immutable: true, + application: argApplication, + oldApplication: argOldApplication, + }, + } +} + +// ApplicationBeforeCreate creates beforeCreate for system:application resource +// +// This function is auto-generated. +func ApplicationBeforeCreate( + argApplication *types.Application, + argOldApplication *types.Application, +) *applicationBeforeCreate { + return &applicationBeforeCreate{ + applicationBase: &applicationBase{ + immutable: false, + application: argApplication, + oldApplication: argOldApplication, + }, + } +} + +// ApplicationBeforeCreateImmutable creates beforeCreate for system:application resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ApplicationBeforeCreateImmutable( + argApplication *types.Application, + argOldApplication *types.Application, +) *applicationBeforeCreate { + return &applicationBeforeCreate{ + applicationBase: &applicationBase{ + immutable: true, + application: argApplication, + oldApplication: argOldApplication, + }, + } +} + +// ApplicationBeforeUpdate creates beforeUpdate for system:application resource +// +// This function is auto-generated. +func ApplicationBeforeUpdate( + argApplication *types.Application, + argOldApplication *types.Application, +) *applicationBeforeUpdate { + return &applicationBeforeUpdate{ + applicationBase: &applicationBase{ + immutable: false, + application: argApplication, + oldApplication: argOldApplication, + }, + } +} + +// ApplicationBeforeUpdateImmutable creates beforeUpdate for system:application resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ApplicationBeforeUpdateImmutable( + argApplication *types.Application, + argOldApplication *types.Application, +) *applicationBeforeUpdate { + return &applicationBeforeUpdate{ + applicationBase: &applicationBase{ + immutable: true, + application: argApplication, + oldApplication: argOldApplication, + }, + } +} + +// ApplicationBeforeDelete creates beforeDelete for system:application resource +// +// This function is auto-generated. +func ApplicationBeforeDelete( + argApplication *types.Application, + argOldApplication *types.Application, +) *applicationBeforeDelete { + return &applicationBeforeDelete{ + applicationBase: &applicationBase{ + immutable: false, + application: argApplication, + oldApplication: argOldApplication, + }, + } +} + +// ApplicationBeforeDeleteImmutable creates beforeDelete for system:application resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ApplicationBeforeDeleteImmutable( + argApplication *types.Application, + argOldApplication *types.Application, +) *applicationBeforeDelete { + return &applicationBeforeDelete{ + applicationBase: &applicationBase{ + immutable: true, + application: argApplication, + oldApplication: argOldApplication, + }, + } +} + +// ApplicationAfterCreate creates afterCreate for system:application resource +// +// This function is auto-generated. +func ApplicationAfterCreate( + argApplication *types.Application, + argOldApplication *types.Application, +) *applicationAfterCreate { + return &applicationAfterCreate{ + applicationBase: &applicationBase{ + immutable: false, + application: argApplication, + oldApplication: argOldApplication, + }, + } +} + +// ApplicationAfterCreateImmutable creates afterCreate for system:application resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ApplicationAfterCreateImmutable( + argApplication *types.Application, + argOldApplication *types.Application, +) *applicationAfterCreate { + return &applicationAfterCreate{ + applicationBase: &applicationBase{ + immutable: true, + application: argApplication, + oldApplication: argOldApplication, + }, + } +} + +// ApplicationAfterUpdate creates afterUpdate for system:application resource +// +// This function is auto-generated. +func ApplicationAfterUpdate( + argApplication *types.Application, + argOldApplication *types.Application, +) *applicationAfterUpdate { + return &applicationAfterUpdate{ + applicationBase: &applicationBase{ + immutable: false, + application: argApplication, + oldApplication: argOldApplication, + }, + } +} + +// ApplicationAfterUpdateImmutable creates afterUpdate for system:application resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ApplicationAfterUpdateImmutable( + argApplication *types.Application, + argOldApplication *types.Application, +) *applicationAfterUpdate { + return &applicationAfterUpdate{ + applicationBase: &applicationBase{ + immutable: true, + application: argApplication, + oldApplication: argOldApplication, + }, + } +} + +// ApplicationAfterDelete creates afterDelete for system:application resource +// +// This function is auto-generated. +func ApplicationAfterDelete( + argApplication *types.Application, + argOldApplication *types.Application, +) *applicationAfterDelete { + return &applicationAfterDelete{ + applicationBase: &applicationBase{ + immutable: false, + application: argApplication, + oldApplication: argOldApplication, + }, + } +} + +// ApplicationAfterDeleteImmutable creates afterDelete for system:application resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func ApplicationAfterDeleteImmutable( + argApplication *types.Application, + argOldApplication *types.Application, +) *applicationAfterDelete { + return &applicationAfterDelete{ + applicationBase: &applicationBase{ + immutable: true, + application: argApplication, + oldApplication: argOldApplication, + }, + } +} + +// SetApplication sets new application value +// +// This function is auto-generated. +func (res *applicationBase) SetApplication(argApplication *types.Application) { + res.application = argApplication +} + +// Application returns application +// +// This function is auto-generated. +func (res applicationBase) Application() *types.Application { + return res.application +} + +// OldApplication returns oldApplication +// +// This function is auto-generated. +func (res applicationBase) OldApplication() *types.Application { + return res.oldApplication +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *applicationBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res applicationBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res applicationBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["application"], err = json.Marshal(res.application); err != nil { + return nil, err + } + + if args["oldApplication"], err = json.Marshal(res.oldApplication); err != nil { + return nil, err + } + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *applicationBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.application != nil { + if r, ok := results["result"]; ok && len(results) == 1 { + if err = json.Unmarshal(r, res.application); err != nil { + return + } + } + } + + if res.application != nil { + if r, ok := results["application"]; ok { + if err = json.Unmarshal(r, res.application); err != nil { + return + } + } + } + + // Do not decode oldApplication; marked as immutable + + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} + +// ResourceType returns "system:auth" +// +// This function is auto-generated. +func (authBase) ResourceType() string { + return "system:auth" +} + +// EventType on authBeforeLogin returns "beforeLogin" +// +// This function is auto-generated. +func (authBeforeLogin) EventType() string { + return "beforeLogin" +} + +// EventType on authBeforeSignup returns "beforeSignup" +// +// This function is auto-generated. +func (authBeforeSignup) EventType() string { + return "beforeSignup" +} + +// EventType on authAfterLogin returns "afterLogin" +// +// This function is auto-generated. +func (authAfterLogin) EventType() string { + return "afterLogin" +} + +// EventType on authAfterSignup returns "afterSignup" +// +// This function is auto-generated. +func (authAfterSignup) EventType() string { + return "afterSignup" +} + +// AuthBeforeLogin creates beforeLogin for system:auth resource +// +// This function is auto-generated. +func AuthBeforeLogin( + argUser *types.User, + argProvider *types.AuthProvider, +) *authBeforeLogin { + return &authBeforeLogin{ + authBase: &authBase{ + immutable: false, + user: argUser, + provider: argProvider, + }, + } +} + +// AuthBeforeLoginImmutable creates beforeLogin for system:auth resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func AuthBeforeLoginImmutable( + argUser *types.User, + argProvider *types.AuthProvider, +) *authBeforeLogin { + return &authBeforeLogin{ + authBase: &authBase{ + immutable: true, + user: argUser, + provider: argProvider, + }, + } +} + +// AuthBeforeSignup creates beforeSignup for system:auth resource +// +// This function is auto-generated. +func AuthBeforeSignup( + argUser *types.User, + argProvider *types.AuthProvider, +) *authBeforeSignup { + return &authBeforeSignup{ + authBase: &authBase{ + immutable: false, + user: argUser, + provider: argProvider, + }, + } +} + +// AuthBeforeSignupImmutable creates beforeSignup for system:auth resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func AuthBeforeSignupImmutable( + argUser *types.User, + argProvider *types.AuthProvider, +) *authBeforeSignup { + return &authBeforeSignup{ + authBase: &authBase{ + immutable: true, + user: argUser, + provider: argProvider, + }, + } +} + +// AuthAfterLogin creates afterLogin for system:auth resource +// +// This function is auto-generated. +func AuthAfterLogin( + argUser *types.User, + argProvider *types.AuthProvider, +) *authAfterLogin { + return &authAfterLogin{ + authBase: &authBase{ + immutable: false, + user: argUser, + provider: argProvider, + }, + } +} + +// AuthAfterLoginImmutable creates afterLogin for system:auth resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func AuthAfterLoginImmutable( + argUser *types.User, + argProvider *types.AuthProvider, +) *authAfterLogin { + return &authAfterLogin{ + authBase: &authBase{ + immutable: true, + user: argUser, + provider: argProvider, + }, + } +} + +// AuthAfterSignup creates afterSignup for system:auth resource +// +// This function is auto-generated. +func AuthAfterSignup( + argUser *types.User, + argProvider *types.AuthProvider, +) *authAfterSignup { + return &authAfterSignup{ + authBase: &authBase{ + immutable: false, + user: argUser, + provider: argProvider, + }, + } +} + +// AuthAfterSignupImmutable creates afterSignup for system:auth resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func AuthAfterSignupImmutable( + argUser *types.User, + argProvider *types.AuthProvider, +) *authAfterSignup { + return &authAfterSignup{ + authBase: &authBase{ + immutable: true, + user: argUser, + provider: argProvider, + }, + } +} + +// SetUser sets new user value +// +// This function is auto-generated. +func (res *authBase) SetUser(argUser *types.User) { + res.user = argUser +} + +// User returns user +// +// This function is auto-generated. +func (res authBase) User() *types.User { + return res.user +} + +// SetProvider sets new provider value +// +// This function is auto-generated. +func (res *authBase) SetProvider(argProvider *types.AuthProvider) { + res.provider = argProvider +} + +// Provider returns provider +// +// This function is auto-generated. +func (res authBase) Provider() *types.AuthProvider { + return res.provider +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *authBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res authBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res authBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["user"], err = json.Marshal(res.user); err != nil { + return nil, err + } + + if args["provider"], err = json.Marshal(res.provider); err != nil { + return nil, err + } + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *authBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.user != nil { + if r, ok := results["result"]; ok && len(results) == 1 { + if err = json.Unmarshal(r, res.user); err != nil { + return + } + } + } + + if res.user != nil { + if r, ok := results["user"]; ok { + if err = json.Unmarshal(r, res.user); err != nil { + return + } + } + } + + if res.provider != nil { + if r, ok := results["provider"]; ok { + if err = json.Unmarshal(r, res.provider); err != nil { + return + } + } + } + + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} + +// ResourceType returns "system:mail" +// +// This function is auto-generated. +func (mailBase) ResourceType() string { + return "system:mail" +} + +// EventType on mailOnManual returns "onManual" +// +// This function is auto-generated. +func (mailOnManual) EventType() string { + return "onManual" +} + +// EventType on mailOnReceive returns "onReceive" +// +// This function is auto-generated. +func (mailOnReceive) EventType() string { + return "onReceive" +} + +// EventType on mailOnSend returns "onSend" +// +// This function is auto-generated. +func (mailOnSend) EventType() string { + return "onSend" +} + +// MailOnManual creates onManual for system:mail resource +// +// This function is auto-generated. +func MailOnManual( + argMessage *types.MailMessage, +) *mailOnManual { + return &mailOnManual{ + mailBase: &mailBase{ + immutable: false, + message: argMessage, + }, + } +} + +// MailOnManualImmutable creates onManual for system:mail resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func MailOnManualImmutable( + argMessage *types.MailMessage, +) *mailOnManual { + return &mailOnManual{ + mailBase: &mailBase{ + immutable: true, + message: argMessage, + }, + } +} + +// MailOnReceive creates onReceive for system:mail resource +// +// This function is auto-generated. +func MailOnReceive( + argMessage *types.MailMessage, +) *mailOnReceive { + return &mailOnReceive{ + mailBase: &mailBase{ + immutable: false, + message: argMessage, + }, + } +} + +// MailOnReceiveImmutable creates onReceive for system:mail resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func MailOnReceiveImmutable( + argMessage *types.MailMessage, +) *mailOnReceive { + return &mailOnReceive{ + mailBase: &mailBase{ + immutable: true, + message: argMessage, + }, + } +} + +// MailOnSend creates onSend for system:mail resource +// +// This function is auto-generated. +func MailOnSend( + argMessage *types.MailMessage, +) *mailOnSend { + return &mailOnSend{ + mailBase: &mailBase{ + immutable: false, + message: argMessage, + }, + } +} + +// MailOnSendImmutable creates onSend for system:mail resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func MailOnSendImmutable( + argMessage *types.MailMessage, +) *mailOnSend { + return &mailOnSend{ + mailBase: &mailBase{ + immutable: true, + message: argMessage, + }, + } +} + +// SetMessage sets new message value +// +// This function is auto-generated. +func (res *mailBase) SetMessage(argMessage *types.MailMessage) { + res.message = argMessage +} + +// Message returns message +// +// This function is auto-generated. +func (res mailBase) Message() *types.MailMessage { + return res.message +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *mailBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res mailBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res mailBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["message"], err = json.Marshal(res.message); err != nil { + return nil, err + } + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *mailBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.message != nil { + if r, ok := results["result"]; ok && len(results) == 1 { + if err = json.Unmarshal(r, res.message); err != nil { + return + } + } + } + + if res.message != nil { + if r, ok := results["message"]; ok { + if err = json.Unmarshal(r, res.message); err != nil { + return + } + } + } + + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} + +// ResourceType returns "system:role" +// +// This function is auto-generated. +func (roleBase) ResourceType() string { + return "system:role" +} + +// EventType on roleOnManual returns "onManual" +// +// This function is auto-generated. +func (roleOnManual) EventType() string { + return "onManual" +} + +// EventType on roleBeforeCreate returns "beforeCreate" +// +// This function is auto-generated. +func (roleBeforeCreate) EventType() string { + return "beforeCreate" +} + +// EventType on roleBeforeUpdate returns "beforeUpdate" +// +// This function is auto-generated. +func (roleBeforeUpdate) EventType() string { + return "beforeUpdate" +} + +// EventType on roleBeforeDelete returns "beforeDelete" +// +// This function is auto-generated. +func (roleBeforeDelete) EventType() string { + return "beforeDelete" +} + +// EventType on roleAfterCreate returns "afterCreate" +// +// This function is auto-generated. +func (roleAfterCreate) EventType() string { + return "afterCreate" +} + +// EventType on roleAfterUpdate returns "afterUpdate" +// +// This function is auto-generated. +func (roleAfterUpdate) EventType() string { + return "afterUpdate" +} + +// EventType on roleAfterDelete returns "afterDelete" +// +// This function is auto-generated. +func (roleAfterDelete) EventType() string { + return "afterDelete" +} + +// RoleOnManual creates onManual for system:role resource +// +// This function is auto-generated. +func RoleOnManual( + argRole *types.Role, + argOldRole *types.Role, +) *roleOnManual { + return &roleOnManual{ + roleBase: &roleBase{ + immutable: false, + role: argRole, + oldRole: argOldRole, + }, + } +} + +// RoleOnManualImmutable creates onManual for system:role resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RoleOnManualImmutable( + argRole *types.Role, + argOldRole *types.Role, +) *roleOnManual { + return &roleOnManual{ + roleBase: &roleBase{ + immutable: true, + role: argRole, + oldRole: argOldRole, + }, + } +} + +// RoleBeforeCreate creates beforeCreate for system:role resource +// +// This function is auto-generated. +func RoleBeforeCreate( + argRole *types.Role, + argOldRole *types.Role, +) *roleBeforeCreate { + return &roleBeforeCreate{ + roleBase: &roleBase{ + immutable: false, + role: argRole, + oldRole: argOldRole, + }, + } +} + +// RoleBeforeCreateImmutable creates beforeCreate for system:role resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RoleBeforeCreateImmutable( + argRole *types.Role, + argOldRole *types.Role, +) *roleBeforeCreate { + return &roleBeforeCreate{ + roleBase: &roleBase{ + immutable: true, + role: argRole, + oldRole: argOldRole, + }, + } +} + +// RoleBeforeUpdate creates beforeUpdate for system:role resource +// +// This function is auto-generated. +func RoleBeforeUpdate( + argRole *types.Role, + argOldRole *types.Role, +) *roleBeforeUpdate { + return &roleBeforeUpdate{ + roleBase: &roleBase{ + immutable: false, + role: argRole, + oldRole: argOldRole, + }, + } +} + +// RoleBeforeUpdateImmutable creates beforeUpdate for system:role resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RoleBeforeUpdateImmutable( + argRole *types.Role, + argOldRole *types.Role, +) *roleBeforeUpdate { + return &roleBeforeUpdate{ + roleBase: &roleBase{ + immutable: true, + role: argRole, + oldRole: argOldRole, + }, + } +} + +// RoleBeforeDelete creates beforeDelete for system:role resource +// +// This function is auto-generated. +func RoleBeforeDelete( + argRole *types.Role, + argOldRole *types.Role, +) *roleBeforeDelete { + return &roleBeforeDelete{ + roleBase: &roleBase{ + immutable: false, + role: argRole, + oldRole: argOldRole, + }, + } +} + +// RoleBeforeDeleteImmutable creates beforeDelete for system:role resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RoleBeforeDeleteImmutable( + argRole *types.Role, + argOldRole *types.Role, +) *roleBeforeDelete { + return &roleBeforeDelete{ + roleBase: &roleBase{ + immutable: true, + role: argRole, + oldRole: argOldRole, + }, + } +} + +// RoleAfterCreate creates afterCreate for system:role resource +// +// This function is auto-generated. +func RoleAfterCreate( + argRole *types.Role, + argOldRole *types.Role, +) *roleAfterCreate { + return &roleAfterCreate{ + roleBase: &roleBase{ + immutable: false, + role: argRole, + oldRole: argOldRole, + }, + } +} + +// RoleAfterCreateImmutable creates afterCreate for system:role resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RoleAfterCreateImmutable( + argRole *types.Role, + argOldRole *types.Role, +) *roleAfterCreate { + return &roleAfterCreate{ + roleBase: &roleBase{ + immutable: true, + role: argRole, + oldRole: argOldRole, + }, + } +} + +// RoleAfterUpdate creates afterUpdate for system:role resource +// +// This function is auto-generated. +func RoleAfterUpdate( + argRole *types.Role, + argOldRole *types.Role, +) *roleAfterUpdate { + return &roleAfterUpdate{ + roleBase: &roleBase{ + immutable: false, + role: argRole, + oldRole: argOldRole, + }, + } +} + +// RoleAfterUpdateImmutable creates afterUpdate for system:role resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RoleAfterUpdateImmutable( + argRole *types.Role, + argOldRole *types.Role, +) *roleAfterUpdate { + return &roleAfterUpdate{ + roleBase: &roleBase{ + immutable: true, + role: argRole, + oldRole: argOldRole, + }, + } +} + +// RoleAfterDelete creates afterDelete for system:role resource +// +// This function is auto-generated. +func RoleAfterDelete( + argRole *types.Role, + argOldRole *types.Role, +) *roleAfterDelete { + return &roleAfterDelete{ + roleBase: &roleBase{ + immutable: false, + role: argRole, + oldRole: argOldRole, + }, + } +} + +// RoleAfterDeleteImmutable creates afterDelete for system:role resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RoleAfterDeleteImmutable( + argRole *types.Role, + argOldRole *types.Role, +) *roleAfterDelete { + return &roleAfterDelete{ + roleBase: &roleBase{ + immutable: true, + role: argRole, + oldRole: argOldRole, + }, + } +} + +// SetRole sets new role value +// +// This function is auto-generated. +func (res *roleBase) SetRole(argRole *types.Role) { + res.role = argRole +} + +// Role returns role +// +// This function is auto-generated. +func (res roleBase) Role() *types.Role { + return res.role +} + +// OldRole returns oldRole +// +// This function is auto-generated. +func (res roleBase) OldRole() *types.Role { + return res.oldRole +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *roleBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res roleBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res roleBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["role"], err = json.Marshal(res.role); err != nil { + return nil, err + } + + if args["oldRole"], err = json.Marshal(res.oldRole); err != nil { + return nil, err + } + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *roleBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.role != nil { + if r, ok := results["result"]; ok && len(results) == 1 { + if err = json.Unmarshal(r, res.role); err != nil { + return + } + } + } + + if res.role != nil { + if r, ok := results["role"]; ok { + if err = json.Unmarshal(r, res.role); err != nil { + return + } + } + } + + // Do not decode oldRole; marked as immutable + + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} + +// ResourceType returns "system:role:member" +// +// This function is auto-generated. +func (roleMemberBase) ResourceType() string { + return "system:role:member" +} + +// EventType on roleMemberBeforeAdd returns "beforeAdd" +// +// This function is auto-generated. +func (roleMemberBeforeAdd) EventType() string { + return "beforeAdd" +} + +// EventType on roleMemberBeforeRemove returns "beforeRemove" +// +// This function is auto-generated. +func (roleMemberBeforeRemove) EventType() string { + return "beforeRemove" +} + +// EventType on roleMemberAfterAdd returns "afterAdd" +// +// This function is auto-generated. +func (roleMemberAfterAdd) EventType() string { + return "afterAdd" +} + +// EventType on roleMemberAfterRemove returns "afterRemove" +// +// This function is auto-generated. +func (roleMemberAfterRemove) EventType() string { + return "afterRemove" +} + +// RoleMemberBeforeAdd creates beforeAdd for system:role:member resource +// +// This function is auto-generated. +func RoleMemberBeforeAdd( + argUser *types.User, + argRole *types.Role, +) *roleMemberBeforeAdd { + return &roleMemberBeforeAdd{ + roleMemberBase: &roleMemberBase{ + immutable: false, + user: argUser, + role: argRole, + }, + } +} + +// RoleMemberBeforeAddImmutable creates beforeAdd for system:role:member resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RoleMemberBeforeAddImmutable( + argUser *types.User, + argRole *types.Role, +) *roleMemberBeforeAdd { + return &roleMemberBeforeAdd{ + roleMemberBase: &roleMemberBase{ + immutable: true, + user: argUser, + role: argRole, + }, + } +} + +// RoleMemberBeforeRemove creates beforeRemove for system:role:member resource +// +// This function is auto-generated. +func RoleMemberBeforeRemove( + argUser *types.User, + argRole *types.Role, +) *roleMemberBeforeRemove { + return &roleMemberBeforeRemove{ + roleMemberBase: &roleMemberBase{ + immutable: false, + user: argUser, + role: argRole, + }, + } +} + +// RoleMemberBeforeRemoveImmutable creates beforeRemove for system:role:member resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RoleMemberBeforeRemoveImmutable( + argUser *types.User, + argRole *types.Role, +) *roleMemberBeforeRemove { + return &roleMemberBeforeRemove{ + roleMemberBase: &roleMemberBase{ + immutable: true, + user: argUser, + role: argRole, + }, + } +} + +// RoleMemberAfterAdd creates afterAdd for system:role:member resource +// +// This function is auto-generated. +func RoleMemberAfterAdd( + argUser *types.User, + argRole *types.Role, +) *roleMemberAfterAdd { + return &roleMemberAfterAdd{ + roleMemberBase: &roleMemberBase{ + immutable: false, + user: argUser, + role: argRole, + }, + } +} + +// RoleMemberAfterAddImmutable creates afterAdd for system:role:member resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RoleMemberAfterAddImmutable( + argUser *types.User, + argRole *types.Role, +) *roleMemberAfterAdd { + return &roleMemberAfterAdd{ + roleMemberBase: &roleMemberBase{ + immutable: true, + user: argUser, + role: argRole, + }, + } +} + +// RoleMemberAfterRemove creates afterRemove for system:role:member resource +// +// This function is auto-generated. +func RoleMemberAfterRemove( + argUser *types.User, + argRole *types.Role, +) *roleMemberAfterRemove { + return &roleMemberAfterRemove{ + roleMemberBase: &roleMemberBase{ + immutable: false, + user: argUser, + role: argRole, + }, + } +} + +// RoleMemberAfterRemoveImmutable creates afterRemove for system:role:member resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func RoleMemberAfterRemoveImmutable( + argUser *types.User, + argRole *types.Role, +) *roleMemberAfterRemove { + return &roleMemberAfterRemove{ + roleMemberBase: &roleMemberBase{ + immutable: true, + user: argUser, + role: argRole, + }, + } +} + +// SetUser sets new user value +// +// This function is auto-generated. +func (res *roleMemberBase) SetUser(argUser *types.User) { + res.user = argUser +} + +// User returns user +// +// This function is auto-generated. +func (res roleMemberBase) User() *types.User { + return res.user +} + +// SetRole sets new role value +// +// This function is auto-generated. +func (res *roleMemberBase) SetRole(argRole *types.Role) { + res.role = argRole +} + +// Role returns role +// +// This function is auto-generated. +func (res roleMemberBase) Role() *types.Role { + return res.role +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *roleMemberBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res roleMemberBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res roleMemberBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["user"], err = json.Marshal(res.user); err != nil { + return nil, err + } + + if args["role"], err = json.Marshal(res.role); err != nil { + return nil, err + } + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *roleMemberBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.user != nil { + if r, ok := results["result"]; ok && len(results) == 1 { + if err = json.Unmarshal(r, res.user); err != nil { + return + } + } + } + + if res.user != nil { + if r, ok := results["user"]; ok { + if err = json.Unmarshal(r, res.user); err != nil { + return + } + } + } + + if res.role != nil { + if r, ok := results["role"]; ok { + if err = json.Unmarshal(r, res.role); err != nil { + return + } + } + } + + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} + +// ResourceType returns "system:sink" +// +// This function is auto-generated. +func (sinkBase) ResourceType() string { + return "system:sink" +} + +// EventType on sinkOnRequest returns "onRequest" +// +// This function is auto-generated. +func (sinkOnRequest) EventType() string { + return "onRequest" +} + +// SinkOnRequest creates onRequest for system:sink resource +// +// This function is auto-generated. +func SinkOnRequest( + argResponse *types.SinkResponse, + argRequest *types.SinkRequest, +) *sinkOnRequest { + return &sinkOnRequest{ + sinkBase: &sinkBase{ + immutable: false, + response: argResponse, + request: argRequest, + }, + } +} + +// SinkOnRequestImmutable creates onRequest for system:sink resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func SinkOnRequestImmutable( + argResponse *types.SinkResponse, + argRequest *types.SinkRequest, +) *sinkOnRequest { + return &sinkOnRequest{ + sinkBase: &sinkBase{ + immutable: true, + response: argResponse, + request: argRequest, + }, + } +} + +// SetResponse sets new response value +// +// This function is auto-generated. +func (res *sinkBase) SetResponse(argResponse *types.SinkResponse) { + res.response = argResponse +} + +// Response returns response +// +// This function is auto-generated. +func (res sinkBase) Response() *types.SinkResponse { + return res.response +} + +// Request returns request +// +// This function is auto-generated. +func (res sinkBase) Request() *types.SinkRequest { + return res.request +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *sinkBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res sinkBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res sinkBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["response"], err = json.Marshal(res.response); err != nil { + return nil, err + } + + if args["request"], err = json.Marshal(res.request); err != nil { + return nil, err + } + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *sinkBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.response != nil { + if r, ok := results["result"]; ok && len(results) == 1 { + if err = json.Unmarshal(r, res.response); err != nil { + return + } + } + } + + if res.response != nil { + if r, ok := results["response"]; ok { + if err = json.Unmarshal(r, res.response); err != nil { + return + } + } + } + + // Do not decode request; marked as immutable + + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} + +// ResourceType returns "system:user" +// +// This function is auto-generated. +func (userBase) ResourceType() string { + return "system:user" +} + +// EventType on userOnManual returns "onManual" +// +// This function is auto-generated. +func (userOnManual) EventType() string { + return "onManual" +} + +// EventType on userBeforeCreate returns "beforeCreate" +// +// This function is auto-generated. +func (userBeforeCreate) EventType() string { + return "beforeCreate" +} + +// EventType on userBeforeUpdate returns "beforeUpdate" +// +// This function is auto-generated. +func (userBeforeUpdate) EventType() string { + return "beforeUpdate" +} + +// EventType on userBeforeDelete returns "beforeDelete" +// +// This function is auto-generated. +func (userBeforeDelete) EventType() string { + return "beforeDelete" +} + +// EventType on userAfterCreate returns "afterCreate" +// +// This function is auto-generated. +func (userAfterCreate) EventType() string { + return "afterCreate" +} + +// EventType on userAfterUpdate returns "afterUpdate" +// +// This function is auto-generated. +func (userAfterUpdate) EventType() string { + return "afterUpdate" +} + +// EventType on userAfterDelete returns "afterDelete" +// +// This function is auto-generated. +func (userAfterDelete) EventType() string { + return "afterDelete" +} + +// UserOnManual creates onManual for system:user resource +// +// This function is auto-generated. +func UserOnManual( + argUser *types.User, + argOldUser *types.User, +) *userOnManual { + return &userOnManual{ + userBase: &userBase{ + immutable: false, + user: argUser, + oldUser: argOldUser, + }, + } +} + +// UserOnManualImmutable creates onManual for system:user resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func UserOnManualImmutable( + argUser *types.User, + argOldUser *types.User, +) *userOnManual { + return &userOnManual{ + userBase: &userBase{ + immutable: true, + user: argUser, + oldUser: argOldUser, + }, + } +} + +// UserBeforeCreate creates beforeCreate for system:user resource +// +// This function is auto-generated. +func UserBeforeCreate( + argUser *types.User, + argOldUser *types.User, +) *userBeforeCreate { + return &userBeforeCreate{ + userBase: &userBase{ + immutable: false, + user: argUser, + oldUser: argOldUser, + }, + } +} + +// UserBeforeCreateImmutable creates beforeCreate for system:user resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func UserBeforeCreateImmutable( + argUser *types.User, + argOldUser *types.User, +) *userBeforeCreate { + return &userBeforeCreate{ + userBase: &userBase{ + immutable: true, + user: argUser, + oldUser: argOldUser, + }, + } +} + +// UserBeforeUpdate creates beforeUpdate for system:user resource +// +// This function is auto-generated. +func UserBeforeUpdate( + argUser *types.User, + argOldUser *types.User, +) *userBeforeUpdate { + return &userBeforeUpdate{ + userBase: &userBase{ + immutable: false, + user: argUser, + oldUser: argOldUser, + }, + } +} + +// UserBeforeUpdateImmutable creates beforeUpdate for system:user resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func UserBeforeUpdateImmutable( + argUser *types.User, + argOldUser *types.User, +) *userBeforeUpdate { + return &userBeforeUpdate{ + userBase: &userBase{ + immutable: true, + user: argUser, + oldUser: argOldUser, + }, + } +} + +// UserBeforeDelete creates beforeDelete for system:user resource +// +// This function is auto-generated. +func UserBeforeDelete( + argUser *types.User, + argOldUser *types.User, +) *userBeforeDelete { + return &userBeforeDelete{ + userBase: &userBase{ + immutable: false, + user: argUser, + oldUser: argOldUser, + }, + } +} + +// UserBeforeDeleteImmutable creates beforeDelete for system:user resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func UserBeforeDeleteImmutable( + argUser *types.User, + argOldUser *types.User, +) *userBeforeDelete { + return &userBeforeDelete{ + userBase: &userBase{ + immutable: true, + user: argUser, + oldUser: argOldUser, + }, + } +} + +// UserAfterCreate creates afterCreate for system:user resource +// +// This function is auto-generated. +func UserAfterCreate( + argUser *types.User, + argOldUser *types.User, +) *userAfterCreate { + return &userAfterCreate{ + userBase: &userBase{ + immutable: false, + user: argUser, + oldUser: argOldUser, + }, + } +} + +// UserAfterCreateImmutable creates afterCreate for system:user resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func UserAfterCreateImmutable( + argUser *types.User, + argOldUser *types.User, +) *userAfterCreate { + return &userAfterCreate{ + userBase: &userBase{ + immutable: true, + user: argUser, + oldUser: argOldUser, + }, + } +} + +// UserAfterUpdate creates afterUpdate for system:user resource +// +// This function is auto-generated. +func UserAfterUpdate( + argUser *types.User, + argOldUser *types.User, +) *userAfterUpdate { + return &userAfterUpdate{ + userBase: &userBase{ + immutable: false, + user: argUser, + oldUser: argOldUser, + }, + } +} + +// UserAfterUpdateImmutable creates afterUpdate for system:user resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func UserAfterUpdateImmutable( + argUser *types.User, + argOldUser *types.User, +) *userAfterUpdate { + return &userAfterUpdate{ + userBase: &userBase{ + immutable: true, + user: argUser, + oldUser: argOldUser, + }, + } +} + +// UserAfterDelete creates afterDelete for system:user resource +// +// This function is auto-generated. +func UserAfterDelete( + argUser *types.User, + argOldUser *types.User, +) *userAfterDelete { + return &userAfterDelete{ + userBase: &userBase{ + immutable: false, + user: argUser, + oldUser: argOldUser, + }, + } +} + +// UserAfterDeleteImmutable creates afterDelete for system:user resource +// +// None of the arguments will be mutable! +// +// This function is auto-generated. +func UserAfterDeleteImmutable( + argUser *types.User, + argOldUser *types.User, +) *userAfterDelete { + return &userAfterDelete{ + userBase: &userBase{ + immutable: true, + user: argUser, + oldUser: argOldUser, + }, + } +} + +// SetUser sets new user value +// +// This function is auto-generated. +func (res *userBase) SetUser(argUser *types.User) { + res.user = argUser +} + +// User returns user +// +// This function is auto-generated. +func (res userBase) User() *types.User { + return res.user +} + +// OldUser returns oldUser +// +// This function is auto-generated. +func (res userBase) OldUser() *types.User { + return res.oldUser +} + +// SetInvoker sets new invoker value +// +// This function is auto-generated. +func (res *userBase) SetInvoker(argInvoker auth.Identifiable) { + res.invoker = argInvoker +} + +// Invoker returns invoker +// +// This function is auto-generated. +func (res userBase) Invoker() auth.Identifiable { + return res.invoker +} + +// Encode internal data to be passed as event params & arguments to triggered Corredor script +func (res userBase) Encode() (args map[string][]byte, err error) { + args = make(map[string][]byte) + + if args["user"], err = json.Marshal(res.user); err != nil { + return nil, err + } + + if args["oldUser"], err = json.Marshal(res.oldUser); err != nil { + return nil, err + } + + if args["invoker"], err = json.Marshal(res.invoker); err != nil { + return nil, err + } + + return +} + +// Decode return values from Corredor script into struct props +func (res *userBase) Decode(results map[string][]byte) (err error) { + if res.immutable { + // Respect immutability + return + } + if res.user != nil { + if r, ok := results["result"]; ok && len(results) == 1 { + if err = json.Unmarshal(r, res.user); err != nil { + return + } + } + } + + if res.user != nil { + if r, ok := results["user"]; ok { + if err = json.Unmarshal(r, res.user); err != nil { + return + } + } + } + + // Do not decode oldUser; marked as immutable + + if res.invoker != nil { + if r, ok := results["invoker"]; ok { + if err = json.Unmarshal(r, res.invoker); err != nil { + return + } + } + } + return +} diff --git a/system/service/event/mail.gen.go b/system/service/event/mail.gen.go deleted file mode 100644 index 561064bd2..000000000 --- a/system/service/event/mail.gen.go +++ /dev/null @@ -1,243 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// system/service/event/events.yaml -// -// Regenerate with: -// go run ./codegen/v2/events --service system -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/system/types" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // mailBase - // - // This type is auto-generated. - mailBase struct { - immutable bool - message *types.MailMessage - invoker auth.Identifiable - } - - // mailOnManual - // - // This type is auto-generated. - mailOnManual struct { - *mailBase - } - - // mailOnReceive - // - // This type is auto-generated. - mailOnReceive struct { - *mailBase - } - - // mailOnSend - // - // This type is auto-generated. - mailOnSend struct { - *mailBase - } -) - -// ResourceType returns "system:mail" -// -// This function is auto-generated. -func (mailBase) ResourceType() string { - return "system:mail" -} - -// EventType on mailOnManual returns "onManual" -// -// This function is auto-generated. -func (mailOnManual) EventType() string { - return "onManual" -} - -// EventType on mailOnReceive returns "onReceive" -// -// This function is auto-generated. -func (mailOnReceive) EventType() string { - return "onReceive" -} - -// EventType on mailOnSend returns "onSend" -// -// This function is auto-generated. -func (mailOnSend) EventType() string { - return "onSend" -} - -// MailOnManual creates onManual for system:mail resource -// -// This function is auto-generated. -func MailOnManual( - argMessage *types.MailMessage, -) *mailOnManual { - return &mailOnManual{ - mailBase: &mailBase{ - immutable: false, - message: argMessage, - }, - } -} - -// MailOnManualImmutable creates onManual for system:mail resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func MailOnManualImmutable( - argMessage *types.MailMessage, -) *mailOnManual { - return &mailOnManual{ - mailBase: &mailBase{ - immutable: true, - message: argMessage, - }, - } -} - -// MailOnReceive creates onReceive for system:mail resource -// -// This function is auto-generated. -func MailOnReceive( - argMessage *types.MailMessage, -) *mailOnReceive { - return &mailOnReceive{ - mailBase: &mailBase{ - immutable: false, - message: argMessage, - }, - } -} - -// MailOnReceiveImmutable creates onReceive for system:mail resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func MailOnReceiveImmutable( - argMessage *types.MailMessage, -) *mailOnReceive { - return &mailOnReceive{ - mailBase: &mailBase{ - immutable: true, - message: argMessage, - }, - } -} - -// MailOnSend creates onSend for system:mail resource -// -// This function is auto-generated. -func MailOnSend( - argMessage *types.MailMessage, -) *mailOnSend { - return &mailOnSend{ - mailBase: &mailBase{ - immutable: false, - message: argMessage, - }, - } -} - -// MailOnSendImmutable creates onSend for system:mail resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func MailOnSendImmutable( - argMessage *types.MailMessage, -) *mailOnSend { - return &mailOnSend{ - mailBase: &mailBase{ - immutable: true, - message: argMessage, - }, - } -} - -// SetMessage sets new message value -// -// This function is auto-generated. -func (res *mailBase) SetMessage(argMessage *types.MailMessage) { - res.message = argMessage -} - -// Message returns message -// -// This function is auto-generated. -func (res mailBase) Message() *types.MailMessage { - return res.message -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *mailBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res mailBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res mailBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["message"], err = json.Marshal(res.message); err != nil { - return nil, err - } - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *mailBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.message != nil { - if r, ok := results["result"]; ok && len(results) == 1 { - if err = json.Unmarshal(r, res.message); err != nil { - return - } - } - } - - if res.message != nil { - if r, ok := results["message"]; ok { - if err = json.Unmarshal(r, res.message); err != nil { - return - } - } - } - - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/system/service/event/role.gen.go b/system/service/event/role.gen.go deleted file mode 100644 index 30c4a1fe2..000000000 --- a/system/service/event/role.gen.go +++ /dev/null @@ -1,461 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// system/service/event/events.yaml -// -// Regenerate with: -// go run ./codegen/v2/events --service system -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/system/types" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // roleBase - // - // This type is auto-generated. - roleBase struct { - immutable bool - role *types.Role - oldRole *types.Role - invoker auth.Identifiable - } - - // roleOnManual - // - // This type is auto-generated. - roleOnManual struct { - *roleBase - } - - // roleBeforeCreate - // - // This type is auto-generated. - roleBeforeCreate struct { - *roleBase - } - - // roleBeforeUpdate - // - // This type is auto-generated. - roleBeforeUpdate struct { - *roleBase - } - - // roleBeforeDelete - // - // This type is auto-generated. - roleBeforeDelete struct { - *roleBase - } - - // roleAfterCreate - // - // This type is auto-generated. - roleAfterCreate struct { - *roleBase - } - - // roleAfterUpdate - // - // This type is auto-generated. - roleAfterUpdate struct { - *roleBase - } - - // roleAfterDelete - // - // This type is auto-generated. - roleAfterDelete struct { - *roleBase - } -) - -// ResourceType returns "system:role" -// -// This function is auto-generated. -func (roleBase) ResourceType() string { - return "system:role" -} - -// EventType on roleOnManual returns "onManual" -// -// This function is auto-generated. -func (roleOnManual) EventType() string { - return "onManual" -} - -// EventType on roleBeforeCreate returns "beforeCreate" -// -// This function is auto-generated. -func (roleBeforeCreate) EventType() string { - return "beforeCreate" -} - -// EventType on roleBeforeUpdate returns "beforeUpdate" -// -// This function is auto-generated. -func (roleBeforeUpdate) EventType() string { - return "beforeUpdate" -} - -// EventType on roleBeforeDelete returns "beforeDelete" -// -// This function is auto-generated. -func (roleBeforeDelete) EventType() string { - return "beforeDelete" -} - -// EventType on roleAfterCreate returns "afterCreate" -// -// This function is auto-generated. -func (roleAfterCreate) EventType() string { - return "afterCreate" -} - -// EventType on roleAfterUpdate returns "afterUpdate" -// -// This function is auto-generated. -func (roleAfterUpdate) EventType() string { - return "afterUpdate" -} - -// EventType on roleAfterDelete returns "afterDelete" -// -// This function is auto-generated. -func (roleAfterDelete) EventType() string { - return "afterDelete" -} - -// RoleOnManual creates onManual for system:role resource -// -// This function is auto-generated. -func RoleOnManual( - argRole *types.Role, - argOldRole *types.Role, -) *roleOnManual { - return &roleOnManual{ - roleBase: &roleBase{ - immutable: false, - role: argRole, - oldRole: argOldRole, - }, - } -} - -// RoleOnManualImmutable creates onManual for system:role resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RoleOnManualImmutable( - argRole *types.Role, - argOldRole *types.Role, -) *roleOnManual { - return &roleOnManual{ - roleBase: &roleBase{ - immutable: true, - role: argRole, - oldRole: argOldRole, - }, - } -} - -// RoleBeforeCreate creates beforeCreate for system:role resource -// -// This function is auto-generated. -func RoleBeforeCreate( - argRole *types.Role, - argOldRole *types.Role, -) *roleBeforeCreate { - return &roleBeforeCreate{ - roleBase: &roleBase{ - immutable: false, - role: argRole, - oldRole: argOldRole, - }, - } -} - -// RoleBeforeCreateImmutable creates beforeCreate for system:role resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RoleBeforeCreateImmutable( - argRole *types.Role, - argOldRole *types.Role, -) *roleBeforeCreate { - return &roleBeforeCreate{ - roleBase: &roleBase{ - immutable: true, - role: argRole, - oldRole: argOldRole, - }, - } -} - -// RoleBeforeUpdate creates beforeUpdate for system:role resource -// -// This function is auto-generated. -func RoleBeforeUpdate( - argRole *types.Role, - argOldRole *types.Role, -) *roleBeforeUpdate { - return &roleBeforeUpdate{ - roleBase: &roleBase{ - immutable: false, - role: argRole, - oldRole: argOldRole, - }, - } -} - -// RoleBeforeUpdateImmutable creates beforeUpdate for system:role resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RoleBeforeUpdateImmutable( - argRole *types.Role, - argOldRole *types.Role, -) *roleBeforeUpdate { - return &roleBeforeUpdate{ - roleBase: &roleBase{ - immutable: true, - role: argRole, - oldRole: argOldRole, - }, - } -} - -// RoleBeforeDelete creates beforeDelete for system:role resource -// -// This function is auto-generated. -func RoleBeforeDelete( - argRole *types.Role, - argOldRole *types.Role, -) *roleBeforeDelete { - return &roleBeforeDelete{ - roleBase: &roleBase{ - immutable: false, - role: argRole, - oldRole: argOldRole, - }, - } -} - -// RoleBeforeDeleteImmutable creates beforeDelete for system:role resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RoleBeforeDeleteImmutable( - argRole *types.Role, - argOldRole *types.Role, -) *roleBeforeDelete { - return &roleBeforeDelete{ - roleBase: &roleBase{ - immutable: true, - role: argRole, - oldRole: argOldRole, - }, - } -} - -// RoleAfterCreate creates afterCreate for system:role resource -// -// This function is auto-generated. -func RoleAfterCreate( - argRole *types.Role, - argOldRole *types.Role, -) *roleAfterCreate { - return &roleAfterCreate{ - roleBase: &roleBase{ - immutable: false, - role: argRole, - oldRole: argOldRole, - }, - } -} - -// RoleAfterCreateImmutable creates afterCreate for system:role resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RoleAfterCreateImmutable( - argRole *types.Role, - argOldRole *types.Role, -) *roleAfterCreate { - return &roleAfterCreate{ - roleBase: &roleBase{ - immutable: true, - role: argRole, - oldRole: argOldRole, - }, - } -} - -// RoleAfterUpdate creates afterUpdate for system:role resource -// -// This function is auto-generated. -func RoleAfterUpdate( - argRole *types.Role, - argOldRole *types.Role, -) *roleAfterUpdate { - return &roleAfterUpdate{ - roleBase: &roleBase{ - immutable: false, - role: argRole, - oldRole: argOldRole, - }, - } -} - -// RoleAfterUpdateImmutable creates afterUpdate for system:role resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RoleAfterUpdateImmutable( - argRole *types.Role, - argOldRole *types.Role, -) *roleAfterUpdate { - return &roleAfterUpdate{ - roleBase: &roleBase{ - immutable: true, - role: argRole, - oldRole: argOldRole, - }, - } -} - -// RoleAfterDelete creates afterDelete for system:role resource -// -// This function is auto-generated. -func RoleAfterDelete( - argRole *types.Role, - argOldRole *types.Role, -) *roleAfterDelete { - return &roleAfterDelete{ - roleBase: &roleBase{ - immutable: false, - role: argRole, - oldRole: argOldRole, - }, - } -} - -// RoleAfterDeleteImmutable creates afterDelete for system:role resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RoleAfterDeleteImmutable( - argRole *types.Role, - argOldRole *types.Role, -) *roleAfterDelete { - return &roleAfterDelete{ - roleBase: &roleBase{ - immutable: true, - role: argRole, - oldRole: argOldRole, - }, - } -} - -// SetRole sets new role value -// -// This function is auto-generated. -func (res *roleBase) SetRole(argRole *types.Role) { - res.role = argRole -} - -// Role returns role -// -// This function is auto-generated. -func (res roleBase) Role() *types.Role { - return res.role -} - -// OldRole returns oldRole -// -// This function is auto-generated. -func (res roleBase) OldRole() *types.Role { - return res.oldRole -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *roleBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res roleBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res roleBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["role"], err = json.Marshal(res.role); err != nil { - return nil, err - } - - if args["oldRole"], err = json.Marshal(res.oldRole); err != nil { - return nil, err - } - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *roleBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.role != nil { - if r, ok := results["result"]; ok && len(results) == 1 { - if err = json.Unmarshal(r, res.role); err != nil { - return - } - } - } - - if res.role != nil { - if r, ok := results["role"]; ok { - if err = json.Unmarshal(r, res.role); err != nil { - return - } - } - } - - // Do not decode oldRole; marked as immutable - - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/system/service/event/role_member.gen.go b/system/service/event/role_member.gen.go deleted file mode 100644 index 23770aab4..000000000 --- a/system/service/event/role_member.gen.go +++ /dev/null @@ -1,330 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// system/service/event/events.yaml -// -// Regenerate with: -// go run ./codegen/v2/events --service system -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/system/types" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // roleMemberBase - // - // This type is auto-generated. - roleMemberBase struct { - immutable bool - user *types.User - role *types.Role - invoker auth.Identifiable - } - - // roleMemberBeforeAdd - // - // This type is auto-generated. - roleMemberBeforeAdd struct { - *roleMemberBase - } - - // roleMemberBeforeRemove - // - // This type is auto-generated. - roleMemberBeforeRemove struct { - *roleMemberBase - } - - // roleMemberAfterAdd - // - // This type is auto-generated. - roleMemberAfterAdd struct { - *roleMemberBase - } - - // roleMemberAfterRemove - // - // This type is auto-generated. - roleMemberAfterRemove struct { - *roleMemberBase - } -) - -// ResourceType returns "system:role:member" -// -// This function is auto-generated. -func (roleMemberBase) ResourceType() string { - return "system:role:member" -} - -// EventType on roleMemberBeforeAdd returns "beforeAdd" -// -// This function is auto-generated. -func (roleMemberBeforeAdd) EventType() string { - return "beforeAdd" -} - -// EventType on roleMemberBeforeRemove returns "beforeRemove" -// -// This function is auto-generated. -func (roleMemberBeforeRemove) EventType() string { - return "beforeRemove" -} - -// EventType on roleMemberAfterAdd returns "afterAdd" -// -// This function is auto-generated. -func (roleMemberAfterAdd) EventType() string { - return "afterAdd" -} - -// EventType on roleMemberAfterRemove returns "afterRemove" -// -// This function is auto-generated. -func (roleMemberAfterRemove) EventType() string { - return "afterRemove" -} - -// RoleMemberBeforeAdd creates beforeAdd for system:role:member resource -// -// This function is auto-generated. -func RoleMemberBeforeAdd( - argUser *types.User, - argRole *types.Role, -) *roleMemberBeforeAdd { - return &roleMemberBeforeAdd{ - roleMemberBase: &roleMemberBase{ - immutable: false, - user: argUser, - role: argRole, - }, - } -} - -// RoleMemberBeforeAddImmutable creates beforeAdd for system:role:member resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RoleMemberBeforeAddImmutable( - argUser *types.User, - argRole *types.Role, -) *roleMemberBeforeAdd { - return &roleMemberBeforeAdd{ - roleMemberBase: &roleMemberBase{ - immutable: true, - user: argUser, - role: argRole, - }, - } -} - -// RoleMemberBeforeRemove creates beforeRemove for system:role:member resource -// -// This function is auto-generated. -func RoleMemberBeforeRemove( - argUser *types.User, - argRole *types.Role, -) *roleMemberBeforeRemove { - return &roleMemberBeforeRemove{ - roleMemberBase: &roleMemberBase{ - immutable: false, - user: argUser, - role: argRole, - }, - } -} - -// RoleMemberBeforeRemoveImmutable creates beforeRemove for system:role:member resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RoleMemberBeforeRemoveImmutable( - argUser *types.User, - argRole *types.Role, -) *roleMemberBeforeRemove { - return &roleMemberBeforeRemove{ - roleMemberBase: &roleMemberBase{ - immutable: true, - user: argUser, - role: argRole, - }, - } -} - -// RoleMemberAfterAdd creates afterAdd for system:role:member resource -// -// This function is auto-generated. -func RoleMemberAfterAdd( - argUser *types.User, - argRole *types.Role, -) *roleMemberAfterAdd { - return &roleMemberAfterAdd{ - roleMemberBase: &roleMemberBase{ - immutable: false, - user: argUser, - role: argRole, - }, - } -} - -// RoleMemberAfterAddImmutable creates afterAdd for system:role:member resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RoleMemberAfterAddImmutable( - argUser *types.User, - argRole *types.Role, -) *roleMemberAfterAdd { - return &roleMemberAfterAdd{ - roleMemberBase: &roleMemberBase{ - immutable: true, - user: argUser, - role: argRole, - }, - } -} - -// RoleMemberAfterRemove creates afterRemove for system:role:member resource -// -// This function is auto-generated. -func RoleMemberAfterRemove( - argUser *types.User, - argRole *types.Role, -) *roleMemberAfterRemove { - return &roleMemberAfterRemove{ - roleMemberBase: &roleMemberBase{ - immutable: false, - user: argUser, - role: argRole, - }, - } -} - -// RoleMemberAfterRemoveImmutable creates afterRemove for system:role:member resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func RoleMemberAfterRemoveImmutable( - argUser *types.User, - argRole *types.Role, -) *roleMemberAfterRemove { - return &roleMemberAfterRemove{ - roleMemberBase: &roleMemberBase{ - immutable: true, - user: argUser, - role: argRole, - }, - } -} - -// SetUser sets new user value -// -// This function is auto-generated. -func (res *roleMemberBase) SetUser(argUser *types.User) { - res.user = argUser -} - -// User returns user -// -// This function is auto-generated. -func (res roleMemberBase) User() *types.User { - return res.user -} - -// SetRole sets new role value -// -// This function is auto-generated. -func (res *roleMemberBase) SetRole(argRole *types.Role) { - res.role = argRole -} - -// Role returns role -// -// This function is auto-generated. -func (res roleMemberBase) Role() *types.Role { - return res.role -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *roleMemberBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res roleMemberBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res roleMemberBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["user"], err = json.Marshal(res.user); err != nil { - return nil, err - } - - if args["role"], err = json.Marshal(res.role); err != nil { - return nil, err - } - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *roleMemberBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.user != nil { - if r, ok := results["result"]; ok && len(results) == 1 { - if err = json.Unmarshal(r, res.user); err != nil { - return - } - } - } - - if res.user != nil { - if r, ok := results["user"]; ok { - if err = json.Unmarshal(r, res.user); err != nil { - return - } - } - } - - if res.role != nil { - if r, ok := results["role"]; ok { - if err = json.Unmarshal(r, res.role); err != nil { - return - } - } - } - - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/system/service/event/sink.gen.go b/system/service/event/sink.gen.go deleted file mode 100644 index d6bc211c3..000000000 --- a/system/service/event/sink.gen.go +++ /dev/null @@ -1,173 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// system/service/event/events.yaml -// -// Regenerate with: -// go run ./codegen/v2/events --service system -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/system/types" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // sinkBase - // - // This type is auto-generated. - sinkBase struct { - immutable bool - response *types.SinkResponse - request *types.SinkRequest - invoker auth.Identifiable - } - - // sinkOnRequest - // - // This type is auto-generated. - sinkOnRequest struct { - *sinkBase - } -) - -// ResourceType returns "system:sink" -// -// This function is auto-generated. -func (sinkBase) ResourceType() string { - return "system:sink" -} - -// EventType on sinkOnRequest returns "onRequest" -// -// This function is auto-generated. -func (sinkOnRequest) EventType() string { - return "onRequest" -} - -// SinkOnRequest creates onRequest for system:sink resource -// -// This function is auto-generated. -func SinkOnRequest( - argResponse *types.SinkResponse, - argRequest *types.SinkRequest, -) *sinkOnRequest { - return &sinkOnRequest{ - sinkBase: &sinkBase{ - immutable: false, - response: argResponse, - request: argRequest, - }, - } -} - -// SinkOnRequestImmutable creates onRequest for system:sink resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func SinkOnRequestImmutable( - argResponse *types.SinkResponse, - argRequest *types.SinkRequest, -) *sinkOnRequest { - return &sinkOnRequest{ - sinkBase: &sinkBase{ - immutable: true, - response: argResponse, - request: argRequest, - }, - } -} - -// SetResponse sets new response value -// -// This function is auto-generated. -func (res *sinkBase) SetResponse(argResponse *types.SinkResponse) { - res.response = argResponse -} - -// Response returns response -// -// This function is auto-generated. -func (res sinkBase) Response() *types.SinkResponse { - return res.response -} - -// Request returns request -// -// This function is auto-generated. -func (res sinkBase) Request() *types.SinkRequest { - return res.request -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *sinkBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res sinkBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res sinkBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["response"], err = json.Marshal(res.response); err != nil { - return nil, err - } - - if args["request"], err = json.Marshal(res.request); err != nil { - return nil, err - } - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *sinkBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.response != nil { - if r, ok := results["result"]; ok && len(results) == 1 { - if err = json.Unmarshal(r, res.response); err != nil { - return - } - } - } - - if res.response != nil { - if r, ok := results["response"]; ok { - if err = json.Unmarshal(r, res.response); err != nil { - return - } - } - } - - // Do not decode request; marked as immutable - - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/system/service/event/system.gen.go b/system/service/event/system.gen.go deleted file mode 100644 index 78b500be3..000000000 --- a/system/service/event/system.gen.go +++ /dev/null @@ -1,188 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// system/service/event/events.yaml -// -// Regenerate with: -// go run ./codegen/v2/events --service system -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // systemBase - // - // This type is auto-generated. - systemBase struct { - immutable bool - invoker auth.Identifiable - } - - // systemOnManual - // - // This type is auto-generated. - systemOnManual struct { - *systemBase - } - - // systemOnInterval - // - // This type is auto-generated. - systemOnInterval struct { - *systemBase - } - - // systemOnTimestamp - // - // This type is auto-generated. - systemOnTimestamp struct { - *systemBase - } -) - -// ResourceType returns "system" -// -// This function is auto-generated. -func (systemBase) ResourceType() string { - return "system" -} - -// EventType on systemOnManual returns "onManual" -// -// This function is auto-generated. -func (systemOnManual) EventType() string { - return "onManual" -} - -// EventType on systemOnInterval returns "onInterval" -// -// This function is auto-generated. -func (systemOnInterval) EventType() string { - return "onInterval" -} - -// EventType on systemOnTimestamp returns "onTimestamp" -// -// This function is auto-generated. -func (systemOnTimestamp) EventType() string { - return "onTimestamp" -} - -// SystemOnManual creates onManual for system resource -// -// This function is auto-generated. -func SystemOnManual() *systemOnManual { - return &systemOnManual{ - systemBase: &systemBase{ - immutable: false, - }, - } -} - -// SystemOnManualImmutable creates onManual for system resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func SystemOnManualImmutable() *systemOnManual { - return &systemOnManual{ - systemBase: &systemBase{ - immutable: true, - }, - } -} - -// SystemOnInterval creates onInterval for system resource -// -// This function is auto-generated. -func SystemOnInterval() *systemOnInterval { - return &systemOnInterval{ - systemBase: &systemBase{ - immutable: false, - }, - } -} - -// SystemOnIntervalImmutable creates onInterval for system resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func SystemOnIntervalImmutable() *systemOnInterval { - return &systemOnInterval{ - systemBase: &systemBase{ - immutable: true, - }, - } -} - -// SystemOnTimestamp creates onTimestamp for system resource -// -// This function is auto-generated. -func SystemOnTimestamp() *systemOnTimestamp { - return &systemOnTimestamp{ - systemBase: &systemBase{ - immutable: false, - }, - } -} - -// SystemOnTimestampImmutable creates onTimestamp for system resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func SystemOnTimestampImmutable() *systemOnTimestamp { - return &systemOnTimestamp{ - systemBase: &systemBase{ - immutable: true, - }, - } -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *systemBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res systemBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res systemBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *systemBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/system/service/event/user.gen.go b/system/service/event/user.gen.go deleted file mode 100644 index f423f5027..000000000 --- a/system/service/event/user.gen.go +++ /dev/null @@ -1,461 +0,0 @@ -package event - -// This file is auto-generated. -// -// YAML event definitions: -// system/service/event/events.yaml -// -// Regenerate with: -// go run ./codegen/v2/events --service system -// - -import ( - "encoding/json" - - "github.com/cortezaproject/corteza-server/system/types" - - "github.com/cortezaproject/corteza-server/pkg/auth" -) - -type ( - // userBase - // - // This type is auto-generated. - userBase struct { - immutable bool - user *types.User - oldUser *types.User - invoker auth.Identifiable - } - - // userOnManual - // - // This type is auto-generated. - userOnManual struct { - *userBase - } - - // userBeforeCreate - // - // This type is auto-generated. - userBeforeCreate struct { - *userBase - } - - // userBeforeUpdate - // - // This type is auto-generated. - userBeforeUpdate struct { - *userBase - } - - // userBeforeDelete - // - // This type is auto-generated. - userBeforeDelete struct { - *userBase - } - - // userAfterCreate - // - // This type is auto-generated. - userAfterCreate struct { - *userBase - } - - // userAfterUpdate - // - // This type is auto-generated. - userAfterUpdate struct { - *userBase - } - - // userAfterDelete - // - // This type is auto-generated. - userAfterDelete struct { - *userBase - } -) - -// ResourceType returns "system:user" -// -// This function is auto-generated. -func (userBase) ResourceType() string { - return "system:user" -} - -// EventType on userOnManual returns "onManual" -// -// This function is auto-generated. -func (userOnManual) EventType() string { - return "onManual" -} - -// EventType on userBeforeCreate returns "beforeCreate" -// -// This function is auto-generated. -func (userBeforeCreate) EventType() string { - return "beforeCreate" -} - -// EventType on userBeforeUpdate returns "beforeUpdate" -// -// This function is auto-generated. -func (userBeforeUpdate) EventType() string { - return "beforeUpdate" -} - -// EventType on userBeforeDelete returns "beforeDelete" -// -// This function is auto-generated. -func (userBeforeDelete) EventType() string { - return "beforeDelete" -} - -// EventType on userAfterCreate returns "afterCreate" -// -// This function is auto-generated. -func (userAfterCreate) EventType() string { - return "afterCreate" -} - -// EventType on userAfterUpdate returns "afterUpdate" -// -// This function is auto-generated. -func (userAfterUpdate) EventType() string { - return "afterUpdate" -} - -// EventType on userAfterDelete returns "afterDelete" -// -// This function is auto-generated. -func (userAfterDelete) EventType() string { - return "afterDelete" -} - -// UserOnManual creates onManual for system:user resource -// -// This function is auto-generated. -func UserOnManual( - argUser *types.User, - argOldUser *types.User, -) *userOnManual { - return &userOnManual{ - userBase: &userBase{ - immutable: false, - user: argUser, - oldUser: argOldUser, - }, - } -} - -// UserOnManualImmutable creates onManual for system:user resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func UserOnManualImmutable( - argUser *types.User, - argOldUser *types.User, -) *userOnManual { - return &userOnManual{ - userBase: &userBase{ - immutable: true, - user: argUser, - oldUser: argOldUser, - }, - } -} - -// UserBeforeCreate creates beforeCreate for system:user resource -// -// This function is auto-generated. -func UserBeforeCreate( - argUser *types.User, - argOldUser *types.User, -) *userBeforeCreate { - return &userBeforeCreate{ - userBase: &userBase{ - immutable: false, - user: argUser, - oldUser: argOldUser, - }, - } -} - -// UserBeforeCreateImmutable creates beforeCreate for system:user resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func UserBeforeCreateImmutable( - argUser *types.User, - argOldUser *types.User, -) *userBeforeCreate { - return &userBeforeCreate{ - userBase: &userBase{ - immutable: true, - user: argUser, - oldUser: argOldUser, - }, - } -} - -// UserBeforeUpdate creates beforeUpdate for system:user resource -// -// This function is auto-generated. -func UserBeforeUpdate( - argUser *types.User, - argOldUser *types.User, -) *userBeforeUpdate { - return &userBeforeUpdate{ - userBase: &userBase{ - immutable: false, - user: argUser, - oldUser: argOldUser, - }, - } -} - -// UserBeforeUpdateImmutable creates beforeUpdate for system:user resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func UserBeforeUpdateImmutable( - argUser *types.User, - argOldUser *types.User, -) *userBeforeUpdate { - return &userBeforeUpdate{ - userBase: &userBase{ - immutable: true, - user: argUser, - oldUser: argOldUser, - }, - } -} - -// UserBeforeDelete creates beforeDelete for system:user resource -// -// This function is auto-generated. -func UserBeforeDelete( - argUser *types.User, - argOldUser *types.User, -) *userBeforeDelete { - return &userBeforeDelete{ - userBase: &userBase{ - immutable: false, - user: argUser, - oldUser: argOldUser, - }, - } -} - -// UserBeforeDeleteImmutable creates beforeDelete for system:user resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func UserBeforeDeleteImmutable( - argUser *types.User, - argOldUser *types.User, -) *userBeforeDelete { - return &userBeforeDelete{ - userBase: &userBase{ - immutable: true, - user: argUser, - oldUser: argOldUser, - }, - } -} - -// UserAfterCreate creates afterCreate for system:user resource -// -// This function is auto-generated. -func UserAfterCreate( - argUser *types.User, - argOldUser *types.User, -) *userAfterCreate { - return &userAfterCreate{ - userBase: &userBase{ - immutable: false, - user: argUser, - oldUser: argOldUser, - }, - } -} - -// UserAfterCreateImmutable creates afterCreate for system:user resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func UserAfterCreateImmutable( - argUser *types.User, - argOldUser *types.User, -) *userAfterCreate { - return &userAfterCreate{ - userBase: &userBase{ - immutable: true, - user: argUser, - oldUser: argOldUser, - }, - } -} - -// UserAfterUpdate creates afterUpdate for system:user resource -// -// This function is auto-generated. -func UserAfterUpdate( - argUser *types.User, - argOldUser *types.User, -) *userAfterUpdate { - return &userAfterUpdate{ - userBase: &userBase{ - immutable: false, - user: argUser, - oldUser: argOldUser, - }, - } -} - -// UserAfterUpdateImmutable creates afterUpdate for system:user resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func UserAfterUpdateImmutable( - argUser *types.User, - argOldUser *types.User, -) *userAfterUpdate { - return &userAfterUpdate{ - userBase: &userBase{ - immutable: true, - user: argUser, - oldUser: argOldUser, - }, - } -} - -// UserAfterDelete creates afterDelete for system:user resource -// -// This function is auto-generated. -func UserAfterDelete( - argUser *types.User, - argOldUser *types.User, -) *userAfterDelete { - return &userAfterDelete{ - userBase: &userBase{ - immutable: false, - user: argUser, - oldUser: argOldUser, - }, - } -} - -// UserAfterDeleteImmutable creates afterDelete for system:user resource -// -// None of the arguments will be mutable! -// -// This function is auto-generated. -func UserAfterDeleteImmutable( - argUser *types.User, - argOldUser *types.User, -) *userAfterDelete { - return &userAfterDelete{ - userBase: &userBase{ - immutable: true, - user: argUser, - oldUser: argOldUser, - }, - } -} - -// SetUser sets new user value -// -// This function is auto-generated. -func (res *userBase) SetUser(argUser *types.User) { - res.user = argUser -} - -// User returns user -// -// This function is auto-generated. -func (res userBase) User() *types.User { - return res.user -} - -// OldUser returns oldUser -// -// This function is auto-generated. -func (res userBase) OldUser() *types.User { - return res.oldUser -} - -// SetInvoker sets new invoker value -// -// This function is auto-generated. -func (res *userBase) SetInvoker(argInvoker auth.Identifiable) { - res.invoker = argInvoker -} - -// Invoker returns invoker -// -// This function is auto-generated. -func (res userBase) Invoker() auth.Identifiable { - return res.invoker -} - -// Encode internal data to be passed as event params & arguments to triggered Corredor script -func (res userBase) Encode() (args map[string][]byte, err error) { - args = make(map[string][]byte) - - if args["user"], err = json.Marshal(res.user); err != nil { - return nil, err - } - - if args["oldUser"], err = json.Marshal(res.oldUser); err != nil { - return nil, err - } - - if args["invoker"], err = json.Marshal(res.invoker); err != nil { - return nil, err - } - - return -} - -// Decode return values from Corredor script into struct props -func (res *userBase) Decode(results map[string][]byte) (err error) { - if res.immutable { - // Respect immutability - return - } - if res.user != nil { - if r, ok := results["result"]; ok && len(results) == 1 { - if err = json.Unmarshal(r, res.user); err != nil { - return - } - } - } - - if res.user != nil { - if r, ok := results["user"]; ok { - if err = json.Unmarshal(r, res.user); err != nil { - return - } - } - } - - // Do not decode oldUser; marked as immutable - - if res.invoker != nil { - if r, ok := results["invoker"]; ok { - if err = json.Unmarshal(r, res.invoker); err != nil { - return - } - } - } - return -} diff --git a/system/service/reminder_actions.gen.go b/system/service/reminder_actions.gen.go index ed367d39f..4668481e6 100644 --- a/system/service/reminder_actions.gen.go +++ b/system/service/reminder_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from system/service/reminder_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// system/service/reminder_actions.yaml import ( "context" diff --git a/system/service/role_actions.gen.go b/system/service/role_actions.gen.go index 4e7314ad9..05255e2e5 100644 --- a/system/service/role_actions.gen.go +++ b/system/service/role_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from system/service/role_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// system/service/role_actions.yaml import ( "context" diff --git a/system/service/service.go b/system/service/service.go index 5583d2db9..98e3656df 100644 --- a/system/service/service.go +++ b/system/service/service.go @@ -2,21 +2,21 @@ package service import ( "context" + "fmt" "github.com/cortezaproject/corteza-server/pkg/healthcheck" + "github.com/cortezaproject/corteza-server/pkg/id" + "github.com/cortezaproject/corteza-server/system/types" "go.uber.org/zap" + "time" "github.com/cortezaproject/corteza-server/pkg/actionlog" - actionlogRepository "github.com/cortezaproject/corteza-server/pkg/actionlog/repository" - "github.com/cortezaproject/corteza-server/pkg/app/options" intAuth "github.com/cortezaproject/corteza-server/pkg/auth" "github.com/cortezaproject/corteza-server/pkg/eventbus" + "github.com/cortezaproject/corteza-server/pkg/options" "github.com/cortezaproject/corteza-server/pkg/permissions" - "github.com/cortezaproject/corteza-server/pkg/settings" "github.com/cortezaproject/corteza-server/pkg/store" "github.com/cortezaproject/corteza-server/pkg/store/minio" "github.com/cortezaproject/corteza-server/pkg/store/plain" - "github.com/cortezaproject/corteza-server/system/repository" - "github.com/cortezaproject/corteza-server/system/types" ) type ( @@ -30,9 +30,8 @@ type ( } Config struct { - ActionLog options.ActionLogOpt - Storage options.StorageOpt - GRPCClientSystem options.GRPCServerOpt + ActionLog options.ActionLogOpt + Storage options.StorageOpt } permitChecker interface { @@ -50,6 +49,11 @@ type ( var ( DefaultStore store.Store + // DefaultNgStore is an interface to storage backend(s) + // ng (next-gen) is a temporary prefix + // so that we can differentiate between it and the file-only store + DefaultNgStore storeInterface + DefaultLogger *zap.Logger // CurrentSubscription holds current subscription info, @@ -67,7 +71,7 @@ var ( DefaultPermissions permissionServicer // DefaultSettings controls system's settings - DefaultSettings settings.Service + DefaultSettings *settings // DefaultAccessControl Access control checking DefaultAccessControl *accessControl @@ -75,7 +79,7 @@ var ( DefaultAuthNotification AuthNotificationService // CurrentSettings represents current system settings - CurrentSettings = &types.Settings{} + CurrentSettings = &types.AppSettings{} DefaultActionlog actionlog.Recorder @@ -85,15 +89,41 @@ var ( DefaultUser UserService DefaultRole RoleService DefaultOrganisation OrganisationService - DefaultApplication ApplicationService + DefaultApplication *application DefaultReminder ReminderService DefaultAttachment AttachmentService DefaultStatistics *statistics + + // wrapper around time.Now() that will aid service testing + now = func() time.Time { + return time.Now() + } + + // returns pointer to time.Time struct that is set to current time + nowPtr = func() *time.Time { + n := now() + return &n + } + + // wrapper around id.Next() that will aid service testing + nextID = func() uint64 { + return id.Next() + } ) -func Initialize(ctx context.Context, log *zap.Logger, c Config) (err error) { - hcd := healthcheck.Defaults() +func Initialize(ctx context.Context, log *zap.Logger, s interface{}, c Config) (err error) { + var ( + hcd = healthcheck.Defaults() + ok bool + ) + + // we're doing conversion to avoid having + // store interface exposed or generated inside app package + if DefaultNgStore, ok = s.(storeInterface); !ok { + return fmt.Errorf("store %T is incompatible with compose storeInterface", s) + } + DefaultLogger = log.Named("service") { @@ -107,28 +137,18 @@ func Initialize(ctx context.Context, log *zap.Logger, c Config) (err error) { tee = log } - DefaultActionlog = actionlog.NewService( - actionlogRepository.Mysql(repository.DB(ctx).Quiet(), "sys_actionlog"), - log, - tee, - policy, - ) + DefaultActionlog = actionlog.NewService(DefaultNgStore, log, tee, policy) } if DefaultPermissions == nil { // Do not override permissions service stored under DefaultPermissions // to allow integration tests to inject own permission service - DefaultPermissions = permissions.Service(ctx, DefaultLogger, repository.DB(ctx), "sys_permission_rules") + DefaultPermissions = permissions.Service(ctx, DefaultLogger, DefaultNgStore) } DefaultAccessControl = AccessControl(DefaultPermissions) - DefaultSettings = settings.NewService( - settings.NewRepository(repository.DB(ctx), "sys_settings"), - DefaultLogger, - DefaultAccessControl, - CurrentSettings, - ) + DefaultSettings = Settings(DefaultNgStore, DefaultLogger, DefaultAccessControl, CurrentSettings) if DefaultStore == nil { const svcPath = "compose" @@ -172,7 +192,7 @@ func Initialize(ctx context.Context, log *zap.Logger, c Config) (err error) { DefaultUser = User(ctx) DefaultRole = Role(ctx) DefaultOrganisation = Organisation(ctx) - DefaultApplication = Application(ctx) + DefaultApplication = Application(DefaultNgStore, DefaultAccessControl, DefaultActionlog, eventbus.Service()) DefaultReminder = Reminder(ctx) DefaultSink = Sink() DefaultStatistics = Statistics() diff --git a/system/service/settings.go b/system/service/settings.go new file mode 100644 index 000000000..99a37b80c --- /dev/null +++ b/system/service/settings.go @@ -0,0 +1,207 @@ +package service + +import ( + "context" + "fmt" + "github.com/cortezaproject/corteza-server/pkg/logger" + "github.com/cortezaproject/corteza-server/store" + "github.com/cortezaproject/corteza-server/system/types" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "strings" + "time" +) + +type ( + settings struct { + store settingsStore + accessControl accessController + logger *zap.Logger + + // Holds reference to the "current" settings that + // are used by the services + current interface{} + } + + //Service interface { + // FindByPrefix(ctx context.Context, pp ...string) (vv types.SettingValueSet, err error) + // BulkSet(ctx context.Context, vv types.SettingValue) (err error) + // Set(ctx context.Context, v *types.SettingValue) (err error) + // Get(ctx context.Context, name string, ownedBy uint64) (out *types.SettingValue, err error) + // Delete(ctx context.Context, name string, ownedBy uint64) error + // UpdateCurrent(ctx context.Context) error + //} + + accessController interface { + CanReadSettings(ctx context.Context) bool + CanManageSettings(ctx context.Context) bool + } +) + +var ( + ErrNoReadPermission = fmt.Errorf("not allowed to read settings") + ErrNoManagePermission = fmt.Errorf("not allowed to manage settings") +) + +func Settings(s settingsStore, log *zap.Logger, ac accessController, current interface{}) *settings { + svc := &settings{ + store: s, + accessControl: ac, + logger: log.Named("settings"), + current: current, + } + + return svc +} + +func (svc settings) log(ctx context.Context, fields ...zapcore.Field) *zap.Logger { + return logger.AddRequestID(ctx, svc.logger).With(fields...) +} + +func (svc settings) FindByPrefix(ctx context.Context, pp ...string) (types.SettingValueSet, error) { + if !svc.accessControl.CanReadSettings(ctx) { + return nil, ErrNoReadPermission + } + + return svc.findByPrefix(ctx, pp...) +} + +func (svc settings) findByPrefix(ctx context.Context, pp ...string) (types.SettingValueSet, error) { + var ( + f = types.SettingsFilter{ + Prefix: strings.Join(pp, "."), + } + ) + + vv, _, err := svc.store.SearchSettings(ctx, f) + return vv, err +} + +func (svc settings) Get(ctx context.Context, name string, ownedBy uint64) (out *types.SettingValue, err error) { + if !svc.accessControl.CanReadSettings(ctx) { + return nil, ErrNoReadPermission + } + + out, err = svc.store.LookupSettingByNameOwnedBy(ctx, name, ownedBy) + if err != nil && err != store.ErrNotFound { + return nil, err + } + + return out, nil +} + +func (svc settings) UpdateCurrent(ctx context.Context) error { + if vv, err := svc.findByPrefix(ctx); err != nil { + return err + } else { + return svc.updateCurrent(ctx, vv) + } +} + +func (svc settings) updateCurrent(ctx context.Context, vv types.SettingValueSet) (err error) { + // update current settings with new values + if err = vv.KV().Decode(svc.current); err != nil { + return + } + + return +} + +func (svc settings) Set(ctx context.Context, v *types.SettingValue) (err error) { + if !svc.accessControl.CanManageSettings(ctx) { + return ErrNoManagePermission + } + + var current *types.SettingValue + current, err = svc.store.LookupSettingByNameOwnedBy(ctx, v.Name, v.OwnedBy) + if err == store.ErrNotFound { + v.UpdatedAt = time.Now() + err = svc.store.CreateSetting(ctx, v) + } else if err != nil { + return err + } + + if !current.Eq(v) { + v.UpdatedAt = time.Now() + err = svc.store.UpdateSetting(ctx, v) + } + + if err != nil || current.Eq(v) { + // Return on error or when there is nothing to update (same value) + return + } + + svc.logChange(ctx, types.SettingValueSet{v}) + return svc.updateCurrent(ctx, types.SettingValueSet{v}) +} + +func (svc settings) BulkSet(ctx context.Context, vv types.SettingValueSet) (err error) { + if !svc.accessControl.CanManageSettings(ctx) { + return ErrNoManagePermission + } + + // Load current settings from repository + // and get changed values + var current, old, new types.SettingValueSet + if current, err = svc.FindByPrefix(ctx); err != nil { + return + } else { + vv = current.Changed(vv) + _ = vv.Walk(func(v *types.SettingValue) error { + v.UpdatedAt = time.Now() + return nil + }) + + old = current.Old(vv) + new = current.New(vv) + } + + if err = svc.store.UpdateSetting(ctx, old...); err != nil { + return + } + + if err = svc.store.CreateSetting(ctx, new...); err != nil { + return + } + + svc.logChange(ctx, vv) + + return svc.updateCurrent(ctx, vv) +} + +func (svc settings) logChange(ctx context.Context, vv types.SettingValueSet) { + for _, v := range vv { + svc.log(ctx, + zap.String("name", v.Name), + zap.Uint64("owned-by", v.OwnedBy), + zap.Stringer("value", v.Value)). + WithOptions(zap.AddCallerSkip(1)). + Debug("setting value updated") + } +} + +func (svc settings) Delete(ctx context.Context, name string, ownedBy uint64) (err error) { + if !svc.accessControl.CanManageSettings(ctx) { + return ErrNoManagePermission + } + + var current *types.SettingValue + if current, err = svc.store.LookupSettingByNameOwnedBy(ctx, name, ownedBy); err == store.ErrNotFound { + return nil + } else if err != nil { + return + } + + err = svc.store.RemoveSetting(ctx, current) + if err != nil { + return + } + + vv := types.SettingValueSet{current} + + svc.log(ctx, + zap.String("name", name), + zap.Uint64("owned-by", ownedBy)).Info("setting value removed") + + return svc.updateCurrent(ctx, vv) +} diff --git a/system/service/sink_actions.gen.go b/system/service/sink_actions.gen.go index 830a48771..2440edb8f 100644 --- a/system/service/sink_actions.gen.go +++ b/system/service/sink_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from system/service/sink_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// system/service/sink_actions.yaml import ( "context" diff --git a/system/service/statistics_actions.gen.go b/system/service/statistics_actions.gen.go index 58075db3d..26f636bd9 100644 --- a/system/service/statistics_actions.gen.go +++ b/system/service/statistics_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from system/service/statistics_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// system/service/statistics_actions.yaml import ( "context" diff --git a/system/service/store_interface.gen.go b/system/service/store_interface.gen.go new file mode 100644 index 000000000..914aa7de8 --- /dev/null +++ b/system/service/store_interface.gen.go @@ -0,0 +1,32 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/actionlog.yaml +// - store/applications.yaml +// - store/credentials.yaml +// - store/rbac_rules.yaml +// - store/reminders.yaml +// - store/roles.yaml +// - store/settings.yaml +// - store/system_attachments.yaml +// - store/users.yaml + +type ( + // Interface combines interfaces of all supported store interfaces + storeInterface interface { + actionlogsStore + applicationsStore + credentialsStore + rbacRulesStore + remindersStore + rolesStore + settingsStore + attachmentsStore + usersStore + } +) diff --git a/system/service/store_interface_actionlog.gen.go b/system/service/store_interface_actionlog.gen.go new file mode 100644 index 000000000..1b67c3e64 --- /dev/null +++ b/system/service/store_interface_actionlog.gen.go @@ -0,0 +1,27 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/actionlog.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/actionlog" +) + +type ( + actionlogsStore interface { + SearchActionlogs(ctx context.Context, f actionlog.Filter) (actionlog.ActionSet, actionlog.Filter, error) + CreateActionlog(ctx context.Context, rr ...*actionlog.Action) error + UpdateActionlog(ctx context.Context, rr ...*actionlog.Action) error + PartialUpdateActionlog(ctx context.Context, onlyColumns []string, rr ...*actionlog.Action) error + RemoveActionlog(ctx context.Context, rr ...*actionlog.Action) error + RemoveActionlogByID(ctx context.Context, ID uint64) error + + TruncateActionlogs(ctx context.Context) error + } +) diff --git a/system/service/store_interface_applications.gen.go b/system/service/store_interface_applications.gen.go new file mode 100644 index 000000000..01a004c9d --- /dev/null +++ b/system/service/store_interface_applications.gen.go @@ -0,0 +1,28 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/applications.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + applicationsStore interface { + SearchApplications(ctx context.Context, f types.ApplicationFilter) (types.ApplicationSet, types.ApplicationFilter, error) + LookupApplicationByID(ctx context.Context, id uint64) (*types.Application, error) + CreateApplication(ctx context.Context, rr ...*types.Application) error + UpdateApplication(ctx context.Context, rr ...*types.Application) error + PartialUpdateApplication(ctx context.Context, onlyColumns []string, rr ...*types.Application) error + RemoveApplication(ctx context.Context, rr ...*types.Application) error + RemoveApplicationByID(ctx context.Context, ID uint64) error + + TruncateApplications(ctx context.Context) error + } +) diff --git a/system/service/store_interface_credentials.gen.go b/system/service/store_interface_credentials.gen.go new file mode 100644 index 000000000..ec327c966 --- /dev/null +++ b/system/service/store_interface_credentials.gen.go @@ -0,0 +1,28 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/credentials.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + credentialsStore interface { + SearchCredentials(ctx context.Context, f types.CredentialsFilter) (types.CredentialsSet, types.CredentialsFilter, error) + LookupCredentialsByID(ctx context.Context, id uint64) (*types.Credentials, error) + CreateCredentials(ctx context.Context, rr ...*types.Credentials) error + UpdateCredentials(ctx context.Context, rr ...*types.Credentials) error + PartialUpdateCredentials(ctx context.Context, onlyColumns []string, rr ...*types.Credentials) error + RemoveCredentials(ctx context.Context, rr ...*types.Credentials) error + RemoveCredentialsByID(ctx context.Context, ID uint64) error + + TruncateCredentials(ctx context.Context) error + } +) diff --git a/system/service/store_interface_rbac_rules.gen.go b/system/service/store_interface_rbac_rules.gen.go new file mode 100644 index 000000000..c244d22ab --- /dev/null +++ b/system/service/store_interface_rbac_rules.gen.go @@ -0,0 +1,27 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/rbac_rules.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/permissions" +) + +type ( + rbacRulesStore interface { + SearchRbacRules(ctx context.Context, f permissions.RuleFilter) (permissions.RuleSet, permissions.RuleFilter, error) + CreateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + UpdateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + PartialUpdateRbacRule(ctx context.Context, onlyColumns []string, rr ...*permissions.Rule) error + RemoveRbacRule(ctx context.Context, rr ...*permissions.Rule) error + RemoveRbacRuleByRoleIDResourceOperation(ctx context.Context, roleID uint64, resource string, operation string) error + + TruncateRbacRules(ctx context.Context) error + } +) diff --git a/system/service/store_interface_reminders.gen.go b/system/service/store_interface_reminders.gen.go new file mode 100644 index 000000000..354fb2291 --- /dev/null +++ b/system/service/store_interface_reminders.gen.go @@ -0,0 +1,28 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/reminders.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + remindersStore interface { + SearchReminders(ctx context.Context, f types.ReminderFilter) (types.ReminderSet, types.ReminderFilter, error) + LookupReminderByID(ctx context.Context, id uint64) (*types.Reminder, error) + CreateReminder(ctx context.Context, rr ...*types.Reminder) error + UpdateReminder(ctx context.Context, rr ...*types.Reminder) error + PartialUpdateReminder(ctx context.Context, onlyColumns []string, rr ...*types.Reminder) error + RemoveReminder(ctx context.Context, rr ...*types.Reminder) error + RemoveReminderByID(ctx context.Context, ID uint64) error + + TruncateReminders(ctx context.Context) error + } +) diff --git a/system/service/store_interface_roles.gen.go b/system/service/store_interface_roles.gen.go new file mode 100644 index 000000000..a17184246 --- /dev/null +++ b/system/service/store_interface_roles.gen.go @@ -0,0 +1,30 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/roles.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + rolesStore interface { + SearchRoles(ctx context.Context, f types.RoleFilter) (types.RoleSet, types.RoleFilter, error) + LookupRoleByID(ctx context.Context, id uint64) (*types.Role, error) + LookupRoleByHandle(ctx context.Context, handle string) (*types.Role, error) + LookupRoleByName(ctx context.Context, name string) (*types.Role, error) + CreateRole(ctx context.Context, rr ...*types.Role) error + UpdateRole(ctx context.Context, rr ...*types.Role) error + PartialUpdateRole(ctx context.Context, onlyColumns []string, rr ...*types.Role) error + RemoveRole(ctx context.Context, rr ...*types.Role) error + RemoveRoleByID(ctx context.Context, ID uint64) error + + TruncateRoles(ctx context.Context) error + } +) diff --git a/system/service/store_interface_settings.gen.go b/system/service/store_interface_settings.gen.go new file mode 100644 index 000000000..dc8497765 --- /dev/null +++ b/system/service/store_interface_settings.gen.go @@ -0,0 +1,28 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/settings.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + settingsStore interface { + SearchSettings(ctx context.Context, f types.SettingsFilter) (types.SettingValueSet, types.SettingsFilter, error) + LookupSettingByNameOwnedBy(ctx context.Context, name string, owned_by uint64) (*types.SettingValue, error) + CreateSetting(ctx context.Context, rr ...*types.SettingValue) error + UpdateSetting(ctx context.Context, rr ...*types.SettingValue) error + PartialUpdateSetting(ctx context.Context, onlyColumns []string, rr ...*types.SettingValue) error + RemoveSetting(ctx context.Context, rr ...*types.SettingValue) error + RemoveSettingByNameOwnedBy(ctx context.Context, name string, ownedBy uint64) error + + TruncateSettings(ctx context.Context) error + } +) diff --git a/system/service/store_interface_system_attachments.gen.go b/system/service/store_interface_system_attachments.gen.go new file mode 100644 index 000000000..b5eb424f8 --- /dev/null +++ b/system/service/store_interface_system_attachments.gen.go @@ -0,0 +1,28 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/system_attachments.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + attachmentsStore interface { + SearchAttachments(ctx context.Context, f types.AttachmentFilter) (types.AttachmentSet, types.AttachmentFilter, error) + LookupAttachmentByID(ctx context.Context, id uint64) (*types.Attachment, error) + CreateAttachment(ctx context.Context, rr ...*types.Attachment) error + UpdateAttachment(ctx context.Context, rr ...*types.Attachment) error + PartialUpdateAttachment(ctx context.Context, onlyColumns []string, rr ...*types.Attachment) error + RemoveAttachment(ctx context.Context, rr ...*types.Attachment) error + RemoveAttachmentByID(ctx context.Context, ID uint64) error + + TruncateAttachments(ctx context.Context) error + } +) diff --git a/system/service/store_interface_users.gen.go b/system/service/store_interface_users.gen.go new file mode 100644 index 000000000..cd82e62db --- /dev/null +++ b/system/service/store_interface_users.gen.go @@ -0,0 +1,31 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/users.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + usersStore interface { + SearchUsers(ctx context.Context, f types.UserFilter) (types.UserSet, types.UserFilter, error) + LookupUserByID(ctx context.Context, id uint64) (*types.User, error) + LookupUserByEmail(ctx context.Context, email string) (*types.User, error) + LookupUserByHandle(ctx context.Context, handle string) (*types.User, error) + LookupUserByUsername(ctx context.Context, username string) (*types.User, error) + CreateUser(ctx context.Context, rr ...*types.User) error + UpdateUser(ctx context.Context, rr ...*types.User) error + PartialUpdateUser(ctx context.Context, onlyColumns []string, rr ...*types.User) error + RemoveUser(ctx context.Context, rr ...*types.User) error + RemoveUserByID(ctx context.Context, ID uint64) error + + TruncateUsers(ctx context.Context) error + } +) diff --git a/system/service/user.go b/system/service/user.go index 2d83421ae..a5c089715 100644 --- a/system/service/user.go +++ b/system/service/user.go @@ -33,7 +33,7 @@ type ( actionlog actionlog.Recorder - settings *types.Settings + settings *types.AppSettings auth userAuth subscription userSubscriptionChecker diff --git a/system/service/user_actions.gen.go b/system/service/user_actions.gen.go index 138206ace..5ed74818e 100644 --- a/system/service/user_actions.gen.go +++ b/system/service/user_actions.gen.go @@ -1,7 +1,12 @@ package service -// This file is auto-generated from system/service/user_actions.yaml +// This file is auto-generated. // +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// system/service/user_actions.yaml import ( "context" diff --git a/tests/compose/main_test.go b/tests/compose/main_test.go index 8c61dc6f2..d1480c819 100644 --- a/tests/compose/main_test.go +++ b/tests/compose/main_test.go @@ -2,31 +2,28 @@ package compose import ( "context" - "github.com/cortezaproject/corteza-server/pkg/eventbus" - "os" - "testing" - - _ "github.com/joho/godotenv/autoload" - "github.com/spf13/afero" - "github.com/steinfletcher/apitest" - "github.com/stretchr/testify/require" - "github.com/titpetric/factory" - - "github.com/go-chi/chi" - - "github.com/cortezaproject/corteza-server/compose" + "github.com/cortezaproject/corteza-server/app" "github.com/cortezaproject/corteza-server/compose/rest" "github.com/cortezaproject/corteza-server/compose/service" "github.com/cortezaproject/corteza-server/compose/types" - "github.com/cortezaproject/corteza-server/corteza" "github.com/cortezaproject/corteza-server/pkg/api" - "github.com/cortezaproject/corteza-server/pkg/app" "github.com/cortezaproject/corteza-server/pkg/auth" + "github.com/cortezaproject/corteza-server/pkg/cli" + "github.com/cortezaproject/corteza-server/pkg/eventbus" "github.com/cortezaproject/corteza-server/pkg/logger" "github.com/cortezaproject/corteza-server/pkg/permissions" "github.com/cortezaproject/corteza-server/pkg/store/plain" sysTypes "github.com/cortezaproject/corteza-server/system/types" "github.com/cortezaproject/corteza-server/tests/helpers" + "github.com/go-chi/chi" + _ "github.com/joho/godotenv/autoload" + "github.com/spf13/afero" + "github.com/steinfletcher/apitest" + "github.com/stretchr/testify/require" + "github.com/titpetric/factory" + "go.uber.org/zap" + "os" + "testing" ) type ( @@ -37,14 +34,10 @@ type ( cUser *sysTypes.User roleID uint64 } - - TestApp struct { - helpers.TestApp - } ) var ( - testApp app.Runnable + testApp *app.CortezaApp r chi.Router eventBus = eventbus.New() @@ -58,29 +51,22 @@ func db() *factory.DB { return factory.Database.MustGet().With(context.Background()) } -func (app *TestApp) Initialize(ctx context.Context) (err error) { - service.DefaultPermissions = permissions.NewTestService(ctx, app.Log, db(), "compose_permission_rules") - service.DefaultStore, err = plain.NewWithAfero(afero.NewMemMapFs(), "test") - - eventBus = eventbus.New() - eventbus.Set(eventBus) - - return -} - -func (app *TestApp) Activate(ctx context.Context) (err error) { - service.DefaultPermissions.(*permissions.TestService).Reload(ctx) - return -} - func InitTestApp() { if testApp == nil { - testApp = helpers.NewIntegrationTestApp( - compose.SERVICE, - &corteza.App{}, - &TestApp{}, - &compose.App{}, - ) + ctx := cli.Context() + + testApp = helpers.NewIntegrationTestApp(ctx, func(app *app.CortezaApp) (err error) { + service.DefaultPermissions = permissions.NewTestService(ctx, zap.NewNop(), app.Store.(rbacRulesStore)) + service.DefaultStore, err = plain.NewWithAfero(afero.NewMemMapFs(), "test") + if err != nil { + return err + } + + eventbus.Set(eventBus) + service.DefaultPermissions.(*permissions.TestService).Reload(ctx) + return nil + }) + } if r == nil { @@ -121,7 +107,7 @@ func (h helper) secCtx() context.Context { // apitest basics, initialize, set handler, add auth func (h helper) apiInit() *apitest.APITest { - InitTestApp() + //InitTestApp() return apitest. New(). diff --git a/tests/compose/settings_test.go b/tests/compose/settings_test.go deleted file mode 100644 index 0777dc2aa..000000000 --- a/tests/compose/settings_test.go +++ /dev/null @@ -1,128 +0,0 @@ -package compose - -import ( - "net/http" - "testing" - - "github.com/cortezaproject/corteza-server/compose/service" - tt "github.com/cortezaproject/corteza-server/compose/types" - "github.com/cortezaproject/corteza-server/pkg/settings" - "github.com/cortezaproject/corteza-server/tests/helpers" - "github.com/jmoiron/sqlx/types" - jsonpath "github.com/steinfletcher/apitest-jsonpath" -) - -func TestSettingsList(t *testing.T) { - h := newHelper(t) - h.allow(tt.ComposePermissionResource, "settings.read") - h.allow(tt.ComposePermissionResource, "settings.manage") - - err := service.DefaultSettings.BulkSet(h.secCtx(), settings.ValueSet{ - &settings.Value{Name: "t_cmp_k1.s1", Value: types.JSONText(`"t_cmp_v1"`)}, - &settings.Value{Name: "t_cmp_k1.s2", Value: types.JSONText(`"t_cmp_v2"`)}, - }) - h.a.NoError(err) - - h.apiInit(). - Get("/settings/"). - Expect(t). - Status(http.StatusOK). - Assert(helpers.AssertNoErrors). - Assert(jsonpath.Present(`$.response[? @.name=="t_cmp_k1.s1"]`)). - Assert(jsonpath.Present(`$.response[? @.value=="t_cmp_v1"]`)). - Assert(jsonpath.Present(`$.response[? @.name=="t_cmp_k1.s2"]`)). - Assert(jsonpath.Present(`$.response[? @.value=="t_cmp_v2"]`)). - End() -} - -func TestSettingsList_noPermissions(t *testing.T) { - h := newHelper(t) - h.deny(tt.ComposePermissionResource, "settings.read") - - h.apiInit(). - Get("/settings/"). - Expect(t). - Status(http.StatusOK). - Assert(helpers.AssertError("not allowed to read settings")). - End() -} - -func TestSettingsUpdate(t *testing.T) { - h := newHelper(t) - h.allow(tt.ComposePermissionResource, "settings.manage") - h.allow(tt.ComposePermissionResource, "settings.read") - - err := service.DefaultSettings.BulkSet(h.secCtx(), settings.ValueSet{ - &settings.Value{Name: "t_cmp_k1.s1", Value: types.JSONText(`"t_cmp_v1"`)}, - }) - h.a.NoError(err) - - h.apiInit(). - Patch("/settings/"). - JSON(`{"values":[{"name":"t_cmp_k1.s1","value":"t_cmp_v1_edited"},{"name":"t_cmp_k2.s1","value":"t_cmp_v2_new"}]}`). - Expect(t). - Status(http.StatusOK). - Assert(helpers.AssertNoErrors). - End() - - s, err := service.DefaultSettings.Get(h.secCtx(), "t_cmp_k1.s1", 0) - h.a.NoError(err) - h.a.Equal(`"t_cmp_v1_edited"`, s.Value.String(), "existing key should be updated") - - s, err = service.DefaultSettings.Get(h.secCtx(), "t_cmp_k2.s1", 0) - h.a.NoError(err) - h.a.Equal(`"t_cmp_v2_new"`, s.Value.String(), "new key should be added") -} - -func TestSettingsUpdate_noPermissions(t *testing.T) { - h := newHelper(t) - h.deny(tt.ComposePermissionResource, "settings.manage") - - h.apiInit(). - Patch("/settings/"). - JSON(`{"values":[]}`). - Expect(t). - Status(http.StatusOK). - Assert(helpers.AssertError("not allowed to manage settings")). - End() -} - -func TestSettingsGet(t *testing.T) { - h := newHelper(t) - h.allow(tt.ComposePermissionResource, "settings.read") - h.allow(tt.ComposePermissionResource, "settings.manage") - - err := service.DefaultSettings.BulkSet(h.secCtx(), settings.ValueSet{ - &settings.Value{Name: "t_cmp_k1.s1", Value: types.JSONText(`"t_cmp_v1"`)}, - }) - h.a.NoError(err) - - h.apiInit(). - Get("/settings/t_cmp_k1.s1"). - Expect(t). - Status(http.StatusOK). - Assert(helpers.AssertNoErrors). - Assert(jsonpath.Present(`$.response.name=="t_cmp_k1.s1"`)). - Assert(jsonpath.Present(`$.response.value=="t_cmp_v1"`)). - End() - - h.apiInit(). - Get("/settings/t_cmp_k1.missing"). - Expect(t). - Status(http.StatusOK). - Assert(helpers.AssertNoErrors). - Assert(jsonpath.Equal(`$.response`, nil)). - End() -} - -func TestSettingsGet_noPermissions(t *testing.T) { - h := newHelper(t) - h.deny(tt.ComposePermissionResource, "settings.read") - - h.apiInit(). - Get("/settings/t_cmp_k1.s1"). - Expect(t). - Status(http.StatusOK). - Assert(helpers.AssertError("not allowed to read settings")). - End() -} diff --git a/tests/compose/store_interface.gen.go b/tests/compose/store_interface.gen.go new file mode 100644 index 000000000..723fb161b --- /dev/null +++ b/tests/compose/store_interface.gen.go @@ -0,0 +1,16 @@ +package compose + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/rbac_rules.yaml + +type ( + // Interface combines interfaces of all supported store interfaces + storeInterface interface { + rbacRulesStore + } +) diff --git a/tests/compose/store_interface_rbac_rules.gen.go b/tests/compose/store_interface_rbac_rules.gen.go new file mode 100644 index 000000000..ccb2ade07 --- /dev/null +++ b/tests/compose/store_interface_rbac_rules.gen.go @@ -0,0 +1,27 @@ +package compose + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/rbac_rules.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/permissions" +) + +type ( + rbacRulesStore interface { + SearchRbacRules(ctx context.Context, f permissions.RuleFilter) (permissions.RuleSet, permissions.RuleFilter, error) + CreateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + UpdateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + PartialUpdateRbacRule(ctx context.Context, onlyColumns []string, rr ...*permissions.Rule) error + RemoveRbacRule(ctx context.Context, rr ...*permissions.Rule) error + RemoveRbacRuleByRoleIDResourceOperation(ctx context.Context, roleID uint64, resource string, operation string) error + + TruncateRbacRules(ctx context.Context) error + } +) diff --git a/tests/helpers/app.go b/tests/helpers/app.go index 603128570..75b66c22e 100644 --- a/tests/helpers/app.go +++ b/tests/helpers/app.go @@ -2,63 +2,27 @@ package helpers import ( "context" - "time" - - "go.uber.org/zap" - - "github.com/cortezaproject/corteza-server/pkg/app" + "github.com/cortezaproject/corteza-server/app" "github.com/cortezaproject/corteza-server/pkg/cli" "github.com/cortezaproject/corteza-server/pkg/logger" "github.com/cortezaproject/corteza-server/pkg/rand" + "time" ) -type ( - TestApp struct { - Opt *app.Options - Log *zap.Logger - } -) - -var _ app.Runnable = &TestApp{} - -func NewIntegrationTestApp(service string, parts ...app.Runnable) app.Runnable { - opt := app.NewOptions(service) +func NewIntegrationTestApp(ctx context.Context, initTestServices func(*app.CortezaApp) error) *app.CortezaApp { + a := app.New() // When running integration tests, we want to upgrade the db. Always. - opt.Upgrade.Always = true + a.Opt.Upgrade.Always = true // Create a new JWT secret (to prevent any security weirdness) - opt.Auth.Secret = string(rand.Bytes(32)) - opt.Auth.Expiry = time.Minute + a.Opt.Auth.Secret = string(rand.Bytes(32)) + a.Opt.Auth.Expiry = time.Minute - logger.DefaultLevel.SetLevel(zap.DebugLevel) - log := logger.MakeDebugLogger() + a.Log = logger.MakeDebugLogger() - testApp := app.New(parts...) - - cli.HandleError(testApp.Setup(log, opt)) - cli.HandleError(testApp.Activate(cli.Context())) - return testApp -} - -func (app *TestApp) Setup(log *zap.Logger, opt *app.Options) (err error) { - app.Log = log - app.Opt = opt - return -} - -func (app *TestApp) Initialize(ctx context.Context) (err error) { - return -} - -func (app *TestApp) Upgrade(ctx context.Context) (err error) { - return -} - -func (app *TestApp) Activate(ctx context.Context) (err error) { - return -} - -func (app *TestApp) Provision(ctx context.Context) (err error) { - return + cli.HandleError(a.InitStore(ctx)) + cli.HandleError(initTestServices(a)) + cli.HandleError(a.InitServices(ctx)) + return a } diff --git a/tests/messaging/main_test.go b/tests/messaging/main_test.go index 659cb19d2..b1cf41cd6 100644 --- a/tests/messaging/main_test.go +++ b/tests/messaging/main_test.go @@ -2,30 +2,28 @@ package messaging import ( "context" - "os" - "testing" - - _ "github.com/joho/godotenv/autoload" - "github.com/spf13/afero" - "github.com/steinfletcher/apitest" - "github.com/stretchr/testify/require" - "github.com/titpetric/factory" - - "github.com/go-chi/chi" - - "github.com/cortezaproject/corteza-server/corteza" - "github.com/cortezaproject/corteza-server/messaging" + "github.com/cortezaproject/corteza-server/app" "github.com/cortezaproject/corteza-server/messaging/rest" "github.com/cortezaproject/corteza-server/messaging/service" "github.com/cortezaproject/corteza-server/messaging/types" "github.com/cortezaproject/corteza-server/pkg/api" - "github.com/cortezaproject/corteza-server/pkg/app" "github.com/cortezaproject/corteza-server/pkg/auth" + "github.com/cortezaproject/corteza-server/pkg/cli" + "github.com/cortezaproject/corteza-server/pkg/eventbus" "github.com/cortezaproject/corteza-server/pkg/logger" "github.com/cortezaproject/corteza-server/pkg/permissions" "github.com/cortezaproject/corteza-server/pkg/store/plain" sysTypes "github.com/cortezaproject/corteza-server/system/types" "github.com/cortezaproject/corteza-server/tests/helpers" + "github.com/go-chi/chi" + _ "github.com/joho/godotenv/autoload" + "github.com/spf13/afero" + "github.com/steinfletcher/apitest" + "github.com/stretchr/testify/require" + "github.com/titpetric/factory" + "go.uber.org/zap" + "os" + "testing" ) type ( @@ -36,15 +34,12 @@ type ( cUser *sysTypes.User roleID uint64 } - - TestApp struct { - helpers.TestApp - } ) var ( - testApp app.Runnable - r chi.Router + testApp *app.CortezaApp + r chi.Router + eventBus = eventbus.New() ) func init() { @@ -55,25 +50,22 @@ func db() *factory.DB { return factory.Database.MustGet().With(context.Background()) } -func (app *TestApp) Initialize(ctx context.Context) (err error) { - service.DefaultPermissions = permissions.NewTestService(ctx, app.Log, db(), "messaging_permission_rules") - service.DefaultStore, err = plain.NewWithAfero(afero.NewMemMapFs(), "test") - return -} - -func (app *TestApp) Activate(ctx context.Context) (err error) { - service.DefaultPermissions.(*permissions.TestService).Reload(ctx) - return -} - func InitTestApp() { if testApp == nil { - testApp = helpers.NewIntegrationTestApp( - messaging.SERVICE, - &corteza.App{}, - &TestApp{}, - &messaging.App{}, - ) + ctx := cli.Context() + + testApp = helpers.NewIntegrationTestApp(ctx, func(app *app.CortezaApp) (err error) { + service.DefaultPermissions = permissions.NewTestService(ctx, zap.NewNop(), app.Store.(rbacRulesStore)) + service.DefaultStore, err = plain.NewWithAfero(afero.NewMemMapFs(), "test") + if err != nil { + return err + } + + eventbus.Set(eventBus) + service.DefaultPermissions.(*permissions.TestService).Reload(ctx) + return nil + }) + } if r == nil { diff --git a/tests/messaging/settings_test.go b/tests/messaging/settings_test.go deleted file mode 100644 index 3f2d41741..000000000 --- a/tests/messaging/settings_test.go +++ /dev/null @@ -1,128 +0,0 @@ -package messaging - -import ( - "net/http" - "testing" - - "github.com/cortezaproject/corteza-server/messaging/service" - tt "github.com/cortezaproject/corteza-server/messaging/types" - "github.com/cortezaproject/corteza-server/pkg/settings" - "github.com/cortezaproject/corteza-server/tests/helpers" - "github.com/jmoiron/sqlx/types" - jsonpath "github.com/steinfletcher/apitest-jsonpath" -) - -func TestSettingsList(t *testing.T) { - h := newHelper(t) - h.allow(tt.MessagingPermissionResource, "settings.read") - h.allow(tt.MessagingPermissionResource, "settings.manage") - - err := service.DefaultSettings.BulkSet(h.secCtx(), settings.ValueSet{ - &settings.Value{Name: "t_msg_k1.s1", Value: types.JSONText(`"t_msg_v1"`)}, - &settings.Value{Name: "t_msg_k1.s2", Value: types.JSONText(`"t_msg_v2"`)}, - }) - h.a.NoError(err) - - h.apiInit(). - Get("/settings/"). - Expect(t). - Status(http.StatusOK). - Assert(helpers.AssertNoErrors). - Assert(jsonpath.Present(`$.response[? @.name=="t_msg_k1.s1"]`)). - Assert(jsonpath.Present(`$.response[? @.value=="t_msg_v1"]`)). - Assert(jsonpath.Present(`$.response[? @.name=="t_msg_k1.s2"]`)). - Assert(jsonpath.Present(`$.response[? @.value=="t_msg_v2"]`)). - End() -} - -func TestSettingsList_noPermissions(t *testing.T) { - h := newHelper(t) - h.deny(tt.MessagingPermissionResource, "settings.read") - - h.apiInit(). - Get("/settings/"). - Expect(t). - Status(http.StatusOK). - Assert(helpers.AssertError("not allowed to read settings")). - End() -} - -func TestSettingsUpdate(t *testing.T) { - h := newHelper(t) - h.allow(tt.MessagingPermissionResource, "settings.manage") - h.allow(tt.MessagingPermissionResource, "settings.read") - - err := service.DefaultSettings.BulkSet(h.secCtx(), settings.ValueSet{ - &settings.Value{Name: "t_msg_k1.s1", Value: types.JSONText(`"t_msg_v1"`)}, - }) - h.a.NoError(err) - - h.apiInit(). - Patch("/settings/"). - JSON(`{"values":[{"name":"t_msg_k1.s1","value":"t_msg_v1_edited"},{"name":"t_msg_k2.s1","value":"t_msg_v2_new"}]}`). - Expect(t). - Status(http.StatusOK). - Assert(helpers.AssertNoErrors). - End() - - s, err := service.DefaultSettings.Get(h.secCtx(), "t_msg_k1.s1", 0) - h.a.NoError(err) - h.a.Equal(`"t_msg_v1_edited"`, s.Value.String(), "existing key should be updated") - - s, err = service.DefaultSettings.Get(h.secCtx(), "t_msg_k2.s1", 0) - h.a.NoError(err) - h.a.Equal(`"t_msg_v2_new"`, s.Value.String(), "new key should be added") -} - -func TestSettingsUpdate_noPermissions(t *testing.T) { - h := newHelper(t) - h.deny(tt.MessagingPermissionResource, "settings.manage") - - h.apiInit(). - Patch("/settings/"). - JSON(`{"values":[]}`). - Expect(t). - Status(http.StatusOK). - Assert(helpers.AssertError("not allowed to manage settings")). - End() -} - -func TestSettingsGet(t *testing.T) { - h := newHelper(t) - h.allow(tt.MessagingPermissionResource, "settings.read") - h.allow(tt.MessagingPermissionResource, "settings.manage") - - err := service.DefaultSettings.BulkSet(h.secCtx(), settings.ValueSet{ - &settings.Value{Name: "t_msg_k1.s1", Value: types.JSONText(`"t_msg_v1"`)}, - }) - h.a.NoError(err) - - h.apiInit(). - Get("/settings/t_msg_k1.s1"). - Expect(t). - Status(http.StatusOK). - Assert(helpers.AssertNoErrors). - Assert(jsonpath.Present(`$.response.name=="t_msg_k1.s1"`)). - Assert(jsonpath.Present(`$.response.value=="t_msg_v1"`)). - End() - - h.apiInit(). - Get("/settings/t_msg_k1.missing"). - Expect(t). - Status(http.StatusOK). - Assert(helpers.AssertNoErrors). - Assert(jsonpath.Equal(`$.response`, nil)). - End() -} - -func TestSettingsGet_noPermissions(t *testing.T) { - h := newHelper(t) - h.deny(tt.MessagingPermissionResource, "settings.read") - - h.apiInit(). - Get("/settings/t_msg_k1.s1"). - Expect(t). - Status(http.StatusOK). - Assert(helpers.AssertError("not allowed to read settings")). - End() -} diff --git a/tests/messaging/store_interface.gen.go b/tests/messaging/store_interface.gen.go new file mode 100644 index 000000000..088aaabea --- /dev/null +++ b/tests/messaging/store_interface.gen.go @@ -0,0 +1,16 @@ +package messaging + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/rbac_rules.yaml + +type ( + // Interface combines interfaces of all supported store interfaces + storeInterface interface { + rbacRulesStore + } +) diff --git a/tests/messaging/store_interface_rbac_rules.gen.go b/tests/messaging/store_interface_rbac_rules.gen.go new file mode 100644 index 000000000..627a8d781 --- /dev/null +++ b/tests/messaging/store_interface_rbac_rules.gen.go @@ -0,0 +1,27 @@ +package messaging + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/rbac_rules.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/permissions" +) + +type ( + rbacRulesStore interface { + SearchRbacRules(ctx context.Context, f permissions.RuleFilter) (permissions.RuleSet, permissions.RuleFilter, error) + CreateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + UpdateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + PartialUpdateRbacRule(ctx context.Context, onlyColumns []string, rr ...*permissions.Rule) error + RemoveRbacRule(ctx context.Context, rr ...*permissions.Rule) error + RemoveRbacRuleByRoleIDResourceOperation(ctx context.Context, roleID uint64, resource string, operation string) error + + TruncateRbacRules(ctx context.Context) error + } +) diff --git a/tests/system/main_test.go b/tests/system/main_test.go index 7a130ee81..3a602d490 100644 --- a/tests/system/main_test.go +++ b/tests/system/main_test.go @@ -2,27 +2,28 @@ package system import ( "context" - "os" - "testing" - - "github.com/go-chi/chi" - _ "github.com/joho/godotenv/autoload" - "github.com/steinfletcher/apitest" - "github.com/stretchr/testify/require" - "github.com/titpetric/factory" - - "github.com/cortezaproject/corteza-server/corteza" + "github.com/cortezaproject/corteza-server/app" "github.com/cortezaproject/corteza-server/pkg/api" - "github.com/cortezaproject/corteza-server/pkg/app" "github.com/cortezaproject/corteza-server/pkg/auth" + "github.com/cortezaproject/corteza-server/pkg/cli" + "github.com/cortezaproject/corteza-server/pkg/eventbus" "github.com/cortezaproject/corteza-server/pkg/logger" "github.com/cortezaproject/corteza-server/pkg/permissions" "github.com/cortezaproject/corteza-server/pkg/rand" - "github.com/cortezaproject/corteza-server/system" + "github.com/cortezaproject/corteza-server/pkg/store/plain" "github.com/cortezaproject/corteza-server/system/rest" "github.com/cortezaproject/corteza-server/system/service" "github.com/cortezaproject/corteza-server/system/types" "github.com/cortezaproject/corteza-server/tests/helpers" + "github.com/go-chi/chi" + _ "github.com/joho/godotenv/autoload" + "github.com/spf13/afero" + "github.com/steinfletcher/apitest" + "github.com/stretchr/testify/require" + "github.com/titpetric/factory" + "go.uber.org/zap" + "os" + "testing" ) type ( @@ -33,15 +34,13 @@ type ( cUser *types.User roleID uint64 } - - TestApp struct { - helpers.TestApp - } ) var ( - testApp app.Runnable + testApp *app.CortezaApp r chi.Router + + eventBus = eventbus.New() ) func init() { @@ -62,24 +61,22 @@ func db() *factory.DB { return factory.Database.MustGet().With(context.Background()) } -func (app *TestApp) Initialize(ctx context.Context) (err error) { - service.DefaultPermissions = permissions.NewTestService(ctx, app.Log, db(), "compose_permission_rules") - return -} - -func (app *TestApp) Activate(ctx context.Context) (err error) { - service.DefaultPermissions.(*permissions.TestService).Reload(ctx) - return -} - func InitTestApp() { if testApp == nil { - testApp = helpers.NewIntegrationTestApp( - system.SERVICE, - &corteza.App{}, - &TestApp{}, - &system.App{}, - ) + ctx := cli.Context() + + testApp = helpers.NewIntegrationTestApp(ctx, func(app *app.CortezaApp) (err error) { + service.DefaultPermissions = permissions.NewTestService(ctx, zap.NewNop(), app.Store.(rbacRulesStore)) + service.DefaultStore, err = plain.NewWithAfero(afero.NewMemMapFs(), "test") + if err != nil { + return err + } + + eventbus.Set(eventBus) + service.DefaultPermissions.(*permissions.TestService).Reload(ctx) + return nil + }) + } if r == nil { diff --git a/tests/system/settings_test.go b/tests/system/settings_test.go index 88e74a744..13715187d 100644 --- a/tests/system/settings_test.go +++ b/tests/system/settings_test.go @@ -1,25 +1,23 @@ package system import ( + "github.com/cortezaproject/corteza-server/system/service" + "github.com/cortezaproject/corteza-server/system/types" + "github.com/cortezaproject/corteza-server/tests/helpers" + sqlTypes "github.com/jmoiron/sqlx/types" + jsonpath "github.com/steinfletcher/apitest-jsonpath" "net/http" "testing" - - "github.com/cortezaproject/corteza-server/pkg/settings" - "github.com/cortezaproject/corteza-server/system/service" - tt "github.com/cortezaproject/corteza-server/system/types" - "github.com/cortezaproject/corteza-server/tests/helpers" - "github.com/jmoiron/sqlx/types" - jsonpath "github.com/steinfletcher/apitest-jsonpath" ) func TestSettingsList(t *testing.T) { h := newHelper(t) - h.allow(tt.SystemPermissionResource, "settings.read") - h.allow(tt.SystemPermissionResource, "settings.manage") + h.allow(types.SystemPermissionResource, "settings.read") + h.allow(types.SystemPermissionResource, "settings.manage") - err := service.DefaultSettings.BulkSet(h.secCtx(), settings.ValueSet{ - &settings.Value{Name: "t_sys_k1.s1", Value: types.JSONText(`"t_sys_v1"`)}, - &settings.Value{Name: "t_sys_k1.s2", Value: types.JSONText(`"t_sys_v2"`)}, + err := service.DefaultSettings.BulkSet(h.secCtx(), types.SettingValueSet{ + &types.SettingValue{Name: "t_sys_k1.s1", Value: sqlTypes.JSONText(`"t_sys_v1"`)}, + &types.SettingValue{Name: "t_sys_k1.s2", Value: sqlTypes.JSONText(`"t_sys_v2"`)}, }) h.a.NoError(err) @@ -37,7 +35,7 @@ func TestSettingsList(t *testing.T) { func TestSettingsList_noPermissions(t *testing.T) { h := newHelper(t) - h.deny(tt.SystemPermissionResource, "settings.read") + h.deny(types.SystemPermissionResource, "settings.read") h.apiInit(). Get("/settings/"). @@ -49,11 +47,11 @@ func TestSettingsList_noPermissions(t *testing.T) { func TestSettingsUpdate(t *testing.T) { h := newHelper(t) - h.allow(tt.SystemPermissionResource, "settings.manage") - h.allow(tt.SystemPermissionResource, "settings.read") + h.allow(types.SystemPermissionResource, "settings.manage") + h.allow(types.SystemPermissionResource, "settings.read") - err := service.DefaultSettings.BulkSet(h.secCtx(), settings.ValueSet{ - &settings.Value{Name: "t_sys_k1.s1", Value: types.JSONText(`"t_sys_v1"`)}, + err := service.DefaultSettings.BulkSet(h.secCtx(), types.SettingValueSet{ + &types.SettingValue{Name: "t_sys_k1.s1", Value: sqlTypes.JSONText(`"t_sys_v1"`)}, }) h.a.NoError(err) @@ -76,7 +74,7 @@ func TestSettingsUpdate(t *testing.T) { func TestSettingsUpdate_noPermissions(t *testing.T) { h := newHelper(t) - h.deny(tt.SystemPermissionResource, "settings.manage") + h.deny(types.SystemPermissionResource, "settings.manage") h.apiInit(). Patch("/settings/"). @@ -89,11 +87,11 @@ func TestSettingsUpdate_noPermissions(t *testing.T) { func TestSettingsGet(t *testing.T) { h := newHelper(t) - h.allow(tt.SystemPermissionResource, "settings.read") - h.allow(tt.SystemPermissionResource, "settings.manage") + h.allow(types.SystemPermissionResource, "settings.read") + h.allow(types.SystemPermissionResource, "settings.manage") - err := service.DefaultSettings.BulkSet(h.secCtx(), settings.ValueSet{ - &settings.Value{Name: "t_sys_k1.s1", Value: types.JSONText(`"t_sys_v1"`)}, + err := service.DefaultSettings.BulkSet(h.secCtx(), types.SettingValueSet{ + &types.SettingValue{Name: "t_sys_k1.s1", Value: sqlTypes.JSONText(`"t_sys_v1"`)}, }) h.a.NoError(err) @@ -117,7 +115,7 @@ func TestSettingsGet(t *testing.T) { func TestSettingsGet_noPermissions(t *testing.T) { h := newHelper(t) - h.deny(tt.SystemPermissionResource, "settings.read") + h.deny(types.SystemPermissionResource, "settings.read") h.apiInit(). Get("/settings/t_sys_k1.s1"). diff --git a/tests/system/store_interface.gen.go b/tests/system/store_interface.gen.go new file mode 100644 index 000000000..4c01a8243 --- /dev/null +++ b/tests/system/store_interface.gen.go @@ -0,0 +1,16 @@ +package system + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/rbac_rules.yaml + +type ( + // Interface combines interfaces of all supported store interfaces + storeInterface interface { + rbacRulesStore + } +) diff --git a/tests/system/store_interface_rbac_rules.gen.go b/tests/system/store_interface_rbac_rules.gen.go new file mode 100644 index 000000000..1bfb461d8 --- /dev/null +++ b/tests/system/store_interface_rbac_rules.gen.go @@ -0,0 +1,27 @@ +package system + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// - store/rbac_rules.yaml + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/permissions" +) + +type ( + rbacRulesStore interface { + SearchRbacRules(ctx context.Context, f permissions.RuleFilter) (permissions.RuleSet, permissions.RuleFilter, error) + CreateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + UpdateRbacRule(ctx context.Context, rr ...*permissions.Rule) error + PartialUpdateRbacRule(ctx context.Context, onlyColumns []string, rr ...*permissions.Rule) error + RemoveRbacRule(ctx context.Context, rr ...*permissions.Rule) error + RemoveRbacRuleByRoleIDResourceOperation(ctx context.Context, roleID uint64, resource string, operation string) error + + TruncateRbacRules(ctx context.Context) error + } +)