From c6bb0afc9fbe46ee9de1b5b937401027e865396c Mon Sep 17 00:00:00 2001 From: Denis Arh Date: Mon, 11 Mar 2019 21:35:01 +0100 Subject: [PATCH] Basic checks added --- crm/service/permissions.go | 160 ++++++++++++++++++++++++++++++++++++- crm/types/chart.go | 13 +++ crm/types/namespace.go | 22 +++++ crm/types/trigger.go | 13 +++ crm/types/types.go | 35 ++++++++ internal/rules/resource.go | 3 + 6 files changed, 242 insertions(+), 4 deletions(-) create mode 100644 crm/types/namespace.go diff --git a/crm/service/permissions.go b/crm/service/permissions.go index 87412887e..447899656 100644 --- a/crm/service/permissions.go +++ b/crm/service/permissions.go @@ -3,7 +3,10 @@ package service import ( "context" + "github.com/davecgh/go-spew/spew" + "github.com/crusttech/crust/crm/repository" + "github.com/crusttech/crust/crm/types" internalRules "github.com/crusttech/crust/internal/rules" systemService "github.com/crusttech/crust/system/service" ) @@ -16,13 +19,49 @@ type ( rules systemService.RulesService } + resource interface { + Resource() internalRules.Resource + } + PermissionsService interface { With(context.Context) PermissionsService CanAccessCompose() bool + CanCreateNamspace() bool + CanCreateModule() bool + CanReadModule(r resource) bool + CanUpdateModule(r resource) bool + CanDeleteModule(r resource) bool + CanDeleteModuleByID(ID uint64) bool + CanCreateRecord(r resource) bool + CanReadRecord(r resource) bool + CanUpdateRecord(r resource) bool + CanDeleteRecord(r resource) bool + CanDeleteRecordByModuleID(ID uint64) bool + CanCreateChart() bool + CanReadChart(r resource) bool + CanUpdateChart(r resource) bool + CanDeleteChart(r resource) bool + CanDeleteChartByID(ID uint64) bool + CanCreateTrigger() bool + CanReadTrigger(r resource) bool + CanUpdateTrigger(r resource) bool + CanDeleteTrigger(r resource) bool + CanDeleteTriggerByID(ID uint64) bool + CanCreatePage() bool + CanReadPage(r resource) bool + CanUpdatePage(r resource) bool + CanDeletePage(r resource) bool + CanDeletePageByID(ID uint64) bool } + + Compose struct{} ) +func (Compose) Resource() internalRules.Resource { + return internalRules.Resource{Service: "compose"} +} + func Permissions() PermissionsService { return (&permissions{ rules: systemService.DefaultRules, @@ -39,16 +78,129 @@ func (p *permissions) With(ctx context.Context) PermissionsService { } } +func (p *permissions) baseResource() resource { + return &Compose{} +} + func (p *permissions) CanAccessCompose() bool { - return p.checkAccess("compose", "access") + spew.Dump(p.baseResource().Resource().String()) + return p.checkAccess(p.baseResource(), "access") } func (p *permissions) CanCreateNamspace() bool { - return p.checkAccess("compose", "namespace.create") + return p.checkAccess(p.baseResource(), "namespace.create") } -func (p *permissions) checkAccess(resource string, operation string, fallbacks ...internalRules.CheckAccessFunc) bool { - access := p.rules.Check(resource, operation, fallbacks...) +func (p *permissions) CanCreateModule() bool { + // @todo move to func args when namespaces are implemented + ns := &types.Namespace{ID: "crm"} + return p.checkAccess(ns, "module.create") +} + +func (p *permissions) CanReadModule(r resource) bool { + return p.checkAccess(r, "read") +} + +func (p *permissions) CanUpdateModule(r resource) bool { + return p.checkAccess(r, "update") +} + +func (p *permissions) CanDeleteModule(r resource) bool { + return p.checkAccess(r, "delete") +} + +func (p *permissions) CanDeleteModuleByID(ID uint64) bool { + return p.CanDeleteModule(&types.Module{ID: ID}) +} + +func (p *permissions) CanCreateRecord(r resource) bool { + return p.checkAccess(r, "record.create") +} + +func (p *permissions) CanReadRecord(r resource) bool { + return p.checkAccess(r, "record.read") +} + +func (p *permissions) CanUpdateRecord(r resource) bool { + return p.checkAccess(r, "record.update") +} + +func (p *permissions) CanDeleteRecord(r resource) bool { + return p.checkAccess(r, "record.delete") +} + +func (p *permissions) CanDeleteRecordByModuleID(moduleID uint64) bool { + return p.CanDeleteRecord(&types.Record{ModuleID: moduleID}) +} + +func (p *permissions) CanCreateChart() bool { + // @todo move to func args when namespaces are implemented + ns := &types.Namespace{ID: "crm"} + return p.checkAccess(ns, "chart.create") +} + +func (p *permissions) CanReadChart(r resource) bool { + return p.checkAccess(r, "read") +} + +func (p *permissions) CanUpdateChart(r resource) bool { + return p.checkAccess(r, "update") +} + +func (p *permissions) CanDeleteChart(r resource) bool { + return p.checkAccess(r, "delete") +} + +func (p *permissions) CanDeleteChartByID(ID uint64) bool { + return p.CanDeleteChart(&types.Chart{ID: ID}) +} + +func (p *permissions) CanCreateTrigger() bool { + // @todo move to func args when namespaces are implemented + ns := &types.Namespace{ID: "crm"} + return p.checkAccess(ns, "trigger.create") +} + +func (p *permissions) CanReadTrigger(r resource) bool { + return p.checkAccess(r, "read") +} + +func (p *permissions) CanUpdateTrigger(r resource) bool { + return p.checkAccess(r, "update") +} + +func (p *permissions) CanDeleteTrigger(r resource) bool { + return p.checkAccess(r, "delete") +} + +func (p *permissions) CanDeleteTriggerByID(ID uint64) bool { + return p.CanDeleteTrigger(&types.Trigger{ID: ID}) +} + +func (p *permissions) CanCreatePage() bool { + // @todo move to func args when namespaces are implemented + ns := &types.Namespace{ID: "crm"} + return p.checkAccess(ns, "page.create") +} + +func (p *permissions) CanReadPage(r resource) bool { + return p.checkAccess(r, "read") +} + +func (p *permissions) CanUpdatePage(r resource) bool { + return p.checkAccess(r, "update") +} + +func (p *permissions) CanDeletePage(r resource) bool { + return p.checkAccess(r, "delete") +} + +func (p *permissions) CanDeletePageByID(ID uint64) bool { + return p.CanDeletePage(&types.Page{ID: ID}) +} + +func (p *permissions) checkAccess(resource resource, operation string, fallbacks ...internalRules.CheckAccessFunc) bool { + access := p.rules.Check(resource.Resource().String(), operation, fallbacks...) if access == internalRules.Allow { return true } diff --git a/crm/types/chart.go b/crm/types/chart.go index 67e0836ac..65182dfb9 100644 --- a/crm/types/chart.go +++ b/crm/types/chart.go @@ -4,6 +4,8 @@ import ( "time" "github.com/jmoiron/sqlx/types" + + "github.com/crusttech/crust/internal/rules" ) type ( @@ -18,3 +20,14 @@ type ( DeletedAt *time.Time `db:"deleted_at" json:"deletedAt,omitempty"` } ) + +// Resource returns a system resource ID for this type +func (r *Chart) Resource() rules.Resource { + resource := rules.Resource{ + Service: "compose", + Scope: "page", + ID: r.ID, + } + + return resource +} diff --git a/crm/types/namespace.go b/crm/types/namespace.go new file mode 100644 index 000000000..a9b7f674c --- /dev/null +++ b/crm/types/namespace.go @@ -0,0 +1,22 @@ +package types + +import ( + "github.com/crusttech/crust/internal/rules" +) + +type ( + Namespace struct { + ID string `json:"id,string" db:"id"` + } +) + +// Resource returns a system resource ID for this type +func (r *Namespace) Resource() rules.Resource { + resource := rules.Resource{ + Service: "compose", + // Hardcoded single namespace (CRM) for now + Scope: "namespace:crm", + } + + return resource +} diff --git a/crm/types/trigger.go b/crm/types/trigger.go index 809080574..14b4c4018 100644 --- a/crm/types/trigger.go +++ b/crm/types/trigger.go @@ -4,6 +4,8 @@ import ( "database/sql/driver" "strings" "time" + + "github.com/crusttech/crust/internal/rules" ) type ( @@ -43,3 +45,14 @@ func (set *ActionSet) Scan(src interface{}) error { func (set ActionSet) Value() (driver.Value, error) { return strings.Trim(strings.Join(set, ","), " ,"), nil } + +// Resource returns a system resource ID for this type +func (r *Trigger) Resource() rules.Resource { + resource := rules.Resource{ + Service: "compose", + Scope: "trigger", + ID: r.ID, + } + + return resource +} diff --git a/crm/types/types.go b/crm/types/types.go index 9ac208a2f..f872a79e8 100644 --- a/crm/types/types.go +++ b/crm/types/types.go @@ -6,6 +6,8 @@ import ( "time" "github.com/jmoiron/sqlx/types" + + "github.com/crusttech/crust/internal/rules" ) type ( @@ -192,3 +194,36 @@ func (set RecordValueSet) FilterByRecordID(recordID uint64) (vv RecordValueSet) return } + +// Resource returns a system resource ID for this type +func (r *Module) Resource() rules.Resource { + resource := rules.Resource{ + Service: "compose", + Scope: "module", + ID: r.ID, + } + + return resource +} + +// Resource returns a system resource ID for this type +func (r *Record) Resource() rules.Resource { + resource := rules.Resource{ + Service: "compose", + Scope: "module", // intentionally using module here so we can use Record's resource + ID: r.ModuleID, + } + + return resource +} + +// Resource returns a system resource ID for this type +func (r *Page) Resource() rules.Resource { + resource := rules.Resource{ + Service: "compose", + Scope: "page", + ID: r.ID, + } + + return resource +} diff --git a/internal/rules/resource.go b/internal/rules/resource.go index 725a036e5..b58686ffd 100644 --- a/internal/rules/resource.go +++ b/internal/rules/resource.go @@ -24,7 +24,10 @@ type ResourceJSON struct { func (r Resource) String() string { if r.ID > 0 { return fmt.Sprintf("%s:%s:%d", r.Service, r.Scope, r.ID) + } else if r.Scope == "" { + return r.Service } + return "" }