Merge branch '2022.3.x-feature-cuelang' into 2022.3.x
This commit is contained in:
@@ -27,7 +27,7 @@ jobs:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-go-
|
||||
- run: make test.all
|
||||
- run: make test.codegen test.all
|
||||
|
||||
snapshot-docker:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -132,14 +132,29 @@ watch.test.%: $(FSWATCH)
|
||||
|
||||
watch.test: watch.test.unit
|
||||
|
||||
# codegen: $(PROTOGEN)
|
||||
codegen: $(CODEGEN)
|
||||
# See codegen/README.md for details
|
||||
codegen: $(CUE) $(JSONTPLEXEC)
|
||||
$(CUE) eval codegen/*.cue --out json -e platform | $(JSONTPLEXEC) -v
|
||||
|
||||
test.codegen: $(CUE) $(JSONTPLEXEC)
|
||||
$(CUE) eval codegen/*.cue --out json -e platform
|
||||
|
||||
cue.fmt: $(CUE)
|
||||
$(CUE) fmt -v codegen/*.cue
|
||||
$(CUE) fmt -v codegen/schema/*.cue
|
||||
$(CUE) fmt -v app/*.cue
|
||||
$(CUE) fmt system/*.cue
|
||||
$(CUE) fmt compose/*.cue
|
||||
# $(CUE) fmt automation/*.cue
|
||||
# $(CUE) fmt federation/*.cue
|
||||
|
||||
codegen-legacy: $(CODEGEN)
|
||||
@ $(CODEGEN) -v
|
||||
|
||||
watch.codegen: $(CODEGEN)
|
||||
watch.codegen-legacy: $(CODEGEN)
|
||||
@ $(CODEGEN) -w -v
|
||||
|
||||
clean.codegen:
|
||||
clean.codegen-legacy:
|
||||
rm -f $(CODEGEN)
|
||||
|
||||
provision:
|
||||
|
||||
@@ -19,7 +19,9 @@ PROTOGEN_GRPC = $(GOPATH)/bin/protoc-gen-go-grpc
|
||||
GIN = $(GOPATH)/bin/gin
|
||||
STATIK = $(GOPATH)/bin/statik
|
||||
MODOUTDATED = $(GOPATH)/bin/go-mod-outdated
|
||||
CUE = $(GOPATH)/bin/cue
|
||||
CODEGEN = build/codegen
|
||||
JSONTPLEXEC = build/json-tpl-exec
|
||||
|
||||
PROTOC = /usr/local/bin/protoc
|
||||
FSWATCH = /usr/local/bin/fswatch
|
||||
@@ -60,6 +62,13 @@ $(MODOUTDATED):
|
||||
$(CODEGEN):
|
||||
$(GO) build -o $@ cmd/codegen/main.go
|
||||
|
||||
$(CUE):
|
||||
$(GOINSTALL) cuelang.org/go/cmd/cue@latest
|
||||
|
||||
$(JSONTPLEXEC):
|
||||
$(GO) build -o $@ ./codegen/tool
|
||||
|
||||
clean-tools:
|
||||
rm -f $(BINS)
|
||||
|
||||
#
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
"github.com/cortezaproject/corteza-server/system"
|
||||
"github.com/cortezaproject/corteza-server/compose"
|
||||
"github.com/cortezaproject/corteza-server/automation"
|
||||
"github.com/cortezaproject/corteza-server/federation"
|
||||
)
|
||||
|
||||
corteza: schema.#platform & {
|
||||
ident: "corteza"
|
||||
|
||||
components: [
|
||||
system.component,
|
||||
compose.component,
|
||||
automation.component,
|
||||
federation.component,
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package automation
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
component: schema.#component & {
|
||||
handle: "automation"
|
||||
|
||||
resources: {
|
||||
"workflow": workflow
|
||||
}
|
||||
|
||||
rbac: operations: {
|
||||
"grant": description: "Manage automation permissions"
|
||||
"workflow.create": description: "Create workflows"
|
||||
"triggers.search": description: "List, search or filter triggers"
|
||||
"sessions.search": description: "List, search or filter sessions"
|
||||
"workflows.search": description: "List, search or filter workflows"
|
||||
"resource-translations.manage": description: "List, search, create, or update resource translations"
|
||||
}
|
||||
}
|
||||
Generated
+29
-27
@@ -6,10 +6,6 @@ package service
|
||||
// the code is regenerated.
|
||||
//
|
||||
|
||||
// Definitions file that controls how this file is generated:
|
||||
// - automation.workflow.yaml
|
||||
// - automation.yaml
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
@@ -249,42 +245,48 @@ func (svc accessControl) CanManageSessionsOnWorkflow(ctx context.Context, r *typ
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanGrant(ctx context.Context) bool {
|
||||
return svc.can(ctx, "grant", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "grant", r)
|
||||
}
|
||||
|
||||
// CanCreateWorkflow checks if current user can create workflows
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanCreateWorkflow(ctx context.Context) bool {
|
||||
return svc.can(ctx, "workflow.create", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "workflow.create", r)
|
||||
}
|
||||
|
||||
// CanSearchTriggers checks if current user can list, search or filter triggers
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanSearchTriggers(ctx context.Context) bool {
|
||||
return svc.can(ctx, "triggers.search", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "triggers.search", r)
|
||||
}
|
||||
|
||||
// CanSearchSessions checks if current user can list, search or filter sessions
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanSearchSessions(ctx context.Context) bool {
|
||||
return svc.can(ctx, "sessions.search", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "sessions.search", r)
|
||||
}
|
||||
|
||||
// CanSearchWorkflows checks if current user can list, search or filter workflows
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanSearchWorkflows(ctx context.Context) bool {
|
||||
return svc.can(ctx, "workflows.search", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "workflows.search", r)
|
||||
}
|
||||
|
||||
// CanManageResourceTranslations checks if current user can list, search, create, or update resource translations
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanManageResourceTranslations(ctx context.Context) bool {
|
||||
return svc.can(ctx, "resource-translations.manage", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "resource-translations.manage", r)
|
||||
}
|
||||
|
||||
// rbacResourceValidator validates known component's resource by routing it to the appropriate validator
|
||||
@@ -330,24 +332,24 @@ func rbacResourceOperations(r string) map[string]bool {
|
||||
return nil
|
||||
}
|
||||
|
||||
// rbacWorkflowResourceValidator checks validity of rbac resource and operations
|
||||
// rbacWorkflowResourceValidator 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 rbacWorkflowResourceValidator(r string, oo ...string) error {
|
||||
defOps := rbacResourceOperations(r)
|
||||
for _, o := range oo {
|
||||
if !defOps[o] {
|
||||
return fmt.Errorf("invalid operation '%s' for automation Workflow resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(r, types.WorkflowResourceType) {
|
||||
// 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 workflow resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
const sep = "/"
|
||||
var (
|
||||
pp = strings.Split(strings.Trim(r[len(types.WorkflowResourceType):], sep), sep)
|
||||
@@ -363,7 +365,7 @@ func rbacWorkflowResourceValidator(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 resource path wildcard level (%d) for Workflow", i)
|
||||
return fmt.Errorf("invalid path wildcard level (%d) for workflow resource", i)
|
||||
}
|
||||
|
||||
if _, err := cast.ToUint64E(pp[i]); err != nil {
|
||||
@@ -374,23 +376,23 @@ func rbacWorkflowResourceValidator(r string, oo ...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// rbacComponentResourceValidator checks validity of rbac resource and operations
|
||||
// rbacComponentResourceValidator 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 rbacComponentResourceValidator(r string, oo ...string) error {
|
||||
defOps := rbacResourceOperations(r)
|
||||
for _, o := range oo {
|
||||
if !defOps[o] {
|
||||
return fmt.Errorf("invalid operation '%s' for automation resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(r, types.ComponentResourceType) {
|
||||
// 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 automation component resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Generated
+5
-6
@@ -6,10 +6,6 @@ package types
|
||||
// the code is regenerated.
|
||||
//
|
||||
|
||||
// Definitions file that controls how this file is generated:
|
||||
// - automation.workflow.yaml
|
||||
// - automation.yaml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
@@ -22,6 +18,11 @@ type (
|
||||
Component struct{}
|
||||
)
|
||||
|
||||
var (
|
||||
_ = fmt.Printf
|
||||
_ = strconv.FormatUint
|
||||
)
|
||||
|
||||
const (
|
||||
WorkflowResourceType = "corteza::automation:workflow"
|
||||
ComponentResourceType = "corteza::automation"
|
||||
@@ -53,7 +54,6 @@ func WorkflowRbacResource(id uint64) string {
|
||||
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func WorkflowRbacResourceTpl() string {
|
||||
return "%s/%s"
|
||||
}
|
||||
@@ -77,7 +77,6 @@ func ComponentRbacResource() string {
|
||||
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func ComponentRbacResourceTpl() string {
|
||||
return "%s"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package automation
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
workflow: schema.#resource & {
|
||||
rbac: {
|
||||
operations: {
|
||||
"read": description: "Read workflow"
|
||||
"update": description: "Update workflow"
|
||||
"delete": description: "Delete workflow"
|
||||
"undelete": description: "Undelete workflow"
|
||||
"execute": description: "Execute workflow"
|
||||
"triggers.manage": description: "Manage workflow triggers"
|
||||
"sessions.manage": description: "Manage workflow sessions"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
ignore: ["vendor/.*"]
|
||||
@@ -0,0 +1,81 @@
|
||||
# Corteza codegen tools and definitions
|
||||
|
||||
## History
|
||||
|
||||
See [old codegen](../pkh/codegen/README.md).
|
||||
|
||||
## Plans
|
||||
|
||||
Right now, Corteza is migrating its old YAML definitions to CUE.
|
||||
We are also simplifying all templates by moving as much data manipulation to Cue as possible.
|
||||
|
||||
## Intro
|
||||
|
||||
Codegen tools are based on [cuelang](https://cuelang.org/docs/tutorials/) and golang templates.
|
||||
|
||||
**What you can find here:**
|
||||
- [codegen definitions in `codegen/`](./)
|
||||
- [templates in `codegen/asset/templates`](./asset/templates)
|
||||
- [schemas in `codegen/schema`](./schema)
|
||||
- [template exec tool in `codegen/tool`](./tool)
|
||||
|
||||
Platform, component and resource definitions (.cue files) can be found in:
|
||||
- `app`
|
||||
- `automation` @todo
|
||||
- `system`
|
||||
- `compose`
|
||||
- `federation` @todo
|
||||
|
||||
## Running code generator
|
||||
|
||||
When a definitions or templates are changed all outputs need to be regenerated
|
||||
|
||||
This can be done with the following command
|
||||
```
|
||||
make codegen
|
||||
```
|
||||
Please note that
|
||||
|
||||
|
||||
## How does it work?
|
||||
|
||||
### High-level overview
|
||||
|
||||
See [Makefile's `codegen-cue` task](../Makefile)
|
||||
|
||||
1. evaluate codegen instructions (see [platform.cue](./platform.cue))
|
||||
2. output instructions as JSON
|
||||
3. pipe JSON into [template exec tool](./tool)
|
||||
4. process instructions, load and execute templates and write to output files.
|
||||
|
||||
### Definition structure
|
||||
|
||||
#### Codegen instructions
|
||||
|
||||
Collection of `#codegen` structs with template + payload + output instructions. Template exec tool iterates over collection and creates output from each one.
|
||||
|
||||
#### Platform
|
||||
|
||||
Main entry point that combines all components
|
||||
|
||||
- @todo options
|
||||
|
||||
- @todo REST endpoints (unrelated to specific component)
|
||||
|
||||
#### Component
|
||||
|
||||
Defines component, it's behaviour, RBAC operations and resources
|
||||
|
||||
- @todo REST endpoints (unrelated to specific resources)
|
||||
|
||||
#### Resource
|
||||
|
||||
Defines resource, it's behaviour, types, RBAC operations, translatable keys
|
||||
|
||||
- @todo events
|
||||
- @todo actions
|
||||
- @todo errors
|
||||
- @todo automation functions
|
||||
- @todo expression types
|
||||
- @todo REST endpoints
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package {{ .package }}
|
||||
|
||||
{{ template "gocode/header-gentext.tpl" }}
|
||||
|
||||
import (
|
||||
{{- range .imports }}
|
||||
{{ . }}
|
||||
{{- end }}
|
||||
)
|
||||
|
||||
{{- range .resources }}
|
||||
// {{ .rbacRefFunc }} generates RBAC references
|
||||
//
|
||||
// Resources with "envoy: false" are skipped
|
||||
//
|
||||
// This function is auto-generated
|
||||
func {{ .rbacRefFunc }}({{- range .references }}{{ .param }} string, {{- end }}) (res *Ref, pp []*Ref, err error) {
|
||||
{{- range .references }}
|
||||
{{- if eq .refField "ID" }}
|
||||
if {{ .param }} != "*" {
|
||||
res = &Ref{ResourceType: types.{{ .expIdent }}ResourceType, Identifiers: MakeIdentifiers({{ .param }})}
|
||||
}
|
||||
{{- else }}
|
||||
if {{ .param }} != "*" {
|
||||
pp = append(pp, &Ref{ResourceType: types.{{ .expIdent }}ResourceType, Identifiers: MakeIdentifiers({{ .param }})})
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
return
|
||||
}
|
||||
{{- end }}
|
||||
+13
-15
@@ -1,12 +1,11 @@
|
||||
package {{ .Package }}
|
||||
package {{ .package }}
|
||||
|
||||
{{ template "header-gentext.tpl" }}
|
||||
{{ template "header-definitions.tpl" . }}
|
||||
{{ template "gocode/header-gentext.tpl" }}
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
{{- range .Imports }}
|
||||
{{- range .imports }}
|
||||
{{ . }}
|
||||
{{- end }}
|
||||
)
|
||||
@@ -45,23 +44,22 @@ func ParseRule(res string) (string, *Ref, []*Ref, error) {
|
||||
|
||||
// make the resource provide the slice of parent resources we should nest under
|
||||
switch resourceType {
|
||||
{{- range .Def }}
|
||||
case {{ unexport .Component "types" }}.{{ export .Resource }}ResourceType:
|
||||
if len(path) != {{ len .RBAC.Resource.References }} {
|
||||
return "", nil, nil, fmt.Errorf("expecting {{ len .RBAC.Resource.References }} reference components in path, got %d", len(path))
|
||||
{{- range .resources }}
|
||||
case {{ .typeConst }}:
|
||||
if len(path) != {{ len .references }} {
|
||||
return "", nil, nil, fmt.Errorf("expecting {{ len .references }} reference components in path, got %d", len(path))
|
||||
}
|
||||
{{- if gt (len .RBAC.Resource.References) 0 }}
|
||||
ref, pp, err := {{ export .Component .Resource }}RbacReferences(
|
||||
{{- range $i, $r := .RBAC.Resource.References }}
|
||||
// {{ unexport $r.Resource }}
|
||||
{{- if gt (len .references) 0 }}
|
||||
ref, pp, err := {{ .rbacRefFunc }}(
|
||||
{{- range $i, $r := .references }}
|
||||
path[{{ $i }}],
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
)
|
||||
return {{ unexport .Component "types" }}.{{ export .Resource }}ResourceType, ref, pp, err
|
||||
return resourceType, ref, pp, err
|
||||
{{ else }}
|
||||
|
||||
// Component resource, no path
|
||||
return {{ unexport .Component "types" }}.{{ export .Resource }}ResourceType, nil, nil, nil
|
||||
return resourceType, nil, nil, nil
|
||||
{{- end }}
|
||||
{{- end}}
|
||||
}
|
||||
+6
-12
@@ -1,27 +1,20 @@
|
||||
package {{ .Package }}
|
||||
package {{ .package }}
|
||||
|
||||
{{ template "header-gentext.tpl" }}
|
||||
{{ template "header-definitions.tpl" . }}
|
||||
{{ template "gocode/header-gentext.tpl" }}
|
||||
|
||||
import (
|
||||
systemTypes "github.com/cortezaproject/corteza-server/system/types"
|
||||
{{- range .Imports }}
|
||||
{{ . }}
|
||||
{{- end }}
|
||||
)
|
||||
|
||||
{{- range .Def }}
|
||||
{{ $Component := .Component }}
|
||||
{{ $Resource := .Resource }}
|
||||
{{ $GoType := printf "types.%s" .Resource }}
|
||||
func (r *{{if not (eq $Component "system")}}{{export $Component}}{{ end }}{{$Resource}}) EncodeTranslations() ([]*ResourceTranslation, error) {
|
||||
{{- range .resources }}
|
||||
func (r *{{ .expIdent }}) EncodeTranslations() ([]*ResourceTranslation, error) {
|
||||
out := make([]*ResourceTranslation, 0, 10)
|
||||
|
||||
rr := r.Res.EncodeTranslations()
|
||||
rr.SetLanguage(defaultLanguage)
|
||||
res, ref, pp := r.ResourceTranslationParts()
|
||||
out = append(out, NewResourceTranslation(systemTypes.FromLocale(rr), res, ref, pp...))
|
||||
{{ if .Locale.Extended }}
|
||||
{{ if .extended }}
|
||||
tmp, err := r.encodeTranslations()
|
||||
return append(out, tmp...), err
|
||||
{{ else }}
|
||||
@@ -29,3 +22,4 @@ func (r *{{if not (eq $Component "system")}}{{export $Component}}{{ end }}{{$Res
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
+13
-17
@@ -1,18 +1,17 @@
|
||||
package {{ .Package }}
|
||||
package {{ .package }}
|
||||
|
||||
{{ template "header-gentext.tpl" }}
|
||||
{{ template "header-definitions.tpl" . }}
|
||||
{{ template "gocode/header-gentext.tpl" }}
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
{{- range .Imports }}
|
||||
{{- range .imports }}
|
||||
{{ . }}
|
||||
{{- end }}
|
||||
)
|
||||
|
||||
|
||||
// Parse generates resource setting logic for each resource
|
||||
// ParseResourceTranslation generates resource setting logic for each resource
|
||||
//
|
||||
// Resources with "envoy: false" are skipped
|
||||
//
|
||||
@@ -47,25 +46,22 @@ func ParseResourceTranslation(res string) (string, *Ref, []*Ref, error) {
|
||||
|
||||
// make the resource provide the slice of parent resources we should nest under
|
||||
switch resourceType {
|
||||
{{- range .Def }}
|
||||
case {{ unexport .Component "types" }}.{{ export .Resource }}ResourceTranslationType:
|
||||
if len(path) != {{ len .Locale.Resource.References }} {
|
||||
return "", nil, nil, fmt.Errorf("expecting {{ len .Locale.Resource.References }} reference components in path, got %d", len(path))
|
||||
{{- range .resources }}
|
||||
case {{ .typeConst }}:
|
||||
if len(path) != {{ len .references }} {
|
||||
return "", nil, nil, fmt.Errorf("expecting {{ len .references }} reference components in path, got %d", len(path))
|
||||
}
|
||||
{{- if gt (len .Locale.Resource.References) 0 }}
|
||||
ref, pp, err := {{ export .Component .Resource }}ResourceTranslationReferences(
|
||||
{{- range $i, $r := .Locale.Resource.References }}
|
||||
// {{ unexport $r.Resource }}
|
||||
ref, pp, err := {{ .resTrRefFunc }}(
|
||||
{{- range $i, $r := .references }}
|
||||
path[{{ $i }}],
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
)
|
||||
return {{ unexport .Component "types" }}.{{ export .Resource }}ResourceTranslationType, ref, pp, err
|
||||
return {{ .typeConst }}, ref, pp, err
|
||||
{{ else }}
|
||||
|
||||
// Component resource, no path
|
||||
return {{ unexport .Component "types" }}.{{ export .Resource }}ResourceTranslationType, nil, nil, nil
|
||||
return {{ .typeConst }}, nil, nil, nil
|
||||
{{- end }}
|
||||
{{- end}}
|
||||
}
|
||||
|
||||
// return unhandled resource as-is
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package {{ .package }}
|
||||
|
||||
{{ template "gocode/header-gentext.tpl" }}
|
||||
|
||||
import (
|
||||
{{- range .imports }}
|
||||
{{ . }}
|
||||
{{- end }}
|
||||
)
|
||||
|
||||
{{- range .resources }}
|
||||
// {{ .resTrRefFunc }} generates Locale references
|
||||
//
|
||||
// This function is auto-generated
|
||||
func {{ .resTrRefFunc }}({{- range .references }}{{ .param }} string, {{- end }} self string) (res *Ref, pp []*Ref, err error) {
|
||||
res = &Ref{ResourceType: types.{{ .expIdent }}ResourceType, Identifiers: MakeIdentifiers(self)}
|
||||
|
||||
{{- range .references }}
|
||||
pp = append(pp, &Ref{ResourceType: types.{{ .expIdent }}ResourceType, Identifiers: MakeIdentifiers({{ .param }})})
|
||||
{{- end }}
|
||||
|
||||
return
|
||||
}
|
||||
{{- end }}
|
||||
+26
-36
@@ -1,12 +1,11 @@
|
||||
package {{ .Package }}
|
||||
package {{ .package }}
|
||||
|
||||
{{ template "header-gentext.tpl" }}
|
||||
{{ template "header-definitions.tpl" . }}
|
||||
{{ template "gocode/header-gentext.tpl" }}
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
{{- range .Imports }}
|
||||
{{- range .imports }}
|
||||
{{ . }}
|
||||
{{- end }}
|
||||
"github.com/cortezaproject/corteza-server/pkg/actionlog"
|
||||
@@ -36,8 +35,8 @@ type (
|
||||
}
|
||||
|
||||
ResourceTranslationsManagerService interface {
|
||||
{{- range .Def }}
|
||||
{{ .Resource }}(ctx context.Context, {{ if .Locale.Resource }}{{ range .Locale.Resource.References }}{{ .Field }} uint64, {{ end }}{{ end }}) (locale.ResourceTranslationSet, error)
|
||||
{{- range .resources }}
|
||||
{{ .expIdent }}(ctx context.Context, {{ range .references }}{{ . }} uint64, {{ end }}) (locale.ResourceTranslationSet, error)
|
||||
{{- end }}
|
||||
|
||||
Upsert(context.Context, locale.ResourceTranslationSet) error
|
||||
@@ -103,7 +102,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
|
||||
@@ -127,50 +126,41 @@ func (svc resourceTranslationsManager) Locale() locale.Resource {
|
||||
return svc.locale
|
||||
}
|
||||
|
||||
{{- range .Def }}
|
||||
{{ $Resource := .Resource }}
|
||||
{{ $GoType := printf "types.%s" .Resource }}
|
||||
{{- range .resources }}
|
||||
|
||||
func (svc resourceTranslationsManager) {{ .Resource }}(ctx context.Context, {{ if .Locale.Resource }}{{ range .Locale.Resource.References }}{{ .Field }} uint64, {{ end }}{{ end }}) (locale.ResourceTranslationSet, error) {
|
||||
func (svc resourceTranslationsManager) {{ .expIdent }}(ctx context.Context, {{ range .references }}{{ . }} uint64, {{ end }}) (locale.ResourceTranslationSet, error) {
|
||||
var (
|
||||
err error
|
||||
out locale.ResourceTranslationSet
|
||||
res *{{ $GoType }}
|
||||
res *types.{{ .expIdent }}
|
||||
k types.LocaleKey
|
||||
)
|
||||
|
||||
res, err = svc.load{{$Resource}}(ctx, svc.store, {{ if .Locale.Resource }}{{ range .Locale.Resource.References }}{{ .Field }}, {{ end }}{{ end }})
|
||||
res, err = svc.load{{ .expIdent }}(ctx, svc.store, {{ range .references }}{{ . }}, {{ end }})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, tag := range svc.locale.Tags() {
|
||||
{{- range .Locale.Keys}}
|
||||
{{- if not .Custom }}
|
||||
k = types.LocaleKey{{ $Resource }}{{coalesce (export .Name) (export .Path) }}
|
||||
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}}
|
||||
|
||||
{{- range .Locale.Keys}}
|
||||
{{- if and .Custom .CustomHandler }}
|
||||
auxResSet, err = svc.{{unexport $Resource}}{{export .CustomHandler}}Handler(ctx, tag, res, k.Path)
|
||||
{{- 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}}
|
||||
{{- end}}
|
||||
}
|
||||
|
||||
{{- if .Locale.Extended }}
|
||||
|
||||
tmp, err := svc.{{unexport $Resource}}Extended(ctx, res)
|
||||
return append(out, tmp...), err
|
||||
{{- else }}
|
||||
return out, nil
|
||||
{{- end }}
|
||||
{{ if .extended }}
|
||||
tmp, err := svc.{{ .ident }}Extended(ctx, res)
|
||||
return append(out, tmp...), err
|
||||
{{- else }}
|
||||
return out, nil
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
{{- end }}
|
||||
@@ -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({{ range .references }}r.{{ .refField }},{{ 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({{ range .references }}{{ .refField }} uint64,{{ end }}) string {
|
||||
{{- if .references }}
|
||||
cpts := []interface{{"{}"}}{
|
||||
{{ .expIdent }}ResourceTranslationType,
|
||||
{{- range .references }}
|
||||
strconv.FormatUint({{ .refField }}, 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 }}
|
||||
+58
-86
@@ -1,7 +1,6 @@
|
||||
package {{ .Package }}
|
||||
package {{ .package }}
|
||||
|
||||
{{ template "header-gentext.tpl" }}
|
||||
{{ template "header-definitions.tpl" . }}
|
||||
{{ template "gocode/header-gentext.tpl" }}
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -10,7 +9,7 @@ import (
|
||||
"context"
|
||||
"github.com/cortezaproject/corteza-server/pkg/rbac"
|
||||
"github.com/cortezaproject/corteza-server/pkg/actionlog"
|
||||
{{- range .Imports }}
|
||||
{{- range .imports }}
|
||||
{{ . }}
|
||||
{{- end }}
|
||||
)
|
||||
@@ -26,7 +25,6 @@ type (
|
||||
FindRulesByRoleID(roleID uint64) (rr rbac.RuleSet)
|
||||
CloneRulesByRoleID(ctx context.Context, fromRoleID uint64, toRoleID ...uint64) error
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
@@ -56,17 +54,13 @@ func (svc accessControl) Effective(ctx context.Context, rr ... rbac.Resource) (e
|
||||
|
||||
func (svc accessControl) List() (out []map[string]string) {
|
||||
def := []map[string]string{
|
||||
{{- range .Def }}
|
||||
{{- $Resource := .Resource }}
|
||||
{{- $RbacResource := .RBAC.Resource }}
|
||||
{{- range .RBAC.Operations }}
|
||||
{{- range .operations }}
|
||||
{
|
||||
"type": types.{{ coalesce $Resource }}ResourceType,
|
||||
"any": types.{{ coalesce $Resource }}RbacResource({{ range $RbacResource.References }}0,{{ end }}),
|
||||
"op": {{ printf "%q" .Operation }},
|
||||
"type": {{ .const }},
|
||||
"any": {{ .resFunc }}({{ range .references }}0,{{ end }}),
|
||||
"op": {{ printf "%q" .op }},
|
||||
},
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
func(svc interface{}) {
|
||||
@@ -143,42 +137,24 @@ func (svc accessControl) CloneRulesByRoleID(ctx context.Context, fromRoleID uint
|
||||
return svc.rbac.CloneRulesByRoleID(ctx, fromRoleID, toRoleID...)
|
||||
}
|
||||
|
||||
{{- range .Def }}
|
||||
{{ $GoType := printf "types.%s" (.Resource) }}
|
||||
|
||||
{{ if .IsComponentResource }}
|
||||
|
||||
{{- range .RBAC.Operations }}
|
||||
// {{ export .CanFnName }} checks if current user can {{ lower .Description }}
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) {{ export .CanFnName }}(ctx context.Context) bool {
|
||||
return svc.can(ctx, {{ printf "%q" .Operation }}, &types.Component{})
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{ else }}
|
||||
{{- range .RBAC.Operations }}
|
||||
// {{ export .CanFnName }} checks if current user can {{ lower .Description }}
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) {{ export .CanFnName }}(ctx context.Context, r * {{ $GoType }}) bool {
|
||||
return svc.can(ctx, {{ printf "%q" .Operation }}, r)
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{ end }}
|
||||
{{- range .operations }}
|
||||
// {{ .checkFuncName }} checks if current user can {{ lower .description }}
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) {{ .checkFuncName }}(ctx context.Context{{ if not .component }}, r *{{ .goType }}{{ end }}) bool {
|
||||
{{- if .component }}r := &{{ .goType }}{}{{ end }}
|
||||
return svc.can(ctx, {{ printf "%q" .op }}, r)
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
|
||||
// rbacResourceValidator validates known component's resource by routing it to the appropriate validator
|
||||
//
|
||||
// This function is auto-generated
|
||||
func rbacResourceValidator(r string, oo ...string) error {
|
||||
switch rbac.ResourceType(r) {
|
||||
{{- range .Def }}
|
||||
case types.{{ coalesce .Resource }}ResourceType:
|
||||
return rbac{{ .Resource }}ResourceValidator(r, oo...)
|
||||
{{- range .validation }}
|
||||
case {{ .const }}:
|
||||
return {{ .funcName }}(r, oo...)
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
@@ -190,11 +166,11 @@ func rbacResourceValidator(r string, oo ...string) error {
|
||||
// This function is auto-generated
|
||||
func rbacResourceOperations(r string) map[string]bool {
|
||||
switch rbac.ResourceType(r) {
|
||||
{{- range .Def }}
|
||||
case types.{{ coalesce .Resource }}ResourceType:
|
||||
{{- range .validation }}
|
||||
case {{ .const }}:
|
||||
return map[string]bool{
|
||||
{{- range .RBAC.Operations }}
|
||||
{{ printf "%q" .Operation }}: true,
|
||||
{{- range .operations }}
|
||||
{{ printf "%q" . }}: true,
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
@@ -203,57 +179,53 @@ func rbacResourceOperations(r string) map[string]bool {
|
||||
return nil
|
||||
}
|
||||
|
||||
{{- range .Def }}
|
||||
{{- range .validation }}
|
||||
|
||||
{{ $Resource := .Resource }}
|
||||
{{ $GoType := printf "types.%s" (.Resource) }}
|
||||
|
||||
// rbac{{ .Resource }}ResourceValidator checks validity of rbac resource and operations
|
||||
// {{ .funcName }} 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 rbac{{ .Resource }}ResourceValidator(r string, oo ...string) error {
|
||||
defOps := rbacResourceOperations(r)
|
||||
for _, o := range oo {
|
||||
if !defOps[o] {
|
||||
return fmt.Errorf("invalid operation '%s' for {{ .Component }}{{ if not .IsComponentResource }} {{ .Resource }}{{end }} resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(r, {{ $GoType }}ResourceType) {
|
||||
func {{ .funcName }}(r string, oo ...string) error {
|
||||
if !strings.HasPrefix(r, {{ .const }}) {
|
||||
// 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 {{ .label }} resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
{{ if .RBAC.Resource.References }}
|
||||
const sep = "/"
|
||||
var (
|
||||
pp = strings.Split(strings.Trim(r[len({{ $GoType }}ResourceType):], sep), sep)
|
||||
prc = []string{
|
||||
{{- range .RBAC.Resource.References }}
|
||||
{{ printf "%q" .Field }},
|
||||
{{ if .references }}
|
||||
const sep = "/"
|
||||
var (
|
||||
pp = strings.Split(strings.Trim(r[len({{ .const }}):], sep), sep)
|
||||
prc = []string{
|
||||
{{- range .references }}
|
||||
{{ printf "%q" . }},
|
||||
{{- end }}
|
||||
}
|
||||
)
|
||||
|
||||
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 {{ .label }} resource", i)
|
||||
}
|
||||
|
||||
if _, err := cast.ToUint64E(pp[i]); err != nil {
|
||||
return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
}
|
||||
)
|
||||
|
||||
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 resource path wildcard level (%d) for {{ .Resource }}", i)
|
||||
}
|
||||
|
||||
if _, err := cast.ToUint64E(pp[i]); err != nil {
|
||||
return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
return nil
|
||||
}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,78 @@
|
||||
package {{ .package }}
|
||||
|
||||
{{ template "gocode/header-gentext.tpl" }}
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type (
|
||||
// Component struct serves as a virtual resource type for the {{ .cmpIdent }} component
|
||||
//
|
||||
// This struct is auto-generated
|
||||
Component struct {}
|
||||
)
|
||||
|
||||
var (
|
||||
{{/*
|
||||
making sure that generated code does not break
|
||||
when these packages are not used
|
||||
*/}}
|
||||
_ = fmt.Printf
|
||||
_ = strconv.FormatUint
|
||||
)
|
||||
|
||||
const (
|
||||
{{- range .types }}
|
||||
{{ .const }} = {{ printf "%q" .type }}
|
||||
{{- end }}
|
||||
)
|
||||
|
||||
|
||||
{{- range .types }}
|
||||
|
||||
// RbacResource returns string representation of RBAC resource for {{ .goType }} by calling {{ .resFunc }} fn
|
||||
//
|
||||
// RBAC resource is in the {{ .type }}/... format
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (r {{ .goType }}) RbacResource() string {
|
||||
return {{ .resFunc }}({{ if not .component }}{{ range .references }}r.{{ .refField }},{{ end }}{{ end }})
|
||||
}
|
||||
|
||||
// {{ .resFunc }} returns string representation of RBAC resource for {{ .goType }}
|
||||
//
|
||||
// RBAC resource is in the {{ .type }}/{{- if .references }}...{{ end }} format
|
||||
//
|
||||
// This function is auto-generated
|
||||
func {{ .resFunc }}({{ if not .component }}{{ range .references }}{{ .param }} uint64,{{ end }}{{ end }}) string {
|
||||
{{- if .references }}
|
||||
cpts := []interface{{"{}"}}{{"{"}}{{ .goType }}ResourceType{{"}"}}
|
||||
{{- range .references }}
|
||||
if {{ .param }} != 0 {
|
||||
cpts = append(cpts, strconv.FormatUint({{ .param }}, 10))
|
||||
} else {
|
||||
cpts = append(cpts, "*")
|
||||
}
|
||||
|
||||
{{ end }}
|
||||
return fmt.Sprintf({{ .tplFunc }}(), cpts...)
|
||||
{{- else }}
|
||||
return {{ .goType }}ResourceType + "/"
|
||||
{{- end }}
|
||||
|
||||
}
|
||||
|
||||
func {{ .tplFunc }}() string {
|
||||
{{- if .references }}
|
||||
return "%s
|
||||
{{- range .references }}/%s{{- end }}"
|
||||
|
||||
{{- else }}
|
||||
return "%s"
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
{{- end }}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/app"
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
// "strings"
|
||||
)
|
||||
|
||||
envoyRBAC:
|
||||
[...schema.#codegen] &
|
||||
[
|
||||
for cmp in app.corteza.components {
|
||||
template: "gocode/envoy/rbac_references_$component.go.tpl"
|
||||
output: "pkg/envoy/resource/rbac_references_\(cmp.ident).gen.go"
|
||||
payload: {
|
||||
package: "resource"
|
||||
imports: [
|
||||
"\"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\"",
|
||||
]
|
||||
|
||||
resources: [
|
||||
for res in cmp.resources {
|
||||
rbacRefFunc: "\(cmp.expIdent)\(res.expIdent)RbacReferences"
|
||||
references: [
|
||||
for p in res.parents {p},
|
||||
{param: res.ident, refField: "ID", expIdent: res.expIdent},
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
]+
|
||||
[
|
||||
{
|
||||
template: "gocode/envoy/rbac_rules_parse.go.tpl"
|
||||
output: "pkg/envoy/resource/rbac_rules_parse.gen.go"
|
||||
payload: {
|
||||
package: "resource"
|
||||
imports: [
|
||||
for cmp in app.corteza.components {
|
||||
"\(cmp.ident)Types \"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\""
|
||||
},
|
||||
]
|
||||
|
||||
resources: [
|
||||
for cmp in app.corteza.components for res in cmp.resources {
|
||||
importAlias: "\(cmp.ident)Types"
|
||||
expIdent: res.expIdent
|
||||
|
||||
typeConst: "\(importAlias).\(expIdent)ResourceType"
|
||||
rbacRefFunc: "\(cmp.expIdent)\(res.expIdent)RbacReferences"
|
||||
references: [
|
||||
for p in res.parents {p},
|
||||
{param: res.ident, refField: "ID", expIdent: res.expIdent},
|
||||
]
|
||||
},
|
||||
|
||||
for cmp in app.corteza.components {
|
||||
importAlias: "\(cmp.ident)Types"
|
||||
expIdent: cmp.expIdent
|
||||
|
||||
typeConst: "\(importAlias).ComponentResourceType"
|
||||
references: []
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
]+
|
||||
[
|
||||
{
|
||||
template: "gocode/envoy/resource_translation.go.tpl"
|
||||
output: "pkg/envoy/resource/resource_translation.gen.go"
|
||||
payload: {
|
||||
package: "resource"
|
||||
resources: [
|
||||
for cmp in app.corteza.components for res in cmp.resources if res.locale != _|_ {
|
||||
expIdent: "\(cmp.expIdent)\(res.expIdent)"
|
||||
extended: res.locale.extended
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
]+
|
||||
[
|
||||
{
|
||||
template: "gocode/envoy/resource_translation_parse.go.tpl"
|
||||
output: "pkg/envoy/resource/resource_translation_parse.gen.go"
|
||||
payload: {
|
||||
package: "resource"
|
||||
imports: [
|
||||
for cmp in app.corteza.components for res in cmp.resources if res.locale != _|_ {
|
||||
"\(cmp.ident)Types \"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\""
|
||||
},
|
||||
]
|
||||
|
||||
resources: [
|
||||
for cmp in app.corteza.components for res in cmp.resources if res.locale != _|_ {
|
||||
importAlias: "\(cmp.ident)Types"
|
||||
typeConst: "\(importAlias).\(res.expIdent)ResourceTranslationType"
|
||||
resTrRefFunc: "\(cmp.expIdent)\(res.expIdent)ResourceTranslationReferences"
|
||||
references: [
|
||||
for p in res.parents {p},
|
||||
{param: res.ident, refField: "ID", expIdent: res.expIdent},
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
]+
|
||||
[
|
||||
// wrapped with additional for loop to trim out templates with empty types list
|
||||
for tpl in [
|
||||
for cmp in app.corteza.components {
|
||||
template: "gocode/envoy/resource_translation_references_$component.go.tpl"
|
||||
output: "pkg/envoy/resource/resource_translation_references_\(cmp.ident).gen.go"
|
||||
payload: {
|
||||
package: "resource"
|
||||
imports: [
|
||||
"\"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\"",
|
||||
]
|
||||
|
||||
resources: [
|
||||
for res in cmp.resources if res.locale != _|_ {
|
||||
resTrRefFunc: "\(cmp.expIdent)\(res.expIdent)ResourceTranslationReferences"
|
||||
expIdent: res.expIdent
|
||||
references: [
|
||||
for p in res.parents {p},
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
] if len(tpl.payload.resources) > 0 {tpl}]+
|
||||
[]
|
||||
@@ -0,0 +1,43 @@
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/app"
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
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/$component_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 p in res.parents {p}, {param: "id", refField: "ID"}]
|
||||
|
||||
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}]
|
||||
@@ -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/$component_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 p in res.parents {p}, {param: "id", refField: "ID"}]
|
||||
|
||||
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}]
|
||||
@@ -0,0 +1,17 @@
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
// 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+
|
||||
envoyRBAC+
|
||||
[] // placeholder
|
||||
@@ -0,0 +1,62 @@
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
"github.com/cortezaproject/corteza-server/app"
|
||||
)
|
||||
|
||||
rbacAccessControl:
|
||||
[...schema.#codegen] &
|
||||
[
|
||||
for cmp in app.corteza.components {
|
||||
template: "gocode/rbac/$component_access_control.go.tpl"
|
||||
output: "\(cmp.ident)/service/access_control.gen.go"
|
||||
payload: {
|
||||
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"
|
||||
resFunc: "types.\(res.expIdent)RbacResource"
|
||||
goType: "types.\(res.expIdent)"
|
||||
description: op.description
|
||||
checkFuncName: op.checkFuncName
|
||||
|
||||
references: [ for p in res.parents {p}, {param: "id", refField: "ID"}]
|
||||
},
|
||||
for op in cmp.rbac.operations {
|
||||
"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: [ 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}]
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,42 @@
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/app"
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
rbacTypes:
|
||||
[...schema.#codegen] &
|
||||
[
|
||||
for cmp in app.corteza.components {
|
||||
template: "gocode/rbac/$component_types.go.tpl"
|
||||
output: "\(cmp.ident)/types/rbac.gen.go"
|
||||
payload: {
|
||||
package: "types"
|
||||
|
||||
cmpIdent: cmp.ident
|
||||
// Operation/resource validators, grouped by resource
|
||||
types: [
|
||||
for res in cmp.resources {
|
||||
const: "\(res.expIdent)ResourceType"
|
||||
type: res.fqrn
|
||||
resFunc: "\(res.expIdent)RbacResource"
|
||||
tplFunc: "\(res.expIdent)RbacResourceTpl"
|
||||
attFunc: "\(res.expIdent)RbacAttributes"
|
||||
goType: res.expIdent
|
||||
|
||||
references: [ for p in res.parents {p}, {param: "id", refField: "ID"}]
|
||||
},
|
||||
{
|
||||
const: "ComponentResourceType"
|
||||
type: cmp.fqrn
|
||||
resFunc: "ComponentRbacResource"
|
||||
tplFunc: "ComponentRbacResourceTpl"
|
||||
attFunc: "ComponentRbacAttributes"
|
||||
goType: "Component"
|
||||
component: true
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,13 @@
|
||||
package schema
|
||||
|
||||
#codegen: {
|
||||
template: string
|
||||
output: string
|
||||
|
||||
syntax: "go"
|
||||
if output =~ "\\.adoc" {
|
||||
syntax: "adoc"
|
||||
}
|
||||
|
||||
payload: _
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
#component: #_base & {
|
||||
// copy field values from #_base
|
||||
handle: handle, ident: ident, expIdent: expIdent
|
||||
|
||||
label: strings.ToTitle(ident)
|
||||
platform: #baseHandle
|
||||
|
||||
resources: {
|
||||
[key=_]: {"handle": key, "component": handle, "platform": platform} & #resource
|
||||
}
|
||||
|
||||
fqrn: platform + "::" + handle
|
||||
|
||||
// All known RBAC operations for this component
|
||||
rbac: #rbacComponent & {
|
||||
operations: {
|
||||
grant: {
|
||||
description: "Manage \(handle) permissions"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"list"
|
||||
)
|
||||
|
||||
#locale: {
|
||||
resourceExpIdent: #expIdent
|
||||
|
||||
// @todo we need a better name here!
|
||||
skipSvc: bool | *false
|
||||
|
||||
extended: bool | *false
|
||||
|
||||
resource: {
|
||||
type: string
|
||||
const: string | *("\(resourceExpIdent)ResourceTranslationType")
|
||||
}
|
||||
|
||||
keys: {
|
||||
[key=_]: #localeKey & {
|
||||
name: key
|
||||
_resourceExpIdent: resourceExpIdent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#localeKey: {
|
||||
name: #handle
|
||||
_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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package schema
|
||||
|
||||
#platform: {
|
||||
ident: #baseHandle | *"corteza"
|
||||
|
||||
components: [...{platform: ident} & #component]
|
||||
|
||||
// env-var definitions
|
||||
// options: {}
|
||||
|
||||
//
|
||||
|
||||
// automation: {
|
||||
// types: ....
|
||||
// function ....
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
#rbacComponent: {
|
||||
resource: {
|
||||
type: string
|
||||
}
|
||||
|
||||
operations: {
|
||||
[key=_]: #rbacOperation & {
|
||||
handle: key
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#rbacResource: {
|
||||
resourceExpIdent: #expIdent
|
||||
|
||||
operations: {
|
||||
[key=_]: #rbacOperation & {
|
||||
handle: key
|
||||
_resourceExpIdent: resourceExpIdent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#rbacOperation: {
|
||||
handle: #handle
|
||||
description: string | *handle
|
||||
_resourceExpIdent?: string
|
||||
|
||||
// Some string manipulation that will result in
|
||||
// more pronouncable access-control check function name
|
||||
|
||||
// When check function name is not explicitly defined we try
|
||||
// to use resource and operation name and generate easy-to-read name
|
||||
//
|
||||
// <res> + <op> => Can<Op><Res>
|
||||
// <res> + <op:foo.bar.verb> => Can<Verb><Foo><Bar>On<Res>
|
||||
|
||||
_operation: strings.Replace(strings.Replace(handle, "-", " ", -1), "_", " ", -1)
|
||||
_opSplit: strings.Split(_operation, ".")
|
||||
|
||||
_opFlip: [_opSplit[len(_opSplit)-1]] + _opSplit[0:len(_opSplit)-1]
|
||||
_opFinal: strings.Replace(strings.ToTitle(strings.Join(_opFlip, " ")), " ", "", -1)
|
||||
|
||||
if _resourceExpIdent == _|_ {
|
||||
checkFuncName: #expIdent | *"Can\(_opFinal)"
|
||||
}
|
||||
|
||||
if len(_opSplit) > 1 && _resourceExpIdent != _|_ {
|
||||
checkFuncName: #expIdent | *"Can\(_opFinal)On\(_resourceExpIdent)"
|
||||
}
|
||||
|
||||
if len(_opSplit) <= 1 && _resourceExpIdent != _|_ {
|
||||
checkFuncName: #expIdent | *"Can\(_opFinal)\(_resourceExpIdent)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package schema
|
||||
|
||||
#resource: #_base & {
|
||||
// copy field values from #_base
|
||||
handle: handle, ident: ident, expIdent: expIdent
|
||||
|
||||
component: #baseHandle | *"component"
|
||||
platform: #baseHandle | *"corteza"
|
||||
|
||||
// Fully qualified resource name
|
||||
fqrn: string | *(platform + "::" + component + ":" + handle)
|
||||
|
||||
// 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: {
|
||||
// @todo can we merge this with RBAC type (FQRN?)
|
||||
type: component + ":" + handle
|
||||
}
|
||||
}
|
||||
|
||||
// List of known keys for resource translation
|
||||
// locale?: {
|
||||
// [Name=_]: {
|
||||
// name: Name & #Handle
|
||||
// path: string
|
||||
// custom: bool | *false
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
//#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
|
||||
//}
|
||||
|
||||
//#Operation: {
|
||||
// name: #ExpIdent
|
||||
// description: string
|
||||
// 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
|
||||
//}
|
||||
@@ -0,0 +1,32 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Identifier
|
||||
#ident: =~"^[a-z][a-zA-Z0-9_]*$"
|
||||
|
||||
// Exported identifier
|
||||
#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]+$"
|
||||
|
||||
// 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)
|
||||
|
||||
...
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"text/template"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/cli"
|
||||
)
|
||||
|
||||
type (
|
||||
task struct {
|
||||
Template string `json:"template"`
|
||||
Output string `json:"output"`
|
||||
Syntax string `json:"syntax"`
|
||||
Payload interface{} `json:"payload"`
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
verbose bool
|
||||
showHelp bool
|
||||
tplRootPath string
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.BoolVar(&showHelp, "h", false, "show help")
|
||||
flag.BoolVar(&verbose, "v", false, "be verbose")
|
||||
flag.StringVar(&tplRootPath, "p", "codegen/assets/templates", "location of the template files")
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
// Takes JSON input with codegen tasks and definitions and generates files
|
||||
func main() {
|
||||
if showHelp {
|
||||
flag.PrintDefaults()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
var (
|
||||
input = json.NewDecoder(os.Stdin)
|
||||
tasks = make([]*task, 0)
|
||||
tpl *template.Template
|
||||
err error
|
||||
)
|
||||
|
||||
print("Waiting for stdin ...\n")
|
||||
if err = input.Decode(&tasks); err != nil {
|
||||
cli.HandleError(fmt.Errorf("failed to decode input from standard input: %v", err))
|
||||
}
|
||||
|
||||
if tpl, err = LoadTemplates(BaseTemplate(), tplRootPath); err != nil {
|
||||
cli.HandleError(fmt.Errorf("failed to load templates: %v", err))
|
||||
}
|
||||
|
||||
for _, j := range tasks {
|
||||
switch j.Syntax {
|
||||
case "go":
|
||||
print(fmt.Sprintf("generating %s (from %s) ...", j.Output, j.Template))
|
||||
if err = GoTemplate(j.Output, tpl.Lookup(j.Template), j.Payload); err != nil {
|
||||
cli.HandleError(fmt.Errorf("failed to write template: %v", err))
|
||||
}
|
||||
print("done\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func print(msg string) {
|
||||
if verbose {
|
||||
_, _ = fmt.Fprint(os.Stderr, msg)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package tpl
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -8,63 +8,15 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/Masterminds/sprig"
|
||||
)
|
||||
|
||||
type (
|
||||
Wrap struct {
|
||||
Package string
|
||||
|
||||
// will be set when grouping definitions by component
|
||||
Component string
|
||||
|
||||
Imports []string
|
||||
Def interface{}
|
||||
}
|
||||
)
|
||||
|
||||
var nonIdentChars = regexp.MustCompile(`[\s\\/\-.]+`)
|
||||
|
||||
func Export(pp ...string) (out string) {
|
||||
for _, p := range pp {
|
||||
if len(p) > 1 {
|
||||
p = strings.ToUpper(p[:1]) + p[1:]
|
||||
}
|
||||
|
||||
if ss := nonIdentChars.Split(p, -1); len(ss) > 1 {
|
||||
p = Export(ss...)
|
||||
}
|
||||
|
||||
out = out + p
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func Unexport(pp ...string) (out string) {
|
||||
out = Export(pp...)
|
||||
if len(out) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if out == "ID" {
|
||||
return "id"
|
||||
}
|
||||
|
||||
return strings.ToLower(out[:1]) + out[1:]
|
||||
}
|
||||
|
||||
func BaseTemplate() *template.Template {
|
||||
return template.New("").
|
||||
Funcs(sprig.TxtFuncMap()).
|
||||
Funcs(map[string]interface{}{
|
||||
"export": Export,
|
||||
"unexport": Unexport,
|
||||
})
|
||||
Funcs(sprig.TxtFuncMap())
|
||||
}
|
||||
|
||||
func LoadTemplates(rTpl *template.Template, rootDir string) (*template.Template, error) {
|
||||
@@ -72,6 +24,10 @@ func LoadTemplates(rTpl *template.Template, rootDir string) (*template.Template,
|
||||
pfx := len(cleanRoot) + 1
|
||||
|
||||
return rTpl, filepath.Walk(cleanRoot, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if info.IsDir() || !strings.HasSuffix(path, ".tpl") || err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -88,7 +44,7 @@ func LoadTemplates(rTpl *template.Template, rootDir string) (*template.Template,
|
||||
})
|
||||
}
|
||||
|
||||
func GoTemplate(dst string, tpl *template.Template, payload Wrap) (err error) {
|
||||
func GoTemplate(dst string, tpl *template.Template, payload interface{}) (err error) {
|
||||
var output io.WriteCloser
|
||||
buf := bytes.Buffer{}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
chart: schema.#resource & {
|
||||
parents: [
|
||||
{handle: "namespace"},
|
||||
]
|
||||
|
||||
rbac: {
|
||||
operations: {
|
||||
"read": {}
|
||||
"update": {}
|
||||
"delete": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
component: schema.#component & {
|
||||
handle: "compose"
|
||||
|
||||
resources: {
|
||||
"chart": chart
|
||||
"module": module
|
||||
"module-field": moduleField
|
||||
"namespace": namespace
|
||||
"page": page
|
||||
"record": record
|
||||
}
|
||||
|
||||
rbac: operations: {
|
||||
"settings.read": description: "Read settings"
|
||||
"settings.manage": description: "Manage settings"
|
||||
"namespace.create": description: "Create namespace"
|
||||
"namespaces.search": description: "List, search or filter namespaces"
|
||||
"resource-translations.manage": description: "List, search, create, or update resource translations"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
moduleField: schema.#resource & {
|
||||
parents: [
|
||||
{handle: "namespace"},
|
||||
{handle: "module"},
|
||||
]
|
||||
|
||||
rbac: {
|
||||
operations: {
|
||||
"record.value.read": description: "Read field value on records"
|
||||
"record.value.update": description: "Update field value on records"
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
module: schema.#resource & {
|
||||
handle: "module"
|
||||
parents: [
|
||||
{handle: "namespace"},
|
||||
]
|
||||
|
||||
rbac: {
|
||||
operations: {
|
||||
"read": {}
|
||||
"update": {}
|
||||
"delete": {}
|
||||
"record.create": description: "Create record"
|
||||
"records.search": description: "List, search or filter records"
|
||||
}
|
||||
}
|
||||
|
||||
locale: {
|
||||
keys: {
|
||||
"name": {}
|
||||
}
|
||||
}
|
||||
|
||||
//locale:
|
||||
// resource:
|
||||
// references: [ namespace, ID ]
|
||||
//
|
||||
// extended: true
|
||||
// keys:
|
||||
// - name
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
namespace: schema.#resource & {
|
||||
rbac: {
|
||||
operations: {
|
||||
"read": {}
|
||||
"update": {}
|
||||
"delete": {}
|
||||
"manage": description: "Access to namespace admin panel"
|
||||
"module.create": description: "Create module on namespace"
|
||||
"modules.search": description: "List, search or filter module on namespace"
|
||||
"chart.create": description: "Create chart on namespace"
|
||||
"charts.search": description: "List, search or filter chart on namespace"
|
||||
"page.create": description: "Create page on namespace"
|
||||
"pages.search": description: "List, search or filter pages on namespace"
|
||||
}
|
||||
}
|
||||
|
||||
locale: {
|
||||
resource: references: [ "ID"]
|
||||
|
||||
keys: {
|
||||
name: {}
|
||||
metaSubtitle: {
|
||||
path: ["meta", "subtitle"]
|
||||
}
|
||||
metaDescription: {
|
||||
path: ["meta", "description"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
page: schema.#resource & {
|
||||
parents: [
|
||||
{handle: "namespace"},
|
||||
]
|
||||
|
||||
rbac: {
|
||||
operations: {
|
||||
"read": {}
|
||||
"update": {}
|
||||
"delete": {}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
record: schema.#resource & {
|
||||
parents: [
|
||||
{handle: "namespace"},
|
||||
{handle: "module"},
|
||||
]
|
||||
|
||||
rbac: {
|
||||
operations: {
|
||||
"read": {}
|
||||
"update": {}
|
||||
"delete": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,8 +51,8 @@ type (
|
||||
CanCreateRecordOnModule(context.Context, *types.Module) bool
|
||||
CanReadRecord(context.Context, *types.Record) bool
|
||||
|
||||
CanReadRecordValue(context.Context, *types.ModuleField) bool
|
||||
CanUpdateRecordValue(context.Context, *types.ModuleField) bool
|
||||
CanReadRecordValueOnModuleField(context.Context, *types.ModuleField) bool
|
||||
CanUpdateRecordValueOnModuleField(context.Context, *types.ModuleField) bool
|
||||
}
|
||||
)
|
||||
|
||||
@@ -196,8 +196,8 @@ func (ctrl Module) makeFieldsPayload(ctx context.Context, m *types.Module) (out
|
||||
out[i] = &moduleFieldPayload{
|
||||
ModuleField: f,
|
||||
|
||||
CanReadRecordValue: ctrl.ac.CanReadRecordValue(ctx, f),
|
||||
CanUpdateRecordValue: ctrl.ac.CanUpdateRecordValue(ctx, f),
|
||||
CanReadRecordValue: ctrl.ac.CanReadRecordValueOnModuleField(ctx, f),
|
||||
CanUpdateRecordValue: ctrl.ac.CanUpdateRecordValueOnModuleField(ctx, f),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Generated
+162
-165
@@ -6,15 +6,6 @@ package service
|
||||
// the code is regenerated.
|
||||
//
|
||||
|
||||
// Definitions file that controls how this file is generated:
|
||||
// - compose.chart.yaml
|
||||
// - compose.module-field.yaml
|
||||
// - compose.module.yaml
|
||||
// - compose.namespace.yaml
|
||||
// - compose.page.yaml
|
||||
// - compose.record.yaml
|
||||
// - compose.yaml
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
@@ -78,16 +69,6 @@ func (svc accessControl) List() (out []map[string]string) {
|
||||
"any": types.ChartRbacResource(0, 0),
|
||||
"op": "delete",
|
||||
},
|
||||
{
|
||||
"type": types.ModuleFieldResourceType,
|
||||
"any": types.ModuleFieldRbacResource(0, 0, 0),
|
||||
"op": "record.value.read",
|
||||
},
|
||||
{
|
||||
"type": types.ModuleFieldResourceType,
|
||||
"any": types.ModuleFieldRbacResource(0, 0, 0),
|
||||
"op": "record.value.update",
|
||||
},
|
||||
{
|
||||
"type": types.ModuleResourceType,
|
||||
"any": types.ModuleRbacResource(0, 0),
|
||||
@@ -113,6 +94,16 @@ func (svc accessControl) List() (out []map[string]string) {
|
||||
"any": types.ModuleRbacResource(0, 0),
|
||||
"op": "records.search",
|
||||
},
|
||||
{
|
||||
"type": types.ModuleFieldResourceType,
|
||||
"any": types.ModuleFieldRbacResource(0, 0, 0),
|
||||
"op": "record.value.read",
|
||||
},
|
||||
{
|
||||
"type": types.ModuleFieldResourceType,
|
||||
"any": types.ModuleFieldRbacResource(0, 0, 0),
|
||||
"op": "record.value.update",
|
||||
},
|
||||
{
|
||||
"type": types.NamespaceResourceType,
|
||||
"any": types.NamespaceRbacResource(0),
|
||||
@@ -296,56 +287,42 @@ func (svc accessControl) CloneRulesByRoleID(ctx context.Context, fromRoleID uint
|
||||
return svc.rbac.CloneRulesByRoleID(ctx, fromRoleID, toRoleID...)
|
||||
}
|
||||
|
||||
// CanReadChart checks if current user can read chart
|
||||
// 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 chart
|
||||
// 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 chart
|
||||
// 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)
|
||||
}
|
||||
|
||||
// CanReadRecordValue checks if current user can read field value on records
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanReadRecordValue(ctx context.Context, r *types.ModuleField) bool {
|
||||
return svc.can(ctx, "record.value.read", r)
|
||||
}
|
||||
|
||||
// CanUpdateRecordValue checks if current user can update field value on records
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanUpdateRecordValue(ctx context.Context, r *types.ModuleField) bool {
|
||||
return svc.can(ctx, "record.value.update", r)
|
||||
}
|
||||
|
||||
// CanReadModule checks if current user can read module
|
||||
// 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 module
|
||||
// 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 module
|
||||
// CanDeleteModule checks if current user can delete
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanDeleteModule(ctx context.Context, r *types.Module) bool {
|
||||
@@ -366,21 +343,35 @@ func (svc accessControl) CanSearchRecordsOnModule(ctx context.Context, r *types.
|
||||
return svc.can(ctx, "records.search", r)
|
||||
}
|
||||
|
||||
// CanReadNamespace checks if current user can read namespace
|
||||
// CanReadRecordValueOnModuleField checks if current user can read field value on records
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanReadRecordValueOnModuleField(ctx context.Context, r *types.ModuleField) bool {
|
||||
return svc.can(ctx, "record.value.read", r)
|
||||
}
|
||||
|
||||
// CanUpdateRecordValueOnModuleField checks if current user can update field value on records
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanUpdateRecordValueOnModuleField(ctx context.Context, r *types.ModuleField) bool {
|
||||
return svc.can(ctx, "record.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 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 namespace
|
||||
// CanDeleteNamespace checks if current user can delete
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanDeleteNamespace(ctx context.Context, r *types.Namespace) bool {
|
||||
@@ -436,42 +427,42 @@ func (svc accessControl) CanSearchPagesOnNamespace(ctx context.Context, r *types
|
||||
return svc.can(ctx, "pages.search", r)
|
||||
}
|
||||
|
||||
// CanReadPage checks if current user can read 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 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 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)
|
||||
}
|
||||
|
||||
// CanReadRecord checks if current user can read record
|
||||
// CanReadRecord checks if current user can read
|
||||
//
|
||||
// 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 record
|
||||
// CanUpdateRecord checks if current user can update
|
||||
//
|
||||
// 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 record
|
||||
// CanDeleteRecord checks if current user can delete
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanDeleteRecord(ctx context.Context, r *types.Record) bool {
|
||||
@@ -482,42 +473,48 @@ func (svc accessControl) CanDeleteRecord(ctx context.Context, r *types.Record) b
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanGrant(ctx context.Context) bool {
|
||||
return svc.can(ctx, "grant", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "grant", r)
|
||||
}
|
||||
|
||||
// CanReadSettings checks if current user can read settings
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanReadSettings(ctx context.Context) bool {
|
||||
return svc.can(ctx, "settings.read", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "settings.read", r)
|
||||
}
|
||||
|
||||
// CanManageSettings checks if current user can manage settings
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanManageSettings(ctx context.Context) bool {
|
||||
return svc.can(ctx, "settings.manage", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "settings.manage", r)
|
||||
}
|
||||
|
||||
// CanCreateNamespace checks if current user can create namespace
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanCreateNamespace(ctx context.Context) bool {
|
||||
return svc.can(ctx, "namespace.create", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "namespace.create", r)
|
||||
}
|
||||
|
||||
// CanSearchNamespaces checks if current user can list, search or filter namespaces
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanSearchNamespaces(ctx context.Context) bool {
|
||||
return svc.can(ctx, "namespaces.search", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "namespaces.search", r)
|
||||
}
|
||||
|
||||
// CanManageResourceTranslations checks if current user can list, search, create, or update resource translations
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanManageResourceTranslations(ctx context.Context) bool {
|
||||
return svc.can(ctx, "resource-translations.manage", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "resource-translations.manage", r)
|
||||
}
|
||||
|
||||
// rbacResourceValidator validates known component's resource by routing it to the appropriate validator
|
||||
@@ -527,10 +524,10 @@ func rbacResourceValidator(r string, oo ...string) error {
|
||||
switch rbac.ResourceType(r) {
|
||||
case types.ChartResourceType:
|
||||
return rbacChartResourceValidator(r, oo...)
|
||||
case types.ModuleFieldResourceType:
|
||||
return rbacModuleFieldResourceValidator(r, oo...)
|
||||
case types.ModuleResourceType:
|
||||
return rbacModuleResourceValidator(r, oo...)
|
||||
case types.ModuleFieldResourceType:
|
||||
return rbacModuleFieldResourceValidator(r, oo...)
|
||||
case types.NamespaceResourceType:
|
||||
return rbacNamespaceResourceValidator(r, oo...)
|
||||
case types.PageResourceType:
|
||||
@@ -555,11 +552,6 @@ func rbacResourceOperations(r string) map[string]bool {
|
||||
"update": true,
|
||||
"delete": true,
|
||||
}
|
||||
case types.ModuleFieldResourceType:
|
||||
return map[string]bool{
|
||||
"record.value.read": true,
|
||||
"record.value.update": true,
|
||||
}
|
||||
case types.ModuleResourceType:
|
||||
return map[string]bool{
|
||||
"read": true,
|
||||
@@ -568,6 +560,11 @@ func rbacResourceOperations(r string) map[string]bool {
|
||||
"record.create": true,
|
||||
"records.search": true,
|
||||
}
|
||||
case types.ModuleFieldResourceType:
|
||||
return map[string]bool{
|
||||
"record.value.read": true,
|
||||
"record.value.update": true,
|
||||
}
|
||||
case types.NamespaceResourceType:
|
||||
return map[string]bool{
|
||||
"read": true,
|
||||
@@ -607,29 +604,29 @@ func rbacResourceOperations(r string) map[string]bool {
|
||||
return nil
|
||||
}
|
||||
|
||||
// rbacChartResourceValidator 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 rbacChartResourceValidator(r string, oo ...string) error {
|
||||
defOps := rbacResourceOperations(r)
|
||||
for _, o := range oo {
|
||||
if !defOps[o] {
|
||||
return fmt.Errorf("invalid operation '%s' for compose Chart resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
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",
|
||||
"NamespaceID",
|
||||
"ID",
|
||||
}
|
||||
)
|
||||
@@ -641,7 +638,7 @@ func rbacChartResourceValidator(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 resource path wildcard level (%d) for Chart", i)
|
||||
return fmt.Errorf("invalid path wildcard level (%d) for chart resource", i)
|
||||
}
|
||||
|
||||
if _, err := cast.ToUint64E(pp[i]); err != nil {
|
||||
@@ -652,75 +649,29 @@ func rbacChartResourceValidator(r string, oo ...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// rbacModuleFieldResourceValidator 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 rbacModuleFieldResourceValidator(r string, oo ...string) error {
|
||||
defOps := rbacResourceOperations(r)
|
||||
for _, o := range oo {
|
||||
if !defOps[o] {
|
||||
return fmt.Errorf("invalid operation '%s' for compose ModuleField resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(r, types.ModuleFieldResourceType) {
|
||||
// expecting resource to always include path
|
||||
return fmt.Errorf("invalid resource type")
|
||||
}
|
||||
|
||||
const sep = "/"
|
||||
var (
|
||||
pp = strings.Split(strings.Trim(r[len(types.ModuleFieldResourceType):], sep), sep)
|
||||
prc = []string{
|
||||
"namespaceID",
|
||||
"moduleID",
|
||||
"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 resource path wildcard level (%d) for ModuleField", i)
|
||||
}
|
||||
|
||||
if _, err := cast.ToUint64E(pp[i]); err != nil {
|
||||
return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// rbacModuleResourceValidator checks validity of rbac resource and operations
|
||||
// rbacModuleResourceValidator 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 rbacModuleResourceValidator(r string, oo ...string) error {
|
||||
defOps := rbacResourceOperations(r)
|
||||
for _, o := range oo {
|
||||
if !defOps[o] {
|
||||
return fmt.Errorf("invalid operation '%s' for compose Module resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(r, types.ModuleResourceType) {
|
||||
// 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 module resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
const sep = "/"
|
||||
var (
|
||||
pp = strings.Split(strings.Trim(r[len(types.ModuleResourceType):], sep), sep)
|
||||
prc = []string{
|
||||
"namespaceID",
|
||||
"NamespaceID",
|
||||
"ID",
|
||||
}
|
||||
)
|
||||
@@ -732,7 +683,7 @@ func rbacModuleResourceValidator(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 resource path wildcard level (%d) for Module", i)
|
||||
return fmt.Errorf("invalid path wildcard level (%d) for module resource", i)
|
||||
}
|
||||
|
||||
if _, err := cast.ToUint64E(pp[i]); err != nil {
|
||||
@@ -743,24 +694,70 @@ func rbacModuleResourceValidator(r string, oo ...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// rbacNamespaceResourceValidator checks validity of rbac resource and operations
|
||||
// rbacModuleFieldResourceValidator 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 rbacModuleFieldResourceValidator(r string, oo ...string) error {
|
||||
if !strings.HasPrefix(r, types.ModuleFieldResourceType) {
|
||||
// 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 moduleField resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
const sep = "/"
|
||||
var (
|
||||
pp = strings.Split(strings.Trim(r[len(types.ModuleFieldResourceType):], sep), sep)
|
||||
prc = []string{
|
||||
"NamespaceID",
|
||||
"ModuleID",
|
||||
"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 moduleField resource", i)
|
||||
}
|
||||
|
||||
if _, err := cast.ToUint64E(pp[i]); err != nil {
|
||||
return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
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 {
|
||||
defOps := rbacResourceOperations(r)
|
||||
for _, o := range oo {
|
||||
if !defOps[o] {
|
||||
return fmt.Errorf("invalid operation '%s' for compose Namespace resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
const sep = "/"
|
||||
var (
|
||||
pp = strings.Split(strings.Trim(r[len(types.NamespaceResourceType):], sep), sep)
|
||||
@@ -776,7 +773,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 resource path wildcard level (%d) for Namespace", i)
|
||||
return fmt.Errorf("invalid path wildcard level (%d) for namespace resource", i)
|
||||
}
|
||||
|
||||
if _, err := cast.ToUint64E(pp[i]); err != nil {
|
||||
@@ -787,29 +784,29 @@ func rbacNamespaceResourceValidator(r string, oo ...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// rbacPageResourceValidator checks validity of rbac resource and operations
|
||||
// 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 {
|
||||
defOps := rbacResourceOperations(r)
|
||||
for _, o := range oo {
|
||||
if !defOps[o] {
|
||||
return fmt.Errorf("invalid operation '%s' for compose Page resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
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",
|
||||
"NamespaceID",
|
||||
"ID",
|
||||
}
|
||||
)
|
||||
@@ -821,7 +818,7 @@ func rbacPageResourceValidator(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 resource path wildcard level (%d) for Page", i)
|
||||
return fmt.Errorf("invalid path wildcard level (%d) for page resource", i)
|
||||
}
|
||||
|
||||
if _, err := cast.ToUint64E(pp[i]); err != nil {
|
||||
@@ -832,30 +829,30 @@ func rbacPageResourceValidator(r string, oo ...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// rbacRecordResourceValidator checks validity of rbac resource and operations
|
||||
// rbacRecordResourceValidator 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 rbacRecordResourceValidator(r string, oo ...string) error {
|
||||
defOps := rbacResourceOperations(r)
|
||||
for _, o := range oo {
|
||||
if !defOps[o] {
|
||||
return fmt.Errorf("invalid operation '%s' for compose Record resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(r, types.RecordResourceType) {
|
||||
// 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 record resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
const sep = "/"
|
||||
var (
|
||||
pp = strings.Split(strings.Trim(r[len(types.RecordResourceType):], sep), sep)
|
||||
prc = []string{
|
||||
"namespaceID",
|
||||
"moduleID",
|
||||
"NamespaceID",
|
||||
"ModuleID",
|
||||
"ID",
|
||||
}
|
||||
)
|
||||
@@ -867,7 +864,7 @@ func rbacRecordResourceValidator(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 resource path wildcard level (%d) for Record", i)
|
||||
return fmt.Errorf("invalid path wildcard level (%d) for record resource", i)
|
||||
}
|
||||
|
||||
if _, err := cast.ToUint64E(pp[i]); err != nil {
|
||||
@@ -878,23 +875,23 @@ func rbacRecordResourceValidator(r string, oo ...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// rbacComponentResourceValidator checks validity of rbac resource and operations
|
||||
// rbacComponentResourceValidator 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 rbacComponentResourceValidator(r string, oo ...string) error {
|
||||
defOps := rbacResourceOperations(r)
|
||||
for _, o := range oo {
|
||||
if !defOps[o] {
|
||||
return fmt.Errorf("invalid operation '%s' for compose resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(r, types.ComponentResourceType) {
|
||||
// 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 compose component resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Generated
+11
-16
@@ -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
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -62,8 +62,8 @@ type (
|
||||
}
|
||||
|
||||
recordValueAccessController interface {
|
||||
CanReadRecordValue(context.Context, *types.ModuleField) bool
|
||||
CanUpdateRecordValue(context.Context, *types.ModuleField) bool
|
||||
CanReadRecordValueOnModuleField(context.Context, *types.ModuleField) bool
|
||||
CanUpdateRecordValueOnModuleField(context.Context, *types.ModuleField) bool
|
||||
}
|
||||
|
||||
recordAccessController interface {
|
||||
@@ -637,7 +637,7 @@ func RecordValueUpdateOpCheck(ctx context.Context, ac recordValueAccessControlle
|
||||
return nil
|
||||
}
|
||||
|
||||
if v.IsUpdated() && !ac.CanUpdateRecordValue(ctx, f) {
|
||||
if v.IsUpdated() && !ac.CanUpdateRecordValueOnModuleField(ctx, f) {
|
||||
rve.Push(types.RecordValueError{Kind: "updateDenied", Meta: map[string]interface{}{"field": v.Name, "value": v.Value}})
|
||||
}
|
||||
|
||||
@@ -908,7 +908,7 @@ func (svc record) procUpdate(ctx context.Context, invokerID uint64, m *types.Mod
|
||||
upd = RecordUpdateOwner(invokerID, upd, old)
|
||||
|
||||
upd.Values = old.Values.Merge(m.Fields, upd.Values, func(f *types.ModuleField) bool {
|
||||
return svc.ac.CanUpdateRecordValue(ctx, m.Fields.FindByName(f.Name))
|
||||
return svc.ac.CanUpdateRecordValueOnModuleField(ctx, m.Fields.FindByName(f.Name))
|
||||
})
|
||||
|
||||
if rve = RecordValueUpdateOpCheck(ctx, svc.ac, m, upd.Values); !rve.IsValid() {
|
||||
@@ -1095,7 +1095,7 @@ func (svc record) Organize(ctx context.Context, namespaceID, moduleID, recordID
|
||||
return fmt.Errorf("cannot reorder on multi-value field %q", posField)
|
||||
}
|
||||
|
||||
if !svc.ac.CanUpdateRecordValue(ctx, sf) {
|
||||
if !svc.ac.CanUpdateRecordValueOnModuleField(ctx, sf) {
|
||||
return RecordErrNotAllowedToUpdate()
|
||||
}
|
||||
|
||||
@@ -1119,7 +1119,7 @@ func (svc record) Organize(ctx context.Context, namespaceID, moduleID, recordID
|
||||
return fmt.Errorf("cannot update multi-value field %q", posField)
|
||||
}
|
||||
|
||||
if !svc.ac.CanUpdateRecordValue(ctx, vf) {
|
||||
if !svc.ac.CanUpdateRecordValueOnModuleField(ctx, vf) {
|
||||
return RecordErrNotAllowedToUpdate()
|
||||
}
|
||||
|
||||
@@ -1404,7 +1404,7 @@ func ComposeRecordFilterAC(ctx context.Context, ac recordValueAccessController,
|
||||
)
|
||||
|
||||
for _, f := range m.Fields {
|
||||
readableFields[f.Name] = ac.CanReadRecordValue(ctx, f)
|
||||
readableFields[f.Name] = ac.CanReadRecordValueOnModuleField(ctx, f)
|
||||
}
|
||||
|
||||
for _, r := range rr {
|
||||
|
||||
Generated
+126
-171
@@ -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,160 +23,32 @@ 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
|
||||
@@ -197,29 +63,31 @@ 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(NamespaceID uint64, ID uint64) string {
|
||||
cpts := []interface{}{
|
||||
ModuleResourceTranslationType,
|
||||
strconv.FormatUint(NamespaceID, 10),
|
||||
strconv.FormatUint(ID, 10),
|
||||
}
|
||||
|
||||
return fmt.Sprintf(ModuleResourceTranslationTpl(), cpts...)
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func ModuleResourceTranslationTpl() string {
|
||||
return "%s/%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 +96,81 @@ 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.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,
|
||||
strconv.FormatUint(NamespaceID, 10),
|
||||
strconv.FormatUint(ModuleID, 10),
|
||||
strconv.FormatUint(ID, 10),
|
||||
}
|
||||
|
||||
return fmt.Sprintf(ModuleFieldResourceTranslationTpl(), cpts...)
|
||||
}
|
||||
|
||||
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.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 +189,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 +228,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),
|
||||
})
|
||||
}
|
||||
@@ -313,23 +262,27 @@ 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(NamespaceID uint64, ID uint64) string {
|
||||
cpts := []interface{}{
|
||||
PageResourceTranslationType,
|
||||
strconv.FormatUint(NamespaceID, 10),
|
||||
strconv.FormatUint(ID, 10),
|
||||
}
|
||||
|
||||
return fmt.Sprintf(PageResourceTranslationTpl(), cpts...)
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func PageResourceTranslationTpl() string {
|
||||
return "%s/%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 +292,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 +300,7 @@ func (r *Page) EncodeTranslations() (out locale.ResourceTranslationSet) {
|
||||
Msg: locale.SanitizeMessage(r.Title),
|
||||
})
|
||||
}
|
||||
|
||||
if r.Description != "" {
|
||||
out = append(out, &locale.ResourceTranslation{
|
||||
Resource: r.ResourceTranslation(),
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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"])
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/filter"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
||||
@@ -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),
|
||||
})
|
||||
}
|
||||
|
||||
Generated
+42
-53
@@ -6,15 +6,6 @@ package types
|
||||
// the code is regenerated.
|
||||
//
|
||||
|
||||
// Definitions file that controls how this file is generated:
|
||||
// - compose.chart.yaml
|
||||
// - compose.module-field.yaml
|
||||
// - compose.module.yaml
|
||||
// - compose.namespace.yaml
|
||||
// - compose.page.yaml
|
||||
// - compose.record.yaml
|
||||
// - compose.yaml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
@@ -27,10 +18,15 @@ type (
|
||||
Component struct{}
|
||||
)
|
||||
|
||||
var (
|
||||
_ = fmt.Printf
|
||||
_ = strconv.FormatUint
|
||||
)
|
||||
|
||||
const (
|
||||
ChartResourceType = "corteza::compose:chart"
|
||||
ModuleFieldResourceType = "corteza::compose:module-field"
|
||||
ModuleResourceType = "corteza::compose:module"
|
||||
ModuleFieldResourceType = "corteza::compose:module-field"
|
||||
NamespaceResourceType = "corteza::compose:namespace"
|
||||
PageResourceType = "corteza::compose:page"
|
||||
RecordResourceType = "corteza::compose:record"
|
||||
@@ -69,11 +65,46 @@ func ChartRbacResource(namespaceID uint64, id uint64) string {
|
||||
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func ChartRbacResourceTpl() string {
|
||||
return "%s/%s/%s"
|
||||
}
|
||||
|
||||
// RbacResource returns string representation of RBAC resource for Module by calling ModuleRbacResource fn
|
||||
//
|
||||
// RBAC resource is in the corteza::compose:module/... format
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (r Module) RbacResource() string {
|
||||
return ModuleRbacResource(r.NamespaceID, r.ID)
|
||||
}
|
||||
|
||||
// ModuleRbacResource returns string representation of RBAC resource for Module
|
||||
//
|
||||
// RBAC resource is in the corteza::compose:module/... format
|
||||
//
|
||||
// This function is auto-generated
|
||||
func ModuleRbacResource(namespaceID uint64, id uint64) string {
|
||||
cpts := []interface{}{ModuleResourceType}
|
||||
if namespaceID != 0 {
|
||||
cpts = append(cpts, strconv.FormatUint(namespaceID, 10))
|
||||
} else {
|
||||
cpts = append(cpts, "*")
|
||||
}
|
||||
|
||||
if id != 0 {
|
||||
cpts = append(cpts, strconv.FormatUint(id, 10))
|
||||
} else {
|
||||
cpts = append(cpts, "*")
|
||||
}
|
||||
|
||||
return fmt.Sprintf(ModuleRbacResourceTpl(), cpts...)
|
||||
|
||||
}
|
||||
|
||||
func ModuleRbacResourceTpl() string {
|
||||
return "%s/%s/%s"
|
||||
}
|
||||
|
||||
// RbacResource returns string representation of RBAC resource for ModuleField by calling ModuleFieldRbacResource fn
|
||||
//
|
||||
// RBAC resource is in the corteza::compose:module-field/... format
|
||||
@@ -112,48 +143,10 @@ func ModuleFieldRbacResource(namespaceID uint64, moduleID uint64, id uint64) str
|
||||
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func ModuleFieldRbacResourceTpl() string {
|
||||
return "%s/%s/%s/%s"
|
||||
}
|
||||
|
||||
// RbacResource returns string representation of RBAC resource for Module by calling ModuleRbacResource fn
|
||||
//
|
||||
// RBAC resource is in the corteza::compose:module/... format
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (r Module) RbacResource() string {
|
||||
return ModuleRbacResource(r.NamespaceID, r.ID)
|
||||
}
|
||||
|
||||
// ModuleRbacResource returns string representation of RBAC resource for Module
|
||||
//
|
||||
// RBAC resource is in the corteza::compose:module/... format
|
||||
//
|
||||
// This function is auto-generated
|
||||
func ModuleRbacResource(namespaceID uint64, id uint64) string {
|
||||
cpts := []interface{}{ModuleResourceType}
|
||||
if namespaceID != 0 {
|
||||
cpts = append(cpts, strconv.FormatUint(namespaceID, 10))
|
||||
} else {
|
||||
cpts = append(cpts, "*")
|
||||
}
|
||||
|
||||
if id != 0 {
|
||||
cpts = append(cpts, strconv.FormatUint(id, 10))
|
||||
} else {
|
||||
cpts = append(cpts, "*")
|
||||
}
|
||||
|
||||
return fmt.Sprintf(ModuleRbacResourceTpl(), cpts...)
|
||||
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func ModuleRbacResourceTpl() string {
|
||||
return "%s/%s/%s"
|
||||
}
|
||||
|
||||
// RbacResource returns string representation of RBAC resource for Namespace by calling NamespaceRbacResource fn
|
||||
//
|
||||
// RBAC resource is in the corteza::compose:namespace/... format
|
||||
@@ -180,7 +173,6 @@ func NamespaceRbacResource(id uint64) string {
|
||||
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func NamespaceRbacResourceTpl() string {
|
||||
return "%s/%s"
|
||||
}
|
||||
@@ -217,7 +209,6 @@ func PageRbacResource(namespaceID uint64, id uint64) string {
|
||||
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func PageRbacResourceTpl() string {
|
||||
return "%s/%s/%s"
|
||||
}
|
||||
@@ -260,7 +251,6 @@ func RecordRbacResource(namespaceID uint64, moduleID uint64, id uint64) string {
|
||||
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func RecordRbacResourceTpl() string {
|
||||
return "%s/%s/%s/%s"
|
||||
}
|
||||
@@ -284,7 +274,6 @@ func ComponentRbacResource() string {
|
||||
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func ComponentRbacResourceTpl() string {
|
||||
return "%s"
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
module: "github.com/cortezaproject/corteza-server"
|
||||
@@ -1 +0,0 @@
|
||||
See `pkg/codegen-v3/README.md`
|
||||
@@ -1,23 +0,0 @@
|
||||
rbac:
|
||||
operations:
|
||||
read:
|
||||
description: Read workflow
|
||||
update:
|
||||
description: Update workflow
|
||||
delete:
|
||||
description: Delete workflow
|
||||
undelete:
|
||||
description: Undelete workflow
|
||||
execute:
|
||||
description: Execute workflow
|
||||
triggers.manage:
|
||||
description: Manage workflow triggers
|
||||
sessions.manage:
|
||||
description: Manage workflow sessions
|
||||
|
||||
# locale:
|
||||
# resource:
|
||||
# references: [ ID ]
|
||||
# keys:
|
||||
# - { path: name, field: "Meta.Name" }
|
||||
# - { path: description, field: "Meta.Description" }
|
||||
@@ -1,21 +0,0 @@
|
||||
rbac:
|
||||
resource: { references: [] }
|
||||
|
||||
operations:
|
||||
grant:
|
||||
description: Manage automation permissions
|
||||
|
||||
workflow.create:
|
||||
description: Create workflows
|
||||
|
||||
triggers.search:
|
||||
description: List, search or filter triggers
|
||||
|
||||
sessions.search:
|
||||
description: List, search or filter sessions
|
||||
|
||||
workflows.search:
|
||||
description: List, search or filter workflows
|
||||
|
||||
resource-translations.manage:
|
||||
description: List, search, create, or update resource translations
|
||||
@@ -1,17 +0,0 @@
|
||||
rbac:
|
||||
resource:
|
||||
references: [ namespace, ID ]
|
||||
|
||||
operations:
|
||||
read:
|
||||
description: Read chart
|
||||
update:
|
||||
description: Update chart
|
||||
delete:
|
||||
description: Delete chart
|
||||
|
||||
# locale:
|
||||
# resource:
|
||||
# references: [ namespace, ID ]
|
||||
# keys:
|
||||
# - name
|
||||
@@ -1,29 +0,0 @@
|
||||
rbac:
|
||||
resource:
|
||||
references: [ namespace, module, ID ]
|
||||
|
||||
operations:
|
||||
record.value.read:
|
||||
canFnName: CanReadRecordValue
|
||||
description: Read field value on records
|
||||
record.value.update:
|
||||
canFnName: CanUpdateRecordValue
|
||||
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
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
rbac:
|
||||
resource:
|
||||
references: [ namespace, ID ]
|
||||
|
||||
operations:
|
||||
read:
|
||||
description: Read module
|
||||
update:
|
||||
description: Update module
|
||||
delete:
|
||||
description: Delete module
|
||||
|
||||
record.create:
|
||||
description: Create record
|
||||
records.search:
|
||||
description: List, search or filter records
|
||||
|
||||
locale:
|
||||
resource:
|
||||
references: [ namespace, ID ]
|
||||
|
||||
extended: true
|
||||
keys:
|
||||
- name
|
||||
@@ -1,31 +0,0 @@
|
||||
rbac:
|
||||
operations:
|
||||
read:
|
||||
description: Read namespace
|
||||
update:
|
||||
description: Update namespace
|
||||
delete:
|
||||
description: Delete namespace
|
||||
manage:
|
||||
description: Access to namespace admin panel
|
||||
|
||||
module.create:
|
||||
description: Create module on namespace
|
||||
modules.search:
|
||||
description: List, search or filter module on namespace
|
||||
|
||||
chart.create:
|
||||
description: Create chart on namespace
|
||||
charts.search:
|
||||
description: List, search or filter chart on namespace
|
||||
|
||||
page.create:
|
||||
description: Create page on namespace
|
||||
pages.search:
|
||||
description: List, search or filter pages on namespace
|
||||
|
||||
locale:
|
||||
keys:
|
||||
- name
|
||||
- { path: subtitle, field: "Meta.Subtitle" }
|
||||
- { path: description, field: "Meta.Description" }
|
||||
@@ -1,23 +0,0 @@
|
||||
rbac:
|
||||
resource:
|
||||
references: [ namespace, ID ]
|
||||
|
||||
operations:
|
||||
read:
|
||||
description: Read page
|
||||
update:
|
||||
description: Update page
|
||||
delete:
|
||||
description: Delete page
|
||||
|
||||
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 }
|
||||
@@ -1,11 +0,0 @@
|
||||
rbac:
|
||||
resource:
|
||||
references: [ namespace, module, ID ]
|
||||
|
||||
operations:
|
||||
read:
|
||||
description: Read record
|
||||
update:
|
||||
description: Update record
|
||||
delete:
|
||||
description: Delete record
|
||||
@@ -1,19 +0,0 @@
|
||||
rbac:
|
||||
resource: { references: [] }
|
||||
|
||||
operations:
|
||||
grant:
|
||||
description: Manage Compose permissions
|
||||
|
||||
settings.read:
|
||||
description: Read settings
|
||||
settings.manage:
|
||||
description: Manage settings
|
||||
|
||||
namespace.create:
|
||||
description: Create namespace
|
||||
namespaces.search:
|
||||
description: List, search or filter namespaces
|
||||
|
||||
resource-translations.manage:
|
||||
description: List, search, create, or update resource translations
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "boolean",
|
||||
"enum": [ "false" ],
|
||||
"title": "Disable envoy support",
|
||||
"description": "Enabled by default"
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"resource": {
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"description": "RBAC resource definition",
|
||||
"properties": {
|
||||
"prefix": {
|
||||
"type": "string",
|
||||
"description": "Resource name",
|
||||
"pattern": "^[a-z]+:?[a-zA-Z]+(:[a-zA-Z]+)?$"
|
||||
},
|
||||
"references": {
|
||||
"type": "array",
|
||||
"title": "Reference components",
|
||||
"description": "When not explicitly defined it fallbacks to one item array with 'ID'",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"field": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"enum": [ "true" ],
|
||||
"title": "Custom implementation of resource attributes",
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"title": "List of resource attributes",
|
||||
"description": "Attributes are used for generating list of contextual roles"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"operations": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {
|
||||
"^([a-z]+(-[a-z]+)*)(\\.[a-z]+)*$": {
|
||||
"anyOf": [
|
||||
{ "type": "boolean", "enum": [ "false" ] },
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"canFnName": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"$id": "https://schemas.cortezaproject.org/def.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"imports": {
|
||||
"type": "array",
|
||||
"title": "List of go packages to be imported when generating files",
|
||||
"description": "Attributes are used for generating list of contextual roles"
|
||||
},
|
||||
|
||||
"component": {
|
||||
"type": "string",
|
||||
"title": "Component of the definition",
|
||||
"description": "By default, component is taken from the filename of the definition: from start of the filename to the first dot"
|
||||
},
|
||||
"resource": {
|
||||
"type": "string",
|
||||
"title": "Resource of the definition",
|
||||
"description": "By default, resource is taken from the filename of the definition: from the first dot to the end of the filename without extension"
|
||||
},
|
||||
"rbac": { "$ref": "def-rbac.json" },
|
||||
"envoy": { "$ref": "def-envoy.json" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
rbac:
|
||||
resource:
|
||||
references: [ node, ID ]
|
||||
|
||||
operations:
|
||||
manage:
|
||||
description: Manage shared module
|
||||
|
||||
envoy: false
|
||||
@@ -1,8 +0,0 @@
|
||||
rbac:
|
||||
operations:
|
||||
manage:
|
||||
description: Manage federation node
|
||||
module.create:
|
||||
description: Create shared module
|
||||
|
||||
envoy: false
|
||||
@@ -1,9 +0,0 @@
|
||||
rbac:
|
||||
resource:
|
||||
references: [ node, ID ]
|
||||
|
||||
operations:
|
||||
map:
|
||||
description: Map shared module
|
||||
|
||||
envoy: false
|
||||
@@ -1,19 +0,0 @@
|
||||
rbac:
|
||||
resource: { references: [] }
|
||||
operations:
|
||||
grant:
|
||||
description: Manage federation permissions
|
||||
pair:
|
||||
description: Pair federation nodes
|
||||
|
||||
settings.read:
|
||||
description: Read settings
|
||||
settings.manage:
|
||||
description: Manage settings
|
||||
|
||||
node.create:
|
||||
description: Create new federation node
|
||||
nodes.search:
|
||||
description: List, search or filter federation nodes
|
||||
|
||||
envoy: false
|
||||
@@ -1,8 +0,0 @@
|
||||
rbac:
|
||||
operations:
|
||||
read:
|
||||
description: Read API Gateway route
|
||||
update:
|
||||
description: Update API Gateway route
|
||||
delete:
|
||||
description: Delete API Gateway route
|
||||
@@ -1,8 +0,0 @@
|
||||
rbac:
|
||||
operations:
|
||||
read:
|
||||
description: Read application
|
||||
update:
|
||||
description: Update application
|
||||
delete:
|
||||
description: Delete application
|
||||
@@ -1,10 +0,0 @@
|
||||
rbac:
|
||||
operations:
|
||||
read:
|
||||
description: Read authorization client
|
||||
update:
|
||||
description: Update authorization client
|
||||
delete:
|
||||
description: Delete authorization client
|
||||
authorize:
|
||||
description: Authorize authorization client
|
||||
@@ -1,12 +0,0 @@
|
||||
rbac:
|
||||
operations:
|
||||
read:
|
||||
description: Read queue
|
||||
update:
|
||||
description: Update queue
|
||||
delete:
|
||||
description: Delete queue
|
||||
queue.read:
|
||||
description: Read from queue
|
||||
queue.write:
|
||||
description: Write to queue
|
||||
@@ -1,18 +0,0 @@
|
||||
rbac:
|
||||
operations:
|
||||
read:
|
||||
description: Read report
|
||||
update:
|
||||
description: Update report
|
||||
delete:
|
||||
description: Delete report
|
||||
run:
|
||||
description: Run report
|
||||
|
||||
# locale:
|
||||
# extended: true
|
||||
# keys:
|
||||
# - { path: name, field: "Meta.Name" }
|
||||
# - { path: description, field: "Meta.Description" }
|
||||
# - { name: block title, path: "block.{{blockID}}.title", custom: true }
|
||||
# - { name: block description, path: "block.{{blockID}}.description", custom: true }
|
||||
@@ -1,10 +0,0 @@
|
||||
rbac:
|
||||
operations:
|
||||
read:
|
||||
description: Read role
|
||||
update:
|
||||
description: Update role
|
||||
delete:
|
||||
description: Delete role
|
||||
members.manage:
|
||||
description: Manage members
|
||||
@@ -1,10 +0,0 @@
|
||||
rbac:
|
||||
operations:
|
||||
read:
|
||||
description: Read template
|
||||
update:
|
||||
description: Update template
|
||||
delete:
|
||||
description: Delete template
|
||||
render:
|
||||
description: Render template
|
||||
@@ -1,18 +0,0 @@
|
||||
rbac:
|
||||
operations:
|
||||
read:
|
||||
description: Read user
|
||||
update:
|
||||
description: Update user
|
||||
delete:
|
||||
description: Delete user
|
||||
suspend:
|
||||
description: Suspemd user
|
||||
unsuspend:
|
||||
description: Unsuspend user
|
||||
email.unmask:
|
||||
description: Unmask email
|
||||
name.unmask:
|
||||
description: Unmask name
|
||||
impersonate:
|
||||
description: Impersonate user
|
||||
@@ -1,64 +0,0 @@
|
||||
rbac:
|
||||
resource: { references: [] }
|
||||
|
||||
operations:
|
||||
grant:
|
||||
description: Manage system permissions
|
||||
|
||||
action-log.read:
|
||||
description: Access to action log
|
||||
|
||||
settings.read:
|
||||
description: Read system settings
|
||||
settings.manage:
|
||||
description: Manage system settings
|
||||
|
||||
auth-client.create:
|
||||
description: Create auth clients
|
||||
auth-clients.search:
|
||||
description: List, search or filter auth clients
|
||||
|
||||
role.create:
|
||||
description: Create roles
|
||||
roles.search:
|
||||
description: List, search or filter roles
|
||||
|
||||
user.create:
|
||||
description: Create users
|
||||
users.search:
|
||||
description: List, search or filter users
|
||||
|
||||
application.create:
|
||||
description: Create applications
|
||||
applications.search:
|
||||
description: List, search or filter auth clients
|
||||
application.flag.self:
|
||||
description: Manage private flags for applications
|
||||
application.flag.global:
|
||||
description: Manage global flags for applications
|
||||
|
||||
template.create:
|
||||
description: Create template
|
||||
templates.search:
|
||||
description: List, search or filter templates
|
||||
|
||||
report.create:
|
||||
description: Create report
|
||||
reports.search:
|
||||
description: List, search or filter reports
|
||||
|
||||
reminder.assign:
|
||||
description: Assign reminders
|
||||
|
||||
queue.create:
|
||||
description: Create messagebus queues
|
||||
queues.search:
|
||||
description: List, search or filter messagebus queues
|
||||
|
||||
apigw-route.create:
|
||||
description: Create API gateway route
|
||||
apigw-routes.search:
|
||||
description: List search or filter API gateway routes
|
||||
|
||||
resource-translations.manage:
|
||||
description: List, search, create, or update resource translations
|
||||
@@ -0,0 +1,24 @@
|
||||
package federation
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
component: schema.#component & {
|
||||
handle: "federation"
|
||||
|
||||
resources: {
|
||||
"node": node
|
||||
"exposed-module": exposedModule
|
||||
"shared-module": sharedModule
|
||||
}
|
||||
|
||||
rbac: operations: {
|
||||
"grant": description: "Manage federation permissions"
|
||||
"pair": description: "Pair federation nodes"
|
||||
"settings.read": description: "Read settings"
|
||||
"settings.manage": description: "Manage settings"
|
||||
"node.create": description: "Create new federation node"
|
||||
"nodes.search": description: "List, search or filter federation nodes"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package federation
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
exposedModule: schema.#resource & {
|
||||
parents: [
|
||||
{handle: "node"},
|
||||
]
|
||||
|
||||
rbac: {
|
||||
operations: {
|
||||
"manage": description: "Manage exposed module module"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package federation
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
node: schema.#resource & {
|
||||
rbac: {
|
||||
operations: {
|
||||
"manage": description: "Manage federation node"
|
||||
"module.create": description: "Create shared module"
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+105
-105
@@ -6,12 +6,6 @@ package service
|
||||
// the code is regenerated.
|
||||
//
|
||||
|
||||
// Definitions file that controls how this file is generated:
|
||||
// - federation.exposed-module.yaml
|
||||
// - federation.node.yaml
|
||||
// - federation.shared-module.yaml
|
||||
// - federation.yaml
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
@@ -60,11 +54,6 @@ 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.ExposedModuleResourceType,
|
||||
"any": types.ExposedModuleRbacResource(0, 0),
|
||||
"op": "manage",
|
||||
},
|
||||
{
|
||||
"type": types.NodeResourceType,
|
||||
"any": types.NodeRbacResource(0),
|
||||
@@ -75,6 +64,11 @@ func (svc accessControl) List() (out []map[string]string) {
|
||||
"any": types.NodeRbacResource(0),
|
||||
"op": "module.create",
|
||||
},
|
||||
{
|
||||
"type": types.ExposedModuleResourceType,
|
||||
"any": types.ExposedModuleRbacResource(0, 0),
|
||||
"op": "manage",
|
||||
},
|
||||
{
|
||||
"type": types.SharedModuleResourceType,
|
||||
"any": types.SharedModuleRbacResource(0, 0),
|
||||
@@ -183,13 +177,6 @@ func (svc accessControl) CloneRulesByRoleID(ctx context.Context, fromRoleID uint
|
||||
return svc.rbac.CloneRulesByRoleID(ctx, fromRoleID, toRoleID...)
|
||||
}
|
||||
|
||||
// CanManageExposedModule checks if current user can manage shared module
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanManageExposedModule(ctx context.Context, r *types.ExposedModule) bool {
|
||||
return svc.can(ctx, "manage", r)
|
||||
}
|
||||
|
||||
// CanManageNode checks if current user can manage federation node
|
||||
//
|
||||
// This function is auto-generated
|
||||
@@ -204,6 +191,13 @@ func (svc accessControl) CanCreateModuleOnNode(ctx context.Context, r *types.Nod
|
||||
return svc.can(ctx, "module.create", r)
|
||||
}
|
||||
|
||||
// CanManageExposedModule checks if current user can manage exposed module module
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanManageExposedModule(ctx context.Context, r *types.ExposedModule) bool {
|
||||
return svc.can(ctx, "manage", r)
|
||||
}
|
||||
|
||||
// CanMapSharedModule checks if current user can map shared module
|
||||
//
|
||||
// This function is auto-generated
|
||||
@@ -215,42 +209,48 @@ func (svc accessControl) CanMapSharedModule(ctx context.Context, r *types.Shared
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanGrant(ctx context.Context) bool {
|
||||
return svc.can(ctx, "grant", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "grant", r)
|
||||
}
|
||||
|
||||
// CanPair checks if current user can pair federation nodes
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanPair(ctx context.Context) bool {
|
||||
return svc.can(ctx, "pair", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "pair", r)
|
||||
}
|
||||
|
||||
// CanReadSettings checks if current user can read settings
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanReadSettings(ctx context.Context) bool {
|
||||
return svc.can(ctx, "settings.read", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "settings.read", r)
|
||||
}
|
||||
|
||||
// CanManageSettings checks if current user can manage settings
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanManageSettings(ctx context.Context) bool {
|
||||
return svc.can(ctx, "settings.manage", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "settings.manage", r)
|
||||
}
|
||||
|
||||
// CanCreateNode checks if current user can create new federation node
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanCreateNode(ctx context.Context) bool {
|
||||
return svc.can(ctx, "node.create", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "node.create", r)
|
||||
}
|
||||
|
||||
// CanSearchNodes checks if current user can list, search or filter federation nodes
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (svc accessControl) CanSearchNodes(ctx context.Context) bool {
|
||||
return svc.can(ctx, "nodes.search", &types.Component{})
|
||||
r := &types.Component{}
|
||||
return svc.can(ctx, "nodes.search", r)
|
||||
}
|
||||
|
||||
// rbacResourceValidator validates known component's resource by routing it to the appropriate validator
|
||||
@@ -258,10 +258,10 @@ func (svc accessControl) CanSearchNodes(ctx context.Context) bool {
|
||||
// This function is auto-generated
|
||||
func rbacResourceValidator(r string, oo ...string) error {
|
||||
switch rbac.ResourceType(r) {
|
||||
case types.ExposedModuleResourceType:
|
||||
return rbacExposedModuleResourceValidator(r, oo...)
|
||||
case types.NodeResourceType:
|
||||
return rbacNodeResourceValidator(r, oo...)
|
||||
case types.ExposedModuleResourceType:
|
||||
return rbacExposedModuleResourceValidator(r, oo...)
|
||||
case types.SharedModuleResourceType:
|
||||
return rbacSharedModuleResourceValidator(r, oo...)
|
||||
case types.ComponentResourceType:
|
||||
@@ -276,15 +276,15 @@ 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.ExposedModuleResourceType:
|
||||
return map[string]bool{
|
||||
"manage": true,
|
||||
}
|
||||
case types.NodeResourceType:
|
||||
return map[string]bool{
|
||||
"manage": true,
|
||||
"module.create": true,
|
||||
}
|
||||
case types.ExposedModuleResourceType:
|
||||
return map[string]bool{
|
||||
"manage": true,
|
||||
}
|
||||
case types.SharedModuleResourceType:
|
||||
return map[string]bool{
|
||||
"map": true,
|
||||
@@ -303,69 +303,24 @@ func rbacResourceOperations(r string) map[string]bool {
|
||||
return nil
|
||||
}
|
||||
|
||||
// rbacExposedModuleResourceValidator 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 rbacExposedModuleResourceValidator(r string, oo ...string) error {
|
||||
defOps := rbacResourceOperations(r)
|
||||
for _, o := range oo {
|
||||
if !defOps[o] {
|
||||
return fmt.Errorf("invalid operation '%s' for federation ExposedModule resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(r, types.ExposedModuleResourceType) {
|
||||
// expecting resource to always include path
|
||||
return fmt.Errorf("invalid resource type")
|
||||
}
|
||||
|
||||
const sep = "/"
|
||||
var (
|
||||
pp = strings.Split(strings.Trim(r[len(types.ExposedModuleResourceType):], sep), sep)
|
||||
prc = []string{
|
||||
"nodeID",
|
||||
"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 resource path wildcard level (%d) for ExposedModule", i)
|
||||
}
|
||||
|
||||
if _, err := cast.ToUint64E(pp[i]); err != nil {
|
||||
return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// rbacNodeResourceValidator checks validity of rbac resource and operations
|
||||
// rbacNodeResourceValidator 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 rbacNodeResourceValidator(r string, oo ...string) error {
|
||||
defOps := rbacResourceOperations(r)
|
||||
for _, o := range oo {
|
||||
if !defOps[o] {
|
||||
return fmt.Errorf("invalid operation '%s' for federation Node resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(r, types.NodeResourceType) {
|
||||
// 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 node resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
const sep = "/"
|
||||
var (
|
||||
pp = strings.Split(strings.Trim(r[len(types.NodeResourceType):], sep), sep)
|
||||
@@ -381,7 +336,7 @@ func rbacNodeResourceValidator(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 resource path wildcard level (%d) for Node", i)
|
||||
return fmt.Errorf("invalid path wildcard level (%d) for node resource", i)
|
||||
}
|
||||
|
||||
if _, err := cast.ToUint64E(pp[i]); err != nil {
|
||||
@@ -392,29 +347,29 @@ func rbacNodeResourceValidator(r string, oo ...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// rbacSharedModuleResourceValidator checks validity of rbac resource and operations
|
||||
// rbacExposedModuleResourceValidator 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 rbacSharedModuleResourceValidator(r string, oo ...string) error {
|
||||
defOps := rbacResourceOperations(r)
|
||||
for _, o := range oo {
|
||||
if !defOps[o] {
|
||||
return fmt.Errorf("invalid operation '%s' for federation SharedModule resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(r, types.SharedModuleResourceType) {
|
||||
func rbacExposedModuleResourceValidator(r string, oo ...string) error {
|
||||
if !strings.HasPrefix(r, types.ExposedModuleResourceType) {
|
||||
// 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 exposedModule resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
const sep = "/"
|
||||
var (
|
||||
pp = strings.Split(strings.Trim(r[len(types.SharedModuleResourceType):], sep), sep)
|
||||
pp = strings.Split(strings.Trim(r[len(types.ExposedModuleResourceType):], sep), sep)
|
||||
prc = []string{
|
||||
"nodeID",
|
||||
"NodeID",
|
||||
"ID",
|
||||
}
|
||||
)
|
||||
@@ -426,7 +381,7 @@ func rbacSharedModuleResourceValidator(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 resource path wildcard level (%d) for SharedModule", i)
|
||||
return fmt.Errorf("invalid path wildcard level (%d) for exposedModule resource", i)
|
||||
}
|
||||
|
||||
if _, err := cast.ToUint64E(pp[i]); err != nil {
|
||||
@@ -437,23 +392,68 @@ func rbacSharedModuleResourceValidator(r string, oo ...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// rbacComponentResourceValidator checks validity of rbac resource and operations
|
||||
// rbacSharedModuleResourceValidator 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 rbacSharedModuleResourceValidator(r string, oo ...string) error {
|
||||
if !strings.HasPrefix(r, types.SharedModuleResourceType) {
|
||||
// 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 sharedModule resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
const sep = "/"
|
||||
var (
|
||||
pp = strings.Split(strings.Trim(r[len(types.SharedModuleResourceType):], sep), sep)
|
||||
prc = []string{
|
||||
"NodeID",
|
||||
"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 sharedModule 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
|
||||
//
|
||||
// This function is auto-generated
|
||||
func rbacComponentResourceValidator(r string, oo ...string) error {
|
||||
defOps := rbacResourceOperations(r)
|
||||
for _, o := range oo {
|
||||
if !defOps[o] {
|
||||
return fmt.Errorf("invalid operation '%s' for federation resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(r, types.ComponentResourceType) {
|
||||
// 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 federation component resource", o)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package federation
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/codegen/schema"
|
||||
)
|
||||
|
||||
sharedModule: schema.#resource & {
|
||||
parents: [
|
||||
{handle: "node"},
|
||||
]
|
||||
|
||||
rbac: {
|
||||
operations: {
|
||||
"map": description: "Map shared module"
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+36
-41
@@ -6,12 +6,6 @@ package types
|
||||
// the code is regenerated.
|
||||
//
|
||||
|
||||
// Definitions file that controls how this file is generated:
|
||||
// - federation.exposed-module.yaml
|
||||
// - federation.node.yaml
|
||||
// - federation.shared-module.yaml
|
||||
// - federation.yaml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
@@ -24,13 +18,48 @@ type (
|
||||
Component struct{}
|
||||
)
|
||||
|
||||
var (
|
||||
_ = fmt.Printf
|
||||
_ = strconv.FormatUint
|
||||
)
|
||||
|
||||
const (
|
||||
ExposedModuleResourceType = "corteza::federation:exposed-module"
|
||||
NodeResourceType = "corteza::federation:node"
|
||||
ExposedModuleResourceType = "corteza::federation:exposed-module"
|
||||
SharedModuleResourceType = "corteza::federation:shared-module"
|
||||
ComponentResourceType = "corteza::federation"
|
||||
)
|
||||
|
||||
// RbacResource returns string representation of RBAC resource for Node by calling NodeRbacResource fn
|
||||
//
|
||||
// RBAC resource is in the corteza::federation:node/... format
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (r Node) RbacResource() string {
|
||||
return NodeRbacResource(r.ID)
|
||||
}
|
||||
|
||||
// NodeRbacResource returns string representation of RBAC resource for Node
|
||||
//
|
||||
// RBAC resource is in the corteza::federation:node/... format
|
||||
//
|
||||
// This function is auto-generated
|
||||
func NodeRbacResource(id uint64) string {
|
||||
cpts := []interface{}{NodeResourceType}
|
||||
if id != 0 {
|
||||
cpts = append(cpts, strconv.FormatUint(id, 10))
|
||||
} else {
|
||||
cpts = append(cpts, "*")
|
||||
}
|
||||
|
||||
return fmt.Sprintf(NodeRbacResourceTpl(), cpts...)
|
||||
|
||||
}
|
||||
|
||||
func NodeRbacResourceTpl() string {
|
||||
return "%s/%s"
|
||||
}
|
||||
|
||||
// RbacResource returns string representation of RBAC resource for ExposedModule by calling ExposedModuleRbacResource fn
|
||||
//
|
||||
// RBAC resource is in the corteza::federation:exposed-module/... format
|
||||
@@ -63,42 +92,10 @@ func ExposedModuleRbacResource(nodeID uint64, id uint64) string {
|
||||
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func ExposedModuleRbacResourceTpl() string {
|
||||
return "%s/%s/%s"
|
||||
}
|
||||
|
||||
// RbacResource returns string representation of RBAC resource for Node by calling NodeRbacResource fn
|
||||
//
|
||||
// RBAC resource is in the corteza::federation:node/... format
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (r Node) RbacResource() string {
|
||||
return NodeRbacResource(r.ID)
|
||||
}
|
||||
|
||||
// NodeRbacResource returns string representation of RBAC resource for Node
|
||||
//
|
||||
// RBAC resource is in the corteza::federation:node/... format
|
||||
//
|
||||
// This function is auto-generated
|
||||
func NodeRbacResource(id uint64) string {
|
||||
cpts := []interface{}{NodeResourceType}
|
||||
if id != 0 {
|
||||
cpts = append(cpts, strconv.FormatUint(id, 10))
|
||||
} else {
|
||||
cpts = append(cpts, "*")
|
||||
}
|
||||
|
||||
return fmt.Sprintf(NodeRbacResourceTpl(), cpts...)
|
||||
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func NodeRbacResourceTpl() string {
|
||||
return "%s/%s"
|
||||
}
|
||||
|
||||
// RbacResource returns string representation of RBAC resource for SharedModule by calling SharedModuleRbacResource fn
|
||||
//
|
||||
// RBAC resource is in the corteza::federation:shared-module/... format
|
||||
@@ -131,7 +128,6 @@ func SharedModuleRbacResource(nodeID uint64, id uint64) string {
|
||||
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func SharedModuleRbacResourceTpl() string {
|
||||
return "%s/%s/%s"
|
||||
}
|
||||
@@ -155,7 +151,6 @@ func ComponentRbacResource() string {
|
||||
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func ComponentRbacResourceTpl() string {
|
||||
return "%s"
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
This is 3rd generation of corteza code generator
|
||||
(1st was written in PHP, apologies 2nd is active and in use)
|
||||
|
||||
Goal for the 3rd generation is:
|
||||
- improved definition structure that addresses all elements that are used for code generation (types, store, rbac)
|
||||
- unify most if not all definitions (stuff in YAML files) into what you can find in /def/...
|
||||
- JSON schema validation for YAML files
|
||||
|
||||
How to run it (temp):
|
||||
```
|
||||
go run pkg/codegen-v3/*.go def
|
||||
```
|
||||
@@ -1,35 +0,0 @@
|
||||
package {{ .Package }}
|
||||
|
||||
{{ template "header-gentext.tpl" }}
|
||||
{{ template "header-definitions.tpl" . }}
|
||||
|
||||
import (
|
||||
{{- range .Imports }}
|
||||
{{ . }}
|
||||
{{- end }}
|
||||
)
|
||||
|
||||
{{- range .Def }}
|
||||
{{- if gt (len .RBAC.Resource.References) 0 }}
|
||||
// {{ export .Component .Resource }}RbacReferences generates RBAC references
|
||||
//
|
||||
// Resources with "envoy: false" are skipped
|
||||
//
|
||||
// This function is auto-generated
|
||||
func {{ export .Component .Resource }}RbacReferences({{- range .RBAC.Resource.References }}{{ unexport .Resource }} string, {{- end }}) (res *Ref, pp []*Ref, err error) {
|
||||
{{- range .RBAC.Resource.References }}
|
||||
{{- if eq .Field "ID" }}
|
||||
if {{ unexport .Resource }} != "*" {
|
||||
res = &Ref{ResourceType: types.{{ export .Resource }}ResourceType, Identifiers: MakeIdentifiers({{ unexport .Resource }})}
|
||||
}
|
||||
{{- else }}
|
||||
if {{ unexport .Resource }} != "*" {
|
||||
pp = append(pp, &Ref{ResourceType: types.{{ export .Resource }}ResourceType, Identifiers: MakeIdentifiers({{ unexport .Resource }})})
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
return
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
package {{ .Package }}
|
||||
|
||||
{{ template "header-gentext.tpl" }}
|
||||
{{ template "header-definitions.tpl" . }}
|
||||
|
||||
import (
|
||||
{{- range .Imports }}
|
||||
{{ . }}
|
||||
{{- end }}
|
||||
)
|
||||
|
||||
{{- range .Def }}
|
||||
{{- if .Locale }}
|
||||
{{- if gt (len .Locale.Resource.References) 0 }}
|
||||
// {{ export .Component .Resource }}ResourceTranslationReferences generates Locale references
|
||||
//
|
||||
// Resources with "envoy: false" are skipped
|
||||
//
|
||||
// This function is auto-generated
|
||||
func {{ export .Component .Resource }}ResourceTranslationReferences({{- range .Locale.Resource.References }}{{ unexport .Resource }} string, {{- end }}) (res *Ref, pp []*Ref, err error) {
|
||||
{{- range .Locale.Resource.References }}
|
||||
{{- if eq .Field "ID" }}
|
||||
res = &Ref{ResourceType: types.{{ export .Resource }}ResourceType, Identifiers: MakeIdentifiers({{ unexport .Resource }})}
|
||||
{{- else }}
|
||||
pp = append(pp, &Ref{ResourceType: types.{{ export .Resource }}ResourceType, Identifiers: MakeIdentifiers({{ unexport .Resource }})})
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
return
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -1,4 +0,0 @@
|
||||
// Definitions file that controls how this file is generated:
|
||||
{{- range .Def }}
|
||||
// - {{ .Source }}
|
||||
{{- end }}
|
||||
@@ -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 }}
|
||||
@@ -1,99 +0,0 @@
|
||||
package {{ .Package }}
|
||||
|
||||
{{ template "header-gentext.tpl" }}
|
||||
{{ template "header-definitions.tpl" . }}
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type (
|
||||
// Component struct serves as a virtual resource type for the {{ .Component }} component
|
||||
//
|
||||
// This struct is auto-generated
|
||||
Component struct {}
|
||||
)
|
||||
|
||||
const (
|
||||
{{- range .Def }}
|
||||
{{ coalesce .Resource "Component" }}ResourceType = "{{ .RBAC.ResourceType }}"
|
||||
{{- end }}
|
||||
)
|
||||
|
||||
|
||||
{{- range .Def }}
|
||||
{{ $Resource := .Resource }}
|
||||
{{ $GoType := printf "types.%s" .Resource }}
|
||||
|
||||
|
||||
// RbacResource returns string representation of RBAC resource for {{ .Resource }} by calling {{ .Resource }}RbacResource fn
|
||||
//
|
||||
// RBAC resource is in the {{ .RBAC.ResourceType }}/... format
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (r {{ .Resource }}) RbacResource() string {
|
||||
return {{ .Resource }}RbacResource({{ if .RBAC.Resource }}{{ range .RBAC.Resource.References }}r.{{ export .Field }},{{ end }}{{ end }})
|
||||
}
|
||||
|
||||
// {{ .Resource }}RbacResource returns string representation of RBAC resource for {{ .Resource }}
|
||||
//
|
||||
// RBAC resource is in the {{ .RBAC.ResourceType }}/{{- if .RBAC.Resource.References }}...{{ end }} format
|
||||
//
|
||||
// This function is auto-generated
|
||||
func {{ .Resource }}RbacResource({{ if .RBAC.Resource }}{{ range .RBAC.Resource.References }}{{ unexport .Field }} uint64,{{ end }}{{ end }}) string {
|
||||
{{- if .RBAC.Resource.References }}
|
||||
cpts := []interface{{"{}"}}{{"{"}}{{ .Resource }}ResourceType{{"}"}}
|
||||
{{- range .RBAC.Resource.References }}
|
||||
if {{ unexport .Field }} != 0 {
|
||||
cpts = append(cpts, strconv.FormatUint({{ unexport .Field }}, 10))
|
||||
} else {
|
||||
cpts = append(cpts, "*")
|
||||
}
|
||||
|
||||
{{ end }}
|
||||
return fmt.Sprintf({{ .Resource }}RbacResourceTpl(), cpts...)
|
||||
{{- else }}
|
||||
return {{ .Resource }}ResourceType + "/"
|
||||
{{- end }}
|
||||
|
||||
}
|
||||
|
||||
// @todo template
|
||||
func {{ .Resource }}RbacResourceTpl() string {
|
||||
{{- if .RBAC.Resource.References }}
|
||||
return "%s
|
||||
{{- range .RBAC.Resource.References }}/%s{{- end }}"
|
||||
|
||||
{{- else }}
|
||||
return "%s"
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
{{ if .RBAC.Resource.Attributes }}
|
||||
// RbacAttributes returns resource attributes used for generating list of contextual roles
|
||||
//
|
||||
// This function is auto-generated
|
||||
func (r {{ .Resource }}) RbacAttributes() map[string]interface{} {
|
||||
return {{ unexport .Resource }}RbacAttributes(r)
|
||||
}
|
||||
|
||||
{{ if .RBAC.Resource.Attributes.Fields }}
|
||||
// {{ .Resource }}RbacResource returns string representation of RBAC resource for {{ .Resource }}
|
||||
//
|
||||
// RBAC resource is in the {{ .RBAC.ResourceType }}/... format
|
||||
//
|
||||
// This function is auto-generated
|
||||
func {{ unexport .Resource }}RbacAttributes(r {{ .Resource }}) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
{{- range .RBAC.Resource.Attributes.Fields }}
|
||||
{{ printf "%q" . }}: r.{{ export . }},
|
||||
{{- end }}
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{- end }}
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
package def
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/codegen-v3/internal/tpl"
|
||||
"github.com/cortezaproject/corteza-server/pkg/y7s"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type (
|
||||
Document struct {
|
||||
Skip bool `yaml:"(skip)"`
|
||||
Imports []string
|
||||
Component string
|
||||
IsComponentResource bool `yaml:"-"`
|
||||
Resource string
|
||||
Source string
|
||||
RBAC *rbac
|
||||
Locale *locale
|
||||
Envoy bool `yaml:"envoy"`
|
||||
}
|
||||
)
|
||||
|
||||
func (set *rbacOperations) UnmarshalYAML(n *yaml.Node) error {
|
||||
return y7s.Each(n, func(k *yaml.Node, v *yaml.Node) (err error) {
|
||||
def := rbacOperation{}
|
||||
if k != nil {
|
||||
def.Operation = k.Value
|
||||
}
|
||||
|
||||
*set = append(*set, &def)
|
||||
return v.Decode(&def)
|
||||
})
|
||||
}
|
||||
|
||||
// Preproc preprocesses the document and sets defaults
|
||||
func (doc *Document) Proc(filename string) error {
|
||||
doc.Source = filename
|
||||
|
||||
// filename parts
|
||||
fp := strings.Split(filename, ".")
|
||||
// trim extension
|
||||
fp = fp[:len(fp)-1]
|
||||
if len(fp) > 0 && doc.Component == "" {
|
||||
// set component from the 1st part
|
||||
// component is system, compose, ...
|
||||
doc.Component = fp[0]
|
||||
}
|
||||
|
||||
if len(fp) > 1 && doc.Resource == "" {
|
||||
// if there are more parts, set resource
|
||||
// resource is user, module, record, workflow, ...
|
||||
doc.Resource = fp[1]
|
||||
}
|
||||
|
||||
if strings.ToLower(doc.Resource) == "component" {
|
||||
return fmt.Errorf("can not use 'component' as a resource name, this is done automatically")
|
||||
} else if doc.Resource == "" {
|
||||
doc.Resource = "component"
|
||||
doc.IsComponentResource = true
|
||||
}
|
||||
|
||||
doc.Imports = normalizeImport(doc.Imports...)
|
||||
|
||||
if err := doc.RBAC.proc(doc.Component, doc.Resource); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := doc.Locale.proc(doc.Component, doc.Resource); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
doc.Resource = tpl.Export(doc.Resource)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func normalizeImport(ii ...string) []string {
|
||||
for i := range ii {
|
||||
if strings.Contains(ii[i], " ") {
|
||||
p := strings.SplitN(ii[i], " ", 2)
|
||||
ii[i] = fmt.Sprintf(`%s "%s"`, p[0], strings.Trim(p[1], `"`))
|
||||
} else {
|
||||
ii[i] = fmt.Sprintf(`"%s"`, strings.Trim(ii[i], `"'`+"`"))
|
||||
}
|
||||
}
|
||||
|
||||
return ii
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
package def
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/codegen-v3/internal/tpl"
|
||||
"github.com/cortezaproject/corteza-server/pkg/y7s"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type (
|
||||
locale struct {
|
||||
ResourceType string `yaml:"resourceType"`
|
||||
Resource *resourceTranslation
|
||||
Extended bool
|
||||
SkipSvc bool `yaml:"skipSvc"`
|
||||
Keys localeKeys
|
||||
}
|
||||
|
||||
resourceTranslation struct {
|
||||
References []*resourceTranslationRef
|
||||
}
|
||||
|
||||
resourceTranslationRef struct {
|
||||
Field string
|
||||
ResourceType string
|
||||
Resource string
|
||||
Component string
|
||||
|
||||
custom bool
|
||||
}
|
||||
|
||||
localeKeys []*localeKey
|
||||
|
||||
localeKey struct {
|
||||
Name string
|
||||
Path string
|
||||
Custom bool
|
||||
CustomHandler string `yaml:"customHandler"`
|
||||
Description string
|
||||
Field string
|
||||
}
|
||||
)
|
||||
|
||||
func (r *locale) proc(component, resource string) error {
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if r.ResourceType == "" {
|
||||
if strings.ToLower(resource) == "component" {
|
||||
r.ResourceType = component
|
||||
} else {
|
||||
r.ResourceType = fmt.Sprintf("%s:%s", component, resource)
|
||||
}
|
||||
}
|
||||
|
||||
if r.Resource == nil {
|
||||
r.Resource = &resourceTranslation{References: []*resourceTranslationRef{{Field: "ID"}}}
|
||||
}
|
||||
|
||||
// check types of each referenced component
|
||||
// and self-references (field==ID) with own resource type
|
||||
for _, rc := range r.Resource.References {
|
||||
if !rc.custom {
|
||||
if rc.Field == "ID" {
|
||||
rc.ResourceType = r.ResourceType
|
||||
rc.Component = component
|
||||
rc.Resource = resource
|
||||
} else {
|
||||
rc.ResourceType = fmt.Sprintf("%s:%s", component, rc.Field)
|
||||
rc.Component = component
|
||||
rc.Resource = rc.Field
|
||||
rc.Field = rc.Field + "ID"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// assure missing key field paths
|
||||
for _, k := range r.Keys {
|
||||
k.Custom = k.Custom || k.CustomHandler != ""
|
||||
|
||||
// Guess the key path
|
||||
if k.Field == "" {
|
||||
k.Field = tpl.Export(k.Path)
|
||||
}
|
||||
|
||||
// Guess the name
|
||||
if k.Name == "" {
|
||||
k.Name = k.Path
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (op *localeKey) UnmarshalYAML(n *yaml.Node) error {
|
||||
type auxType localeKey
|
||||
|
||||
switch {
|
||||
case y7s.IsKind(n, yaml.ScalarNode):
|
||||
return y7s.DecodeScalar(n, "locale key", &op.Path)
|
||||
|
||||
case y7s.IsKind(n, yaml.MappingNode):
|
||||
var aux = (*auxType)(op)
|
||||
return n.Decode(aux)
|
||||
}
|
||||
|
||||
return y7s.NodeErr(n, "unsupported formatting")
|
||||
}
|
||||
|
||||
func (op *resourceTranslationRef) UnmarshalYAML(n *yaml.Node) error {
|
||||
if y7s.IsKind(n, yaml.ScalarNode) {
|
||||
op.Field = n.Value
|
||||
if n.Value != "ID" {
|
||||
op.ResourceType = n.Value
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type auxType resourceTranslationRef
|
||||
var aux = (*auxType)(op)
|
||||
aux.custom = true
|
||||
return n.Decode(aux)
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
package def
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/codegen-v3/internal/tpl"
|
||||
"github.com/cortezaproject/corteza-server/pkg/y7s"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type (
|
||||
rbac struct {
|
||||
// fully qualified resource name
|
||||
ResourceType string `yaml:"resourceType"`
|
||||
Resource *rbacResource
|
||||
Operations rbacOperations
|
||||
}
|
||||
|
||||
rbacResource struct {
|
||||
References []*rbacResourceRef
|
||||
Attributes *rbacAttributes
|
||||
}
|
||||
|
||||
rbacResourceRef struct {
|
||||
Field string
|
||||
ResourceType string
|
||||
Resource string
|
||||
Component string
|
||||
|
||||
custom bool
|
||||
}
|
||||
|
||||
rbacOperations []*rbacOperation
|
||||
|
||||
rbacOperation struct {
|
||||
Operation string
|
||||
CanFnName string `yaml:"canFnName"`
|
||||
Description string
|
||||
}
|
||||
|
||||
rbacAttributes struct {
|
||||
Fields []string `yaml:"-"`
|
||||
}
|
||||
)
|
||||
|
||||
func (r *rbac) proc(component, resource string) error {
|
||||
const (
|
||||
defaultNS = "corteza"
|
||||
nsDelimiter = "::"
|
||||
)
|
||||
|
||||
if r.ResourceType == "" {
|
||||
if strings.ToLower(resource) == "component" {
|
||||
r.ResourceType = component
|
||||
} else {
|
||||
r.ResourceType = fmt.Sprintf("%s:%s", component, resource)
|
||||
}
|
||||
|
||||
r.ResourceType = defaultNS + nsDelimiter + r.ResourceType
|
||||
}
|
||||
|
||||
if !strings.Contains(r.ResourceType, nsDelimiter) {
|
||||
return fmt.Errorf("no namespace prefix found (e.g.: 'corteza::') in resource type")
|
||||
}
|
||||
|
||||
for _, op := range r.Operations {
|
||||
// Generate all check name
|
||||
if op.CanFnName == "" {
|
||||
op.CanFnName = RbacOperationCanFnName(resource, op.Operation)
|
||||
}
|
||||
}
|
||||
|
||||
if r.Resource == nil {
|
||||
r.Resource = &rbacResource{References: []*rbacResourceRef{{Field: "ID"}}}
|
||||
}
|
||||
|
||||
// check types of each referenced component
|
||||
// and prefix non-custom components with corteza::<component>
|
||||
// and self-references (field==ID) with own resource type
|
||||
for _, rc := range r.Resource.References {
|
||||
if !rc.custom {
|
||||
if rc.Field == "ID" {
|
||||
rc.ResourceType = r.ResourceType
|
||||
rc.Component = component
|
||||
rc.Resource = resource
|
||||
} else {
|
||||
rc.ResourceType = defaultNS + nsDelimiter + fmt.Sprintf("%s:%s", component, rc.Field)
|
||||
rc.Component = component
|
||||
rc.Resource = rc.Field
|
||||
rc.Field = rc.Field + "ID"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (op *rbacOperation) UnmarshalYAML(n *yaml.Node) error {
|
||||
if y7s.IsKind(n, yaml.ScalarNode) {
|
||||
// @todo handle disabled operations
|
||||
// the idea is that when service operations are defined we implicitly define
|
||||
// RBAC operations. Here, we'll be able to remove implicitly defined operation
|
||||
return nil
|
||||
}
|
||||
|
||||
type auxType rbacOperation
|
||||
var aux = (*auxType)(op)
|
||||
return n.Decode(aux)
|
||||
}
|
||||
|
||||
func (op *rbacResourceRef) UnmarshalYAML(n *yaml.Node) error {
|
||||
if y7s.IsKind(n, yaml.ScalarNode) {
|
||||
op.Field = n.Value
|
||||
if n.Value != "ID" {
|
||||
op.ResourceType = n.Value
|
||||
// @todo expand resource & component
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type auxType rbacResourceRef
|
||||
var aux = (*auxType)(op)
|
||||
aux.custom = true
|
||||
return n.Decode(aux)
|
||||
}
|
||||
|
||||
func (a *rbacAttributes) UnmarshalYAML(n *yaml.Node) error {
|
||||
if y7s.IsKind(n, yaml.ScalarNode) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// if not scalar, assume we will get list of fields
|
||||
a.Fields = make([]string, 0)
|
||||
return n.Decode(&a.Fields)
|
||||
}
|
||||
|
||||
func RbacOperationCanFnName(res, op string) string {
|
||||
// when check function name is not explicitly defined we try
|
||||
// to use resource and operation name and generate easy-to-read name
|
||||
//
|
||||
// <res> + <op> => Can<Op><Res>
|
||||
// <res> + <op:foo.bar.verb> => Can<Verb><Foo><Bar>On<Res>
|
||||
|
||||
if strings.ToLower(res) == "component" {
|
||||
res = ""
|
||||
}
|
||||
|
||||
if strings.Contains(op, ".") {
|
||||
parts := strings.Split(op, ".")
|
||||
l := len(parts)
|
||||
|
||||
parts = append(parts[l-1:], parts[:l-1]...)
|
||||
|
||||
if res != "" {
|
||||
// Only append "on" if there is resource
|
||||
parts = append(parts, "on")
|
||||
}
|
||||
|
||||
op = tpl.Export(parts...)
|
||||
}
|
||||
|
||||
return tpl.Export("can", op, res)
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"text/template"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/codegen-v3/internal/def"
|
||||
"github.com/cortezaproject/corteza-server/pkg/codegen-v3/internal/tpl"
|
||||
"github.com/cortezaproject/corteza-server/pkg/slice"
|
||||
)
|
||||
|
||||
func Envoy(t *template.Template, dd []*def.Document) error {
|
||||
return List{
|
||||
"resource rbac parse": envoyResourceRbacUnmarshal,
|
||||
"resource rbac references": envoyResourceRbacReferences,
|
||||
|
||||
"resource translation": envoyResourceTranslation,
|
||||
"resource translation parse": envoyResourceTranslationUnmarshal,
|
||||
"resource translation references": envoyResourceTranslationReferences,
|
||||
}.Generate(t, dd)
|
||||
}
|
||||
|
||||
// EnvoyResourceRbacUnmarshal envoy rbac unmarshal
|
||||
// <service>/service/rbac.gen.go
|
||||
//
|
||||
// Contains all RBAC related definitions
|
||||
func envoyResourceRbacUnmarshal(t *template.Template, dd []*def.Document) (err error) {
|
||||
const (
|
||||
templateName = "envoy/resource-rbac_rules_parse.go.tpl"
|
||||
outputPathTpl = "pkg/envoy/resource/rbac_rules_parse.gen.go"
|
||||
)
|
||||
|
||||
dd = filter(dd, func(d *def.Document) bool { return d.Envoy })
|
||||
|
||||
// build list of component type imports
|
||||
ctImports := make([]string, 0)
|
||||
for _, d := range dd {
|
||||
imp := d.Component + "Types " + cImport(d.Component, "types")
|
||||
if !slice.HasString(ctImports, imp) {
|
||||
ctImports = append(ctImports, imp)
|
||||
}
|
||||
}
|
||||
|
||||
w := tpl.Wrap{
|
||||
Package: "resource",
|
||||
Def: dd,
|
||||
Imports: append(collectImports(dd...), ctImports...),
|
||||
}
|
||||
|
||||
err = tpl.GoTemplate(outputPathTpl, t.Lookup(templateName), w)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// EnvoyResourceRbacReferences generates one rbac definition file per component
|
||||
// <service>/service/rbac.gen.go
|
||||
//
|
||||
// Contains all RBAC related definitions
|
||||
func envoyResourceRbacReferences(t *template.Template, dd []*def.Document) (err error) {
|
||||
const (
|
||||
templateName = "envoy/resource-rbac_references.go.tpl"
|
||||
outputPathTpl = "pkg/envoy/resource/rbac_references_%s.gen.go"
|
||||
)
|
||||
|
||||
dd = filter(dd, func(d *def.Document) bool { return d.Envoy })
|
||||
|
||||
for component, perComponent := range partByComponent(dd) {
|
||||
|
||||
w := tpl.Wrap{
|
||||
Package: "resource",
|
||||
Component: component,
|
||||
Def: perComponent,
|
||||
Imports: append(collectImports(perComponent...), cImport(component, "types")),
|
||||
}
|
||||
|
||||
err = tpl.GoTemplate(fmt.Sprintf(outputPathTpl, component), t.Lookup(templateName), w)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func envoyResourceTranslation(t *template.Template, dd []*def.Document) (err error) {
|
||||
const (
|
||||
templateName = "envoy/resource-resource_translation.go.tpl"
|
||||
outputPathTpl = "pkg/envoy/resource/resource_translation.gen.go"
|
||||
)
|
||||
|
||||
dd = filter(dd, func(d *def.Document) bool { return d.Envoy && d.Locale != nil })
|
||||
|
||||
// build list of component type imports
|
||||
ctImports := make([]string, 0)
|
||||
|
||||
w := tpl.Wrap{
|
||||
Package: "resource",
|
||||
Def: dd,
|
||||
Imports: append(collectImports(dd...), ctImports...),
|
||||
}
|
||||
|
||||
err = tpl.GoTemplate(outputPathTpl, t.Lookup(templateName), w)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func envoyResourceTranslationUnmarshal(t *template.Template, dd []*def.Document) (err error) {
|
||||
const (
|
||||
templateName = "envoy/resource-resource_translation_parse.go.tpl"
|
||||
outputPathTpl = "pkg/envoy/resource/resource_translation_parse.gen.go"
|
||||
)
|
||||
|
||||
dd = filter(dd, func(d *def.Document) bool { return d.Envoy && d.Locale != nil })
|
||||
|
||||
// build list of component type imports
|
||||
ctImports := make([]string, 0)
|
||||
for _, d := range dd {
|
||||
imp := d.Component + "Types " + cImport(d.Component, "types")
|
||||
if !slice.HasString(ctImports, imp) {
|
||||
ctImports = append(ctImports, imp)
|
||||
}
|
||||
}
|
||||
|
||||
w := tpl.Wrap{
|
||||
Package: "resource",
|
||||
Def: dd,
|
||||
Imports: append(collectImports(dd...), ctImports...),
|
||||
}
|
||||
|
||||
err = tpl.GoTemplate(outputPathTpl, t.Lookup(templateName), w)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func envoyResourceTranslationReferences(t *template.Template, dd []*def.Document) (err error) {
|
||||
const (
|
||||
templateName = "envoy/resource-resource_translation_references.go.tpl"
|
||||
outputPathTpl = "pkg/envoy/resource/resource_translation_references_%s.gen.go"
|
||||
)
|
||||
|
||||
dd = filter(dd, func(d *def.Document) bool { return d.Envoy && d.Locale != nil })
|
||||
|
||||
for component, perComponent := range partByComponent(dd) {
|
||||
|
||||
w := tpl.Wrap{
|
||||
Package: "resource",
|
||||
Component: component,
|
||||
Def: perComponent,
|
||||
Imports: append(collectImports(perComponent...), cImport(component, "types")),
|
||||
}
|
||||
|
||||
err = tpl.GoTemplate(fmt.Sprintf(outputPathTpl, component), t.Lookup(templateName), w)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
Generated
-67
@@ -1,67 +0,0 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"text/template"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/codegen-v3/internal/def"
|
||||
)
|
||||
|
||||
type (
|
||||
List map[string]func(*template.Template, []*def.Document) error
|
||||
)
|
||||
|
||||
func (gg List) Generate(tpls *template.Template, dd []*def.Document) (err error) {
|
||||
for l, g := range gg {
|
||||
if err = g(tpls, dd); err != nil {
|
||||
return fmt.Errorf("codegen for %s failed: %w", l, err)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func filter(dd []*def.Document, check func(*def.Document) bool) []*def.Document {
|
||||
aux := make([]*def.Document, 0, len(dd))
|
||||
for _, d := range dd {
|
||||
if !check(d) {
|
||||
continue
|
||||
}
|
||||
|
||||
aux = append(aux, d)
|
||||
}
|
||||
return aux
|
||||
}
|
||||
|
||||
func partByComponent(dd []*def.Document) map[string][]*def.Document {
|
||||
var (
|
||||
parted = make(map[string][]*def.Document)
|
||||
)
|
||||
|
||||
for _, d := range dd {
|
||||
parted[d.Component] = append(parted[d.Component], d)
|
||||
}
|
||||
|
||||
return parted
|
||||
}
|
||||
|
||||
func collectImports(dd ...*def.Document) []string {
|
||||
mm := make(map[string]bool)
|
||||
for _, d := range dd {
|
||||
for _, i := range d.Imports {
|
||||
mm[i] = true
|
||||
}
|
||||
}
|
||||
|
||||
ii := make([]string, 0, len(mm))
|
||||
for i := range mm {
|
||||
ii = append(ii, i)
|
||||
}
|
||||
|
||||
return ii
|
||||
}
|
||||
|
||||
// component import
|
||||
func cImport(c, s string) string {
|
||||
return fmt.Sprintf(`"github.com/cortezaproject/corteza-server/%s/%s"`, c, s)
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"text/template"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/codegen-v3/internal/def"
|
||||
"github.com/cortezaproject/corteza-server/pkg/codegen-v3/internal/tpl"
|
||||
)
|
||||
|
||||
func Locale(t *template.Template, dd []*def.Document) error {
|
||||
return List{
|
||||
"types": localeTypes,
|
||||
"services": localeServices,
|
||||
}.Generate(t, dd)
|
||||
}
|
||||
|
||||
func localeTypes(t *template.Template, dd []*def.Document) (err error) {
|
||||
const (
|
||||
templateName = "locale/types.go.tpl"
|
||||
outputPathTpl = "%s/types/locale.gen.go"
|
||||
)
|
||||
|
||||
dd = filter(dd, func(d *def.Document) bool { return d.Locale != nil })
|
||||
|
||||
for component, perComponent := range partByComponent(dd) {
|
||||
w := tpl.Wrap{
|
||||
Package: "types",
|
||||
Component: component,
|
||||
Def: perComponent,
|
||||
}
|
||||
|
||||
err = tpl.GoTemplate(fmt.Sprintf(outputPathTpl, component), t.Lookup(templateName), w)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func localeServices(t *template.Template, dd []*def.Document) (err error) {
|
||||
const (
|
||||
templateName = "locale/service.go.tpl"
|
||||
outputPathTpl = "%s/service/locale.gen.go"
|
||||
)
|
||||
|
||||
dd = filter(dd, func(d *def.Document) bool { return d.Locale != nil && !d.Locale.SkipSvc })
|
||||
|
||||
for component, perComponent := range partByComponent(dd) {
|
||||
w := tpl.Wrap{
|
||||
Package: "service",
|
||||
Component: component,
|
||||
Def: perComponent,
|
||||
Imports: append(collectImports(perComponent...), cImport(component, "types")),
|
||||
}
|
||||
|
||||
err = tpl.GoTemplate(fmt.Sprintf(outputPathTpl, component), t.Lookup(templateName), w)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range dd {
|
||||
if d.Locale != nil {
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user