diff --git a/compose/types/chart.go b/compose/types/chart.go index ffff8aa35..ba8c2cdb1 100644 --- a/compose/types/chart.go +++ b/compose/types/chart.go @@ -3,10 +3,11 @@ package types import ( "database/sql/driver" "encoding/json" + "time" + "github.com/cortezaproject/corteza-server/pkg/filter" "github.com/cortezaproject/corteza-server/pkg/rbac" "github.com/pkg/errors" - "time" ) type ( @@ -45,6 +46,7 @@ type ( NamespaceID uint64 `json:"namespaceID,string"` ChartID []uint64 `json:"chartID"` Handle string `json:"handle"` + Name string `json:"name"` Query string `json:"query"` LabeledIDs []uint64 `json:"-"` diff --git a/compose/types/page.go b/compose/types/page.go index 17f325890..710e5c94c 100644 --- a/compose/types/page.go +++ b/compose/types/page.go @@ -3,9 +3,10 @@ package types import ( "database/sql/driver" "encoding/json" - "github.com/cortezaproject/corteza-server/pkg/filter" "time" + "github.com/cortezaproject/corteza-server/pkg/filter" + "github.com/pkg/errors" "github.com/cortezaproject/corteza-server/pkg/rbac" @@ -59,6 +60,7 @@ type ( ParentID uint64 `json:"parentID,string,omitempty"` Root bool `json:"root,omitempty"` Handle string `json:"handle"` + Title string `json:"title"` Query string `json:"query"` LabeledIDs []uint64 `json:"-"` diff --git a/pkg/envoy/store/application.go b/pkg/envoy/store/application.go index ee9f8cc53..9dc62e61c 100644 --- a/pkg/envoy/store/application.go +++ b/pkg/envoy/store/application.go @@ -157,18 +157,16 @@ func findApplicationS(ctx context.Context, s store.Storer, gf genericFilter) (ap } } - q := gf.handle - if q == "" { - q = gf.name - } - - if q != "" { + for _, i := range gf.identifiers { var aa types.ApplicationSet - aa, _, err = store.SearchApplications(ctx, s, types.ApplicationFilter{Name: q}) + aa, _, err = store.SearchApplications(ctx, s, types.ApplicationFilter{Name: i}) if err != nil && err != store.ErrNotFound { return nil, err } - if len(aa) > 0 { + if len(aa) > 1 { + return nil, resourceErrIdentifierNotUnique(i) + } + if len(aa) == 1 { ap = aa[0] return } diff --git a/pkg/envoy/store/compose_chart.go b/pkg/envoy/store/compose_chart.go index 0fe634ebb..49f158da8 100644 --- a/pkg/envoy/store/compose_chart.go +++ b/pkg/envoy/store/compose_chart.go @@ -8,6 +8,7 @@ import ( "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/envoy" "github.com/cortezaproject/corteza-server/pkg/envoy/resource" + "github.com/cortezaproject/corteza-server/pkg/filter" "github.com/cortezaproject/corteza-server/store" ) @@ -202,6 +203,10 @@ func findComposeChartRS(ctx context.Context, s store.Storer, nsID uint64, rr res // findComposeChartS looks for the chart in the store func findComposeChartS(ctx context.Context, s store.Storer, nsID uint64, gf genericFilter) (ch *types.Chart, err error) { + if nsID == 0 { + return nil, nil + } + if gf.id > 0 { ch, err = store.LookupComposeChartByID(ctx, s, gf.id) if err != nil && err != store.ErrNotFound { @@ -213,8 +218,25 @@ func findComposeChartS(ctx context.Context, s store.Storer, nsID uint64, gf gene } } - if gf.handle != "" { - ch, err = store.LookupComposeChartByNamespaceIDHandle(ctx, s, nsID, gf.handle) + for _, i := range gf.identifiers { + ch, err = store.LookupComposeChartByNamespaceIDHandle(ctx, s, nsID, i) + if err == store.ErrNotFound { + var cc types.ChartSet + cc, _, err = store.SearchComposeCharts(ctx, s, types.ChartFilter{ + NamespaceID: nsID, + Name: i, + Paging: filter.Paging{ + Limit: 2, + }, + }) + if len(cc) > 1 { + return nil, resourceErrIdentifierNotUnique(i) + } + if len(cc) == 1 { + ch = cc[0] + } + } + if err != nil && err != store.ErrNotFound { return nil, err } diff --git a/pkg/envoy/store/compose_module.go b/pkg/envoy/store/compose_module.go index be635c019..2fdb10bf9 100644 --- a/pkg/envoy/store/compose_module.go +++ b/pkg/envoy/store/compose_module.go @@ -9,6 +9,7 @@ import ( "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/envoy" "github.com/cortezaproject/corteza-server/pkg/envoy/resource" + "github.com/cortezaproject/corteza-server/pkg/filter" "github.com/cortezaproject/corteza-server/store" ) @@ -309,6 +310,10 @@ func findComposeModuleRS(ctx context.Context, s store.Storer, nsID uint64, rr re // findComposeModuleS looks for the module in the store func findComposeModuleS(ctx context.Context, s store.Storer, nsID uint64, gf genericFilter) (mod *types.Module, err error) { + if nsID == 0 { + return nil, nil + } + if gf.id > 0 { mod, err = store.LookupComposeModuleByID(ctx, s, gf.id) if err != nil && err != store.ErrNotFound { @@ -320,8 +325,25 @@ func findComposeModuleS(ctx context.Context, s store.Storer, nsID uint64, gf gen } } - if gf.handle != "" { - mod, err = store.LookupComposeModuleByNamespaceIDHandle(ctx, s, nsID, gf.handle) + for _, i := range gf.identifiers { + mod, err = store.LookupComposeModuleByNamespaceIDHandle(ctx, s, nsID, i) + if err == store.ErrNotFound { + var mm types.ModuleSet + mm, _, err = store.SearchComposeModules(ctx, s, types.ModuleFilter{ + NamespaceID: nsID, + Name: i, + Paging: filter.Paging{ + Limit: 2, + }, + }) + if len(mm) > 1 { + return nil, resourceErrIdentifierNotUnique(i) + } + if len(mm) == 1 { + mod = mm[0] + } + } + if err != nil && err != store.ErrNotFound { return nil, err } diff --git a/pkg/envoy/store/compose_namespace.go b/pkg/envoy/store/compose_namespace.go index 98358b317..17b89188e 100644 --- a/pkg/envoy/store/compose_namespace.go +++ b/pkg/envoy/store/compose_namespace.go @@ -8,6 +8,7 @@ import ( "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/envoy" "github.com/cortezaproject/corteza-server/pkg/envoy/resource" + "github.com/cortezaproject/corteza-server/pkg/filter" "github.com/cortezaproject/corteza-server/store" ) @@ -158,8 +159,24 @@ func findComposeNamespaceS(ctx context.Context, s store.Storer, gf genericFilter } } - if gf.handle != "" { - ns, err = store.LookupComposeNamespaceBySlug(ctx, s, gf.handle) + for _, i := range gf.identifiers { + ns, err = store.LookupComposeNamespaceBySlug(ctx, s, i) + if err == store.ErrNotFound { + var nn types.NamespaceSet + nn, _, err = store.SearchComposeNamespaces(ctx, s, types.NamespaceFilter{ + Name: i, + Paging: filter.Paging{ + Limit: 2, + }, + }) + if len(nn) > 1 { + return nil, resourceErrIdentifierNotUnique(i) + } + if len(nn) == 1 { + ns = nn[0] + } + } + if err != nil && err != store.ErrNotFound { return nil, err } diff --git a/pkg/envoy/store/compose_page.go b/pkg/envoy/store/compose_page.go index 199ab1ef0..ced594590 100644 --- a/pkg/envoy/store/compose_page.go +++ b/pkg/envoy/store/compose_page.go @@ -9,6 +9,7 @@ import ( "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/envoy" "github.com/cortezaproject/corteza-server/pkg/envoy/resource" + "github.com/cortezaproject/corteza-server/pkg/filter" "github.com/cortezaproject/corteza-server/store" ) @@ -338,6 +339,10 @@ func findComposePageRS(ctx context.Context, s store.Storer, nsID uint64, rr reso // findComposePageS looks for the page in the store func findComposePageS(ctx context.Context, s store.Storer, nsID uint64, gf genericFilter) (pg *types.Page, err error) { + if nsID == 0 { + return nil, nil + } + if gf.id > 0 { pg, err = store.LookupComposePageByID(ctx, s, gf.id) if err != nil && err != store.ErrNotFound { @@ -349,8 +354,25 @@ func findComposePageS(ctx context.Context, s store.Storer, nsID uint64, gf gener } } - if gf.handle != "" { - pg, err = store.LookupComposePageByNamespaceIDHandle(ctx, s, nsID, gf.handle) + for _, i := range gf.identifiers { + pg, err = store.LookupComposePageByNamespaceIDHandle(ctx, s, nsID, i) + if err == store.ErrNotFound { + var pp types.PageSet + pp, _, err = store.SearchComposePages(ctx, s, types.PageFilter{ + NamespaceID: nsID, + Title: i, + Paging: filter.Paging{ + Limit: 2, + }, + }) + if len(pp) > 1 { + return nil, resourceErrIdentifierNotUnique(i) + } + if len(pp) == 1 { + pg = pp[0] + } + } + if err != nil && err != store.ErrNotFound { return nil, err } diff --git a/pkg/envoy/store/encoder.go b/pkg/envoy/store/encoder.go index 5ed105fc3..f78c46f8f 100644 --- a/pkg/envoy/store/encoder.go +++ b/pkg/envoy/store/encoder.go @@ -156,3 +156,7 @@ func (se *storeEncoder) WrapError(act string, res resource.Interface, err error) rt := strings.Join(strings.Split(strings.TrimSpace(strings.TrimRight(res.ResourceType(), ":")), ":"), " ") return fmt.Errorf("store encoder %s %s %v: %s", act, rt, res.Identifiers().StringSlice(), err) } + +func resourceErrIdentifierNotUnique(i string) error { + return fmt.Errorf("bad resource identifier %v: not unique", i) +} diff --git a/pkg/envoy/store/messaging_channel.go b/pkg/envoy/store/messaging_channel.go index bdce089b0..a991ce63e 100644 --- a/pkg/envoy/store/messaging_channel.go +++ b/pkg/envoy/store/messaging_channel.go @@ -178,18 +178,16 @@ func findMessagingChannelS(ctx context.Context, s store.Storer, gf genericFilter } } - q := gf.handle - if q == "" { - q = gf.name - } - - if q != "" { + for _, i := range gf.identifiers { var aa types.ChannelSet - aa, _, err = store.SearchMessagingChannels(ctx, s, types.ChannelFilter{Query: q}) + aa, _, err = store.SearchMessagingChannels(ctx, s, types.ChannelFilter{Query: i}) if err != nil && err != store.ErrNotFound { return nil, err } - if len(aa) > 0 { + if len(aa) > 1 { + return nil, resourceErrIdentifierNotUnique(i) + } + if len(aa) == 1 { ap = aa[0] return } diff --git a/pkg/envoy/store/role.go b/pkg/envoy/store/role.go index 366f9fe8a..9e579b8f5 100644 --- a/pkg/envoy/store/role.go +++ b/pkg/envoy/store/role.go @@ -7,6 +7,7 @@ import ( "github.com/cortezaproject/corteza-server/pkg/envoy" "github.com/cortezaproject/corteza-server/pkg/envoy/resource" + "github.com/cortezaproject/corteza-server/pkg/filter" "github.com/cortezaproject/corteza-server/store" "github.com/cortezaproject/corteza-server/system/types" ) @@ -155,8 +156,24 @@ func findRoleS(ctx context.Context, s store.Storer, gf genericFilter) (rl *types } } - if gf.handle != "" { - rl, err = store.LookupRoleByHandle(ctx, s, gf.handle) + for _, i := range gf.identifiers { + rl, err = store.LookupRoleByHandle(ctx, s, i) + if err == store.ErrNotFound { + var rr types.RoleSet + rr, _, err = store.SearchRoles(ctx, s, types.RoleFilter{ + Name: i, + Paging: filter.Paging{ + Limit: 2, + }, + }) + if len(rr) > 1 { + return nil, resourceErrIdentifierNotUnique(i) + } + if len(rr) == 1 { + rl = rr[0] + } + } + if err != nil && err != store.ErrNotFound { return nil, err } diff --git a/pkg/envoy/store/user.go b/pkg/envoy/store/user.go index 621e26475..a3a294d4c 100644 --- a/pkg/envoy/store/user.go +++ b/pkg/envoy/store/user.go @@ -3,6 +3,7 @@ package store import ( "context" "fmt" + "net/mail" "time" "github.com/cortezaproject/corteza-server/pkg/envoy" @@ -169,8 +170,22 @@ func findUserS(ctx context.Context, s store.Storer, gf genericFilter) (u *types. } } - if gf.handle != "" { - u, err = store.LookupUserByHandle(ctx, s, gf.handle) + for _, i := range gf.identifiers { + // email + if _, err = mail.ParseAddress(i); err != nil { + u, err = store.LookupUserByEmail(ctx, s, i) + if err == store.ErrNotFound { + return nil, nil + } else if err != nil { + return nil, err + } + } + + // Handle & username + u, err = store.LookupUserByHandle(ctx, s, i) + if err == store.ErrNotFound { + u, err = store.LookupUserByUsername(ctx, s, i) + } if err != nil && err != store.ErrNotFound { return nil, err } diff --git a/pkg/envoy/store/util.go b/pkg/envoy/store/util.go index 06dd65ebf..871739b16 100644 --- a/pkg/envoy/store/util.go +++ b/pkg/envoy/store/util.go @@ -8,16 +8,14 @@ import ( "github.com/cortezaproject/corteza-server/pkg/envoy/resource" "github.com/cortezaproject/corteza-server/pkg/expr" - "github.com/cortezaproject/corteza-server/pkg/handle" "github.com/cortezaproject/corteza-server/pkg/id" "github.com/cortezaproject/corteza-server/store" ) type ( genericFilter struct { - id uint64 - handle string - name string + id uint64 + identifiers []string } ) @@ -49,10 +47,8 @@ func makeGenericFilter(ii resource.Identifiers) (f genericFilter) { continue } f.id = id - } else if handle.IsValid(i) && f.handle == "" { - f.handle = i - } else if f.name == "" { - f.name = i + } else { + f.identifiers = append(f.identifiers, i) } } diff --git a/store/rdbms/compose_charts.go b/store/rdbms/compose_charts.go index 81be9a7fb..673ba3f0a 100644 --- a/store/rdbms/compose_charts.go +++ b/store/rdbms/compose_charts.go @@ -1,10 +1,11 @@ package rdbms import ( + "strings" + "github.com/Masterminds/squirrel" "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/filter" - "strings" ) func (s Store) convertComposeChartFilter(f types.ChartFilter) (query squirrel.SelectBuilder, err error) { @@ -36,5 +37,9 @@ func (s Store) convertComposeChartFilter(f types.ChartFilter) (query squirrel.Se query = query.Where(squirrel.Eq{"LOWER(cch.handle)": strings.ToLower(f.Handle)}) } + if f.Name != "" { + query = query.Where(squirrel.Eq{"LOWER(cch.name)": strings.ToLower(f.Name)}) + } + return } diff --git a/store/rdbms/compose_pages.go b/store/rdbms/compose_pages.go index 9110d0801..aa1653bcc 100644 --- a/store/rdbms/compose_pages.go +++ b/store/rdbms/compose_pages.go @@ -2,11 +2,12 @@ package rdbms import ( "context" + "strings" + "github.com/Masterminds/squirrel" "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/filter" "github.com/cortezaproject/corteza-server/store" - "strings" ) func (s Store) convertComposePageFilter(f types.PageFilter) (query squirrel.SelectBuilder, err error) { @@ -41,6 +42,10 @@ func (s Store) convertComposePageFilter(f types.PageFilter) (query squirrel.Sele query = query.Where(squirrel.Eq{"LOWER(cpg.handle)": strings.ToLower(f.Handle)}) } + if f.Title != "" { + query = query.Where(squirrel.Eq{"LOWER(cpg.title)": strings.ToLower(f.Title)}) + } + return }