From b2f6deb597968f0e05dc55e2863ab92df5a0618b Mon Sep 17 00:00:00 2001 From: Denis Arh Date: Wed, 16 Oct 2019 19:55:34 +0200 Subject: [PATCH] Refactor read perm check for charts, modules, namespaces & pages --- compose/repository/chart.go | 4 ++++ compose/repository/module.go | 4 ++++ compose/repository/namespace.go | 4 ++++ compose/repository/page.go | 4 ++++ compose/service/access_control.go | 16 ++++++++++++++++ compose/service/chart.go | 9 +++++---- compose/service/module.go | 5 +++++ compose/service/namespace.go | 8 ++++---- compose/service/page.go | 29 ++++++++++++----------------- compose/types/chart.go | 3 +++ compose/types/module.go | 3 +++ compose/types/namespace.go | 3 +++ compose/types/page.go | 3 +++ 13 files changed, 70 insertions(+), 25 deletions(-) diff --git a/compose/repository/chart.go b/compose/repository/chart.go index 0dbe76d21..190153ce6 100644 --- a/compose/repository/chart.go +++ b/compose/repository/chart.go @@ -104,6 +104,10 @@ func (r chart) Find(filter types.ChartFilter) (set types.ChartSet, f types.Chart query = query.Where("LOWER(handle) = ?", strings.ToLower(f.Handle)) } + if f.IsReadable != nil { + query = query.Where(f.IsReadable) + } + if f.Count, err = r.count(query); err != nil || f.Count == 0 { return } diff --git a/compose/repository/module.go b/compose/repository/module.go index 16f31da48..efdb0f1ed 100644 --- a/compose/repository/module.go +++ b/compose/repository/module.go @@ -123,6 +123,10 @@ func (r module) Find(filter types.ModuleFilter) (set types.ModuleSet, f types.Mo query = query.Where("LOWER(handle) = ?", strings.ToLower(f.Handle)) } + if f.IsReadable != nil { + query = query.Where(f.IsReadable) + } + if f.Count, err = r.count(query); err != nil || f.Count == 0 { return } diff --git a/compose/repository/namespace.go b/compose/repository/namespace.go index 06eaded18..43c9c4b68 100644 --- a/compose/repository/namespace.go +++ b/compose/repository/namespace.go @@ -105,6 +105,10 @@ func (r *namespace) Find(filter types.NamespaceFilter) (set types.NamespaceSet, query = query.Where("LOWER(slug) = LOWER(?)", f.Slug) } + if f.IsReadable != nil { + query = query.Where(f.IsReadable) + } + if f.Count, err = r.count(query); err != nil || f.Count == 0 { return } diff --git a/compose/repository/page.go b/compose/repository/page.go index 6f54f28e2..e9d1d897f 100644 --- a/compose/repository/page.go +++ b/compose/repository/page.go @@ -120,6 +120,10 @@ func (r page) Find(filter types.PageFilter) (set types.PageSet, f types.PageFilt query = query.Where("title LIKE ? OR description LIKE ?", q, q) } + if f.IsReadable != nil { + query = query.Where(f.IsReadable) + } + if f.Count, err = r.count(query); err != nil || f.Count == 0 { return } diff --git a/compose/service/access_control.go b/compose/service/access_control.go index a12e7dfff..59b52a95c 100644 --- a/compose/service/access_control.go +++ b/compose/service/access_control.go @@ -68,6 +68,10 @@ func (svc accessControl) CanReadNamespace(ctx context.Context, r *types.Namespac return svc.can(ctx, r, "read", permissions.Allowed) } +func (svc accessControl) FilterReadableNamespaces(ctx context.Context) *permissions.ResourceFilter { + return svc.permissions.ResourceFilter(ctx, types.NamespacePermissionResource, "read", permissions.Deny) +} + func (svc accessControl) CanUpdateNamespace(ctx context.Context, r *types.Namespace) bool { return svc.can(ctx, r, "update") } @@ -92,6 +96,10 @@ func (svc accessControl) CanReadModule(ctx context.Context, r *types.Module) boo return svc.can(ctx, r, "read") } +func (svc accessControl) FilterReadableModules(ctx context.Context) *permissions.ResourceFilter { + return svc.permissions.ResourceFilter(ctx, types.ModulePermissionResource, "read", permissions.Deny) +} + func (svc accessControl) CanUpdateModule(ctx context.Context, r *types.Module) bool { return svc.can(ctx, r, "update") } @@ -136,6 +144,10 @@ func (svc accessControl) CanReadChart(ctx context.Context, r *types.Chart) bool return svc.can(ctx, r, "read") } +func (svc accessControl) FilterReadableCharts(ctx context.Context) *permissions.ResourceFilter { + return svc.permissions.ResourceFilter(ctx, types.ChartPermissionResource, "read", permissions.Deny) +} + func (svc accessControl) CanUpdateChart(ctx context.Context, r *types.Chart) bool { return svc.can(ctx, r, "update") } @@ -153,6 +165,10 @@ func (svc accessControl) CanReadPage(ctx context.Context, r *types.Page) bool { return svc.can(ctx, r, "read") } +func (svc accessControl) FilterReadablePages(ctx context.Context) *permissions.ResourceFilter { + return svc.permissions.ResourceFilter(ctx, types.PagePermissionResource, "read", permissions.Deny) +} + func (svc accessControl) CanUpdatePage(ctx context.Context, r *types.Page) bool { return svc.can(ctx, r, "update") } diff --git a/compose/service/chart.go b/compose/service/chart.go index 0193bd919..a3e9b8f3c 100644 --- a/compose/service/chart.go +++ b/compose/service/chart.go @@ -11,6 +11,7 @@ import ( "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/handle" "github.com/cortezaproject/corteza-server/pkg/logger" + "github.com/cortezaproject/corteza-server/pkg/permissions" ) type ( @@ -31,6 +32,8 @@ type ( CanReadChart(context.Context, *types.Chart) bool CanUpdateChart(context.Context, *types.Chart) bool CanDeleteChart(context.Context, *types.Chart) bool + + FilterReadableCharts(ctx context.Context) *permissions.ResourceFilter } ChartService interface { @@ -99,15 +102,13 @@ func (svc chart) checkPermissions(c *types.Chart, err error) (*types.Chart, erro } func (svc chart) Find(filter types.ChartFilter) (set types.ChartSet, f types.ChartFilter, err error) { + f.IsReadable = svc.ac.FilterReadableCharts(svc.ctx) + set, f, err = svc.chartRepo.Find(filter) if err != nil { return } - set, _ = set.Filter(func(m *types.Chart) (bool, error) { - return svc.ac.CanReadChart(svc.ctx, m), nil - }) - return } diff --git a/compose/service/module.go b/compose/service/module.go index 685e4c066..5ac20bfff 100644 --- a/compose/service/module.go +++ b/compose/service/module.go @@ -11,6 +11,7 @@ import ( "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/handle" "github.com/cortezaproject/corteza-server/pkg/logger" + "github.com/cortezaproject/corteza-server/pkg/permissions" ) type ( @@ -32,6 +33,8 @@ type ( CanReadModule(context.Context, *types.Module) bool CanUpdateModule(context.Context, *types.Module) bool CanDeleteModule(context.Context, *types.Module) bool + + FilterReadableModules(ctx context.Context) *permissions.ResourceFilter } ModuleService interface { @@ -120,6 +123,8 @@ func (svc module) loader(m *types.Module, err error) (*types.Module, error) { } func (svc module) Find(filter types.ModuleFilter) (set types.ModuleSet, f types.ModuleFilter, err error) { + f.IsReadable = svc.ac.FilterReadableModules(svc.ctx) + set, f, err = svc.moduleRepo.Find(filter) if err != nil { return diff --git a/compose/service/namespace.go b/compose/service/namespace.go index 276cdcdce..4d522aefa 100644 --- a/compose/service/namespace.go +++ b/compose/service/namespace.go @@ -32,6 +32,8 @@ type ( CanDeleteNamespace(context.Context, *types.Namespace) bool Grant(ctx context.Context, rr ...*permissions.Rule) error + + FilterReadableNamespaces(ctx context.Context) *permissions.ResourceFilter } NamespaceService interface { @@ -95,15 +97,13 @@ func (svc namespace) checkPermissions(p *types.Namespace, err error) (*types.Nam } func (svc namespace) Find(filter types.NamespaceFilter) (set types.NamespaceSet, f types.NamespaceFilter, err error) { + f.IsReadable = svc.ac.FilterReadableNamespaces(svc.ctx) + set, f, err = svc.namespaceRepo.Find(filter) if err != nil { return } - set, _ = set.Filter(func(ns *types.Namespace) (bool, error) { - return svc.ac.CanReadNamespace(svc.ctx, ns), nil - }) - return } diff --git a/compose/service/page.go b/compose/service/page.go index 13fe3b29b..e3be9f809 100644 --- a/compose/service/page.go +++ b/compose/service/page.go @@ -11,6 +11,7 @@ import ( "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/handle" "github.com/cortezaproject/corteza-server/pkg/logger" + "github.com/cortezaproject/corteza-server/pkg/permissions" ) type ( @@ -32,6 +33,8 @@ type ( CanReadPage(context.Context, *types.Page) bool CanUpdatePage(context.Context, *types.Page) bool CanDeletePage(context.Context, *types.Page) bool + + FilterReadablePages(ctx context.Context) *permissions.ResourceFilter } PageService interface { @@ -118,21 +121,25 @@ func (svc page) FindBySelfID(namespaceID, parentID uint64) (pp types.PageSet, f return nil, f, ErrNamespaceRequired.withStack() } - return svc.filterPageSetByPermission(svc.pageRepo.Find(types.PageFilter{ + return svc.pageRepo.Find(types.PageFilter{ NamespaceID: namespaceID, ParentID: parentID, // This will enable parentID=0 query Root: true, - })) + + IsReadable: svc.ac.FilterReadablePages(svc.ctx), + }) } func (svc page) Find(filter types.PageFilter) (set types.PageSet, f types.PageFilter, err error) { + f.IsReadable = svc.ac.FilterReadablePages(svc.ctx) + if filter.NamespaceID == 0 { return nil, f, ErrNamespaceRequired.withStack() } - return svc.filterPageSetByPermission(svc.pageRepo.Find(filter)) + return svc.pageRepo.Find(filter) } func (svc page) Tree(namespaceID uint64) (pages types.PageSet, err error) { @@ -144,11 +151,12 @@ func (svc page) Tree(namespaceID uint64) (pages types.PageSet, err error) { tree types.PageSet filter = types.PageFilter{ NamespaceID: namespaceID, + IsReadable: svc.ac.FilterReadablePages(svc.ctx), } ) return tree, svc.db.Transaction(func() (err error) { - if pages, _, err = svc.filterPageSetByPermission(svc.pageRepo.Find(filter)); err != nil { + if pages, _, err = svc.pageRepo.Find(filter); err != nil { return } @@ -176,19 +184,6 @@ func (svc page) Tree(namespaceID uint64) (pages types.PageSet, err error) { }) } -func (svc page) filterPageSetByPermission(pp types.PageSet, f types.PageFilter, err error) (types.PageSet, types.PageFilter, error) { - if err != nil { - return nil, f, err - } - - // @todo Filter-by-permission can/will mess up filter's count & paging... - pp, err = pp.Filter(func(m *types.Page) (bool, error) { - return svc.ac.CanReadPage(svc.ctx, m), nil - }) - - return pp, f, err -} - func (svc page) Reorder(namespaceID, selfID uint64, pageIDs []uint64) error { if ns, err := svc.loadNamespace(namespaceID); err != nil { return err diff --git a/compose/types/chart.go b/compose/types/chart.go index 9d629fd7c..756a15f3a 100644 --- a/compose/types/chart.go +++ b/compose/types/chart.go @@ -46,6 +46,9 @@ type ( PerPage uint `json:"perPage"` // Sort string `json:"sort"` Count uint `json:"count"` + + // Resource permission check filter + IsReadable *permissions.ResourceFilter `json:"-"` } ) diff --git a/compose/types/module.go b/compose/types/module.go index 90d5fca1e..359258034 100644 --- a/compose/types/module.go +++ b/compose/types/module.go @@ -32,6 +32,9 @@ type ( PerPage uint `json:"perPage"` // Sort string `json:"sort"` Count uint `json:"count"` + + // Resource permission check filter + IsReadable *permissions.ResourceFilter `json:"-"` } ) diff --git a/compose/types/namespace.go b/compose/types/namespace.go index 737995dcf..3d3ca72bf 100644 --- a/compose/types/namespace.go +++ b/compose/types/namespace.go @@ -30,6 +30,9 @@ type ( PerPage uint `json:"perPage"` Sort string `json:"sort"` Count uint `json:"count"` + + // Resource permission check filter + IsReadable *permissions.ResourceFilter `json:"-"` } NamespaceMeta struct { diff --git a/compose/types/page.go b/compose/types/page.go index e0c6fe197..f39f7bb9f 100644 --- a/compose/types/page.go +++ b/compose/types/page.go @@ -60,6 +60,9 @@ type ( Page uint `json:"page"` PerPage uint `json:"perPage"` Count uint `json:"count"` + + // Resource permission check filter + IsReadable *permissions.ResourceFilter `json:"-"` } )