From 7a7839809dfdc31d29423590dcd289e0b28be0bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toma=C5=BE=20Jerman?= Date: Fri, 11 Oct 2019 13:13:47 +0200 Subject: [PATCH] Add system setting import/export --- system/commands/exporter.go | 135 ++++++++++++++++++++++++++++++++++++ system/importer/default.go | 3 + system/importer/importer.go | 15 +++- system/system.go | 3 + 4 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 system/commands/exporter.go diff --git a/system/commands/exporter.go b/system/commands/exporter.go new file mode 100644 index 000000000..7700f690f --- /dev/null +++ b/system/commands/exporter.go @@ -0,0 +1,135 @@ +package commands + +import ( + "context" + "strings" + + "github.com/pkg/errors" + "github.com/spf13/cobra" + "gopkg.in/yaml.v2" + + "github.com/cortezaproject/corteza-server/pkg/auth" + "github.com/cortezaproject/corteza-server/pkg/cli" + "github.com/cortezaproject/corteza-server/pkg/permissions" + "github.com/cortezaproject/corteza-server/pkg/settings" + "github.com/cortezaproject/corteza-server/system/service" + sysTypes "github.com/cortezaproject/corteza-server/system/types" +) + +func Exporter(ctx context.Context, c *cli.Config) *cobra.Command { + cmd := &cobra.Command{ + Use: "export", + Short: "Export", + Long: `Export system resources`, + + Run: func(cmd *cobra.Command, args []string) { + + c.InitServices(ctx, c) + ctx = auth.SetSuperUserContext(ctx) + + var ( + sFlag = cmd.Flags().Lookup("settings").Changed + pFlag = cmd.Flags().Lookup("permissions").Changed + + out = &System{ + Settings: yaml.MapSlice{}, + } + ) + + if !sFlag && !pFlag { + cli.HandleError(errors.New("Specify setting or permissions flag")) + } + + if pFlag { + permissionExporter(ctx, out) + } + + if sFlag { + settingExporter(ctx, out) + } + + y := yaml.NewEncoder(cmd.OutOrStdout()) + cli.HandleError(y.Encode(out)) + }, + } + + cmd.Flags().BoolP("settings", "s", false, "Export settings") + cmd.Flags().BoolP("permissions", "p", false, "Export permission") + + return cmd +} + +func permissionExporter(ctx context.Context, out *System) { + roles = sysTypes.RoleSet{ + &sysTypes.Role{ID: permissions.EveryoneRoleID, Handle: "everyone"}, + &sysTypes.Role{ID: permissions.AdminsRoleID, Handle: "admins"}, + } + + out.Allow = expServicePermissions(permissions.Allow) + out.Deny = expServicePermissions(permissions.Deny) +} + +func settingExporter(ctx context.Context, out *System) { + var ( + err error + ) + + ss, err := service.DefaultSettings.FindByPrefix("") + cli.HandleError(err) + + out.Settings = settings.Export(ss) +} + +// This is PoC for exporting system resources +// + +type ( + System struct { + Settings yaml.MapSlice `yaml:",omitempty"` + + Allow map[string]map[string][]string `yaml:",omitempty"` + Deny map[string]map[string][]string `yaml:",omitempty"` + } +) + +var ( + roles sysTypes.RoleSet +) + +// @todo move to pkg/permissions +func expServicePermissions(access permissions.Access) map[string]map[string][]string { + var ( + has bool + res string + rules permissions.RuleSet + sp = make(map[string]map[string][]string) + ) + + for _, r := range roles { + rules = service.DefaultPermissions.FindRulesByRoleID(r.ID) + + if len(rules) == 0 { + continue + } + + for _, rule := range rules { + if rule.Resource.GetService() != rule.Resource && !rule.Resource.HasWildcard() { + continue + } + + res = strings.TrimRight(rule.Resource.String(), ":*") + + if _, has = sp[r.Handle]; !has { + sp[r.Handle] = map[string][]string{} + } + + if _, has = sp[r.Handle][res]; !has { + sp[r.Handle][res] = make([]string, 0) + } + + sp[r.Handle][res] = append(sp[r.Handle][res], rule.Operation.String()) + } + } + + return sp +} diff --git a/system/importer/default.go b/system/importer/default.go index 489c66c36..4f3f492ec 100644 --- a/system/importer/default.go +++ b/system/importer/default.go @@ -7,6 +7,7 @@ import ( "gopkg.in/yaml.v2" "github.com/cortezaproject/corteza-server/pkg/permissions" + "github.com/cortezaproject/corteza-server/pkg/settings" "github.com/cortezaproject/corteza-server/system/service" "github.com/cortezaproject/corteza-server/system/types" ) @@ -26,6 +27,7 @@ func Import(ctx context.Context, ff ...io.Reader) (err error) { pi := permissions.NewImporter(service.DefaultAccessControl.Whitelist()) imp := NewImporter( pi, + settings.NewImporter(), NewRoleImport(pi, roles), ) @@ -51,6 +53,7 @@ func Import(ctx context.Context, ff ...io.Reader) (err error) { ctx, service.DefaultRole.With(ctx), service.DefaultAccessControl, + service.DefaultSettings, roles, ) } diff --git a/system/importer/importer.go b/system/importer/importer.go index b9d444c98..0810dc510 100644 --- a/system/importer/importer.go +++ b/system/importer/importer.go @@ -7,13 +7,16 @@ import ( "github.com/cortezaproject/corteza-server/pkg/deinterfacer" "github.com/cortezaproject/corteza-server/pkg/importer" "github.com/cortezaproject/corteza-server/pkg/permissions" + "github.com/cortezaproject/corteza-server/pkg/settings" "github.com/cortezaproject/corteza-server/system/types" + "github.com/pkg/errors" ) type ( Importer struct { roles *Role permissions importer.PermissionImporter + settings importer.SettingImporter } roleFinder interface { @@ -21,10 +24,11 @@ type ( } ) -func NewImporter(p importer.PermissionImporter, ri *Role) *Importer { +func NewImporter(p importer.PermissionImporter, s importer.SettingImporter, ri *Role) *Importer { return &Importer{ roles: ri, permissions: p, + settings: s, } } @@ -39,6 +43,9 @@ func (imp *Importer) Cast(in interface{}) (err error) { case "allow", "deny": return imp.permissions.CastResourcesSet(key, val) + case "settings": + return imp.settings.CastSet(val) + default: err = fmt.Errorf("unexpected key %q", key) } @@ -51,6 +58,7 @@ func (imp *Importer) Store( ctx context.Context, rk roleKeeper, pk permissions.ImportKeeper, + sk settings.ImportKeeper, roles types.RoleSet, ) (err error) { err = imp.roles.Store(ctx, rk) @@ -69,5 +77,10 @@ func (imp *Importer) Store( return } + err = imp.settings.Store(ctx, sk) + if err != nil { + return errors.Wrap(err, "could not import settings") + } + return nil } diff --git a/system/system.go b/system/system.go index 5b54849eb..2c1477acd 100644 --- a/system/system.go +++ b/system/system.go @@ -126,6 +126,9 @@ func Configure() *cli.Config { func(ctx context.Context, c *cli.Config) *cobra.Command { return commands.Importer(ctx, c) }, + func(ctx context.Context, c *cli.Config) *cobra.Command { + return commands.Exporter(ctx, c) + }, func(ctx context.Context, c *cli.Config) *cobra.Command { return commands.Users(ctx, c) },