From 3568d0841e1abad2a770eae8d048740626330502 Mon Sep 17 00:00:00 2001 From: Denis Arh Date: Tue, 28 Dec 2021 21:36:59 +0100 Subject: [PATCH] Migrate codegen for locale to CUE --- codegen/all.cue | 14 +- .../templates/gocode/locale/service.go.tpl | 206 ++++++++ .../templates/gocode/locale/types.go.tpl | 120 +++++ .../gocode/rbac/access_control.go.tpl | 4 +- .../assets/templates/gocode/rbac/types.go.tpl | 8 +- codegen/locale-service.cue | 44 ++ codegen/locale-types.cue | 55 ++ codegen/rbac-access_control.cue | 60 ++- codegen/rbac-types.cue | 31 +- compose/chart.cue | 16 +- compose/component.cue | 8 +- compose/module-field.cue | 55 +- compose/module.cue | 13 +- compose/namespace.cue | 19 +- compose/page.cue | 37 +- compose/record.cue | 7 +- compose/service/access_control.gen.go | 496 +++++++++--------- compose/service/locale.gen.go | 27 +- compose/service/locale.go | 16 +- compose/types/locale.gen.go | 301 +++++------ compose/types/module_field.go | 48 +- compose/types/module_field_test.go | 2 +- compose/types/namespace.go | 1 - compose/types/page.go | 12 +- compose/types/rbac.gen.go | 147 +++--- def/schema/component.cue | 15 +- def/schema/locale.cue | 37 +- def/schema/platform.cue | 2 +- def/schema/rbac.cue | 27 +- def/schema/resource.cue | 116 ++-- def/schema/shared.cue | 23 +- .../templates/gocode/locale/types.go.tpl | 135 ----- system/component.cue | 2 +- system/service/access_control.gen.go | 256 ++------- system/types/rbac.gen.go | 136 ++--- 35 files changed, 1284 insertions(+), 1212 deletions(-) create mode 100644 codegen/assets/templates/gocode/locale/service.go.tpl create mode 100644 codegen/assets/templates/gocode/locale/types.go.tpl create mode 100644 codegen/locale-service.cue create mode 100644 codegen/locale-types.cue delete mode 100644 pkg/codegen-v3/assets/templates/gocode/locale/types.go.tpl diff --git a/codegen/all.cue b/codegen/all.cue index 198b29124..693e5570d 100644 --- a/codegen/all.cue +++ b/codegen/all.cue @@ -1,10 +1,16 @@ package codegen import ( - "github.com/cortezaproject/corteza-server/codegen/schema" + "github.com/cortezaproject/corteza-server/codegen/schema" ) -all: [...schema.#codegen] & - rbacAccessControl + - rbacTypes + +// List of all codegen jobs for the entire platform +// +// How to run it? +// @todo when this gets into +// cue eval codegen/*.cue --out json -e platform | go run codegen/tool/*.go -v +platform: [...schema.#codegen] & + rbacAccessControl+ + rbacTypes+ + localeTypes+ [] // placeholder diff --git a/codegen/assets/templates/gocode/locale/service.go.tpl b/codegen/assets/templates/gocode/locale/service.go.tpl new file mode 100644 index 000000000..f18b25cdd --- /dev/null +++ b/codegen/assets/templates/gocode/locale/service.go.tpl @@ -0,0 +1,206 @@ +package {{ .package }} + +{{ template "gocode/header-gentext.tpl" }} + +import ( + "context" + +{{- range .imports }} + {{ . }} +{{- end }} + "github.com/cortezaproject/corteza-server/pkg/actionlog" + intAuth "github.com/cortezaproject/corteza-server/pkg/auth" + "github.com/cortezaproject/corteza-server/pkg/errors" + "github.com/cortezaproject/corteza-server/pkg/locale" + "github.com/cortezaproject/corteza-server/pkg/options" + "github.com/cortezaproject/corteza-server/store" + systemTypes "github.com/cortezaproject/corteza-server/system/types" + "golang.org/x/text/language" +) + +type ( + localeAccessControl interface { + CanManageResourceTranslations(ctx context.Context) bool + } + + resourceTranslationsManager struct { + actionlog actionlog.Recorder + locale locale.Resource + store store.Storer + ac localeAccessController + } + + localeAccessController interface { + CanManageResourceTranslations(context.Context) bool + } + + ResourceTranslationsManagerService interface { +{{- range .resources }} + {{ .expIdent }}(ctx context.Context, {{ range .references }}{{ . }} uint64, {{ end }}) (locale.ResourceTranslationSet, error) +{{- end }} + + Upsert(context.Context, locale.ResourceTranslationSet) error + Locale() locale.Resource + } +) + +var ErrNotAllowedToManageResourceTranslations = errors.Unauthorized("not allowed to manage resource translations") + +func ResourceTranslationsManager(ls locale.Resource) *resourceTranslationsManager { + return &resourceTranslationsManager{ + actionlog: DefaultActionlog, + store: DefaultStore, + ac: DefaultAccessControl, + locale: ls, + } +} + +func (svc resourceTranslationsManager) Upsert(ctx context.Context, rr locale.ResourceTranslationSet) (err error) { + // User is allowed to manage resource translations when: + // - managed resource translation strings are all for default language + // or + // - user is allowed to manage resource translations + if rr.ContainsForeign(svc.Locale().Default().Tag) { + if !svc.ac.CanManageResourceTranslations(ctx) { + return ErrNotAllowedToManageResourceTranslations + } + } + + for _, r := range rr { + r.Msg = locale.SanitizeMessage(r.Msg) + } + + // @todo validation + + me := intAuth.GetIdentityFromContext(ctx) + + // - group by resource + localeByRes := make(map[string]locale.ResourceTranslationSet) + for _, r := range rr { + localeByRes[r.Resource] = append(localeByRes[r.Resource], r) + } + + // - for each resource, fetch the current state + sysLocale := make(systemTypes.ResourceTranslationSet, 0, len(rr)) + for res, rr := range localeByRes { + current, _, err := store.SearchResourceTranslations(ctx, svc.store, systemTypes.ResourceTranslationFilter{ + Resource: res, + }) + if err != nil { + return err + } + + // get deltas and prepare upsert accordingly + aux := current.New(rr) + aux.Walk(func(cc *systemTypes.ResourceTranslation) error { + cc.ID = nextID() + cc.CreatedAt = *now() + cc.CreatedBy = me.Identity() + + return nil + }) + sysLocale = append(sysLocale, aux...) + + aux = current.Old(rr) + _ = aux.Walk(func(cc *systemTypes.ResourceTranslation) error { + cc.UpdatedAt = now() + cc.UpdatedBy = me.Identity() + return nil + }) + sysLocale = append(sysLocale, aux...) + } + + err = store.UpsertResourceTranslation(ctx, svc.store, sysLocale...) + if err != nil { + return err + } + + // Reload ALL resource translations + // @todo we could probably do this more selectively and refresh only updated resources? + _ = locale.Global().ReloadResourceTranslations(ctx) + + return nil +} + +func (svc resourceTranslationsManager) Locale() locale.Resource { + return svc.locale +} + +{{- range .resources }} + +func (svc resourceTranslationsManager) {{ .expIdent }}(ctx context.Context, {{ range .references }}{{ . }} uint64, {{ end }}) (locale.ResourceTranslationSet, error) { + var ( + err error + out locale.ResourceTranslationSet + res *types.{{ .expIdent }} + k types.LocaleKey + ) + + res, err = svc.load{{ .expIdent }}(ctx, svc.store, {{ range .references }}{{ . }}, {{ end }}) + if err != nil { + return nil, err + } + + for _, tag := range svc.locale.Tags() { + {{- range .keys}} + {{- if not .customHandler }} + k = types.{{ .struct }} + out = append(out, &locale.ResourceTranslation{ + Resource: res.ResourceTranslation(), + Lang: tag.String(), + Key: k.Path, + Msg: svc.locale.TResourceFor(tag, res.ResourceTranslation(), k.Path), + }) + {{ end }} + {{- end}} + } + + {{ if .extended }} + tmp, err := svc.{{ .ident }}Extended(ctx, res) + return append(out, tmp...), err + {{- else }} + return out, nil + {{- end }} +} + +{{- end }} + +func updateTranslations(ctx context.Context, ac localeAccessControl, lsvc ResourceTranslationsManagerService, tt ...*locale.ResourceTranslation) error { + if lsvc == nil || lsvc.Locale() == nil || lsvc.Locale().Default() == nil { + // gracefully handle partial initializations + return nil + } + + var ( + // assuming options will not change after start + contentLang = lsvc.Locale().Default().Tag + ) + + if options.Locale().ResourceTranslationsEnabled { + contentLang = locale.GetContentLanguageFromContext(ctx) + // Resource translations enabled + if contentLang == language.Und { + // If no content-language meta (HTTP header) info was + // used, do not run update translations - we do not know + // what is the language that we're sending in + return nil + } + + if !lsvc.Locale().SupportedLang(contentLang) { + // unsupported language + return errors.InvalidData("unsupported language") + } + + if !ac.CanManageResourceTranslations(ctx) { + return errors.Unauthorized("not allowed to manage resource translations") + } + } + + locale.ResourceTranslationSet(tt).SetLanguage(contentLang) + if err := lsvc.Upsert(ctx, tt); err != nil { + return err + } + + return nil +} + diff --git a/codegen/assets/templates/gocode/locale/types.go.tpl b/codegen/assets/templates/gocode/locale/types.go.tpl new file mode 100644 index 000000000..28a957631 --- /dev/null +++ b/codegen/assets/templates/gocode/locale/types.go.tpl @@ -0,0 +1,120 @@ +package {{ .package }} + +{{ template "gocode/header-gentext.tpl" }} + +import ( + "fmt" + "strconv" + "github.com/cortezaproject/corteza-server/pkg/locale" +) + +type ( + LocaleKey struct { + Name string + Resource string + Path string + CustomHandler string + } +) + +// Types and stuff +const ( +{{- range .resources }} + {{ .const }} = "{{ .type }}" +{{- end }} +) + +var ( + // @todo can we remove LocaleKey struct for string constant? +{{- range .resources }} +{{- range .keys }} + {{ .struct }} = LocaleKey{ Path: {{ printf "%q" .path }} } +{{- end }} +{{- end }} +) + +{{- range .resources }} + +// ResourceTranslation returns string representation of Locale resource for {{ .expIdent }} by calling {{ .expIdent }}ResourceTranslation fn +// +// Locale resource is in "{{ .type }}/..." format +// +// This function is auto-generated +func (r {{ .expIdent }}) ResourceTranslation() string { + return {{ .expIdent }}ResourceTranslation({{ if .references }}{{ range .references }}r.{{ . }},{{ end }}{{ end }}) +} + +// {{ .expIdent }}ResourceTranslation returns string representation of Locale resource for {{ .expIdent }} +// +// Locale resource is in the {{ .type }}/{{- if .references }}...{{ end }} format +// +// This function is auto-generated +func {{ .expIdent }}ResourceTranslation({{ if .references }}{{ range .references }}{{ . }} uint64,{{ end }}{{ end }}) string { + {{- if .references }} + cpts := []interface{{"{}"}}{ + {{ .expIdent }}ResourceTranslationType, + {{- range .references }} + strconv.FormatUint({{ . }}, 10), + {{- end }} + } + + return fmt.Sprintf({{ .expIdent }}ResourceTranslationTpl(), cpts...) + {{- end }} +} + +func {{ .expIdent }}ResourceTranslationTpl() string { + {{- if .references }} + return "%s + {{- range .references }}/%s{{- end }}" + + {{- else }} + return "%s" + {{- end }} +} + +func (r *{{ .expIdent }}) DecodeTranslations(tt locale.ResourceTranslationIndex) { + var aux *locale.ResourceTranslation + + {{- range .keys }} + {{ if .decodeFunc }} + {{ if not .extended }} + r.{{ .decodeFunc }}(tt) + {{- end}} + {{ else }} + if aux = tt.FindByKey({{ .struct }}.Path); aux != nil { + r.{{ .fieldPath }} = aux.Msg + } + {{- end}} + {{- end}} + + {{- if .extended }} + r.decodeTranslations(tt) + {{- end }} +} + +func (r *{{ .expIdent }}) EncodeTranslations() (out locale.ResourceTranslationSet) { + out = locale.ResourceTranslationSet{} + {{- range .keys }} + {{ if .encodeFunc }} + {{ if not .extended }} + out = append(out, r.{{ .encodeFunc }}()...) + {{- end}} + {{ else }} + if r.{{ .fieldPath }} != "" { + out = append(out, &locale.ResourceTranslation{ + Resource: r.ResourceTranslation(), + Key: {{ .struct }}.Path, + Msg: locale.SanitizeMessage(r.{{ .fieldPath }}), + }) + } + {{- end}} + {{- end}} + + {{- if .extended }} + out = append(out, r.encodeTranslations()...) + {{- end }} + + return out +} + +{{- end }} diff --git a/codegen/assets/templates/gocode/rbac/access_control.go.tpl b/codegen/assets/templates/gocode/rbac/access_control.go.tpl index e26ac69cc..907532aa1 100644 --- a/codegen/assets/templates/gocode/rbac/access_control.go.tpl +++ b/codegen/assets/templates/gocode/rbac/access_control.go.tpl @@ -10,7 +10,7 @@ import ( "github.com/cortezaproject/corteza-server/pkg/rbac" "github.com/cortezaproject/corteza-server/pkg/actionlog" {{- range .imports }} - "{{ . }}" + {{ . }} {{- end }} ) @@ -57,7 +57,7 @@ func (svc accessControl) List() (out []map[string]string) { {{- range .operations }} { "type": {{ .const }}, - "any": {{ .ctor }}, + "any": {{ .resFunc }}({{ range .references }}0,{{ end }}), "op": {{ printf "%q" .op }}, }, {{- end }} diff --git a/codegen/assets/templates/gocode/rbac/types.go.tpl b/codegen/assets/templates/gocode/rbac/types.go.tpl index fc1e294eb..760f0c04b 100644 --- a/codegen/assets/templates/gocode/rbac/types.go.tpl +++ b/codegen/assets/templates/gocode/rbac/types.go.tpl @@ -38,7 +38,7 @@ const ( // // This function is auto-generated func (r {{ .goType }}) RbacResource() string { - return {{ .resFunc }}({{ if not .component }}{{ range .references }}r.{{ . }},{{ end }}{{ end }}) + return {{ .resFunc }}({{ if not .component }}{{ range .references }}r.{{ .refField }},{{ end }}{{ end }}) } // {{ .resFunc }} returns string representation of RBAC resource for {{ .goType }} @@ -46,12 +46,12 @@ func (r {{ .goType }}) RbacResource() string { // RBAC resource is in the {{ .type }}/{{- if .references }}...{{ end }} format // // This function is auto-generated -func {{ .resFunc }}({{ if not .component }}{{ range .references }}{{ . }} uint64,{{ end }}{{ end }}) string { +func {{ .resFunc }}({{ if not .component }}{{ range .references }}{{ .param }} uint64,{{ end }}{{ end }}) string { {{- if .references }} cpts := []interface{{"{}"}}{{"{"}}{{ .goType }}ResourceType{{"}"}} {{- range .references }} - if {{ . }} != 0 { - cpts = append(cpts, strconv.FormatUint({{ . }}, 10)) + if {{ .param }} != 0 { + cpts = append(cpts, strconv.FormatUint({{ .param }}, 10)) } else { cpts = append(cpts, "*") } diff --git a/codegen/locale-service.cue b/codegen/locale-service.cue new file mode 100644 index 000000000..2807d4597 --- /dev/null +++ b/codegen/locale-service.cue @@ -0,0 +1,44 @@ +package codegen + +import ( + "github.com/cortezaproject/corteza-server/app" + "github.com/cortezaproject/corteza-server/codegen/schema" + "strings" +) + +localeService: + [...schema.#codegen] & + [ + // wrapped with additional for loop to trim out templates with empty types list + for tpl in [ + for cmp in app.corteza.components { + template: "gocode/locale/service.go.tpl" + output: "\(cmp.ident)/service/locale.gen.go" + payload: { + package: "service" + imports: [ + "\"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\"", + ] + + resources: [ + for res in cmp.resources if (res.locale != _|_) if (!res.locale.skipSvc) { + expIdent: res.expIdent + ident: res.ident + + references: [ for field in res.locale.resource.references {strings.ToTitle(field)}] + + extended: res.locale.extended + + keys: [ for key in res.locale.keys if key.handlerFunc == _|_ { + struct: key.struct + + extended: extended + customHandler: key.customHandler + if key.serviceFunc != _|_ {serviceFunc: key.serviceFunc} + }] + }, + ] + } + }, + // skip empty type lists + ] if len(tpl.payload.resources) > 0 {tpl}] diff --git a/codegen/locale-types.cue b/codegen/locale-types.cue new file mode 100644 index 000000000..ff0b7c993 --- /dev/null +++ b/codegen/locale-types.cue @@ -0,0 +1,55 @@ +package codegen + +import ( + "github.com/cortezaproject/corteza-server/app" + "github.com/cortezaproject/corteza-server/codegen/schema" + "strings" +) + +localeTypes: + [...schema.#codegen] & + [ + // wrapped with additional for loop to trim out templates with empty types list + for tpl in [ + for cmp in app.corteza.components { + template: "gocode/locale/types.go.tpl" + output: "\(cmp.ident)/types/locale.gen.go" + payload: { + package: "types" + + resources: [ + for res in cmp.resources if res.locale != _|_ { + expIdent: res.expIdent + const: res.locale.resource.const + type: res.locale.resource.type + + references: [ for field in res.locale.resource.references {strings.ToTitle(field)}] + + extended: res.locale.extended + + keys: [ for key in res.locale.keys if key.handlerFunc == _|_ { + struct: key.struct + field: strings.ToTitle(key.name) + + path: strings.Join([ for p in key.expandedPath { + if p.var {"{{\(p.part)}}"} + if !p.var {p.part} + }], ".") + + if !key.customHandler { + fieldPath: strings.Join([ for p in key.expandedPath { + strings.ToTitle(p.part) + }], ".") + } + + "extended": extended + if key.decodeFunc != _|_ {decodeFunc: key.decodeFunc} + if key.encodeFunc != _|_ {encodeFunc: key.encodeFunc} + + }] + }, + ] + } + }, + // skip empty type lists + ] if len(tpl.payload.resources) > 0 {tpl}] diff --git a/codegen/rbac-access_control.cue b/codegen/rbac-access_control.cue index 49e777ba1..46cec3af7 100644 --- a/codegen/rbac-access_control.cue +++ b/codegen/rbac-access_control.cue @@ -1,8 +1,8 @@ package codegen import ( - "github.com/cortezaproject/corteza-server/codegen/schema" - "github.com/cortezaproject/corteza-server/app" + "github.com/cortezaproject/corteza-server/codegen/schema" + "github.com/cortezaproject/corteza-server/app" ) rbacAccessControl: @@ -12,47 +12,53 @@ rbacAccessControl: template: "gocode/rbac/access_control.go.tpl" output: "\(cmp.ident)/service/access_control.gen.go" payload: { - imports: [ - "github.com/cortezaproject/corteza-server/\(cmp.ident)/types", - ] package: "service" + imports: [ + "\"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\"", + ] // All possible RBAC operations on component and resources // flattened operations: [ for res in cmp.resources for op in res.rbac.operations { - "op": op.handle - "const": "types.\(res.expIdent)ResourceType" - "ctor": "types.\(res.expIdent)RbacResource(\(len(res.rbac.resource.references)*"0,"))" - "goType": res.goType - "description": op.description - "checkFuncName": op.checkFuncName + "op": op.handle + const: "types.\(res.expIdent)ResourceType" + resFunc: "types.\(res.expIdent)RbacResource" + goType: "types.\(res.expIdent)" + description: op.description + checkFuncName: op.checkFuncName + + if len(res.parents) > 0 { + references: [ for p in res.parents {p}, {param: "id", refField: "ID"}] + } }, for op in cmp.rbac.operations { - "op": op.handle - "const": "types.ComponentResourceType" - "ctor": "types.ComponentRbacResource()" - "goType": "types.Component" - "description": op.description - "checkFuncName": op.checkFuncName - "component": true + "op": op.handle + const: "types.ComponentResourceType" + resFunc: "types.ComponentRbacResource" + goType: "types.Component" + description: op.description + checkFuncName: op.checkFuncName + component: true }, ] // Operation/resource validators, grouped by resource validation: [ for res in cmp.resources { - "label": res.ident - "const": "types.\(res.expIdent)ResourceType" - "funcName": "rbac\(res.expIdent)ResourceValidator" - "references": res.rbac.resource.references - "operations": [ for op in res.rbac.operations {op.handle}] + label: res.ident + const: "types.\(res.expIdent)ResourceType" + funcName: "rbac\(res.expIdent)ResourceValidator" + if len(res.parents) > 0 { + references: [ for p in res.parents {p.refField}, "ID"] + } + operations: [ for op in res.rbac.operations {op.handle}] }, { - "label": "\(cmp.ident) component" - "const": "types.ComponentResourceType" - "funcName": "rbacComponentResourceValidator" - "operations": [ for op in cmp.rbac.operations {op.handle}] + label: "\(cmp.ident) component" + const: "types.ComponentResourceType" + funcName: "rbacComponentResourceValidator" + operations: [ for op in cmp.rbac.operations {op.handle}] }, ] } diff --git a/codegen/rbac-types.cue b/codegen/rbac-types.cue index 1f5ecc5ef..6982f2342 100644 --- a/codegen/rbac-types.cue +++ b/codegen/rbac-types.cue @@ -3,7 +3,6 @@ package codegen import ( "github.com/cortezaproject/corteza-server/app" "github.com/cortezaproject/corteza-server/codegen/schema" - "strings" ) rbacTypes: @@ -19,23 +18,25 @@ rbacTypes: // Operation/resource validators, grouped by resource types: [ for res in cmp.resources { - "const": "\(res.expIdent)ResourceType" - "type": res.rbac.resource.type - "resFunc": "\(res.expIdent)RbacResource" - "tplFunc": "\(res.expIdent)RbacResourceTpl" - "attFunc": "\(res.expIdent)RbacAttributes" - "goType": res.expIdent + const: "\(res.expIdent)ResourceType" + type: res.fqrn + resFunc: "\(res.expIdent)RbacResource" + tplFunc: "\(res.expIdent)RbacResourceTpl" + attFunc: "\(res.expIdent)RbacAttributes" + goType: res.expIdent - "references": [ for field in res.rbac.resource.references { strings.ToTitle(field) } ] + if len(res.parents) > 0 { + references: [ for p in res.parents {p}, {param: "id", refField: "ID"}] + } }, { - "const": "ComponentResourceType" - "type": cmp.rbac.resource.type - "resFunc": "ComponentRbacResource" - "tplFunc": "ComponentRbacResourceTpl" - "attFunc": "ComponentRbacAttributes" - "goType": "Component" - "component": true + const: "ComponentResourceType" + type: cmp.fqrn + resFunc: "ComponentRbacResource" + tplFunc: "ComponentRbacResourceTpl" + attFunc: "ComponentRbacAttributes" + goType: "Component" + component: true }, ] } diff --git a/compose/chart.cue b/compose/chart.cue index 2435dc156..25e87c424 100644 --- a/compose/chart.cue +++ b/compose/chart.cue @@ -5,19 +5,15 @@ import ( ) chart: schema.#resource & { - rbac: { - resource: references: [ "namespaceID", "ID"] + parents: [ + {handle: "namespace"}, + ] + rbac: { operations: { "read": {} - "update": {} - "delete": {} + "update": {} + "delete": {} } } - - // locale: - // resource: - // references: [ namespace, ID ] - // keys: - // - name } diff --git a/compose/component.cue b/compose/component.cue index 931accdcf..0136b3b78 100644 --- a/compose/component.cue +++ b/compose/component.cue @@ -5,15 +5,15 @@ import ( ) component: schema.#component & { - ident: "compose" + handle: "compose" resources: { - "namespace": namespace + "chart": chart "module": module "module-field": moduleField - "record": record + "namespace": namespace "page": page - "chart": chart + "record": record } rbac: operations: { diff --git a/compose/module-field.cue b/compose/module-field.cue index 0e7f174eb..57bb11a78 100644 --- a/compose/module-field.cue +++ b/compose/module-field.cue @@ -5,30 +5,47 @@ import ( ) moduleField: schema.#resource & { - rbac: { - resource: references: [ "namespaceID", "moduleID", "ID"] + parents: [ + {handle: "namespace"}, + {handle: "module"}, + ] + rbac: { operations: { "recod.value.read": description: "Read field value on records" "recod.value.update": description: "Update field value on records" } } - //locale: - // resource: - // references: [ namespace, module, ID ] - // - // skipSvc: true - // keys: - // - label - // - { name: descriptionView, path: meta.description.view, custom: true, customHandler: descriptionView } - // - { name: descriptionEdit, path: meta.description.edit, custom: true, customHandler: descriptionEdit } - // - { name: hintView, path: meta.hint.view, custom: true, customHandler: hintView } - // - { name: hintEdit, path: meta.hint.edit, custom: true, customHandler: hintEdit } - // - { name: validatorError, path: "expression.validator.{{validatorID}}.error", custom: true, customHandler: validatorError } - // - { name: optionsOptionTexts, - // path: "meta.options.{{value}}.text", - // custom: true, - // customHandler: optionsOptionTexts - // } + locale: { + skipSvc: true + + keys: { + label: {} + descriptionView: { + path: ["meta", "description", "view"] + customHandler: true + } + descriptionEdit: { + path: ["meta", "description", "edit"] + customHandler: true + } + hintView: { + path: ["meta", "hint", "view"] + customHandler: true + } + hintEdit: { + path: ["meta", "hint", "edit"] + customHandler: true + } + validatorError: { + path: ["expression", "validator", {part: "validatorID", var: true}, "error"] + customHandler: true + } + optionsOptionTexts: { + path: ["meta", "options", {part: "value", var: true}, "text"] + customHandler: true + } + } + } } diff --git a/compose/module.cue b/compose/module.cue index c1b0409f6..a08099d1d 100644 --- a/compose/module.cue +++ b/compose/module.cue @@ -5,9 +5,12 @@ import ( ) module: schema.#resource & { - rbac: { - resource: references: [ "namespaceID", "ID"] + handle: "module" + parents: [ + {handle: "namespace"}, + ] + rbac: { operations: { "read": {} "update": {} @@ -17,6 +20,12 @@ module: schema.#resource & { } } + locale: { + keys: { + "name": {} + } + } + //locale: // resource: // references: [ namespace, ID ] diff --git a/compose/namespace.cue b/compose/namespace.cue index 4ecf6d130..434c2dcf5 100644 --- a/compose/namespace.cue +++ b/compose/namespace.cue @@ -20,10 +20,17 @@ namespace: schema.#resource & { } } - // - //locale: - // keys: - // - name - // - { path: subtitle, field: "Meta.Subtitle" } - // - { path: description, field: "Meta.Description" } + locale: { + resource: references: [ "ID"] + + keys: { + name: {} + metaSubtitle: { + path: ["meta", "subtitle"] + } + metaDescription: { + path: ["meta", "description"] + } + } + } } diff --git a/compose/page.cue b/compose/page.cue index 04ffa49a4..dfe088f48 100644 --- a/compose/page.cue +++ b/compose/page.cue @@ -5,9 +5,11 @@ import ( ) page: schema.#resource & { - rbac: { - resource: references: [ "namespaceID", "ID"] + parents: [ + {handle: "namespace"}, + ] + rbac: { operations: { "read": {} "update": {} @@ -15,15 +17,24 @@ page: schema.#resource & { } } - //locale: - // resource: - // references: [ namespace, ID ] - // - // extended: true - // keys: - // - title - // - description - // - { name: blockTitle, path: "pageBlock.{{blockID}}.title", custom: true } - // - { name: blockDescription, path: "pageBlock.{{blockID}}.description", custom: true } - // - { name: blockAutomationButtonlabel, path: "pageBlock.{{blockID}}.button.{{buttonID}}.label", custom: true } + locale: { + extended: true + + keys: { + title: {} + description: {} + blockTitle: { + path: ["pageBlock", {part: "blockID", var: true}, "title"] + customHandler: true + } + blockDescription: { + path: ["pageBlock", {part: "blockID", var: true}, "description"] + customHandler: true + } + blockAutomationButtonLabel: { + path: ["pageBlock", {part: "blockID", var: true}, "button", {part: "buttonID", var: true}, "label"] + customHandler: true + } + } + } } diff --git a/compose/record.cue b/compose/record.cue index dfbfe11fe..dd10bc163 100644 --- a/compose/record.cue +++ b/compose/record.cue @@ -5,9 +5,12 @@ import ( ) record: schema.#resource & { - rbac: { - resource: references: [ "namespaceID", "moduleID", "ID"] + parents: [ + {handle: "namespace"}, + {handle: "module"}, + ] + rbac: { operations: { "read": {} "update": {} diff --git a/compose/service/access_control.gen.go b/compose/service/access_control.gen.go index 4f8173af1..70eac31ea 100644 --- a/compose/service/access_control.gen.go +++ b/compose/service/access_control.gen.go @@ -9,11 +9,12 @@ package service import ( "context" "fmt" + "strings" + "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/actionlog" "github.com/cortezaproject/corteza-server/pkg/rbac" "github.com/spf13/cast" - "strings" ) type ( @@ -55,55 +56,20 @@ func (svc accessControl) Effective(ctx context.Context, rr ...rbac.Resource) (ee func (svc accessControl) List() (out []map[string]string) { def := []map[string]string{ { - "type": types.NamespaceResourceType, - "any": types.NamespaceRbacResource(0), + "type": types.ChartResourceType, + "any": types.ChartRbacResource(0, 0), "op": "read", }, { - "type": types.NamespaceResourceType, - "any": types.NamespaceRbacResource(0), + "type": types.ChartResourceType, + "any": types.ChartRbacResource(0, 0), "op": "update", }, { - "type": types.NamespaceResourceType, - "any": types.NamespaceRbacResource(0), + "type": types.ChartResourceType, + "any": types.ChartRbacResource(0, 0), "op": "delete", }, - { - "type": types.NamespaceResourceType, - "any": types.NamespaceRbacResource(0), - "op": "manage", - }, - { - "type": types.NamespaceResourceType, - "any": types.NamespaceRbacResource(0), - "op": "module.create", - }, - { - "type": types.NamespaceResourceType, - "any": types.NamespaceRbacResource(0), - "op": "modules.search", - }, - { - "type": types.NamespaceResourceType, - "any": types.NamespaceRbacResource(0), - "op": "chart.create", - }, - { - "type": types.NamespaceResourceType, - "any": types.NamespaceRbacResource(0), - "op": "charts.search", - }, - { - "type": types.NamespaceResourceType, - "any": types.NamespaceRbacResource(0), - "op": "page.create", - }, - { - "type": types.NamespaceResourceType, - "any": types.NamespaceRbacResource(0), - "op": "pages.search", - }, { "type": types.ModuleResourceType, "any": types.ModuleRbacResource(0, 0), @@ -140,20 +106,55 @@ func (svc accessControl) List() (out []map[string]string) { "op": "recod.value.update", }, { - "type": types.RecordResourceType, - "any": types.RecordRbacResource(0, 0, 0), + "type": types.NamespaceResourceType, + "any": types.NamespaceRbacResource(), "op": "read", }, { - "type": types.RecordResourceType, - "any": types.RecordRbacResource(0, 0, 0), + "type": types.NamespaceResourceType, + "any": types.NamespaceRbacResource(), "op": "update", }, { - "type": types.RecordResourceType, - "any": types.RecordRbacResource(0, 0, 0), + "type": types.NamespaceResourceType, + "any": types.NamespaceRbacResource(), "op": "delete", }, + { + "type": types.NamespaceResourceType, + "any": types.NamespaceRbacResource(), + "op": "manage", + }, + { + "type": types.NamespaceResourceType, + "any": types.NamespaceRbacResource(), + "op": "module.create", + }, + { + "type": types.NamespaceResourceType, + "any": types.NamespaceRbacResource(), + "op": "modules.search", + }, + { + "type": types.NamespaceResourceType, + "any": types.NamespaceRbacResource(), + "op": "chart.create", + }, + { + "type": types.NamespaceResourceType, + "any": types.NamespaceRbacResource(), + "op": "charts.search", + }, + { + "type": types.NamespaceResourceType, + "any": types.NamespaceRbacResource(), + "op": "page.create", + }, + { + "type": types.NamespaceResourceType, + "any": types.NamespaceRbacResource(), + "op": "pages.search", + }, { "type": types.PageResourceType, "any": types.PageRbacResource(0, 0), @@ -170,18 +171,18 @@ func (svc accessControl) List() (out []map[string]string) { "op": "delete", }, { - "type": types.ChartResourceType, - "any": types.ChartRbacResource(0, 0), + "type": types.RecordResourceType, + "any": types.RecordRbacResource(0, 0, 0), "op": "read", }, { - "type": types.ChartResourceType, - "any": types.ChartRbacResource(0, 0), + "type": types.RecordResourceType, + "any": types.RecordRbacResource(0, 0, 0), "op": "update", }, { - "type": types.ChartResourceType, - "any": types.ChartRbacResource(0, 0), + "type": types.RecordResourceType, + "any": types.RecordRbacResource(0, 0, 0), "op": "delete", }, { @@ -287,21 +288,91 @@ func (svc accessControl) CloneRulesByRoleID(ctx context.Context, fromRoleID uint return svc.rbac.CloneRulesByRoleID(ctx, fromRoleID, toRoleID...) } -// CanReadNamespace checks if current user can read corteza::compose:namespace +// CanReadChart checks if current user can read +// +// This function is auto-generated +func (svc accessControl) CanReadChart(ctx context.Context, r *types.Chart) bool { + return svc.can(ctx, "read", r) +} + +// CanUpdateChart checks if current user can update +// +// This function is auto-generated +func (svc accessControl) CanUpdateChart(ctx context.Context, r *types.Chart) bool { + return svc.can(ctx, "update", r) +} + +// CanDeleteChart checks if current user can delete +// +// This function is auto-generated +func (svc accessControl) CanDeleteChart(ctx context.Context, r *types.Chart) bool { + return svc.can(ctx, "delete", r) +} + +// CanReadModule checks if current user can read +// +// This function is auto-generated +func (svc accessControl) CanReadModule(ctx context.Context, r *types.Module) bool { + return svc.can(ctx, "read", r) +} + +// CanUpdateModule checks if current user can update +// +// This function is auto-generated +func (svc accessControl) CanUpdateModule(ctx context.Context, r *types.Module) bool { + return svc.can(ctx, "update", r) +} + +// CanDeleteModule checks if current user can delete +// +// This function is auto-generated +func (svc accessControl) CanDeleteModule(ctx context.Context, r *types.Module) bool { + return svc.can(ctx, "delete", r) +} + +// CanCreateRecordModule checks if current user can create record +// +// This function is auto-generated +func (svc accessControl) CanCreateRecordModule(ctx context.Context, r *types.Module) bool { + return svc.can(ctx, "record.create", r) +} + +// CanSearchRecordsModule checks if current user can list, search or filter records +// +// This function is auto-generated +func (svc accessControl) CanSearchRecordsModule(ctx context.Context, r *types.Module) bool { + return svc.can(ctx, "records.search", r) +} + +// CanReadRecodValueModuleField checks if current user can read field value on records +// +// This function is auto-generated +func (svc accessControl) CanReadRecodValueModuleField(ctx context.Context, r *types.ModuleField) bool { + return svc.can(ctx, "recod.value.read", r) +} + +// CanUpdateRecodValueModuleField checks if current user can update field value on records +// +// This function is auto-generated +func (svc accessControl) CanUpdateRecodValueModuleField(ctx context.Context, r *types.ModuleField) bool { + return svc.can(ctx, "recod.value.update", r) +} + +// CanReadNamespace checks if current user can read // // This function is auto-generated func (svc accessControl) CanReadNamespace(ctx context.Context, r *types.Namespace) bool { return svc.can(ctx, "read", r) } -// CanUpdateNamespace checks if current user can update corteza::compose:namespace +// CanUpdateNamespace checks if current user can update // // This function is auto-generated func (svc accessControl) CanUpdateNamespace(ctx context.Context, r *types.Namespace) bool { return svc.can(ctx, "update", r) } -// CanDeleteNamespace checks if current user can delete corteza::compose:namespace +// CanDeleteNamespace checks if current user can delete // // This function is auto-generated func (svc accessControl) CanDeleteNamespace(ctx context.Context, r *types.Namespace) bool { @@ -357,115 +428,45 @@ func (svc accessControl) CanSearchPagesNamespace(ctx context.Context, r *types.N return svc.can(ctx, "pages.search", r) } -// CanReadModule checks if current user can read corteza::compose:module -// -// This function is auto-generated -func (svc accessControl) CanReadModule(ctx context.Context, r *types.Module) bool { - return svc.can(ctx, "read", r) -} - -// CanUpdateModule checks if current user can update corteza::compose:module -// -// This function is auto-generated -func (svc accessControl) CanUpdateModule(ctx context.Context, r *types.Module) bool { - return svc.can(ctx, "update", r) -} - -// CanDeleteModule checks if current user can delete corteza::compose:module -// -// This function is auto-generated -func (svc accessControl) CanDeleteModule(ctx context.Context, r *types.Module) bool { - return svc.can(ctx, "delete", r) -} - -// CanCreateRecordModule checks if current user can create record -// -// This function is auto-generated -func (svc accessControl) CanCreateRecordModule(ctx context.Context, r *types.Module) bool { - return svc.can(ctx, "record.create", r) -} - -// CanSearchRecordsModule checks if current user can list, search or filter records -// -// This function is auto-generated -func (svc accessControl) CanSearchRecordsModule(ctx context.Context, r *types.Module) bool { - return svc.can(ctx, "records.search", r) -} - -// CanReadRecodValueModuleField checks if current user can read field value on records -// -// This function is auto-generated -func (svc accessControl) CanReadRecodValueModuleField(ctx context.Context, r *types.ModuleField) bool { - return svc.can(ctx, "recod.value.read", r) -} - -// CanUpdateRecodValueModuleField checks if current user can update field value on records -// -// This function is auto-generated -func (svc accessControl) CanUpdateRecodValueModuleField(ctx context.Context, r *types.ModuleField) bool { - return svc.can(ctx, "recod.value.update", r) -} - -// CanReadRecord checks if current user can read corteza::compose:record -// -// This function is auto-generated -func (svc accessControl) CanReadRecord(ctx context.Context, r *types.Record) bool { - return svc.can(ctx, "read", r) -} - -// CanUpdateRecord checks if current user can update corteza::compose:record -// -// This function is auto-generated -func (svc accessControl) CanUpdateRecord(ctx context.Context, r *types.Record) bool { - return svc.can(ctx, "update", r) -} - -// CanDeleteRecord checks if current user can delete corteza::compose:record -// -// This function is auto-generated -func (svc accessControl) CanDeleteRecord(ctx context.Context, r *types.Record) bool { - return svc.can(ctx, "delete", r) -} - -// CanReadPage checks if current user can read corteza::compose:page +// CanReadPage checks if current user can read // // This function is auto-generated func (svc accessControl) CanReadPage(ctx context.Context, r *types.Page) bool { return svc.can(ctx, "read", r) } -// CanUpdatePage checks if current user can update corteza::compose:page +// CanUpdatePage checks if current user can update // // This function is auto-generated func (svc accessControl) CanUpdatePage(ctx context.Context, r *types.Page) bool { return svc.can(ctx, "update", r) } -// CanDeletePage checks if current user can delete corteza::compose:page +// CanDeletePage checks if current user can delete // // This function is auto-generated func (svc accessControl) CanDeletePage(ctx context.Context, r *types.Page) bool { return svc.can(ctx, "delete", r) } -// CanReadChart checks if current user can read corteza::compose:chart +// CanReadRecord checks if current user can read // // This function is auto-generated -func (svc accessControl) CanReadChart(ctx context.Context, r *types.Chart) bool { +func (svc accessControl) CanReadRecord(ctx context.Context, r *types.Record) bool { return svc.can(ctx, "read", r) } -// CanUpdateChart checks if current user can update corteza::compose:chart +// CanUpdateRecord checks if current user can update // // This function is auto-generated -func (svc accessControl) CanUpdateChart(ctx context.Context, r *types.Chart) bool { +func (svc accessControl) CanUpdateRecord(ctx context.Context, r *types.Record) bool { return svc.can(ctx, "update", r) } -// CanDeleteChart checks if current user can delete corteza::compose:chart +// CanDeleteRecord checks if current user can delete // // This function is auto-generated -func (svc accessControl) CanDeleteChart(ctx context.Context, r *types.Chart) bool { +func (svc accessControl) CanDeleteRecord(ctx context.Context, r *types.Record) bool { return svc.can(ctx, "delete", r) } @@ -522,18 +523,18 @@ func (svc accessControl) CanManageResourceTranslations(ctx context.Context) bool // This function is auto-generated func rbacResourceValidator(r string, oo ...string) error { switch rbac.ResourceType(r) { - case types.NamespaceResourceType: - return rbacNamespaceResourceValidator(r, oo...) + case types.ChartResourceType: + return rbacChartResourceValidator(r, oo...) case types.ModuleResourceType: return rbacModuleResourceValidator(r, oo...) case types.ModuleFieldResourceType: return rbacModuleFieldResourceValidator(r, oo...) - case types.RecordResourceType: - return rbacRecordResourceValidator(r, oo...) + case types.NamespaceResourceType: + return rbacNamespaceResourceValidator(r, oo...) case types.PageResourceType: return rbacPageResourceValidator(r, oo...) - case types.ChartResourceType: - return rbacChartResourceValidator(r, oo...) + case types.RecordResourceType: + return rbacRecordResourceValidator(r, oo...) case types.ComponentResourceType: return rbacComponentResourceValidator(r, oo...) } @@ -546,18 +547,11 @@ func rbacResourceValidator(r string, oo ...string) error { // This function is auto-generated func rbacResourceOperations(r string) map[string]bool { switch rbac.ResourceType(r) { - case types.NamespaceResourceType: + case types.ChartResourceType: return map[string]bool{ - "read": true, - "update": true, - "delete": true, - "manage": true, - "module.create": true, - "modules.search": true, - "chart.create": true, - "charts.search": true, - "page.create": true, - "pages.search": true, + "read": true, + "update": true, + "delete": true, } case types.ModuleResourceType: return map[string]bool{ @@ -572,11 +566,18 @@ func rbacResourceOperations(r string) map[string]bool { "recod.value.read": true, "recod.value.update": true, } - case types.RecordResourceType: + case types.NamespaceResourceType: return map[string]bool{ - "read": true, - "update": true, - "delete": true, + "read": true, + "update": true, + "delete": true, + "manage": true, + "module.create": true, + "modules.search": true, + "chart.create": true, + "charts.search": true, + "page.create": true, + "pages.search": true, } case types.PageResourceType: return map[string]bool{ @@ -584,7 +585,7 @@ func rbacResourceOperations(r string) map[string]bool { "update": true, "delete": true, } - case types.ChartResourceType: + case types.RecordResourceType: return map[string]bool{ "read": true, "update": true, @@ -604,13 +605,13 @@ func rbacResourceOperations(r string) map[string]bool { return nil } -// rbacNamespaceResourceValidator checks validity of RBAC resource and operations +// rbacChartResourceValidator checks validity of RBAC resource and operations // // Can be called without operations to check for validity of resource string only // // This function is auto-generated -func rbacNamespaceResourceValidator(r string, oo ...string) error { - if !strings.HasPrefix(r, types.NamespaceResourceType) { +func rbacChartResourceValidator(r string, oo ...string) error { + if !strings.HasPrefix(r, types.ChartResourceType) { // expecting resource to always include path return fmt.Errorf("invalid resource type") } @@ -618,14 +619,15 @@ func rbacNamespaceResourceValidator(r string, oo ...string) error { defOps := rbacResourceOperations(r) for _, o := range oo { if !defOps[o] { - return fmt.Errorf("invalid operation '%s' for namespace resource", o) + return fmt.Errorf("invalid operation '%s' for chart resource", o) } } const sep = "/" var ( - pp = strings.Split(strings.Trim(r[len(types.NamespaceResourceType):], sep), sep) + pp = strings.Split(strings.Trim(r[len(types.ChartResourceType):], sep), sep) prc = []string{ + "NamespaceID", "ID", } ) @@ -637,7 +639,7 @@ func rbacNamespaceResourceValidator(r string, oo ...string) error { for i := 0; i < len(pp); i++ { if pp[i] != "*" { if i > 0 && pp[i-1] == "*" { - return fmt.Errorf("invalid path wildcard level (%d) for namespace resource", i) + return fmt.Errorf("invalid path wildcard level (%d) for chart resource", i) } if _, err := cast.ToUint64E(pp[i]); err != nil { @@ -670,7 +672,7 @@ func rbacModuleResourceValidator(r string, oo ...string) error { var ( pp = strings.Split(strings.Trim(r[len(types.ModuleResourceType):], sep), sep) prc = []string{ - "namespaceID", + "NamespaceID", "ID", } ) @@ -715,8 +717,8 @@ func rbacModuleFieldResourceValidator(r string, oo ...string) error { var ( pp = strings.Split(strings.Trim(r[len(types.ModuleFieldResourceType):], sep), sep) prc = []string{ - "namespaceID", - "moduleID", + "NamespaceID", + "ModuleID", "ID", } ) @@ -739,6 +741,72 @@ func rbacModuleFieldResourceValidator(r string, oo ...string) error { return nil } +// rbacNamespaceResourceValidator checks validity of RBAC resource and operations +// +// Can be called without operations to check for validity of resource string only +// +// This function is auto-generated +func rbacNamespaceResourceValidator(r string, oo ...string) error { + if !strings.HasPrefix(r, types.NamespaceResourceType) { + // expecting resource to always include path + return fmt.Errorf("invalid resource type") + } + + defOps := rbacResourceOperations(r) + for _, o := range oo { + if !defOps[o] { + return fmt.Errorf("invalid operation '%s' for namespace resource", o) + } + } + + return nil +} + +// rbacPageResourceValidator checks validity of RBAC resource and operations +// +// Can be called without operations to check for validity of resource string only +// +// This function is auto-generated +func rbacPageResourceValidator(r string, oo ...string) error { + if !strings.HasPrefix(r, types.PageResourceType) { + // expecting resource to always include path + return fmt.Errorf("invalid resource type") + } + + defOps := rbacResourceOperations(r) + for _, o := range oo { + if !defOps[o] { + return fmt.Errorf("invalid operation '%s' for page resource", o) + } + } + + const sep = "/" + var ( + pp = strings.Split(strings.Trim(r[len(types.PageResourceType):], sep), sep) + prc = []string{ + "NamespaceID", + "ID", + } + ) + + if len(pp) != len(prc) { + return fmt.Errorf("invalid resource path structure") + } + + for i := 0; i < len(pp); i++ { + if pp[i] != "*" { + if i > 0 && pp[i-1] == "*" { + return fmt.Errorf("invalid path wildcard level (%d) for page resource", i) + } + + if _, err := cast.ToUint64E(pp[i]); err != nil { + return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i]) + } + } + } + return nil +} + // rbacRecordResourceValidator checks validity of RBAC resource and operations // // Can be called without operations to check for validity of resource string only @@ -761,8 +829,8 @@ func rbacRecordResourceValidator(r string, oo ...string) error { var ( pp = strings.Split(strings.Trim(r[len(types.RecordResourceType):], sep), sep) prc = []string{ - "namespaceID", - "moduleID", + "NamespaceID", + "ModuleID", "ID", } ) @@ -785,96 +853,6 @@ func rbacRecordResourceValidator(r string, oo ...string) error { return nil } -// rbacPageResourceValidator checks validity of RBAC resource and operations -// -// Can be called without operations to check for validity of resource string only -// -// This function is auto-generated -func rbacPageResourceValidator(r string, oo ...string) error { - if !strings.HasPrefix(r, types.PageResourceType) { - // expecting resource to always include path - return fmt.Errorf("invalid resource type") - } - - defOps := rbacResourceOperations(r) - for _, o := range oo { - if !defOps[o] { - return fmt.Errorf("invalid operation '%s' for page resource", o) - } - } - - const sep = "/" - var ( - pp = strings.Split(strings.Trim(r[len(types.PageResourceType):], sep), sep) - prc = []string{ - "namespaceID", - "ID", - } - ) - - if len(pp) != len(prc) { - return fmt.Errorf("invalid resource path structure") - } - - for i := 0; i < len(pp); i++ { - if pp[i] != "*" { - if i > 0 && pp[i-1] == "*" { - return fmt.Errorf("invalid path wildcard level (%d) for page resource", i) - } - - if _, err := cast.ToUint64E(pp[i]); err != nil { - return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i]) - } - } - } - return nil -} - -// rbacChartResourceValidator checks validity of RBAC resource and operations -// -// Can be called without operations to check for validity of resource string only -// -// This function is auto-generated -func rbacChartResourceValidator(r string, oo ...string) error { - if !strings.HasPrefix(r, types.ChartResourceType) { - // expecting resource to always include path - return fmt.Errorf("invalid resource type") - } - - defOps := rbacResourceOperations(r) - for _, o := range oo { - if !defOps[o] { - return fmt.Errorf("invalid operation '%s' for chart resource", o) - } - } - - const sep = "/" - var ( - pp = strings.Split(strings.Trim(r[len(types.ChartResourceType):], sep), sep) - prc = []string{ - "namespaceID", - "ID", - } - ) - - if len(pp) != len(prc) { - return fmt.Errorf("invalid resource path structure") - } - - for i := 0; i < len(pp); i++ { - if pp[i] != "*" { - if i > 0 && pp[i-1] == "*" { - return fmt.Errorf("invalid path wildcard level (%d) for chart resource", i) - } - - if _, err := cast.ToUint64E(pp[i]); err != nil { - return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i]) - } - } - } - return nil -} - // rbacComponentResourceValidator checks validity of RBAC resource and operations // // Can be called without operations to check for validity of resource string only diff --git a/compose/service/locale.gen.go b/compose/service/locale.gen.go index d2428001e..00e3a1936 100644 --- a/compose/service/locale.gen.go +++ b/compose/service/locale.gen.go @@ -6,11 +6,6 @@ package service // the code is regenerated. // -// Definitions file that controls how this file is generated: -// - compose.module.yaml -// - compose.namespace.yaml -// - compose.page.yaml - import ( "context" "github.com/cortezaproject/corteza-server/compose/types" @@ -41,9 +36,9 @@ type ( } ResourceTranslationsManagerService interface { - Module(ctx context.Context, namespaceID uint64, ID uint64) (locale.ResourceTranslationSet, error) + Module(ctx context.Context, NamespaceID uint64, ID uint64) (locale.ResourceTranslationSet, error) Namespace(ctx context.Context, ID uint64) (locale.ResourceTranslationSet, error) - Page(ctx context.Context, namespaceID uint64, ID uint64) (locale.ResourceTranslationSet, error) + Page(ctx context.Context, NamespaceID uint64, ID uint64) (locale.ResourceTranslationSet, error) Upsert(context.Context, locale.ResourceTranslationSet) error Locale() locale.Resource @@ -108,7 +103,7 @@ func (svc resourceTranslationsManager) Upsert(ctx context.Context, rr locale.Res sysLocale = append(sysLocale, aux...) aux = current.Old(rr) - aux.Walk(func(cc *systemTypes.ResourceTranslation) error { + _ = aux.Walk(func(cc *systemTypes.ResourceTranslation) error { cc.UpdatedAt = now() cc.UpdatedBy = me.Identity() return nil @@ -132,7 +127,7 @@ func (svc resourceTranslationsManager) Locale() locale.Resource { return svc.locale } -func (svc resourceTranslationsManager) Module(ctx context.Context, namespaceID uint64, ID uint64) (locale.ResourceTranslationSet, error) { +func (svc resourceTranslationsManager) Module(ctx context.Context, NamespaceID uint64, ID uint64) (locale.ResourceTranslationSet, error) { var ( err error out locale.ResourceTranslationSet @@ -140,7 +135,7 @@ func (svc resourceTranslationsManager) Module(ctx context.Context, namespaceID u k types.LocaleKey ) - res, err = svc.loadModule(ctx, svc.store, namespaceID, ID) + res, err = svc.loadModule(ctx, svc.store, NamespaceID, ID) if err != nil { return nil, err } @@ -156,8 +151,7 @@ func (svc resourceTranslationsManager) Module(ctx context.Context, namespaceID u } - tmp, err := svc.moduleExtended(ctx, res) - return append(out, tmp...), err + return out, nil } func (svc resourceTranslationsManager) Namespace(ctx context.Context, ID uint64) (locale.ResourceTranslationSet, error) { @@ -182,7 +176,7 @@ func (svc resourceTranslationsManager) Namespace(ctx context.Context, ID uint64) Msg: svc.locale.TResourceFor(tag, res.ResourceTranslation(), k.Path), }) - k = types.LocaleKeyNamespaceSubtitle + k = types.LocaleKeyNamespaceMetaSubtitle out = append(out, &locale.ResourceTranslation{ Resource: res.ResourceTranslation(), Lang: tag.String(), @@ -190,7 +184,7 @@ func (svc resourceTranslationsManager) Namespace(ctx context.Context, ID uint64) Msg: svc.locale.TResourceFor(tag, res.ResourceTranslation(), k.Path), }) - k = types.LocaleKeyNamespaceDescription + k = types.LocaleKeyNamespaceMetaDescription out = append(out, &locale.ResourceTranslation{ Resource: res.ResourceTranslation(), Lang: tag.String(), @@ -199,10 +193,11 @@ func (svc resourceTranslationsManager) Namespace(ctx context.Context, ID uint64) }) } + return out, nil } -func (svc resourceTranslationsManager) Page(ctx context.Context, namespaceID uint64, ID uint64) (locale.ResourceTranslationSet, error) { +func (svc resourceTranslationsManager) Page(ctx context.Context, NamespaceID uint64, ID uint64) (locale.ResourceTranslationSet, error) { var ( err error out locale.ResourceTranslationSet @@ -210,7 +205,7 @@ func (svc resourceTranslationsManager) Page(ctx context.Context, namespaceID uin k types.LocaleKey ) - res, err = svc.loadPage(ctx, svc.store, namespaceID, ID) + res, err = svc.loadPage(ctx, svc.store, NamespaceID, ID) if err != nil { return nil, err } diff --git a/compose/service/locale.go b/compose/service/locale.go index 60a0c6364..d34c5bc9a 100644 --- a/compose/service/locale.go +++ b/compose/service/locale.go @@ -28,14 +28,14 @@ func (svc resourceTranslationsManager) moduleExtended(ctx context.Context, res * Msg: svc.locale.TResourceFor(tag, f.ResourceTranslation(), k.Path), }) - k = types.LocaleKeyModuleFieldDescriptionView + k = types.LocaleKeyModuleFieldMetaDescriptionView out = append(out, &locale.ResourceTranslation{ Resource: f.ResourceTranslation(), Lang: tag.String(), Key: k.Path, Msg: svc.locale.TResourceFor(tag, f.ResourceTranslation(), k.Path), }) - k = types.LocaleKeyModuleFieldDescriptionEdit + k = types.LocaleKeyModuleFieldMetaDescriptionEdit out = append(out, &locale.ResourceTranslation{ Resource: f.ResourceTranslation(), Lang: tag.String(), @@ -43,14 +43,14 @@ func (svc resourceTranslationsManager) moduleExtended(ctx context.Context, res * Msg: svc.locale.TResourceFor(tag, f.ResourceTranslation(), k.Path), }) - k = types.LocaleKeyModuleFieldHintView + k = types.LocaleKeyModuleFieldMetaHintView out = append(out, &locale.ResourceTranslation{ Resource: f.ResourceTranslation(), Lang: tag.String(), Key: k.Path, Msg: svc.locale.TResourceFor(tag, f.ResourceTranslation(), k.Path), }) - k = types.LocaleKeyModuleFieldHintEdit + k = types.LocaleKeyModuleFieldMetaHintEdit out = append(out, &locale.ResourceTranslation{ Resource: f.ResourceTranslation(), Lang: tag.String(), @@ -86,7 +86,7 @@ func (svc resourceTranslationsManager) moduleFieldExpressionsHandler(ctx context "{{validatorID}}", strconv.FormatUint(vContentID, 10), ) - tKey := rpl.Replace(types.LocaleKeyModuleFieldValidatorError.Path) + tKey := rpl.Replace(types.LocaleKeyModuleFieldExpressionValidatorValidatorIDError.Path) out = append(out, &locale.ResourceTranslation{ Resource: f.ResourceTranslation(), @@ -128,7 +128,7 @@ func (svc resourceTranslationsManager) moduleFieldOptionsHandler(ctx context.Con } } - trKey := strings.NewReplacer("{{value}}", value).Replace(types.LocaleKeyModuleFieldOptionsOptionTexts.Path) + trKey := strings.NewReplacer("{{value}}", value).Replace(types.LocaleKeyModuleFieldMetaOptionsValueText.Path) out = append(out, &locale.ResourceTranslation{ Resource: f.ResourceTranslation(), @@ -154,7 +154,7 @@ func (svc resourceTranslationsManager) pageExtended(ctx context.Context, res *ty ) // base stuff - k = types.LocaleKeyPageBlockTitle + k = types.LocaleKeyPagePageBlockBlockIDTitle out = append(out, &locale.ResourceTranslation{ Resource: res.ResourceTranslation(), Lang: tag.String(), @@ -162,7 +162,7 @@ func (svc resourceTranslationsManager) pageExtended(ctx context.Context, res *ty Msg: svc.locale.TResourceFor(tag, res.ResourceTranslation(), rpl.Replace(k.Path)), }) - k = types.LocaleKeyPageBlockDescription + k = types.LocaleKeyPagePageBlockBlockIDDescription out = append(out, &locale.ResourceTranslation{ Resource: res.ResourceTranslation(), Lang: tag.String(), diff --git a/compose/types/locale.gen.go b/compose/types/locale.gen.go index c180e9788..d267f6df4 100644 --- a/compose/types/locale.gen.go +++ b/compose/types/locale.gen.go @@ -6,12 +6,6 @@ package types // the code is regenerated. // -// Definitions file that controls how this file is generated: -// - compose.module-field.yaml -// - compose.module.yaml -// - compose.namespace.yaml -// - compose.page.yaml - import ( "fmt" "github.com/cortezaproject/corteza-server/pkg/locale" @@ -29,167 +23,39 @@ type ( // Types and stuff const ( - ModuleFieldResourceTranslationType = "compose:module-field" ModuleResourceTranslationType = "compose:module" + ModuleFieldResourceTranslationType = "compose:module-field" NamespaceResourceTranslationType = "compose:namespace" PageResourceTranslationType = "compose:page" ) var ( - LocaleKeyModuleFieldLabel = LocaleKey{ - Name: "label", - Resource: ModuleFieldResourceTranslationType, - Path: "label", - } - LocaleKeyModuleFieldDescriptionView = LocaleKey{ - Name: "descriptionView", - Resource: ModuleFieldResourceTranslationType, - Path: "meta.description.view", - CustomHandler: "descriptionView", - } - LocaleKeyModuleFieldDescriptionEdit = LocaleKey{ - Name: "descriptionEdit", - Resource: ModuleFieldResourceTranslationType, - Path: "meta.description.edit", - CustomHandler: "descriptionEdit", - } - LocaleKeyModuleFieldHintView = LocaleKey{ - Name: "hintView", - Resource: ModuleFieldResourceTranslationType, - Path: "meta.hint.view", - CustomHandler: "hintView", - } - LocaleKeyModuleFieldHintEdit = LocaleKey{ - Name: "hintEdit", - Resource: ModuleFieldResourceTranslationType, - Path: "meta.hint.edit", - CustomHandler: "hintEdit", - } - LocaleKeyModuleFieldValidatorError = LocaleKey{ - Name: "validatorError", - Resource: ModuleFieldResourceTranslationType, - Path: "expression.validator.{{validatorID}}.error", - CustomHandler: "validatorError", - } - LocaleKeyModuleFieldOptionsOptionTexts = LocaleKey{ - Name: "optionsOptionTexts", - Resource: ModuleFieldResourceTranslationType, - Path: "meta.options.{{value}}.text", - CustomHandler: "optionsOptionTexts", - } - LocaleKeyModuleName = LocaleKey{ - Name: "name", - Resource: ModuleResourceTranslationType, - Path: "name", - } - LocaleKeyNamespaceName = LocaleKey{ - Name: "name", - Resource: NamespaceResourceTranslationType, - Path: "name", - } - LocaleKeyNamespaceSubtitle = LocaleKey{ - Name: "subtitle", - Resource: NamespaceResourceTranslationType, - Path: "subtitle", - } - LocaleKeyNamespaceDescription = LocaleKey{ - Name: "description", - Resource: NamespaceResourceTranslationType, - Path: "description", - } - LocaleKeyPageTitle = LocaleKey{ - Name: "title", - Resource: PageResourceTranslationType, - Path: "title", - } - LocaleKeyPageDescription = LocaleKey{ - Name: "description", - Resource: PageResourceTranslationType, - Path: "description", - } - LocaleKeyPageBlockTitle = LocaleKey{ - Name: "blockTitle", - Resource: PageResourceTranslationType, - Path: "pageBlock.{{blockID}}.title", - } - LocaleKeyPageBlockDescription = LocaleKey{ - Name: "blockDescription", - Resource: PageResourceTranslationType, - Path: "pageBlock.{{blockID}}.description", - } - LocaleKeyPageBlockAutomationButtonlabel = LocaleKey{ - Name: "blockAutomationButtonlabel", - Resource: PageResourceTranslationType, - Path: "pageBlock.{{blockID}}.button.{{buttonID}}.label", - } + // @todo can we remove LocaleKey struct for string constant? + LocaleKeyModuleName = LocaleKey{Path: "name"} + LocaleKeyModuleFieldLabel = LocaleKey{Path: "label"} + LocaleKeyModuleFieldMetaDescriptionView = LocaleKey{Path: "meta.description.view"} + LocaleKeyModuleFieldMetaDescriptionEdit = LocaleKey{Path: "meta.description.edit"} + LocaleKeyModuleFieldMetaHintView = LocaleKey{Path: "meta.hint.view"} + LocaleKeyModuleFieldMetaHintEdit = LocaleKey{Path: "meta.hint.edit"} + LocaleKeyModuleFieldExpressionValidatorValidatorIDError = LocaleKey{Path: "expression.validator.{{validatorID}}.error"} + LocaleKeyModuleFieldMetaOptionsValueText = LocaleKey{Path: "meta.options.{{value}}.text"} + LocaleKeyNamespaceName = LocaleKey{Path: "name"} + LocaleKeyNamespaceMetaSubtitle = LocaleKey{Path: "meta.subtitle"} + LocaleKeyNamespaceMetaDescription = LocaleKey{Path: "meta.description"} + LocaleKeyPageTitle = LocaleKey{Path: "title"} + LocaleKeyPageDescription = LocaleKey{Path: "description"} + LocaleKeyPagePageBlockBlockIDTitle = LocaleKey{Path: "pageBlock.{{blockID}}.title"} + LocaleKeyPagePageBlockBlockIDDescription = LocaleKey{Path: "pageBlock.{{blockID}}.description"} + LocaleKeyPagePageBlockBlockIDButtonButtonIDLabel = LocaleKey{Path: "pageBlock.{{blockID}}.button.{{buttonID}}.label"} ) -// ResourceTranslation returns string representation of Locale resource for ModuleField by calling ModuleFieldResourceTranslation fn -// -// Locale resource is in "compose:module-field/..." format -// -// This function is auto-generated -func (r ModuleField) ResourceTranslation() string { - return ModuleFieldResourceTranslation(r.NamespaceID, r.ModuleID, r.ID) -} - -// ModuleFieldResourceTranslation returns string representation of Locale resource for ModuleField -// -// Locale resource is in the compose:module-field/... format -// -// This function is auto-generated -func ModuleFieldResourceTranslation(namespaceID uint64, moduleID uint64, id uint64) string { - cpts := []interface{}{ModuleFieldResourceTranslationType} - cpts = append(cpts, strconv.FormatUint(namespaceID, 10), strconv.FormatUint(moduleID, 10), strconv.FormatUint(id, 10)) - - return fmt.Sprintf(ModuleFieldResourceTranslationTpl(), cpts...) -} - -// @todo template -func ModuleFieldResourceTranslationTpl() string { - return "%s/%s/%s/%s" -} - -func (r *ModuleField) DecodeTranslations(tt locale.ResourceTranslationIndex) { - var aux *locale.ResourceTranslation - if aux = tt.FindByKey(LocaleKeyModuleFieldLabel.Path); aux != nil { - r.Label = aux.Msg - } - r.decodeTranslationsDescriptionView(tt) - r.decodeTranslationsDescriptionEdit(tt) - r.decodeTranslationsHintView(tt) - r.decodeTranslationsHintEdit(tt) - r.decodeTranslationsValidatorError(tt) - r.decodeTranslationsOptionsOptionTexts(tt) -} - -func (r *ModuleField) EncodeTranslations() (out locale.ResourceTranslationSet) { - out = locale.ResourceTranslationSet{} - if r.Label != "" { - out = append(out, &locale.ResourceTranslation{ - Resource: r.ResourceTranslation(), - Key: LocaleKeyModuleFieldLabel.Path, - Msg: locale.SanitizeMessage(r.Label), - }) - } - - out = append(out, r.encodeTranslationsDescriptionView()...) - out = append(out, r.encodeTranslationsDescriptionEdit()...) - out = append(out, r.encodeTranslationsHintView()...) - out = append(out, r.encodeTranslationsHintEdit()...) - out = append(out, r.encodeTranslationsValidatorError()...) - out = append(out, r.encodeTranslationsOptionsOptionTexts()...) - - return out -} - // ResourceTranslation returns string representation of Locale resource for Module by calling ModuleResourceTranslation fn // // Locale resource is in "compose:module/..." format // // This function is auto-generated func (r Module) ResourceTranslation() string { - return ModuleResourceTranslation(r.NamespaceID, r.ID) + return ModuleResourceTranslation(r.ID) } // ModuleResourceTranslation returns string representation of Locale resource for Module @@ -197,29 +63,30 @@ func (r Module) ResourceTranslation() string { // Locale resource is in the compose:module/... format // // This function is auto-generated -func ModuleResourceTranslation(namespaceID uint64, id uint64) string { - cpts := []interface{}{ModuleResourceTranslationType} - cpts = append(cpts, strconv.FormatUint(namespaceID, 10), strconv.FormatUint(id, 10)) +func ModuleResourceTranslation(ID uint64) string { + cpts := []interface{}{ + ModuleResourceTranslationType, + strconv.FormatUint(ID, 10), + } return fmt.Sprintf(ModuleResourceTranslationTpl(), cpts...) } -// @todo template func ModuleResourceTranslationTpl() string { - return "%s/%s/%s" + return "%s/%s" } func (r *Module) DecodeTranslations(tt locale.ResourceTranslationIndex) { var aux *locale.ResourceTranslation + if aux = tt.FindByKey(LocaleKeyModuleName.Path); aux != nil { r.Name = aux.Msg } - - r.decodeTranslations(tt) } func (r *Module) EncodeTranslations() (out locale.ResourceTranslationSet) { out = locale.ResourceTranslationSet{} + if r.Name != "" { out = append(out, &locale.ResourceTranslation{ Resource: r.ResourceTranslation(), @@ -228,7 +95,79 @@ func (r *Module) EncodeTranslations() (out locale.ResourceTranslationSet) { }) } - out = append(out, r.encodeTranslations()...) + return out +} + +// ResourceTranslation returns string representation of Locale resource for ModuleField by calling ModuleFieldResourceTranslation fn +// +// Locale resource is in "compose:module-field/..." format +// +// This function is auto-generated +func (r ModuleField) ResourceTranslation() string { + return ModuleFieldResourceTranslation(r.ID) +} + +// ModuleFieldResourceTranslation returns string representation of Locale resource for ModuleField +// +// Locale resource is in the compose:module-field/... format +// +// This function is auto-generated +func ModuleFieldResourceTranslation(ID uint64) string { + cpts := []interface{}{ + ModuleFieldResourceTranslationType, + strconv.FormatUint(ID, 10), + } + + return fmt.Sprintf(ModuleFieldResourceTranslationTpl(), cpts...) +} + +func ModuleFieldResourceTranslationTpl() string { + return "%s/%s" +} + +func (r *ModuleField) DecodeTranslations(tt locale.ResourceTranslationIndex) { + var aux *locale.ResourceTranslation + + if aux = tt.FindByKey(LocaleKeyModuleFieldLabel.Path); aux != nil { + r.Label = aux.Msg + } + + r.decodeTranslationsMetaDescriptionView(tt) + + r.decodeTranslationsMetaDescriptionEdit(tt) + + r.decodeTranslationsMetaHintView(tt) + + r.decodeTranslationsMetaHintEdit(tt) + + r.decodeTranslationsExpressionValidatorValidatorIDError(tt) + + r.decodeTranslationsMetaOptionsValueText(tt) + +} + +func (r *ModuleField) EncodeTranslations() (out locale.ResourceTranslationSet) { + out = locale.ResourceTranslationSet{} + + if r.Label != "" { + out = append(out, &locale.ResourceTranslation{ + Resource: r.ResourceTranslation(), + Key: LocaleKeyModuleFieldLabel.Path, + Msg: locale.SanitizeMessage(r.Label), + }) + } + + out = append(out, r.encodeTranslationsMetaDescriptionView()...) + + out = append(out, r.encodeTranslationsMetaDescriptionEdit()...) + + out = append(out, r.encodeTranslationsMetaHintView()...) + + out = append(out, r.encodeTranslationsMetaHintEdit()...) + + out = append(out, r.encodeTranslationsExpressionValidatorValidatorIDError()...) + + out = append(out, r.encodeTranslationsMetaOptionsValueText()...) return out } @@ -247,33 +186,38 @@ func (r Namespace) ResourceTranslation() string { // Locale resource is in the compose:namespace/... format // // This function is auto-generated -func NamespaceResourceTranslation(id uint64) string { - cpts := []interface{}{NamespaceResourceTranslationType} - cpts = append(cpts, strconv.FormatUint(id, 10)) +func NamespaceResourceTranslation(ID uint64) string { + cpts := []interface{}{ + NamespaceResourceTranslationType, + strconv.FormatUint(ID, 10), + } return fmt.Sprintf(NamespaceResourceTranslationTpl(), cpts...) } -// @todo template func NamespaceResourceTranslationTpl() string { return "%s/%s" } func (r *Namespace) DecodeTranslations(tt locale.ResourceTranslationIndex) { var aux *locale.ResourceTranslation + if aux = tt.FindByKey(LocaleKeyNamespaceName.Path); aux != nil { r.Name = aux.Msg } - if aux = tt.FindByKey(LocaleKeyNamespaceSubtitle.Path); aux != nil { + + if aux = tt.FindByKey(LocaleKeyNamespaceMetaSubtitle.Path); aux != nil { r.Meta.Subtitle = aux.Msg } - if aux = tt.FindByKey(LocaleKeyNamespaceDescription.Path); aux != nil { + + if aux = tt.FindByKey(LocaleKeyNamespaceMetaDescription.Path); aux != nil { r.Meta.Description = aux.Msg } } func (r *Namespace) EncodeTranslations() (out locale.ResourceTranslationSet) { out = locale.ResourceTranslationSet{} + if r.Name != "" { out = append(out, &locale.ResourceTranslation{ Resource: r.ResourceTranslation(), @@ -281,17 +225,19 @@ func (r *Namespace) EncodeTranslations() (out locale.ResourceTranslationSet) { Msg: locale.SanitizeMessage(r.Name), }) } + if r.Meta.Subtitle != "" { out = append(out, &locale.ResourceTranslation{ Resource: r.ResourceTranslation(), - Key: LocaleKeyNamespaceSubtitle.Path, + Key: LocaleKeyNamespaceMetaSubtitle.Path, Msg: locale.SanitizeMessage(r.Meta.Subtitle), }) } + if r.Meta.Description != "" { out = append(out, &locale.ResourceTranslation{ Resource: r.ResourceTranslation(), - Key: LocaleKeyNamespaceDescription.Path, + Key: LocaleKeyNamespaceMetaDescription.Path, Msg: locale.SanitizeMessage(r.Meta.Description), }) } @@ -305,7 +251,7 @@ func (r *Namespace) EncodeTranslations() (out locale.ResourceTranslationSet) { // // This function is auto-generated func (r Page) ResourceTranslation() string { - return PageResourceTranslation(r.NamespaceID, r.ID) + return PageResourceTranslation(r.ID) } // PageResourceTranslation returns string representation of Locale resource for Page @@ -313,23 +259,26 @@ func (r Page) ResourceTranslation() string { // Locale resource is in the compose:page/... format // // This function is auto-generated -func PageResourceTranslation(namespaceID uint64, id uint64) string { - cpts := []interface{}{PageResourceTranslationType} - cpts = append(cpts, strconv.FormatUint(namespaceID, 10), strconv.FormatUint(id, 10)) +func PageResourceTranslation(ID uint64) string { + cpts := []interface{}{ + PageResourceTranslationType, + strconv.FormatUint(ID, 10), + } return fmt.Sprintf(PageResourceTranslationTpl(), cpts...) } -// @todo template func PageResourceTranslationTpl() string { - return "%s/%s/%s" + return "%s/%s" } func (r *Page) DecodeTranslations(tt locale.ResourceTranslationIndex) { var aux *locale.ResourceTranslation + if aux = tt.FindByKey(LocaleKeyPageTitle.Path); aux != nil { r.Title = aux.Msg } + if aux = tt.FindByKey(LocaleKeyPageDescription.Path); aux != nil { r.Description = aux.Msg } @@ -339,6 +288,7 @@ func (r *Page) DecodeTranslations(tt locale.ResourceTranslationIndex) { func (r *Page) EncodeTranslations() (out locale.ResourceTranslationSet) { out = locale.ResourceTranslationSet{} + if r.Title != "" { out = append(out, &locale.ResourceTranslation{ Resource: r.ResourceTranslation(), @@ -346,6 +296,7 @@ func (r *Page) EncodeTranslations() (out locale.ResourceTranslationSet) { Msg: locale.SanitizeMessage(r.Title), }) } + if r.Description != "" { out = append(out, &locale.ResourceTranslation{ Resource: r.ResourceTranslation(), diff --git a/compose/types/module_field.go b/compose/types/module_field.go index cc3bc30d9..cfd5ef329 100644 --- a/compose/types/module_field.go +++ b/compose/types/module_field.go @@ -56,7 +56,7 @@ var ( _ sort.Interface = &ModuleFieldSet{} ) -func (f *ModuleField) decodeTranslationsValidatorError(tt locale.ResourceTranslationIndex) { +func (f *ModuleField) decodeTranslationsExpressionValidatorValidatorIDError(tt locale.ResourceTranslationIndex) { var aux *locale.ResourceTranslation for i, e := range f.Expressions.Validators { @@ -65,40 +65,40 @@ func (f *ModuleField) decodeTranslationsValidatorError(tt locale.ResourceTransla "{{validatorID}}", strconv.FormatUint(validatorID, 10), ) - if aux = tt.FindByKey(rpl.Replace(LocaleKeyModuleFieldValidatorError.Path)); aux != nil { + if aux = tt.FindByKey(rpl.Replace(LocaleKeyModuleFieldExpressionValidatorValidatorIDError.Path)); aux != nil { f.Expressions.Validators[i].Error = aux.Msg } } } -func (f *ModuleField) decodeTranslationsDescriptionView(tt locale.ResourceTranslationIndex) { +func (f *ModuleField) decodeTranslationsMetaDescriptionView(tt locale.ResourceTranslationIndex) { var aux *locale.ResourceTranslation - if aux = tt.FindByKey(LocaleKeyModuleFieldDescriptionView.Path); aux != nil { + if aux = tt.FindByKey(LocaleKeyModuleFieldMetaDescriptionView.Path); aux != nil { f.setOptionKey(aux.Msg, "description", "edit") } } -func (f *ModuleField) decodeTranslationsDescriptionEdit(tt locale.ResourceTranslationIndex) { +func (f *ModuleField) decodeTranslationsMetaDescriptionEdit(tt locale.ResourceTranslationIndex) { var aux *locale.ResourceTranslation - if aux = tt.FindByKey(LocaleKeyModuleFieldDescriptionEdit.Path); aux != nil { + if aux = tt.FindByKey(LocaleKeyModuleFieldMetaDescriptionEdit.Path); aux != nil { f.setOptionKey(aux.Msg, "description", "view") } } -func (f *ModuleField) decodeTranslationsHintView(tt locale.ResourceTranslationIndex) { +func (f *ModuleField) decodeTranslationsMetaHintView(tt locale.ResourceTranslationIndex) { var aux *locale.ResourceTranslation - if aux = tt.FindByKey(LocaleKeyModuleFieldHintView.Path); aux != nil { + if aux = tt.FindByKey(LocaleKeyModuleFieldMetaHintView.Path); aux != nil { f.setOptionKey(aux.Msg, "hint", "edit") } } -func (f *ModuleField) decodeTranslationsHintEdit(tt locale.ResourceTranslationIndex) { +func (f *ModuleField) decodeTranslationsMetaHintEdit(tt locale.ResourceTranslationIndex) { var aux *locale.ResourceTranslation - if aux = tt.FindByKey(LocaleKeyModuleFieldHintEdit.Path); aux != nil { + if aux = tt.FindByKey(LocaleKeyModuleFieldMetaHintEdit.Path); aux != nil { f.setOptionKey(aux.Msg, "hint", "view") } } @@ -106,7 +106,7 @@ func (f *ModuleField) decodeTranslationsHintEdit(tt locale.ResourceTranslationIn // Decodes translations and modifies options // // Why "options-option-texts"? Because we're translating option txts under options key-value -func (f *ModuleField) decodeTranslationsOptionsOptionTexts(tt locale.ResourceTranslationIndex) { +func (f *ModuleField) decodeTranslationsMetaOptionsValueText(tt locale.ResourceTranslationIndex) { var ( tr *locale.ResourceTranslation ) @@ -145,7 +145,7 @@ func (f *ModuleField) decodeTranslationsOptionsOptionTexts(tt locale.ResourceTra // find the translation for that value // and update the option (effectively overwriting // the original text value (in case of map option) - trKey := strings.NewReplacer("{{value}}", outOpt["value"]).Replace(LocaleKeyModuleFieldOptionsOptionTexts.Path) + trKey := strings.NewReplacer("{{value}}", outOpt["value"]).Replace(LocaleKeyModuleFieldMetaOptionsValueText.Path) if tr = tt.FindByKey(trKey); tr != nil { outOpt["text"] = tr.Msg } @@ -155,7 +155,7 @@ func (f *ModuleField) decodeTranslationsOptionsOptionTexts(tt locale.ResourceTra } } -func (m *ModuleField) encodeTranslationsValidatorError() (out locale.ResourceTranslationSet) { +func (m *ModuleField) encodeTranslationsExpressionValidatorValidatorIDError() (out locale.ResourceTranslationSet) { out = make(locale.ResourceTranslationSet, 0, 3) // Module field expressions @@ -167,7 +167,7 @@ func (m *ModuleField) encodeTranslationsValidatorError() (out locale.ResourceTra out = append(out, &locale.ResourceTranslation{ Resource: m.ResourceTranslation(), - Key: rpl.Replace(LocaleKeyModuleFieldValidatorError.Path), + Key: rpl.Replace(LocaleKeyModuleFieldExpressionValidatorValidatorIDError.Path), Msg: e.Error, }) } @@ -175,53 +175,53 @@ func (m *ModuleField) encodeTranslationsValidatorError() (out locale.ResourceTra return } -func (f *ModuleField) encodeTranslationsDescriptionView() (out locale.ResourceTranslationSet) { +func (f *ModuleField) encodeTranslationsMetaDescriptionView() (out locale.ResourceTranslationSet) { out = locale.ResourceTranslationSet{} if v := f.getOptionKey("description", "edit"); v != nil { aux := cast.ToString(v) out = append(out, &locale.ResourceTranslation{ Resource: f.ResourceTranslation(), - Key: LocaleKeyModuleFieldDescriptionView.Path, + Key: LocaleKeyModuleFieldMetaDescriptionView.Path, Msg: aux, }) } return out } -func (f *ModuleField) encodeTranslationsDescriptionEdit() (out locale.ResourceTranslationSet) { +func (f *ModuleField) encodeTranslationsMetaDescriptionEdit() (out locale.ResourceTranslationSet) { out = locale.ResourceTranslationSet{} if v := f.getOptionKey("description", "view"); v != nil { aux := cast.ToString(v) out = append(out, &locale.ResourceTranslation{ Resource: f.ResourceTranslation(), - Key: LocaleKeyModuleFieldDescriptionEdit.Path, + Key: LocaleKeyModuleFieldMetaDescriptionEdit.Path, Msg: aux, }) } return out } -func (f *ModuleField) encodeTranslationsHintView() (out locale.ResourceTranslationSet) { +func (f *ModuleField) encodeTranslationsMetaHintView() (out locale.ResourceTranslationSet) { out = locale.ResourceTranslationSet{} if v := f.getOptionKey("hint", "edit"); v != nil { aux := cast.ToString(v) out = append(out, &locale.ResourceTranslation{ Resource: f.ResourceTranslation(), - Key: LocaleKeyModuleFieldHintView.Path, + Key: LocaleKeyModuleFieldMetaHintView.Path, Msg: aux, }) } return out } -func (f *ModuleField) encodeTranslationsHintEdit() (out locale.ResourceTranslationSet) { +func (f *ModuleField) encodeTranslationsMetaHintEdit() (out locale.ResourceTranslationSet) { out = locale.ResourceTranslationSet{} if v := f.getOptionKey("hint", "view"); v != nil { aux := cast.ToString(v) out = append(out, &locale.ResourceTranslation{ Resource: f.ResourceTranslation(), - Key: LocaleKeyModuleFieldHintEdit.Path, + Key: LocaleKeyModuleFieldMetaHintEdit.Path, Msg: aux, }) } @@ -229,7 +229,7 @@ func (f *ModuleField) encodeTranslationsHintEdit() (out locale.ResourceTranslati } // extracts option texts and converts (encodes) them to translations -func (f *ModuleField) encodeTranslationsOptionsOptionTexts() (out locale.ResourceTranslationSet) { +func (f *ModuleField) encodeTranslationsMetaOptionsValueText() (out locale.ResourceTranslationSet) { out = make(locale.ResourceTranslationSet, 0, 3) optsUnknown, has := f.Options["options"] @@ -252,7 +252,7 @@ func (f *ModuleField) encodeTranslationsOptionsOptionTexts() (out locale.Resourc out = append(out, &locale.ResourceTranslation{ Resource: f.ResourceTranslation(), Key: strings.NewReplacer("{{value}}", value). - Replace(LocaleKeyModuleFieldOptionsOptionTexts.Path), + Replace(LocaleKeyModuleFieldMetaOptionsValueText.Path), Msg: text, }) } diff --git a/compose/types/module_field_test.go b/compose/types/module_field_test.go index 8746de13e..1ddc15af0 100644 --- a/compose/types/module_field_test.go +++ b/compose/types/module_field_test.go @@ -68,7 +68,7 @@ func TestModuleField_decodeTranslationsOptionsOptionTexts(t *testing.T) { f = &ModuleField{Options: tt.opts} ) - f.decodeTranslationsOptionsOptionTexts(rti) + f.decodeTranslationsMetaOptionsValueText(rti) if tt.out != nil { req.Equal(tt.out, f.Options["options"]) diff --git a/compose/types/namespace.go b/compose/types/namespace.go index 40a04f989..c27ac56ef 100644 --- a/compose/types/namespace.go +++ b/compose/types/namespace.go @@ -6,7 +6,6 @@ import ( "time" "github.com/cortezaproject/corteza-server/pkg/filter" - "github.com/pkg/errors" ) diff --git a/compose/types/page.go b/compose/types/page.go index 034effc1e..9808f955f 100644 --- a/compose/types/page.go +++ b/compose/types/page.go @@ -124,10 +124,10 @@ func (p *Page) decodeTranslations(tt locale.ResourceTranslationIndex) { ) // - generic page block stuff - if aux = tt.FindByKey(rpl.Replace(LocaleKeyPageBlockTitle.Path)); aux != nil { + if aux = tt.FindByKey(rpl.Replace(LocaleKeyPagePageBlockBlockIDTitle.Path)); aux != nil { p.Blocks[i].Title = aux.Msg } - if aux = tt.FindByKey(rpl.Replace(LocaleKeyPageBlockDescription.Path)); aux != nil { + if aux = tt.FindByKey(rpl.Replace(LocaleKeyPagePageBlockBlockIDDescription.Path)); aux != nil { p.Blocks[i].Description = aux.Msg } @@ -148,7 +148,7 @@ func (p *Page) decodeTranslations(tt locale.ResourceTranslationIndex) { "{{buttonID}}", strconv.FormatUint(buttonID, 10), ) - if aux = tt.FindByKey(rpl.Replace(LocaleKeyPageBlockAutomationButtonlabel.Path)); aux != nil { + if aux = tt.FindByKey(rpl.Replace(LocaleKeyPagePageBlockBlockIDButtonButtonIDLabel.Path)); aux != nil { btn["label"] = aux.Msg } } @@ -169,13 +169,13 @@ func (p *Page) encodeTranslations() (out locale.ResourceTranslationSet) { // - generic page block stuff out = append(out, &locale.ResourceTranslation{ Resource: p.ResourceTranslation(), - Key: rpl.Replace(LocaleKeyPageBlockTitle.Path), + Key: rpl.Replace(LocaleKeyPagePageBlockBlockIDTitle.Path), Msg: block.Title, }) out = append(out, &locale.ResourceTranslation{ Resource: p.ResourceTranslation(), - Key: rpl.Replace(LocaleKeyPageBlockDescription.Path), + Key: rpl.Replace(LocaleKeyPagePageBlockBlockIDDescription.Path), Msg: block.Description, }) @@ -202,7 +202,7 @@ func (p *Page) encodeTranslations() (out locale.ResourceTranslationSet) { out = append(out, &locale.ResourceTranslation{ Resource: p.ResourceTranslation(), - Key: rpl.Replace(LocaleKeyPageBlockAutomationButtonlabel.Path), + Key: rpl.Replace(LocaleKeyPagePageBlockBlockIDButtonButtonIDLabel.Path), Msg: btn["label"].(string), }) } diff --git a/compose/types/rbac.gen.go b/compose/types/rbac.gen.go index 5d0f02249..98f15e2a4 100644 --- a/compose/types/rbac.gen.go +++ b/compose/types/rbac.gen.go @@ -24,43 +24,49 @@ var ( ) const ( - NamespaceResourceType = "corteza::compose:namespace" + ChartResourceType = "corteza::compose:chart" ModuleResourceType = "corteza::compose:module" ModuleFieldResourceType = "corteza::compose:module-field" - RecordResourceType = "corteza::compose:record" + NamespaceResourceType = "corteza::compose:namespace" PageResourceType = "corteza::compose:page" - ChartResourceType = "corteza::compose:chart" + RecordResourceType = "corteza::compose:record" ComponentResourceType = "corteza::compose" ) -// RbacResource returns string representation of RBAC resource for Namespace by calling NamespaceRbacResource fn +// RbacResource returns string representation of RBAC resource for Chart by calling ChartRbacResource fn // -// RBAC resource is in the corteza::compose:namespace/... format +// RBAC resource is in the corteza::compose:chart/... format // // This function is auto-generated -func (r Namespace) RbacResource() string { - return NamespaceRbacResource(r.ID) +func (r Chart) RbacResource() string { + return ChartRbacResource(r.NamespaceID, r.ID) } -// NamespaceRbacResource returns string representation of RBAC resource for Namespace +// ChartRbacResource returns string representation of RBAC resource for Chart // -// RBAC resource is in the corteza::compose:namespace/... format +// RBAC resource is in the corteza::compose:chart/... format // // This function is auto-generated -func NamespaceRbacResource(ID uint64) string { - cpts := []interface{}{NamespaceResourceType} - if ID != 0 { - cpts = append(cpts, strconv.FormatUint(ID, 10)) +func ChartRbacResource(namespaceID uint64, id uint64) string { + cpts := []interface{}{ChartResourceType} + if namespaceID != 0 { + cpts = append(cpts, strconv.FormatUint(namespaceID, 10)) } else { cpts = append(cpts, "*") } - return fmt.Sprintf(NamespaceRbacResourceTpl(), cpts...) + if id != 0 { + cpts = append(cpts, strconv.FormatUint(id, 10)) + } else { + cpts = append(cpts, "*") + } + + return fmt.Sprintf(ChartRbacResourceTpl(), cpts...) } -func NamespaceRbacResourceTpl() string { - return "%s/%s" +func ChartRbacResourceTpl() string { + return "%s/%s/%s" } // RbacResource returns string representation of RBAC resource for Module by calling ModuleRbacResource fn @@ -77,16 +83,16 @@ func (r Module) RbacResource() string { // RBAC resource is in the corteza::compose:module/... format // // This function is auto-generated -func ModuleRbacResource(NamespaceID uint64, ID uint64) string { +func ModuleRbacResource(namespaceID uint64, id uint64) string { cpts := []interface{}{ModuleResourceType} - if NamespaceID != 0 { - cpts = append(cpts, strconv.FormatUint(NamespaceID, 10)) + if namespaceID != 0 { + cpts = append(cpts, strconv.FormatUint(namespaceID, 10)) } else { cpts = append(cpts, "*") } - if ID != 0 { - cpts = append(cpts, strconv.FormatUint(ID, 10)) + if id != 0 { + cpts = append(cpts, strconv.FormatUint(id, 10)) } else { cpts = append(cpts, "*") } @@ -113,22 +119,22 @@ func (r ModuleField) RbacResource() string { // RBAC resource is in the corteza::compose:module-field/... format // // This function is auto-generated -func ModuleFieldRbacResource(NamespaceID uint64, ModuleID uint64, ID uint64) string { +func ModuleFieldRbacResource(namespaceID uint64, moduleID uint64, id uint64) string { cpts := []interface{}{ModuleFieldResourceType} - if NamespaceID != 0 { - cpts = append(cpts, strconv.FormatUint(NamespaceID, 10)) + if namespaceID != 0 { + cpts = append(cpts, strconv.FormatUint(namespaceID, 10)) } else { cpts = append(cpts, "*") } - if ModuleID != 0 { - cpts = append(cpts, strconv.FormatUint(ModuleID, 10)) + if moduleID != 0 { + cpts = append(cpts, strconv.FormatUint(moduleID, 10)) } else { cpts = append(cpts, "*") } - if ID != 0 { - cpts = append(cpts, strconv.FormatUint(ID, 10)) + if id != 0 { + cpts = append(cpts, strconv.FormatUint(id, 10)) } else { cpts = append(cpts, "*") } @@ -141,46 +147,27 @@ func ModuleFieldRbacResourceTpl() string { return "%s/%s/%s/%s" } -// RbacResource returns string representation of RBAC resource for Record by calling RecordRbacResource fn +// RbacResource returns string representation of RBAC resource for Namespace by calling NamespaceRbacResource fn // -// RBAC resource is in the corteza::compose:record/... format +// RBAC resource is in the corteza::compose:namespace/... format // // This function is auto-generated -func (r Record) RbacResource() string { - return RecordRbacResource(r.NamespaceID, r.ModuleID, r.ID) +func (r Namespace) RbacResource() string { + return NamespaceRbacResource() } -// RecordRbacResource returns string representation of RBAC resource for Record +// NamespaceRbacResource returns string representation of RBAC resource for Namespace // -// RBAC resource is in the corteza::compose:record/... format +// RBAC resource is in the corteza::compose:namespace/ format // // This function is auto-generated -func RecordRbacResource(NamespaceID uint64, ModuleID uint64, ID uint64) string { - cpts := []interface{}{RecordResourceType} - if NamespaceID != 0 { - cpts = append(cpts, strconv.FormatUint(NamespaceID, 10)) - } else { - cpts = append(cpts, "*") - } - - if ModuleID != 0 { - cpts = append(cpts, strconv.FormatUint(ModuleID, 10)) - } else { - cpts = append(cpts, "*") - } - - if ID != 0 { - cpts = append(cpts, strconv.FormatUint(ID, 10)) - } else { - cpts = append(cpts, "*") - } - - return fmt.Sprintf(RecordRbacResourceTpl(), cpts...) +func NamespaceRbacResource() string { + return NamespaceResourceType + "/" } -func RecordRbacResourceTpl() string { - return "%s/%s/%s/%s" +func NamespaceRbacResourceTpl() string { + return "%s" } // RbacResource returns string representation of RBAC resource for Page by calling PageRbacResource fn @@ -197,16 +184,16 @@ func (r Page) RbacResource() string { // RBAC resource is in the corteza::compose:page/... format // // This function is auto-generated -func PageRbacResource(NamespaceID uint64, ID uint64) string { +func PageRbacResource(namespaceID uint64, id uint64) string { cpts := []interface{}{PageResourceType} - if NamespaceID != 0 { - cpts = append(cpts, strconv.FormatUint(NamespaceID, 10)) + if namespaceID != 0 { + cpts = append(cpts, strconv.FormatUint(namespaceID, 10)) } else { cpts = append(cpts, "*") } - if ID != 0 { - cpts = append(cpts, strconv.FormatUint(ID, 10)) + if id != 0 { + cpts = append(cpts, strconv.FormatUint(id, 10)) } else { cpts = append(cpts, "*") } @@ -219,40 +206,46 @@ func PageRbacResourceTpl() string { return "%s/%s/%s" } -// RbacResource returns string representation of RBAC resource for Chart by calling ChartRbacResource fn +// RbacResource returns string representation of RBAC resource for Record by calling RecordRbacResource fn // -// RBAC resource is in the corteza::compose:chart/... format +// RBAC resource is in the corteza::compose:record/... format // // This function is auto-generated -func (r Chart) RbacResource() string { - return ChartRbacResource(r.NamespaceID, r.ID) +func (r Record) RbacResource() string { + return RecordRbacResource(r.NamespaceID, r.ModuleID, r.ID) } -// ChartRbacResource returns string representation of RBAC resource for Chart +// RecordRbacResource returns string representation of RBAC resource for Record // -// RBAC resource is in the corteza::compose:chart/... format +// RBAC resource is in the corteza::compose:record/... format // // This function is auto-generated -func ChartRbacResource(NamespaceID uint64, ID uint64) string { - cpts := []interface{}{ChartResourceType} - if NamespaceID != 0 { - cpts = append(cpts, strconv.FormatUint(NamespaceID, 10)) +func RecordRbacResource(namespaceID uint64, moduleID uint64, id uint64) string { + cpts := []interface{}{RecordResourceType} + if namespaceID != 0 { + cpts = append(cpts, strconv.FormatUint(namespaceID, 10)) } else { cpts = append(cpts, "*") } - if ID != 0 { - cpts = append(cpts, strconv.FormatUint(ID, 10)) + if moduleID != 0 { + cpts = append(cpts, strconv.FormatUint(moduleID, 10)) } else { cpts = append(cpts, "*") } - return fmt.Sprintf(ChartRbacResourceTpl(), cpts...) + if id != 0 { + cpts = append(cpts, strconv.FormatUint(id, 10)) + } else { + cpts = append(cpts, "*") + } + + return fmt.Sprintf(RecordRbacResourceTpl(), cpts...) } -func ChartRbacResourceTpl() string { - return "%s/%s/%s" +func RecordRbacResourceTpl() string { + return "%s/%s/%s/%s" } // RbacResource returns string representation of RBAC resource for Component by calling ComponentRbacResource fn diff --git a/def/schema/component.cue b/def/schema/component.cue index 280cbbf98..6e85fe61f 100644 --- a/def/schema/component.cue +++ b/def/schema/component.cue @@ -4,23 +4,24 @@ import ( "strings" ) -#component: { - ident: #baseHandle - expIdent: #expIdent | *strings.ToTitle(ident) +#component: #_base & { + // copy field values from #_base + handle: handle, ident: ident, expIdent: expIdent + label: strings.ToTitle(ident) platform: #baseHandle resources: { - [key=_]: {handle: key, "component": ident, "platform": platform} & #resource + [key=_]: {"handle": key, "component": handle, "platform": platform} & #resource } + fqrn: platform + "::" + handle + // All known RBAC operations for this component rbac: #rbacComponent & { - resource: type: platform + "::" + ident - operations: { grant: { - description: "Manage \(ident) permissions" + description: "Manage \(handle) permissions" } } } diff --git a/def/schema/locale.cue b/def/schema/locale.cue index 974a59aa8..24ece587c 100644 --- a/def/schema/locale.cue +++ b/def/schema/locale.cue @@ -1,29 +1,58 @@ package schema import ( -// "strings" + "strings" + "list" ) #locale: { + resourceExpIdent: #expIdent + // @todo we need a better name here! skipSvc: bool | *false + extended: bool | *false + resource: { // @todo merge with RBAC res-ref and move 2 levels lower. references: [ ...string] | *["ID"] + type: string + const: string | *("\(resourceExpIdent)ResourceTranslationType") } keys: { [key=_]: #localeKey & { name: key + _resourceExpIdent: resourceExpIdent } } } #localeKey: { name: #handle - path: string | *(name) - custom?: true - customHandler?: string + _resourceExpIdent: #expIdent + + path: [...(#ident | { part: #ident, var: bool | *false })] | *([name]) + + expandedPath: [for p in path { + if (p & { "p": #ident }) != _|_ { p, var: p.var } + if (p & string) != _|_ { "part": p, var: false } + }] + + + _suffix: strings.Join([for p in expandedPath { strings.ToTitle(p.part) }], "") + + struct: string | *("LocaleKey" + _resourceExpIdent + _suffix) + + // As soon as we use vars in the path, + // custom handler must be present + _hasVars: list.Contains([for p in path { p.var | false }], true) + customHandler: bool | *_hasVars + + if customHandler { + decodeFunc: string | *("decodeTranslations" + _suffix) + encodeFunc: string | *("encodeTranslations" + _suffix) + serviceFunc: string | *("handle" + _resourceExpIdent + _suffix) + } } diff --git a/def/schema/platform.cue b/def/schema/platform.cue index f4c489f8a..f0901df4f 100644 --- a/def/schema/platform.cue +++ b/def/schema/platform.cue @@ -1,7 +1,7 @@ package schema #platform: { - ident: #baseHandle + ident: #baseHandle | *"corteza" components: [...{platform: ident} & #component] diff --git a/def/schema/rbac.cue b/def/schema/rbac.cue index f0228c20d..6d85a3146 100644 --- a/def/schema/rbac.cue +++ b/def/schema/rbac.cue @@ -10,32 +10,27 @@ import ( } operations: { - [key=_]: #rbacOperation & {handle: key} + [key=_]: #rbacOperation & { + handle: key + } } } #rbacResource: { - resource: { - type: string - expIdent: #expIdent - references: [ ...string] | *["ID"] - } + resourceExpIdent: #expIdent operations: { [key=_]: #rbacOperation & { handle: key - resourceExpIdent: resource.expIdent - description: string | *(strings.ToTitle(key) + " " + resource.type) + _resourceExpIdent: resourceExpIdent } } } #rbacOperation: { - handle: #handle - description: string - resourceExpIdent?: string - - _isComponent: resourceExpIdent == _|_ + handle: #handle + description: string | *handle + _resourceExpIdent?: string // Some string manipulation that will result in // more pronouncable access-control check function name @@ -51,11 +46,11 @@ import ( _opFlip: [_opSplit[len(_opSplit)-1]] + _opSplit[0:len(_opSplit)-1] _opFinal: strings.Replace(strings.ToTitle(strings.Join(_opFlip, " ")), " ", "", -1) - if _isComponent { + if _resourceExpIdent == _|_ { checkFuncName: #expIdent | *("Can" + _opFinal) } - if !_isComponent { - checkFuncName: #expIdent | *("Can" + _opFinal + resourceExpIdent) + if _resourceExpIdent != _|_ { + checkFuncName: #expIdent | *("Can" + _opFinal + _resourceExpIdent) } } diff --git a/def/schema/resource.cue b/def/schema/resource.cue index d290ce446..5a95e77a0 100644 --- a/def/schema/resource.cue +++ b/def/schema/resource.cue @@ -1,32 +1,38 @@ package schema -import ( - "strings" -) +#resource: #_base & { + // copy field values from #_base + handle: handle, ident: ident, expIdent: expIdent -#resource: { - handle: #baseHandle | *"unknown-resource" + component: #baseHandle | *"component" + platform: #baseHandle | *"corteza" - _words: strings.Replace(strings.Replace(strings.Replace(handle, "-", " ", -1), "_", " ", -1), ".", " ", -1) - - ident: #ident | *strings.ToCamel(strings.Replace(strings.ToTitle(_words), " ", "", -1)) - expIdent: #expIdent | *strings.Replace(strings.ToTitle(_words), " ", "", -1) - platform: #baseHandle | *"unknown-platform" - component: string | *"unknown-component" // Fully qualified resource name fqrn: string | *(platform + "::" + component + ":" + handle) - goType: string | *("types." + expIdent) - // fields: #Fields // operations: #Operations + // All parent resources + parents: [... #_base & { + // copy field values from #_base + handle: handle, ident: ident, expIdent: expIdent + + refField: #expIdent | *(expIdent + "ID") + param: #ident | *(ident + "ID") + }] + // All known RBAC operations for this resource rbac: #rbacResource & { + resourceExpIdent: expIdent + } + + locale?: #locale & { + resourceExpIdent: expIdent resource: { - type: fqrn - "expIdent": expIdent + // @todo can we merge this with RBAC type (FQRN?) + type: component + ":" + handle } } @@ -40,25 +46,25 @@ import ( // } } -#fields: { - // Each field can be - [key=_]: #fields | *({name: key} & #field) -} - -#field: { - name: #expIdent - unique: bool | *false - - // Golang type (built-in or other) - type: string | *"string" - - // System fields, - system: bool | *false - - if name =~ "At$" { - type: string | *"*time.Time" - } -} +//#fields: { +// // Each field can be +// [key=_]: #fields | *({name: key} & #field) +//} +// +//#field: { +// name: #expIdent +// unique: bool | *false +// +// // Golang type (built-in or other) +// type: string | *"string" +// +// // System fields, +// system: bool | *false +// +// if name =~ "At$" { +// type: string | *"*time.Time" +// } +//} //#Operations: { // [Operation=_]: {operation: Operation} & #Operation @@ -70,24 +76,24 @@ import ( // can: string | false | *"\(name)" //} -idField: { - // Expecting ID field to allways have name ID - name: "ID" - unique: true - - // Service fields, - // @todo We might want to have a better name for this - // service: true - - // @todo someday we'll replace this with the "ID" type - type: "uint64" -} - -handleField: { - // Expecting ID field to allways have name ID - name: "handle" - unique: true - - // @todo someday we'll replace this with the "ID" type - type: "string" & #handle -} +//idField: { +// // Expecting ID field to allways have name ID +// name: "ID" +// unique: true +// +// // Service fields, +// // @todo We might want to have a better name for this +// // service: true +// +// // @todo someday we'll replace this with the "ID" type +// type: "uint64" +//} +// +//handleField: { +// // Expecting ID field to allways have name ID +// name: "handle" +// unique: true +// +// // @todo someday we'll replace this with the "ID" type +// type: "string" & #handle +//} diff --git a/def/schema/shared.cue b/def/schema/shared.cue index 557d73ead..323d84df0 100644 --- a/def/schema/shared.cue +++ b/def/schema/shared.cue @@ -1,10 +1,14 @@ package schema -// Resource definition identifier +import ( + "strings" +) + +// Identifier #ident: =~"^[a-z][a-zA-Z0-9_]*$" // Exported identifier -#expIdent: =~"^[A-Z][a-zA-Z0-9]*$" +#expIdent: =~"^[A-Z][a-zA-Z0-9_]*$" // More liberal then identifier, allows underscores and dots #handle: =~"^[A-Za-z][a-zA-Z0-9_\\-\\.]*[a-zA-Z0-9]+$" @@ -12,3 +16,18 @@ package schema // More liberal then identifier, allows underscores and dots #baseHandle: =~"^[a-z][a-z0-9-]*[a-z0-9]+$" + +#_base: { + // lowercase dash-separated words + // used to build ident and exported identifiers + handle: #baseHandle | *"base" + _words: strings.Replace(strings.Replace(strings.Replace(handle, "-", " ", -1), "_", " ", -1), ".", " ", -1) + + // lowercased (unexported, golang) identifier + ident: #ident | *strings.ToCamel(strings.Replace(strings.ToTitle(_words), " ", "", -1)) + + // upercased (exported, golang) identifier + expIdent: #expIdent | *strings.Replace(strings.ToTitle(_words), " ", "", -1) + + ... +} diff --git a/pkg/codegen-v3/assets/templates/gocode/locale/types.go.tpl b/pkg/codegen-v3/assets/templates/gocode/locale/types.go.tpl deleted file mode 100644 index 05be93e59..000000000 --- a/pkg/codegen-v3/assets/templates/gocode/locale/types.go.tpl +++ /dev/null @@ -1,135 +0,0 @@ -package {{ .Package }} - -{{ template "header-gentext.tpl" }} -{{ template "header-definitions.tpl" . }} - -import ( - "fmt" - "strconv" - "github.com/cortezaproject/corteza-server/pkg/locale" -) - -type ( - LocaleKey struct { - Name string - Resource string - Path string - CustomHandler string - } -) - -// Types and stuff -const ( -{{- range .Def }} - {{ .Resource }}ResourceTranslationType = "{{ .Locale.ResourceType }}" -{{- end }} -) - -var ( -{{- range .Def }} -{{- $Resource := .Resource }} - {{- range .Locale.Keys}} - LocaleKey{{ $Resource }}{{coalesce (export .Name) (export .Path) }} = LocaleKey{ - Name: "{{.Name}}", - Resource: {{ $Resource }}ResourceTranslationType, - Path: "{{.Path }}",{{ if .CustomHandler }} - CustomHandler: "{{ .CustomHandler }}", - {{- end }} - } - {{- end}} -{{- end }} -) - -{{- range .Def }} -{{ $Resource := .Resource }} -{{ $GoType := printf "types.%s" .Resource }} - - -// ResourceTranslation returns string representation of Locale resource for {{ .Resource }} by calling {{ .Resource }}ResourceTranslation fn -// -// Locale resource is in "{{ .Locale.ResourceType }}/..." format -// -// This function is auto-generated -func (r {{ .Resource }}) ResourceTranslation() string { - return {{ .Resource }}ResourceTranslation({{ if .Locale.Resource }}{{ range .Locale.Resource.References }}r.{{ export .Field }},{{ end }}{{ end }}) -} - -// {{ .Resource }}ResourceTranslation returns string representation of Locale resource for {{ .Resource }} -// -// Locale resource is in the {{ .Locale.ResourceType }}/{{- if .Locale.Resource.References }}...{{ end }} format -// -// This function is auto-generated -func {{ .Resource }}ResourceTranslation({{ if .Locale.Resource }}{{ range .Locale.Resource.References }}{{ unexport .Field }} uint64,{{ end }}{{ end }}) string { - {{- if .Locale.Resource.References }} - cpts := []interface{{"{}"}}{{"{"}}{{ .Resource }}ResourceTranslationType{{"}"}} - cpts = append(cpts, {{range .Locale.Resource.References -}} - strconv.FormatUint({{ unexport .Field }}, 10), - {{- end }}) - - return fmt.Sprintf({{ .Resource }}ResourceTranslationTpl(), cpts...) - {{- end }} -} - -// @todo template -func {{ .Resource }}ResourceTranslationTpl() string { - {{- if .Locale.Resource.References }} - return "%s - {{- range .Locale.Resource.References }}/%s{{- end }}" - - {{- else }} - return "%s" - {{- end }} -} - -func (r *{{ .Resource }}) DecodeTranslations(tt locale.ResourceTranslationIndex) { - var aux *locale.ResourceTranslation - -{{- range .Locale.Keys}} -{{- if not .Custom }} - if aux = tt.FindByKey(LocaleKey{{ $Resource }}{{coalesce (export .Name) (export .Path) }}.Path); aux != nil { - r.{{ .Field }} = aux.Msg - } -{{- end}} -{{- end}} - -{{- range .Locale.Keys}} -{{- if and .Custom .CustomHandler }} - r.decodeTranslations{{export .CustomHandler }}(tt) -{{- end}} -{{- end}} - -{{- if .Locale.Extended }} - - r.decodeTranslations(tt) -{{- end }} -} - -func (r *{{ .Resource }}) EncodeTranslations() (out locale.ResourceTranslationSet) { - out = locale.ResourceTranslationSet{} -{{- range .Locale.Keys}} -{{- if not .Custom }} - if r.{{ .Field }} != "" { - out = append(out, &locale.ResourceTranslation{ - Resource: r.ResourceTranslation(), - Key: LocaleKey{{ $Resource }}{{coalesce (export .Name) (export .Path) }}.Path, - Msg: locale.SanitizeMessage(r.{{ .Field }}), - }) - } - -{{- end}} -{{- end}} - -{{range .Locale.Keys}} -{{- if and .Custom .CustomHandler }} - out = append(out, r.encodeTranslations{{export .CustomHandler}}()...) -{{- end}} -{{- end}} - -{{- if .Locale.Extended }} - out = append(out, r.encodeTranslations()...) -{{- end }} - - return out -} - -{{- end }} diff --git a/system/component.cue b/system/component.cue index d7d9e2b07..f50a08338 100644 --- a/system/component.cue +++ b/system/component.cue @@ -5,7 +5,7 @@ import ( ) component: schema.#component & { - ident: "system" + handle: "system" resources: { "apigw-route": apigwRoute diff --git a/system/service/access_control.gen.go b/system/service/access_control.gen.go index 4f9afe093..d5fc40d1e 100644 --- a/system/service/access_control.gen.go +++ b/system/service/access_control.gen.go @@ -56,182 +56,182 @@ func (svc accessControl) List() (out []map[string]string) { def := []map[string]string{ { "type": types.ApigwRouteResourceType, - "any": types.ApigwRouteRbacResource(0), + "any": types.ApigwRouteRbacResource(), "op": "read", }, { "type": types.ApigwRouteResourceType, - "any": types.ApigwRouteRbacResource(0), + "any": types.ApigwRouteRbacResource(), "op": "update", }, { "type": types.ApigwRouteResourceType, - "any": types.ApigwRouteRbacResource(0), + "any": types.ApigwRouteRbacResource(), "op": "delete", }, { "type": types.ApplicationResourceType, - "any": types.ApplicationRbacResource(0), + "any": types.ApplicationRbacResource(), "op": "read", }, { "type": types.ApplicationResourceType, - "any": types.ApplicationRbacResource(0), + "any": types.ApplicationRbacResource(), "op": "update", }, { "type": types.ApplicationResourceType, - "any": types.ApplicationRbacResource(0), + "any": types.ApplicationRbacResource(), "op": "delete", }, { "type": types.AuthClientResourceType, - "any": types.AuthClientRbacResource(0), + "any": types.AuthClientRbacResource(), "op": "read", }, { "type": types.AuthClientResourceType, - "any": types.AuthClientRbacResource(0), + "any": types.AuthClientRbacResource(), "op": "update", }, { "type": types.AuthClientResourceType, - "any": types.AuthClientRbacResource(0), + "any": types.AuthClientRbacResource(), "op": "delete", }, { "type": types.AuthClientResourceType, - "any": types.AuthClientRbacResource(0), + "any": types.AuthClientRbacResource(), "op": "authorize", }, { "type": types.QueueResourceType, - "any": types.QueueRbacResource(0), + "any": types.QueueRbacResource(), "op": "render", }, { "type": types.QueueResourceType, - "any": types.QueueRbacResource(0), + "any": types.QueueRbacResource(), "op": "read", }, { "type": types.QueueResourceType, - "any": types.QueueRbacResource(0), + "any": types.QueueRbacResource(), "op": "update", }, { "type": types.QueueResourceType, - "any": types.QueueRbacResource(0), + "any": types.QueueRbacResource(), "op": "delete", }, { "type": types.QueueResourceType, - "any": types.QueueRbacResource(0), + "any": types.QueueRbacResource(), "op": "queue.read", }, { "type": types.QueueResourceType, - "any": types.QueueRbacResource(0), + "any": types.QueueRbacResource(), "op": "queue.write", }, { "type": types.ReportResourceType, - "any": types.ReportRbacResource(0), + "any": types.ReportRbacResource(), "op": "read", }, { "type": types.ReportResourceType, - "any": types.ReportRbacResource(0), + "any": types.ReportRbacResource(), "op": "update", }, { "type": types.ReportResourceType, - "any": types.ReportRbacResource(0), + "any": types.ReportRbacResource(), "op": "delete", }, { "type": types.ReportResourceType, - "any": types.ReportRbacResource(0), + "any": types.ReportRbacResource(), "op": "run", }, { "type": types.RoleResourceType, - "any": types.RoleRbacResource(0), + "any": types.RoleRbacResource(), "op": "read", }, { "type": types.RoleResourceType, - "any": types.RoleRbacResource(0), + "any": types.RoleRbacResource(), "op": "update", }, { "type": types.RoleResourceType, - "any": types.RoleRbacResource(0), + "any": types.RoleRbacResource(), "op": "delete", }, { "type": types.RoleResourceType, - "any": types.RoleRbacResource(0), + "any": types.RoleRbacResource(), "op": "members.manage", }, { "type": types.TemplateResourceType, - "any": types.TemplateRbacResource(0), + "any": types.TemplateRbacResource(), "op": "read", }, { "type": types.TemplateResourceType, - "any": types.TemplateRbacResource(0), + "any": types.TemplateRbacResource(), "op": "update", }, { "type": types.TemplateResourceType, - "any": types.TemplateRbacResource(0), + "any": types.TemplateRbacResource(), "op": "delete", }, { "type": types.TemplateResourceType, - "any": types.TemplateRbacResource(0), + "any": types.TemplateRbacResource(), "op": "render", }, { "type": types.UserResourceType, - "any": types.UserRbacResource(0), + "any": types.UserRbacResource(), "op": "read", }, { "type": types.UserResourceType, - "any": types.UserRbacResource(0), + "any": types.UserRbacResource(), "op": "update", }, { "type": types.UserResourceType, - "any": types.UserRbacResource(0), + "any": types.UserRbacResource(), "op": "delete", }, { "type": types.UserResourceType, - "any": types.UserRbacResource(0), + "any": types.UserRbacResource(), "op": "suspend", }, { "type": types.UserResourceType, - "any": types.UserRbacResource(0), + "any": types.UserRbacResource(), "op": "unsuspend", }, { "type": types.UserResourceType, - "any": types.UserRbacResource(0), + "any": types.UserRbacResource(), "op": "email.unmask", }, { "type": types.UserResourceType, - "any": types.UserRbacResource(0), + "any": types.UserRbacResource(), "op": "name.unmask", }, { "type": types.UserResourceType, - "any": types.UserRbacResource(0), + "any": types.UserRbacResource(), "op": "impersonate", }, { @@ -1014,29 +1014,6 @@ func rbacApigwRouteResourceValidator(r string, oo ...string) error { } } - const sep = "/" - var ( - pp = strings.Split(strings.Trim(r[len(types.ApigwRouteResourceType):], sep), sep) - prc = []string{ - "ID", - } - ) - - if len(pp) != len(prc) { - return fmt.Errorf("invalid resource path structure") - } - - for i := 0; i < len(pp); i++ { - if pp[i] != "*" { - if i > 0 && pp[i-1] == "*" { - return fmt.Errorf("invalid path wildcard level (%d) for apigwRoute resource", i) - } - - if _, err := cast.ToUint64E(pp[i]); err != nil { - return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i]) - } - } - } return nil } @@ -1058,29 +1035,6 @@ func rbacApplicationResourceValidator(r string, oo ...string) error { } } - const sep = "/" - var ( - pp = strings.Split(strings.Trim(r[len(types.ApplicationResourceType):], sep), sep) - prc = []string{ - "ID", - } - ) - - if len(pp) != len(prc) { - return fmt.Errorf("invalid resource path structure") - } - - for i := 0; i < len(pp); i++ { - if pp[i] != "*" { - if i > 0 && pp[i-1] == "*" { - return fmt.Errorf("invalid path wildcard level (%d) for application resource", i) - } - - if _, err := cast.ToUint64E(pp[i]); err != nil { - return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i]) - } - } - } return nil } @@ -1102,29 +1056,6 @@ func rbacAuthClientResourceValidator(r string, oo ...string) error { } } - const sep = "/" - var ( - pp = strings.Split(strings.Trim(r[len(types.AuthClientResourceType):], sep), sep) - prc = []string{ - "ID", - } - ) - - if len(pp) != len(prc) { - return fmt.Errorf("invalid resource path structure") - } - - for i := 0; i < len(pp); i++ { - if pp[i] != "*" { - if i > 0 && pp[i-1] == "*" { - return fmt.Errorf("invalid path wildcard level (%d) for authClient resource", i) - } - - if _, err := cast.ToUint64E(pp[i]); err != nil { - return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i]) - } - } - } return nil } @@ -1146,29 +1077,6 @@ func rbacQueueResourceValidator(r string, oo ...string) error { } } - const sep = "/" - var ( - pp = strings.Split(strings.Trim(r[len(types.QueueResourceType):], sep), sep) - prc = []string{ - "ID", - } - ) - - if len(pp) != len(prc) { - return fmt.Errorf("invalid resource path structure") - } - - for i := 0; i < len(pp); i++ { - if pp[i] != "*" { - if i > 0 && pp[i-1] == "*" { - return fmt.Errorf("invalid path wildcard level (%d) for queue resource", i) - } - - if _, err := cast.ToUint64E(pp[i]); err != nil { - return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i]) - } - } - } return nil } @@ -1190,29 +1098,6 @@ func rbacReportResourceValidator(r string, oo ...string) error { } } - const sep = "/" - var ( - pp = strings.Split(strings.Trim(r[len(types.ReportResourceType):], sep), sep) - prc = []string{ - "ID", - } - ) - - if len(pp) != len(prc) { - return fmt.Errorf("invalid resource path structure") - } - - for i := 0; i < len(pp); i++ { - if pp[i] != "*" { - if i > 0 && pp[i-1] == "*" { - return fmt.Errorf("invalid path wildcard level (%d) for report resource", i) - } - - if _, err := cast.ToUint64E(pp[i]); err != nil { - return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i]) - } - } - } return nil } @@ -1234,29 +1119,6 @@ func rbacRoleResourceValidator(r string, oo ...string) error { } } - const sep = "/" - var ( - pp = strings.Split(strings.Trim(r[len(types.RoleResourceType):], sep), sep) - prc = []string{ - "ID", - } - ) - - if len(pp) != len(prc) { - return fmt.Errorf("invalid resource path structure") - } - - for i := 0; i < len(pp); i++ { - if pp[i] != "*" { - if i > 0 && pp[i-1] == "*" { - return fmt.Errorf("invalid path wildcard level (%d) for role resource", i) - } - - if _, err := cast.ToUint64E(pp[i]); err != nil { - return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i]) - } - } - } return nil } @@ -1278,29 +1140,6 @@ func rbacTemplateResourceValidator(r string, oo ...string) error { } } - const sep = "/" - var ( - pp = strings.Split(strings.Trim(r[len(types.TemplateResourceType):], sep), sep) - prc = []string{ - "ID", - } - ) - - if len(pp) != len(prc) { - return fmt.Errorf("invalid resource path structure") - } - - for i := 0; i < len(pp); i++ { - if pp[i] != "*" { - if i > 0 && pp[i-1] == "*" { - return fmt.Errorf("invalid path wildcard level (%d) for template resource", i) - } - - if _, err := cast.ToUint64E(pp[i]); err != nil { - return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i]) - } - } - } return nil } @@ -1322,29 +1161,6 @@ func rbacUserResourceValidator(r string, oo ...string) error { } } - const sep = "/" - var ( - pp = strings.Split(strings.Trim(r[len(types.UserResourceType):], sep), sep) - prc = []string{ - "ID", - } - ) - - if len(pp) != len(prc) { - return fmt.Errorf("invalid resource path structure") - } - - for i := 0; i < len(pp); i++ { - if pp[i] != "*" { - if i > 0 && pp[i-1] == "*" { - return fmt.Errorf("invalid path wildcard level (%d) for user resource", i) - } - - if _, err := cast.ToUint64E(pp[i]); err != nil { - return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i]) - } - } - } return nil } diff --git a/system/types/rbac.gen.go b/system/types/rbac.gen.go index a0e8d625c..ccb3413e5 100644 --- a/system/types/rbac.gen.go +++ b/system/types/rbac.gen.go @@ -41,28 +41,21 @@ const ( // // This function is auto-generated func (r ApigwRoute) RbacResource() string { - return ApigwRouteRbacResource(r.ID) + return ApigwRouteRbacResource() } // ApigwRouteRbacResource returns string representation of RBAC resource for ApigwRoute // -// RBAC resource is in the corteza::system:apigw-route/... format +// RBAC resource is in the corteza::system:apigw-route/ format // // This function is auto-generated -func ApigwRouteRbacResource(ID uint64) string { - cpts := []interface{}{ApigwRouteResourceType} - if ID != 0 { - cpts = append(cpts, strconv.FormatUint(ID, 10)) - } else { - cpts = append(cpts, "*") - } - - return fmt.Sprintf(ApigwRouteRbacResourceTpl(), cpts...) +func ApigwRouteRbacResource() string { + return ApigwRouteResourceType + "/" } func ApigwRouteRbacResourceTpl() string { - return "%s/%s" + return "%s" } // RbacResource returns string representation of RBAC resource for Application by calling ApplicationRbacResource fn @@ -71,28 +64,21 @@ func ApigwRouteRbacResourceTpl() string { // // This function is auto-generated func (r Application) RbacResource() string { - return ApplicationRbacResource(r.ID) + return ApplicationRbacResource() } // ApplicationRbacResource returns string representation of RBAC resource for Application // -// RBAC resource is in the corteza::system:application/... format +// RBAC resource is in the corteza::system:application/ format // // This function is auto-generated -func ApplicationRbacResource(ID uint64) string { - cpts := []interface{}{ApplicationResourceType} - if ID != 0 { - cpts = append(cpts, strconv.FormatUint(ID, 10)) - } else { - cpts = append(cpts, "*") - } - - return fmt.Sprintf(ApplicationRbacResourceTpl(), cpts...) +func ApplicationRbacResource() string { + return ApplicationResourceType + "/" } func ApplicationRbacResourceTpl() string { - return "%s/%s" + return "%s" } // RbacResource returns string representation of RBAC resource for AuthClient by calling AuthClientRbacResource fn @@ -101,28 +87,21 @@ func ApplicationRbacResourceTpl() string { // // This function is auto-generated func (r AuthClient) RbacResource() string { - return AuthClientRbacResource(r.ID) + return AuthClientRbacResource() } // AuthClientRbacResource returns string representation of RBAC resource for AuthClient // -// RBAC resource is in the corteza::system:auth-client/... format +// RBAC resource is in the corteza::system:auth-client/ format // // This function is auto-generated -func AuthClientRbacResource(ID uint64) string { - cpts := []interface{}{AuthClientResourceType} - if ID != 0 { - cpts = append(cpts, strconv.FormatUint(ID, 10)) - } else { - cpts = append(cpts, "*") - } - - return fmt.Sprintf(AuthClientRbacResourceTpl(), cpts...) +func AuthClientRbacResource() string { + return AuthClientResourceType + "/" } func AuthClientRbacResourceTpl() string { - return "%s/%s" + return "%s" } // RbacResource returns string representation of RBAC resource for Queue by calling QueueRbacResource fn @@ -131,28 +110,21 @@ func AuthClientRbacResourceTpl() string { // // This function is auto-generated func (r Queue) RbacResource() string { - return QueueRbacResource(r.ID) + return QueueRbacResource() } // QueueRbacResource returns string representation of RBAC resource for Queue // -// RBAC resource is in the corteza::system:queue/... format +// RBAC resource is in the corteza::system:queue/ format // // This function is auto-generated -func QueueRbacResource(ID uint64) string { - cpts := []interface{}{QueueResourceType} - if ID != 0 { - cpts = append(cpts, strconv.FormatUint(ID, 10)) - } else { - cpts = append(cpts, "*") - } - - return fmt.Sprintf(QueueRbacResourceTpl(), cpts...) +func QueueRbacResource() string { + return QueueResourceType + "/" } func QueueRbacResourceTpl() string { - return "%s/%s" + return "%s" } // RbacResource returns string representation of RBAC resource for Report by calling ReportRbacResource fn @@ -161,28 +133,21 @@ func QueueRbacResourceTpl() string { // // This function is auto-generated func (r Report) RbacResource() string { - return ReportRbacResource(r.ID) + return ReportRbacResource() } // ReportRbacResource returns string representation of RBAC resource for Report // -// RBAC resource is in the corteza::system:report/... format +// RBAC resource is in the corteza::system:report/ format // // This function is auto-generated -func ReportRbacResource(ID uint64) string { - cpts := []interface{}{ReportResourceType} - if ID != 0 { - cpts = append(cpts, strconv.FormatUint(ID, 10)) - } else { - cpts = append(cpts, "*") - } - - return fmt.Sprintf(ReportRbacResourceTpl(), cpts...) +func ReportRbacResource() string { + return ReportResourceType + "/" } func ReportRbacResourceTpl() string { - return "%s/%s" + return "%s" } // RbacResource returns string representation of RBAC resource for Role by calling RoleRbacResource fn @@ -191,28 +156,21 @@ func ReportRbacResourceTpl() string { // // This function is auto-generated func (r Role) RbacResource() string { - return RoleRbacResource(r.ID) + return RoleRbacResource() } // RoleRbacResource returns string representation of RBAC resource for Role // -// RBAC resource is in the corteza::system:role/... format +// RBAC resource is in the corteza::system:role/ format // // This function is auto-generated -func RoleRbacResource(ID uint64) string { - cpts := []interface{}{RoleResourceType} - if ID != 0 { - cpts = append(cpts, strconv.FormatUint(ID, 10)) - } else { - cpts = append(cpts, "*") - } - - return fmt.Sprintf(RoleRbacResourceTpl(), cpts...) +func RoleRbacResource() string { + return RoleResourceType + "/" } func RoleRbacResourceTpl() string { - return "%s/%s" + return "%s" } // RbacResource returns string representation of RBAC resource for Template by calling TemplateRbacResource fn @@ -221,28 +179,21 @@ func RoleRbacResourceTpl() string { // // This function is auto-generated func (r Template) RbacResource() string { - return TemplateRbacResource(r.ID) + return TemplateRbacResource() } // TemplateRbacResource returns string representation of RBAC resource for Template // -// RBAC resource is in the corteza::system:template/... format +// RBAC resource is in the corteza::system:template/ format // // This function is auto-generated -func TemplateRbacResource(ID uint64) string { - cpts := []interface{}{TemplateResourceType} - if ID != 0 { - cpts = append(cpts, strconv.FormatUint(ID, 10)) - } else { - cpts = append(cpts, "*") - } - - return fmt.Sprintf(TemplateRbacResourceTpl(), cpts...) +func TemplateRbacResource() string { + return TemplateResourceType + "/" } func TemplateRbacResourceTpl() string { - return "%s/%s" + return "%s" } // RbacResource returns string representation of RBAC resource for User by calling UserRbacResource fn @@ -251,28 +202,21 @@ func TemplateRbacResourceTpl() string { // // This function is auto-generated func (r User) RbacResource() string { - return UserRbacResource(r.ID) + return UserRbacResource() } // UserRbacResource returns string representation of RBAC resource for User // -// RBAC resource is in the corteza::system:user/... format +// RBAC resource is in the corteza::system:user/ format // // This function is auto-generated -func UserRbacResource(ID uint64) string { - cpts := []interface{}{UserResourceType} - if ID != 0 { - cpts = append(cpts, strconv.FormatUint(ID, 10)) - } else { - cpts = append(cpts, "*") - } - - return fmt.Sprintf(UserRbacResourceTpl(), cpts...) +func UserRbacResource() string { + return UserResourceType + "/" } func UserRbacResourceTpl() string { - return "%s/%s" + return "%s" } // RbacResource returns string representation of RBAC resource for Component by calling ComponentRbacResource fn