3
0

Remove handle requirement from resource API

We removed handle requirement for all resource like namespace(slug), module, user, page, chart.

Due to that namespace import/export was broken as we were using handle as reference, hence fixed it by replacing handle usage with ID of resource.

It also fixes index of template table for handle column.
This commit is contained in:
Vivek Patel
2022-11-15 19:13:19 +05:30
committed by Katrin Yordanova
parent 16082d1766
commit 1699e3f94b
14 changed files with 106 additions and 42 deletions
-2
View File
@@ -154,7 +154,6 @@ endpoints:
title: Duplicate name
- type: string
name: slug
required: true
title: Duplicate slug
- name: export
path: "/{namespaceID}/export/{filename}.zip"
@@ -201,7 +200,6 @@ endpoints:
title: Imported namespace name
- type: string
name: slug
required: true
title: Imported namespace slug
- name: triggerScript
method: POST
+26 -19
View File
@@ -39,10 +39,11 @@ type (
}
namespaceImportSession struct {
Name string `json:"name"`
Slug string `json:"handle"`
SessionID uint64 `json:"sessionID,string"`
UserID uint64 `json:"userID,string"`
Name string `json:"name"`
Slug string `json:"handle"`
NamespaceID uint64 `json:"namespaceID,string"`
SessionID uint64 `json:"sessionID,string"`
UserID uint64 `json:"userID,string"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
@@ -285,12 +286,14 @@ func (svc namespace) Clone(ctx context.Context, namespaceID uint64, dup *types.N
aProps.setNamespace(targetNs)
// - destination namespace
dstNs, err := store.LookupComposeNamespaceBySlug(ctx, svc.store, dup.Slug)
if err != nil && err != store.ErrNotFound {
return err
}
if dstNs != nil {
return NamespaceErrHandleNotUnique()
if dup.Slug != "" {
dstNs, err := store.LookupComposeNamespaceBySlug(ctx, svc.store, dup.Slug)
if err != nil && err != store.ErrNotFound {
return err
}
if dstNs != nil {
return NamespaceErrHandleNotUnique()
}
}
// Access control
@@ -403,6 +406,8 @@ func (svc namespace) ImportInit(ctx context.Context, f multipart.File, size int6
return NamespaceErrImportMissingNamespace()
}
// session needs to have namespaceID if ns Handle is not provided
session.NamespaceID = ns.ID
session.Name = ns.Name
session.Slug = ns.Slug
namespaceSessionStore[session.SessionID] = session
@@ -425,17 +430,19 @@ func (svc namespace) ImportRun(ctx context.Context, sessionID uint64, dup *types
return err
}
if dup.Slug == "" || !handle.IsValid(dup.Slug) {
if !handle.IsValid(dup.Slug) {
return NamespaceErrInvalidHandle()
}
// check for duplicate
dstNs, err := store.LookupComposeNamespaceBySlug(ctx, svc.store, dup.Slug)
if err != nil && err != store.ErrNotFound {
return err
}
if dstNs != nil {
return NamespaceErrHandleNotUnique()
if dup.Slug != "" {
// check for duplicate
dstNs, err := store.LookupComposeNamespaceBySlug(ctx, svc.store, dup.Slug)
if err != nil && err != store.ErrNotFound {
return err
}
if dstNs != nil {
return NamespaceErrHandleNotUnique()
}
}
// session
@@ -453,7 +460,7 @@ func (svc namespace) ImportRun(ctx context.Context, sessionID uint64, dup *types
aProps.setNamespace(dup)
newNS, err = svc.envoyRun(ctx, session.Resources, &types.Namespace{Slug: session.Slug, Name: session.Name}, dup, encoder)
newNS, err = svc.envoyRun(ctx, session.Resources, &types.Namespace{ID: session.NamespaceID, Slug: session.Slug, Name: session.Name}, dup, encoder)
if err != nil {
return err
}
@@ -85,6 +85,7 @@ func (n *composeChart) Encode(ctx context.Context, doc *Document, state *envoy.R
func (c *composeChart) MarshalYAML() (interface{}, error) {
nn, err := makeMap(
"chartID", c.res.ID,
"handle", c.res.Handle,
"name", c.res.Name,
"config", c.chartConfig,
@@ -58,6 +58,9 @@ func (wrap *composeChart) UnmarshalYAML(n *yaml.Node) (err error) {
return y7s.EachMap(n, func(k, v *yaml.Node) (err error) {
switch k.Value {
case "chartID":
return y7s.DecodeScalar(v, "chart ID", &wrap.res.ID)
case "handle":
return y7s.DecodeScalar(v, "chart handle", &wrap.res.Handle)
@@ -123,6 +123,7 @@ func (c *composeModule) MarshalYAML() (interface{}, error) {
}
nn, err := makeMap(
"moduleID", c.res.ID,
"handle", c.res.Handle,
"name", c.res.Name,
"meta", auxMeta,
@@ -63,6 +63,9 @@ func (wrap *composeModule) UnmarshalYAML(n *yaml.Node) (err error) {
return y7s.EachMap(n, func(k, v *yaml.Node) (err error) {
switch k.Value {
case "moduleID":
return y7s.DecodeScalar(v, "module ID", &wrap.res.ID)
case "name":
return y7s.DecodeScalar(v, "module name", &wrap.res.Name)
@@ -40,6 +40,7 @@ func (c *composeNamespace) MarshalYAML() (interface{}, error) {
var err error
nn, err := makeMap(
"namespaceID", c.res.ID,
"name", c.res.Name,
"slug", c.res.Slug,
"enabled", c.res.Enabled,
@@ -75,6 +75,9 @@ func (wrap *composeNamespace) UnmarshalYAML(n *yaml.Node) (err error) {
return y7s.Each(n, func(k, v *yaml.Node) (err error) {
switch k.Value {
case "namespaceID":
return y7s.DecodeScalar(v, "namespace ID", &wrap.res.ID)
case "modules":
return v.Decode(&wrap.modules)
@@ -73,7 +73,7 @@ func (wrap *composePage) UnmarshalYAML(n *yaml.Node) (err error) {
return y7s.EachMap(n, func(k, v *yaml.Node) (err error) {
switch strings.ToLower(k.Value) {
case "id", "pageid":
case "id", "pageid", "pageID":
return y7s.DecodeScalar(v, "page ID", &wrap.res.ID)
case "title":
+11 -3
View File
@@ -3,9 +3,9 @@ package yaml
import (
"context"
"io"
"regexp"
"strings"
"github.com/cortezaproject/corteza/server/pkg/handle"
"github.com/cortezaproject/corteza/server/pkg/y7s"
. "github.com/cortezaproject/corteza/server/pkg/y7s"
@@ -23,6 +23,10 @@ type (
}
)
var (
validReference = regexp.MustCompile(`^[A-Za-z1-9][0-9A-Za-z_\-.]*[A-Za-z0-9]$`)
)
func Decoder() *decoder {
return &decoder{}
}
@@ -68,10 +72,14 @@ func decodeRef(n *yaml.Node, refType string, ref *string) error {
return y7s.NodeErr(n, "%s reference must be scalar", refType)
}
if !handle.IsValid(n.Value) {
return y7s.NodeErr(n, "%s reference must be a valid handle", refType)
if !IsValidRef(n.Value) {
return y7s.NodeErr(n, "%s reference must be a valid ID or Handle", refType)
}
*ref = n.Value
return nil
}
func IsValidRef(s string) bool {
return len(s) >= 2 && validReference.MatchString(s)
}
@@ -4,12 +4,12 @@ import (
"context"
"fmt"
"sort"
"strconv"
"strings"
composeTypes "github.com/cortezaproject/corteza/server/compose/types"
"github.com/cortezaproject/corteza/server/pkg/envoy"
"github.com/cortezaproject/corteza/server/pkg/envoy/resource"
"github.com/spf13/cast"
"golang.org/x/text/language"
)
@@ -92,7 +92,11 @@ func (r *resourceTranslation) makeResourceTranslationResource(state *envoy.Resou
if p1 == nil {
return "", resource.ComposeNamespaceErrUnresolved(res.RefRes.Identifiers)
}
p1ID = p1.Slug
if p1.Slug == "" {
p1ID = cast.ToString(p1.ID)
} else {
p1ID = p1.Slug
}
}
return fmt.Sprintf(composeTypes.NamespaceResourceTranslationTpl(), composeTypes.NamespaceResourceTranslationType, p1ID), nil
@@ -103,7 +107,12 @@ func (r *resourceTranslation) makeResourceTranslationResource(state *envoy.Resou
if p0 == nil {
return "", resource.ComposeNamespaceErrUnresolved(res.RefPath[0].Identifiers)
}
p0ID = p0.Slug
if p0.Slug == "" {
p0ID = cast.ToString(p0.ID)
} else {
p0ID = p0.Slug
}
}
if res.RefRes != nil {
@@ -111,7 +120,12 @@ func (r *resourceTranslation) makeResourceTranslationResource(state *envoy.Resou
if p1 == nil {
return "", resource.ComposeModuleErrUnresolved(res.RefRes.Identifiers)
}
p1ID = p1.Handle
if p1.Handle == "" {
p1ID = cast.ToString(p1.ID)
} else {
p1ID = p1.Handle
}
}
return fmt.Sprintf(composeTypes.ModuleResourceTranslationTpl(), composeTypes.ModuleResourceTranslationType, p0ID, p1ID), nil
@@ -122,7 +136,12 @@ func (r *resourceTranslation) makeResourceTranslationResource(state *envoy.Resou
if p0 == nil {
return "", resource.ComposeNamespaceErrUnresolved(res.RefPath[0].Identifiers)
}
p0ID = p0.Slug
if p0.Slug == "" {
p0ID = cast.ToString(p0.ID)
} else {
p0ID = p0.Slug
}
}
if res.RefRes != nil {
@@ -132,7 +151,7 @@ func (r *resourceTranslation) makeResourceTranslationResource(state *envoy.Resou
}
if p1.Handle == "" {
p1ID = strconv.FormatUint(p1.ID, 10)
p1ID = cast.ToString(p1.ID)
} else {
p1ID = p1.Handle
}
@@ -145,13 +164,23 @@ func (r *resourceTranslation) makeResourceTranslationResource(state *envoy.Resou
if p0 == nil {
return "", resource.ComposeNamespaceErrUnresolved(res.RefPath[0].Identifiers)
}
p0ID = p0.Slug
if p0.Slug == "" {
p0ID = cast.ToString(p0.ID)
} else {
p0ID = p0.Slug
}
p1 := resource.FindComposeModule(state.ParentResources, res.RefPath[1].Identifiers)
if p1 == nil {
return "", resource.ComposeModuleErrUnresolved(res.RefPath[1].Identifiers)
}
p1ID = p1.Handle
if p1.Handle == "" {
p1ID = cast.ToString(p1.ID)
} else {
p1ID = p1.Handle
}
// field
f := resource.FindComposeModuleField(state.ParentResources, res.RefPath[1].Identifiers, res.RefRes.Identifiers)
@@ -168,7 +197,12 @@ func (r *resourceTranslation) makeResourceTranslationResource(state *envoy.Resou
if p0 == nil {
return "", resource.ComposeNamespaceErrUnresolved(res.RefPath[0].Identifiers)
}
p0ID = p0.Slug
if p0.Slug == "" {
p0ID = cast.ToString(p0.ID)
} else {
p0ID = p0.Slug
}
}
if res.RefRes != nil {
@@ -176,7 +210,12 @@ func (r *resourceTranslation) makeResourceTranslationResource(state *envoy.Resou
if p1 == nil {
return "", resource.ComposeChartErrUnresolved(res.RefRes.Identifiers)
}
p1ID = p1.Handle
if p1.Handle == "" {
p1ID = cast.ToString(p1.ID)
} else {
p1ID = p1.Handle
}
}
return fmt.Sprintf(composeTypes.ChartResourceTranslationTpl(), composeTypes.ChartResourceTranslationType, p0ID, p1ID), nil
+4 -4
View File
@@ -2328,10 +2328,10 @@ var Template = &dal.Model{
},
&dal.Index{
Ident: "templates_uniqueLanguageHandle",
Type: "BTREE",
Unique: true,
Ident: "templates_uniqueLanguageHandle",
Type: "BTREE",
Unique: true,
Predicate: "handle != '' AND deleted_at IS NULL",
Fields: []*dal.IndexField{
{
AttributeIdent: "Language",
+2 -2
View File
@@ -871,7 +871,7 @@ endpoints:
path: "/"
parameters:
post:
- { name: handle, type: "string", required: true }
- { name: handle, type: "string", }
- { name: type, type: "string", required: true }
- { name: meta, type: "types.ConnectionMeta", required: true, parser: "types.ParseConnectionMeta" }
- { name: config, type: "types.ConnectionConfig", required: true, parser: "types.ParseConnectionConfig" }
@@ -883,7 +883,7 @@ endpoints:
parameters:
path: [ { type: uint64, name: connectionID, required: true, title: "Connection ID" } ]
post:
- { name: handle, type: "string", required: true }
- { name: handle, type: "string", }
- { name: type, type: "string", required: true }
- { name: meta, type: "types.ConnectionMeta", required: true, parser: "types.ParseConnectionMeta" }
- { name: config, type: "types.ConnectionConfig", required: true, parser: "types.ParseConnectionConfig" }
+1 -1
View File
@@ -49,11 +49,11 @@ template: {
indexes: {
"primary": { attribute: "id" }
"unique_language_handle": {
unique: true
fields: [
{ attribute: "language" },
{ attribute: "handle", modifier: [ "LOWERCASE" ] }
]
predicate: "handle != '' AND deleted_at IS NULL"
}
}
}