From 908e232ac4039696f4940c9f7f9110622baff287 Mon Sep 17 00:00:00 2001 From: Denis Arh Date: Fri, 24 May 2019 12:38:45 +0200 Subject: [PATCH] More flexible "system", move to Corteza - more control over starting procedure, cli commands... - fix package paths - remove separated system-cli entrypoint - renaming symbols, comments, strings from Crust to Corteza --- system/cli/cli.go | 41 --- system/cli/roles.go | 83 ----- system/{cli => commands}/auth.go | 35 +- system/commands/commands.go | 11 + system/commands/roles.go | 81 +++++ system/{cli => commands}/settings.go | 94 +++-- system/{cli => commands}/users.go | 36 +- system/db/migrate.go | 10 +- system/db/migrate_test.go | 18 +- system/flags.go | 54 --- system/internal/auth/external/external.go | 4 +- system/internal/auth/external/main_test.go | 2 +- system/internal/auth/external/register.go | 4 +- system/internal/auth/external/settings.go | 6 +- .../internal/auth/external/settings_test.go | 2 +- system/internal/repository/application.go | 19 +- .../internal/repository/application_test.go | 6 +- system/internal/repository/credentials.go | 2 +- .../internal/repository/credentials_test.go | 6 +- system/internal/repository/error.go | 2 +- system/internal/repository/main_test.go | 13 +- .../internal/repository/mocks/credentials.go | 7 +- system/internal/repository/mocks/user.go | 9 +- system/internal/repository/organisation.go | 2 +- .../internal/repository/organisation_test.go | 6 +- system/internal/repository/repository.go | 2 +- system/internal/repository/repository_test.go | 2 +- system/internal/repository/role.go | 2 +- system/internal/repository/role_test.go | 6 +- system/internal/repository/user.go | 2 +- system/internal/repository/user_test.go | 6 +- system/internal/service/access_control.go | 4 +- system/internal/service/application.go | 4 +- system/internal/service/auth.go | 8 +- system/internal/service/auth_notification.go | 10 +- system/internal/service/auth_settings.go | 4 +- system/internal/service/auth_test.go | 8 +- system/internal/service/error.go | 2 +- system/internal/service/main_test.go | 15 +- system/internal/service/organisation.go | 12 +- system/internal/service/role.go | 12 +- system/internal/service/service.go | 22 +- system/internal/service/settings.go | 12 +- system/internal/service/user.go | 16 +- system/provision.go | 26 -- system/rest/application.go | 6 +- system/rest/auth.go | 10 +- system/rest/auth_external.go | 12 +- system/rest/auth_internal.go | 12 +- system/rest/handlers/application.go | 4 +- system/rest/handlers/auth.go | 4 +- system/rest/handlers/auth_internal.go | 4 +- system/rest/handlers/organisation.go | 4 +- system/rest/handlers/permissions.go | 4 +- system/rest/handlers/role.go | 4 +- system/rest/handlers/settings.go | 4 +- system/rest/handlers/user.go | 4 +- system/rest/organisation.go | 6 +- system/rest/permissions.go | 6 +- system/rest/request/permissions.go | 2 +- system/rest/request/user.go | 2 +- system/rest/request/util.go | 6 +- system/rest/role.go | 8 +- system/rest/router.go | 37 +- system/rest/settings.go | 6 +- system/rest/user.go | 6 +- system/routes.go | 37 -- system/routes_test.go | 343 ------------------ system/service/init.go | 2 +- system/service/user.go | 4 +- system/start.go | 116 ------ system/system.go | 167 +++++++++ system/types/application.gen_test.go | 2 +- system/types/applications.go | 3 +- system/types/credentials.gen_test.go | 2 +- system/types/organisation.gen_test.go | 2 +- system/types/organisation.go | 2 +- system/types/permission_resources.go | 2 +- system/types/role.gen_test.go | 2 +- system/types/role.go | 2 +- system/types/user.gen_test.go | 2 +- system/types/user.go | 5 +- 82 files changed, 570 insertions(+), 1002 deletions(-) delete mode 100644 system/cli/cli.go delete mode 100644 system/cli/roles.go rename system/{cli => commands}/auth.go (75%) create mode 100644 system/commands/commands.go create mode 100644 system/commands/roles.go rename system/{cli => commands}/settings.go (72%) rename system/{cli => commands}/users.go (81%) delete mode 100644 system/flags.go delete mode 100644 system/provision.go delete mode 100644 system/routes.go delete mode 100644 system/routes_test.go delete mode 100644 system/start.go create mode 100644 system/system.go diff --git a/system/cli/cli.go b/system/cli/cli.go deleted file mode 100644 index 7c6490815..000000000 --- a/system/cli/cli.go +++ /dev/null @@ -1,41 +0,0 @@ -package cli - -import ( - "context" - "fmt" - "os" - - "github.com/spf13/cobra" - - "github.com/crusttech/crust/internal/settings" - "github.com/crusttech/crust/system/internal/repository" -) - -func StartCLI(ctx context.Context) { - var ( - db = repository.DB(ctx) - settingsService = settings.NewService(settings.NewRepository(db, "sys_settings")) - - cmd = &cobra.Command{Use: "system-cli"} - ) - - cmd.AddCommand( - settingsCmd(ctx, settingsService), - authCmd(ctx, db, settingsService), - usersCmd(ctx, db), - rolesCmd(ctx, db), - ) - - if err := cmd.Execute(); err != nil { - fmt.Println(err) - } -} - -func exit(cmd *cobra.Command, err error) { - if err != nil { - cmd.Printf("Error: %v\n", err) - os.Exit(1) - } else { - os.Exit(0) - } -} diff --git a/system/cli/roles.go b/system/cli/roles.go deleted file mode 100644 index 92a8f21c1..000000000 --- a/system/cli/roles.go +++ /dev/null @@ -1,83 +0,0 @@ -package cli - -import ( - "context" - "strconv" - - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/titpetric/factory" - - "github.com/crusttech/crust/system/internal/repository" - "github.com/crusttech/crust/system/types" -) - -func rolesCmd(ctx context.Context, db *factory.DB) *cobra.Command { - cmd := &cobra.Command{ - Use: "roles", - Short: "Role management", - } - - addUserCmd := &cobra.Command{ - Use: "useradd [role-ID-or-name-or-handle] [user-ID-or-email]", - Short: "Add user to role", - Args: cobra.ExactArgs(2), - Run: rolesUserAddCmd(ctx, db), - } - - cmd.AddCommand(addUserCmd) - - return cmd -} - -func rolesUserAddCmd(ctx context.Context, db *factory.DB) func(cmd *cobra.Command, args []string) { - return func(cmd *cobra.Command, args []string) { - // Create role and user repository. - var ( - roleStr, userStr = args[0], args[1] - - roleRepo = repository.Role(ctx, db) - userRepo = repository.User(ctx, db) - - rr []*types.Role - role *types.Role - user *types.User - ID uint64 - - err error - ) - - // Try to find role by name and by ID - if rr, err = roleRepo.Find(&types.RoleFilter{Query: roleStr}); err != nil { - exit(cmd, err) - } else if len(rr) == 1 { - role = rr[0] - } else if len(rr) > 1 { - exit(cmd, errors.Errorf("too many roles found with name %q", roleStr)) - } else if role == nil { - if ID, err = strconv.ParseUint(roleStr, 10, 64); err != nil { - // Could not parse ID out of role string - return - } else if role, err = roleRepo.FindByID(ID); err != nil { - return - } - } - - if user, err = userRepo.FindByEmail(userStr); repository.ErrUserNotFound.Eq(err) { - exit(cmd, err) - } else if user == nil || user.ID == 0 { - if ID, err = strconv.ParseUint(userStr, 10, 64); err != nil { - exit(cmd, err) - } else if user, err = userRepo.FindByID(ID); err != nil { - exit(cmd, err) - } - } - - // Add user to role. - if err = roleRepo.MemberAddByID(role.ID, user.ID); err != nil { - exit(cmd, err) - } - - cmd.Printf("Added user [%d] %q to [%d] %q role\n", user.ID, user.Email, role.ID, role.Name) - } -} diff --git a/system/cli/auth.go b/system/commands/auth.go similarity index 75% rename from system/cli/auth.go rename to system/commands/auth.go index 89cca0902..b5121fa55 100644 --- a/system/cli/auth.go +++ b/system/commands/auth.go @@ -1,4 +1,4 @@ -package cli +package commands import ( "context" @@ -8,16 +8,15 @@ import ( "github.com/spf13/cobra" "github.com/titpetric/factory" - "github.com/crusttech/crust/internal/auth" - "github.com/crusttech/crust/internal/settings" - "github.com/crusttech/crust/system/internal/auth/external" - "github.com/crusttech/crust/system/internal/repository" - "github.com/crusttech/crust/system/internal/service" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/internal/auth" + "github.com/cortezaproject/corteza-server/system/internal/auth/external" + "github.com/cortezaproject/corteza-server/system/internal/repository" + "github.com/cortezaproject/corteza-server/system/internal/service" + "github.com/cortezaproject/corteza-server/system/types" ) // Will perform OpenID connect auto-configuration -func authCmd(ctx context.Context, db *factory.DB, settingsService settings.Service) *cobra.Command { +func Auth(ctx context.Context) *cobra.Command { cmd := &cobra.Command{ Use: "auth", Short: "External authentication", @@ -30,14 +29,14 @@ func authCmd(ctx context.Context, db *factory.DB, settingsService settings.Servi Run: func(cmd *cobra.Command, args []string) { var name, url = args[0], args[1] - if eas, err := external.ExternalAuthSettings(settingsService); err != nil { - exit(cmd, err) + if eas, err := external.ExternalAuthSettings(service.DefaultIntSettings); err != nil { + exit(err) } else if eap, err := external.RegisterNewOpenIdClient(ctx, eas, name, url); err != nil { - exit(cmd, err) + exit(err) } else if vv, err := eap.MakeValueSet("openid-connect." + name); err != nil { - exit(cmd, err) - } else if err := settingsService.BulkSet(vv); err != nil { - exit(cmd, err) + exit(err) + } else if err := service.DefaultIntSettings.BulkSet(vv); err != nil { + exit(err) } }, } @@ -48,6 +47,8 @@ func authCmd(ctx context.Context, db *factory.DB, settingsService settings.Servi Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { var ( + db = factory.Database.MustGet("system") + userRepo = repository.User(ctx, db) roleRepo = repository.Role(ctx, db) // authSvc = service.Auth(ctx) @@ -73,7 +74,7 @@ func authCmd(ctx context.Context, db *factory.DB, settingsService settings.Servi } if err != nil { - exit(cmd, err) + exit(err) } user.SetRoles(rr.IDs()) @@ -94,12 +95,12 @@ func authCmd(ctx context.Context, db *factory.DB, settingsService settings.Servi err = ntf.EmailConfirmation("en", args[0], "notification-testing-token") if err != nil { - exit(cmd, err) + exit(err) } err = ntf.PasswordReset("en", args[0], "notification-testing-token") if err != nil { - exit(cmd, err) + exit(err) } }, diff --git a/system/commands/commands.go b/system/commands/commands.go new file mode 100644 index 000000000..a821257df --- /dev/null +++ b/system/commands/commands.go @@ -0,0 +1,11 @@ +package commands + +import ( + "fmt" + "os" +) + +func exit(err error) { + fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(1) +} diff --git a/system/commands/roles.go b/system/commands/roles.go new file mode 100644 index 000000000..47bad18eb --- /dev/null +++ b/system/commands/roles.go @@ -0,0 +1,81 @@ +package commands + +import ( + "context" + "strconv" + + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/titpetric/factory" + + "github.com/cortezaproject/corteza-server/system/internal/repository" + "github.com/cortezaproject/corteza-server/system/types" +) + +func Roles(ctx context.Context) *cobra.Command { + cmd := &cobra.Command{ + Use: "roles", + Short: "Role management", + } + + addUserCmd := &cobra.Command{ + Use: "useradd [role-ID-or-name-or-handle] [user-ID-or-email]", + Short: "Add user to role", + Args: cobra.ExactArgs(2), + Run: func(cmd *cobra.Command, args []string) { + // Create role and user repository. + var ( + db = factory.Database.MustGet("system") + + roleStr, userStr = args[0], args[1] + + roleRepo = repository.Role(ctx, db) + userRepo = repository.User(ctx, db) + + rr []*types.Role + role *types.Role + user *types.User + ID uint64 + + err error + ) + + // Try to find role by name and by ID + if rr, err = roleRepo.Find(&types.RoleFilter{Query: roleStr}); err != nil { + exit(err) + } else if len(rr) == 1 { + role = rr[0] + } else if len(rr) > 1 { + exit(errors.Errorf("too many roles found with name %q", roleStr)) + } else if role == nil { + if ID, err = strconv.ParseUint(roleStr, 10, 64); err != nil { + // Could not parse ID out of role string + return + } else if role, err = roleRepo.FindByID(ID); err != nil { + return + } + } + + if user, err = userRepo.FindByEmail(userStr); repository.ErrUserNotFound.Eq(err) { + exit(err) + } else if user == nil || user.ID == 0 { + if ID, err = strconv.ParseUint(userStr, 10, 64); err != nil { + exit(err) + } else if user, err = userRepo.FindByID(ID); err != nil { + exit(err) + } + } + + // Add user to role. + if err = roleRepo.MemberAddByID(role.ID, user.ID); err != nil { + exit(err) + } + + cmd.Printf("Added user [%d] %q to [%d] %q role\n", user.ID, user.Email, role.ID, role.Name) + }, + } + + cmd.AddCommand(addUserCmd) + + return cmd +} diff --git a/system/cli/settings.go b/system/commands/settings.go similarity index 72% rename from system/cli/settings.go rename to system/commands/settings.go index b95c5064a..eb1236316 100644 --- a/system/cli/settings.go +++ b/system/commands/settings.go @@ -1,4 +1,4 @@ -package cli +package commands import ( "context" @@ -8,46 +8,72 @@ import ( "github.com/spf13/cobra" - "github.com/crusttech/crust/internal/rand" - "github.com/crusttech/crust/internal/settings" - systemService "github.com/crusttech/crust/system/internal/service" + "github.com/cortezaproject/corteza-server/internal/rand" + "github.com/cortezaproject/corteza-server/internal/settings" + "github.com/cortezaproject/corteza-server/system/internal/service" ) -func settingsCmd(ctx context.Context, setSvc settings.Service) *cobra.Command { - cmd := &cobra.Command{ - Use: "settings", - Short: "Settings management", - } +func Settings(ctx context.Context) *cobra.Command { + var ( + systemApiUrl, authFrontendUrl, authFromAddress, authFromName string + + cmd = &cobra.Command{ + Use: "settings", + Short: "Settings management", + } + ) auto := &cobra.Command{ Use: "auto-configure", Short: "Run autoconfiguration", Run: func(cmd *cobra.Command, args []string) { - systemService.DefaultSettings.LoadAuthSettings() + _, _ = service.DefaultSettings.LoadAuthSettings() settingsAutoConfigure( cmd, - setSvc, - cmd.Flags().Lookup("system-api-url").Value.String(), - cmd.Flags().Lookup("auth-frontend-url").Value.String(), - cmd.Flags().Lookup("auth-from-address").Value.String(), - cmd.Flags().Lookup("auth-from-address").Value.String(), + systemApiUrl, + authFrontendUrl, + authFromAddress, + authFromName, ) }, } - auto.Flags().String("system-api-url", "", "System API URL (http://sytem.api.example.tld)") - auto.Flags().String("auth-frontend-url", "", "http://example.tld") - auto.Flags().String("auth-from-address", "", "name@example.tld") - auto.Flags().String("auth-from-name", "", "Name Surname") + auto.Flags().StringVar( + &systemApiUrl, + "system-api-url", + "", + "System API URL (http://sytem.api.example.tld)", + ) + + auto.Flags().StringVar( + &authFrontendUrl, + "auth-frontend-url", + "", + "http://example.tld", + ) + + auto.Flags().StringVar( + &authFromAddress, + "auth-from-address", + "", + "name@example.tld", + ) + + auto.Flags().StringVar( + &authFromName, + "auth-from-name", + "", + "Name Surname", + ) list := &cobra.Command{ Use: "list", Short: "List all", Run: func(cmd *cobra.Command, args []string) { prefix := cmd.Flags().Lookup("prefix").Value.String() - if kv, err := setSvc.FindByPrefix(prefix); err != nil { - exit(cmd, err) + if kv, err := service.DefaultIntSettings.FindByPrefix(prefix); err != nil { + exit(err) } else { for _, v := range kv { cmd.Printf("%s\t%v\n", v.Name, v.Value) @@ -64,12 +90,12 @@ func settingsCmd(ctx context.Context, setSvc settings.Service) *cobra.Command { Short: "Get value (raw JSON) for a specific key", Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { - if v, err := setSvc.Get(args[0], 0); err != nil { - exit(cmd, err) + if v, err := service.DefaultIntSettings.Get(args[0], 0); err != nil { + exit(err) } else if v != nil { cmd.Printf("%v\n", v.Value) } - exit(cmd, nil) + exit(nil) }, } @@ -84,10 +110,10 @@ func settingsCmd(ctx context.Context, setSvc settings.Service) *cobra.Command { } if err := v.SetValueAsString(value); err != nil { - exit(cmd, err) + exit(err) } - exit(cmd, setSvc.Set(v)) + exit(service.DefaultIntSettings.Set(v)) }, } @@ -96,7 +122,7 @@ func settingsCmd(ctx context.Context, setSvc settings.Service) *cobra.Command { Short: "Set value (raw JSON) for a specific key", Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { - exit(cmd, setSvc.Delete(args[0], 0)) + exit(service.DefaultIntSettings.Delete(args[0], 0)) }, } @@ -111,7 +137,7 @@ func settingsCmd(ctx context.Context, setSvc settings.Service) *cobra.Command { return cmd } -func settingsAutoConfigure(cmd *cobra.Command, setSvc settings.Service, systemApiUrl, frontendUrl, fromAddress, fromName string) { +func settingsAutoConfigure(cmd *cobra.Command, systemApiUrl, frontendUrl, fromAddress, fromName string) { set := func(name string, value interface{}) { var ( v *settings.Value @@ -137,14 +163,14 @@ func settingsAutoConfigure(cmd *cobra.Command, setSvc settings.Service, systemAp } } - err = setSvc.Set(v) + err = service.DefaultIntSettings.Set(v) if err != nil { cmd.Printf("could not store setting: %v", err) } } setIfMissing := func(name string, value interface{}) { - if existing, err := setSvc.Get(name, 0); err == nil && existing == nil { + if existing, err := service.DefaultIntSettings.Get(name, 0); err == nil && existing == nil { set(name, value) } } @@ -178,8 +204,8 @@ func settingsAutoConfigure(cmd *cobra.Command, setSvc settings.Service, systemAp setIfMissing("auth.external.session-store-secure", func() interface{} { // Try to determines if we need secure session store from redirect URL scheme - extRedirUrl, _ := setSvc.GetGlobalString("auth.external.redirect-url") - return strings.Index(extRedirUrl, "https://") > -1 + extRedirUrl, _ := service.DefaultIntSettings.GetGlobalString("auth.external.redirect-url") + return strings.Contains(extRedirUrl, "https://") }) if len(frontendUrl) > 0 { @@ -205,7 +231,7 @@ func settingsAutoConfigure(cmd *cobra.Command, setSvc settings.Service, systemAp if len(fromAddress) > 0 { return fromAddress } - return "change-me@local.crust.tech" + return "change-me@example.tld" }) setIfMissing("auth.mail.from-name", func() interface{} { @@ -213,7 +239,7 @@ func settingsAutoConfigure(cmd *cobra.Command, setSvc settings.Service, systemAp return fromName } - return "Crust Team" + return "Corteza Team" }) // No external providers preconfigured, so disable diff --git a/system/cli/users.go b/system/commands/users.go similarity index 81% rename from system/cli/users.go rename to system/commands/users.go index 3609dd6eb..f9a8f279b 100644 --- a/system/cli/users.go +++ b/system/commands/users.go @@ -1,4 +1,4 @@ -package cli +package commands import ( "context" @@ -9,12 +9,12 @@ import ( "github.com/titpetric/factory" "golang.org/x/crypto/ssh/terminal" - "github.com/crusttech/crust/system/internal/repository" - "github.com/crusttech/crust/system/internal/service" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/system/internal/repository" + "github.com/cortezaproject/corteza-server/system/internal/service" + "github.com/cortezaproject/corteza-server/system/types" ) -func usersCmd(ctx context.Context, db *factory.DB) *cobra.Command { +func Users(ctx context.Context) *cobra.Command { // User management commands. cmd := &cobra.Command{ Use: "users", @@ -26,6 +26,10 @@ func usersCmd(ctx context.Context, db *factory.DB) *cobra.Command { Use: "list", Short: "List users", Run: func(cmd *cobra.Command, args []string) { + var ( + db = factory.Database.MustGet("system") + ) + userRepo := repository.User(ctx, db) uf := &types.UserFilter{ OrderBy: "updated_at", @@ -33,7 +37,7 @@ func usersCmd(ctx context.Context, db *factory.DB) *cobra.Command { users, err := userRepo.Find(uf) if err != nil { - exit(cmd, err) + exit(err) } fmt.Println(" Created Updated EmailAddress") @@ -61,6 +65,8 @@ func usersCmd(ctx context.Context, db *factory.DB) *cobra.Command { Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { var ( + db = factory.Database.MustGet("system") + userRepo = repository.User(ctx, db) authSvc = service.Auth(ctx) @@ -72,23 +78,23 @@ func usersCmd(ctx context.Context, db *factory.DB) *cobra.Command { ) if user, err = userRepo.Create(user); err != nil { - exit(cmd, err) + exit(err) } cmd.Printf("User created [%d].\n", user.ID) cmd.Print("Set password: ") if password, err = terminal.ReadPassword(syscall.Stdin); err != nil { - exit(cmd, err) + exit(err) } if len(password) == 0 { // Password not set, that's ok too. - exit(cmd, nil) + exit(nil) } if err = authSvc.SetPassword(user.ID, string(password)); err != nil { - exit(cmd, err) + exit(err) } }, } @@ -99,6 +105,8 @@ func usersCmd(ctx context.Context, db *factory.DB) *cobra.Command { Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { var ( + db = factory.Database.MustGet("system") + userRepo = repository.User(ctx, db) authSvc = service.Auth(ctx) @@ -108,21 +116,21 @@ func usersCmd(ctx context.Context, db *factory.DB) *cobra.Command { ) if user, err = userRepo.FindByEmail(args[0]); err != nil { - exit(cmd, err) + exit(err) } cmd.Print("Set password: ") if password, err = terminal.ReadPassword(syscall.Stdin); err != nil { - exit(cmd, err) + exit(err) } if len(password) == 0 { // Password not set, that's ok too. - exit(cmd, nil) + exit(nil) } if err = authSvc.SetPassword(user.ID, string(password)); err != nil { - exit(cmd, err) + exit(err) } }, } diff --git a/system/db/migrate.go b/system/db/migrate.go index f362bec37..2c481784d 100644 --- a/system/db/migrate.go +++ b/system/db/migrate.go @@ -13,7 +13,7 @@ import ( "github.com/pkg/errors" "github.com/titpetric/factory" - "github.com/crusttech/crust/system/db/mysql" + "github.com/cortezaproject/corteza-server/system/db/mysql" ) func statements(contents []byte, err error) ([]string, error) { @@ -31,13 +31,17 @@ func Migrate(db *factory.DB) error { var files []string - if err := fs.Walk(statikFS, "/", func(filename string, info os.FileInfo, err error) error { + fn := func(filename string, info os.FileInfo, err error) error { + _ = err matched, err := filepath.Match("/*.up.sql", filename) if matched { files = append(files, filename) } + return err - }); err != nil { + } + + if err := fs.Walk(statikFS, "/", fn); err != nil { return errors.Wrap(err, "Error when listing files for migrations") } diff --git a/system/db/migrate_test.go b/system/db/migrate_test.go index 008aad3ad..5773dff39 100644 --- a/system/db/migrate_test.go +++ b/system/db/migrate_test.go @@ -3,27 +3,17 @@ package db import ( + "os" "testing" - "github.com/namsral/flag" "github.com/titpetric/factory" ) func TestMigrations(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - return - } + factory.Database.Add("system", os.Getenv("SYSTEM_DB_DSN")) + db := factory.Database.MustGet("system") + db.Profiler = &factory.Database.ProfilerStdout - var dsn string - - flag.StringVar(&dsn, "db-dsn", "crust:crust@tcp(crust-db:3306)/crust?collation=utf8mb4_general_ci", "DSN for database connection") - flag.Parse() - - factory.Database.Add("default", dsn) - factory.Database.Add("system", dsn) - - db := factory.Database.MustGet() if err := Migrate(db); err != nil { t.Fatalf("Unexpected error: %#v", err) } diff --git a/system/flags.go b/system/flags.go deleted file mode 100644 index e78fce8af..000000000 --- a/system/flags.go +++ /dev/null @@ -1,54 +0,0 @@ -package service - -import ( - "github.com/pkg/errors" - - "github.com/crusttech/crust/internal/config" -) - -type ( - appFlags struct { - smtp *config.SMTP - http *config.HTTP - monitor *config.Monitor - db *config.Database - jwt *config.JWT - } -) - -var flags *appFlags - -func (c *appFlags) Validate() error { - if c == nil { - return errors.New("Flags are not initialized, need to call Flags()") - } - if err := c.http.Validate(); err != nil { - return err - } - if err := c.smtp.Validate(); err != nil { - return err - } - if err := c.monitor.Validate(); err != nil { - return err - } - if err := c.db.Validate(); err != nil { - return err - } - return nil -} - -func Flags(prefix ...string) { - if flags != nil { - return - } - if len(prefix) == 0 { - panic("Flags() needs prefix on first call") - } - flags = &appFlags{ - new(config.SMTP).Init(prefix...), - new(config.HTTP).Init(prefix...), - new(config.Monitor).Init(prefix...), - new(config.Database).Init(prefix...), - new(config.JWT).Init(), - } -} diff --git a/system/internal/auth/external/external.go b/system/internal/auth/external/external.go index 40623c644..87567997a 100644 --- a/system/internal/auth/external/external.go +++ b/system/internal/auth/external/external.go @@ -3,8 +3,8 @@ package external import ( "go.uber.org/zap" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/internal/settings" + "github.com/cortezaproject/corteza-server/internal/logger" + "github.com/cortezaproject/corteza-server/internal/settings" ) func Init(settingsService settings.Service) { diff --git a/system/internal/auth/external/main_test.go b/system/internal/auth/external/main_test.go index 6ef980618..1a5bb247d 100644 --- a/system/internal/auth/external/main_test.go +++ b/system/internal/auth/external/main_test.go @@ -6,7 +6,7 @@ import ( "go.uber.org/zap/zapcore" - "github.com/crusttech/crust/internal/logger" + "github.com/cortezaproject/corteza-server/internal/logger" ) func TestMain(m *testing.M) { diff --git a/system/internal/auth/external/register.go b/system/internal/auth/external/register.go index 79623d28a..3e2267944 100644 --- a/system/internal/auth/external/register.go +++ b/system/internal/auth/external/register.go @@ -7,6 +7,8 @@ import ( "github.com/crusttech/go-oidc" ) +// @todo remove dependency on github.com/crusttech/go-oidc (and github.com/coreos/go-oidc) +// and move client registration to corteza codebase func RegisterNewOpenIdClient(ctx context.Context, eas *externalAuthSettings, name, url string) (eap *externalAuthProvider, err error) { var ( provider *oidc.Provider @@ -19,7 +21,7 @@ func RegisterNewOpenIdClient(ctx context.Context, eas *externalAuthSettings, nam } client, err = provider.RegisterClient(ctx, &oidc.ClientRegistration{ - Name: "Crust", + Name: "Corteza", RedirectURIs: []string{redirectUrl}, ResponseTypes: []string{"token id_token", "code"}, }) diff --git a/system/internal/auth/external/settings.go b/system/internal/auth/external/settings.go index 3966cb050..f93f7e3eb 100644 --- a/system/internal/auth/external/settings.go +++ b/system/internal/auth/external/settings.go @@ -8,8 +8,8 @@ import ( "github.com/pkg/errors" - "github.com/crusttech/crust/internal/rand" - intset "github.com/crusttech/crust/internal/settings" + "github.com/cortezaproject/corteza-server/internal/rand" + intset "github.com/cortezaproject/corteza-server/internal/settings" ) const ( @@ -28,8 +28,6 @@ type ( sessionStoreSecret string sessionStoreSecure bool providers map[string]externalAuthProvider - - service intset.Service } externalAuthProvider struct { diff --git a/system/internal/auth/external/settings_test.go b/system/internal/auth/external/settings_test.go index 3d7eb22bc..f06162ab9 100644 --- a/system/internal/auth/external/settings_test.go +++ b/system/internal/auth/external/settings_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - intset "github.com/crusttech/crust/internal/settings" + intset "github.com/cortezaproject/corteza-server/internal/settings" "github.com/jmoiron/sqlx/types" ) diff --git a/system/internal/repository/application.go b/system/internal/repository/application.go index 7e6154538..95e5f1091 100644 --- a/system/internal/repository/application.go +++ b/system/internal/repository/application.go @@ -6,7 +6,7 @@ import ( "github.com/titpetric/factory" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/system/types" ) type ( @@ -26,8 +26,7 @@ type ( *repository // sql table reference - applications string - members string + table string } ) @@ -44,13 +43,13 @@ func Application(ctx context.Context, db *factory.DB) ApplicationRepository { func (r *application) With(ctx context.Context, db *factory.DB) ApplicationRepository { return &application{ - repository: r.repository.With(ctx, db), - applications: "sys_application", + repository: r.repository.With(ctx, db), + table: "sys_application", } } func (r *application) FindByID(id uint64) (*types.Application, error) { - sql := "SELECT " + sqlApplicationColumns + " FROM " + r.applications + " WHERE id = ? AND " + sqlApplicationScope + sql := "SELECT " + sqlApplicationColumns + " FROM " + r.table + " WHERE id = ? AND " + sqlApplicationScope mod := &types.Application{} return mod, isFound(r.db().Get(mod, sql, id), mod.ID > 0, ErrApplicationNotFound) @@ -60,7 +59,7 @@ func (r *application) Find() (types.ApplicationSet, error) { rval := make([]*types.Application, 0) params := make([]interface{}, 0) - sql := "SELECT " + sqlApplicationColumns + " FROM " + r.applications + " WHERE " + sqlApplicationScope + sql := "SELECT " + sqlApplicationColumns + " FROM " + r.table + " WHERE " + sqlApplicationScope sql += " ORDER BY id ASC" @@ -71,15 +70,15 @@ func (r *application) Create(mod *types.Application) (*types.Application, error) mod.ID = factory.Sonyflake.NextID() mod.CreatedAt = time.Now() - return mod, r.db().Insert(r.applications, mod) + return mod, r.db().Insert(r.table, mod) } func (r *application) Update(mod *types.Application) (*types.Application, error) { mod.UpdatedAt = timeNowPtr() - return mod, r.db().Replace(r.applications, mod) + return mod, r.db().Replace(r.table, mod) } func (r *application) DeleteByID(id uint64) error { - return r.updateColumnByID(r.applications, "deleted_at", time.Now(), id) + return r.updateColumnByID(r.table, "deleted_at", time.Now(), id) } diff --git a/system/internal/repository/application_test.go b/system/internal/repository/application_test.go index d7180ef27..b85d35fe5 100644 --- a/system/internal/repository/application_test.go +++ b/system/internal/repository/application_test.go @@ -9,8 +9,8 @@ import ( "github.com/pkg/errors" "github.com/titpetric/factory" - "github.com/crusttech/crust/internal/test" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/internal/test" + "github.com/cortezaproject/corteza-server/system/types" ) func TestApplication(t *testing.T) { @@ -19,7 +19,7 @@ func TestApplication(t *testing.T) { return } - db := factory.Database.MustGet() + db := factory.Database.MustGet("system") // Create application repository. crepo := Application(context.Background(), db) diff --git a/system/internal/repository/credentials.go b/system/internal/repository/credentials.go index 9a5d804a0..669a850c4 100644 --- a/system/internal/repository/credentials.go +++ b/system/internal/repository/credentials.go @@ -7,7 +7,7 @@ import ( "github.com/titpetric/factory" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/system/types" ) type ( diff --git a/system/internal/repository/credentials_test.go b/system/internal/repository/credentials_test.go index 1e5203c71..2194992f3 100644 --- a/system/internal/repository/credentials_test.go +++ b/system/internal/repository/credentials_test.go @@ -9,8 +9,8 @@ import ( "github.com/pkg/errors" "github.com/titpetric/factory" - "github.com/crusttech/crust/internal/test" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/internal/test" + "github.com/cortezaproject/corteza-server/system/types" ) func TestCredentials(t *testing.T) { @@ -19,7 +19,7 @@ func TestCredentials(t *testing.T) { return } - db := factory.Database.MustGet() + db := factory.Database.MustGet("system") // Create credentials repository. crepo := Credentials(context.Background(), db) diff --git a/system/internal/repository/error.go b/system/internal/repository/error.go index 3de0dcb6b..0dabf8a07 100644 --- a/system/internal/repository/error.go +++ b/system/internal/repository/error.go @@ -14,7 +14,7 @@ func (e repositoryError) Error() string { } func (e repositoryError) String() string { - return "crust.system.repository." + string(e) + return "system.repository." + string(e) } func (e repositoryError) Eq(err error) bool { diff --git a/system/internal/repository/main_test.go b/system/internal/repository/main_test.go index 1d43b51ab..daf943307 100644 --- a/system/internal/repository/main_test.go +++ b/system/internal/repository/main_test.go @@ -7,21 +7,14 @@ import ( "os" "testing" - "github.com/namsral/flag" "github.com/titpetric/factory" - systemMigrate "github.com/crusttech/crust/system/db" + systemMigrate "github.com/cortezaproject/corteza-server/system/db" ) func TestMain(m *testing.M) { - dsn := "" - flag.StringVar(&dsn, "db-dsn", "crust:crust@tcp(crust-db:3306)/crust?collation=utf8mb4_general_ci", "DSN for database connection") - flag.Parse() - - factory.Database.Add("default", dsn) - factory.Database.Add("system", dsn) - - db := factory.Database.MustGet() + factory.Database.Add("system", os.Getenv("SYSTEM_DB_DSN")) + db := factory.Database.MustGet("system") db.Profiler = &factory.Database.ProfilerStdout // migrate database schema diff --git a/system/internal/repository/mocks/credentials.go b/system/internal/repository/mocks/credentials.go index b4f620eb5..6f3cded9d 100644 --- a/system/internal/repository/mocks/credentials.go +++ b/system/internal/repository/mocks/credentials.go @@ -6,11 +6,12 @@ package repository import ( context "context" - repository "github.com/crusttech/crust/system/internal/repository" - types "github.com/crusttech/crust/system/types" + reflect "reflect" + + repository "github.com/cortezaproject/corteza-server/system/internal/repository" + types "github.com/cortezaproject/corteza-server/system/types" gomock "github.com/golang/mock/gomock" factory "github.com/titpetric/factory" - reflect "reflect" ) // MockCredentialsRepository is a mock of CredentialsRepository interface diff --git a/system/internal/repository/mocks/user.go b/system/internal/repository/mocks/user.go index 83a1d1868..01fe56cb8 100644 --- a/system/internal/repository/mocks/user.go +++ b/system/internal/repository/mocks/user.go @@ -6,12 +6,13 @@ package repository import ( context "context" - repository "github.com/crusttech/crust/system/internal/repository" - types "github.com/crusttech/crust/system/types" - gomock "github.com/golang/mock/gomock" - factory "github.com/titpetric/factory" io "io" reflect "reflect" + + repository "github.com/cortezaproject/corteza-server/system/internal/repository" + types "github.com/cortezaproject/corteza-server/system/types" + gomock "github.com/golang/mock/gomock" + factory "github.com/titpetric/factory" ) // MockUserRepository is a mock of UserRepository interface diff --git a/system/internal/repository/organisation.go b/system/internal/repository/organisation.go index a5ed40657..de2bd6e98 100644 --- a/system/internal/repository/organisation.go +++ b/system/internal/repository/organisation.go @@ -6,7 +6,7 @@ import ( "github.com/titpetric/factory" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/system/types" ) type ( diff --git a/system/internal/repository/organisation_test.go b/system/internal/repository/organisation_test.go index 70f83e3b3..8f4dd1aa3 100644 --- a/system/internal/repository/organisation_test.go +++ b/system/internal/repository/organisation_test.go @@ -9,8 +9,8 @@ import ( "github.com/pkg/errors" "github.com/titpetric/factory" - "github.com/crusttech/crust/internal/test" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/internal/test" + "github.com/cortezaproject/corteza-server/system/types" ) func TestOrganisation(t *testing.T) { @@ -19,7 +19,7 @@ func TestOrganisation(t *testing.T) { return } - db := factory.Database.MustGet() + db := factory.Database.MustGet("system") // Run tests in transaction to maintain DB state. test.Error(t, db.Transaction(func() error { diff --git a/system/internal/repository/repository.go b/system/internal/repository/repository.go index a58e4016e..64993a25f 100644 --- a/system/internal/repository/repository.go +++ b/system/internal/repository/repository.go @@ -5,7 +5,7 @@ import ( "github.com/titpetric/factory" - "github.com/crusttech/crust/internal/auth" + "github.com/cortezaproject/corteza-server/internal/auth" ) type ( diff --git a/system/internal/repository/repository_test.go b/system/internal/repository/repository_test.go index 52ad121c8..1998c4de7 100644 --- a/system/internal/repository/repository_test.go +++ b/system/internal/repository/repository_test.go @@ -6,7 +6,7 @@ import ( "context" "testing" - "github.com/crusttech/crust/internal/test" + "github.com/cortezaproject/corteza-server/internal/test" ) func TestRepository(t *testing.T) { diff --git a/system/internal/repository/role.go b/system/internal/repository/role.go index 84970f8f4..8b7374249 100644 --- a/system/internal/repository/role.go +++ b/system/internal/repository/role.go @@ -6,7 +6,7 @@ import ( "github.com/titpetric/factory" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/system/types" ) type ( diff --git a/system/internal/repository/role_test.go b/system/internal/repository/role_test.go index 740f252aa..fecf0c2b9 100644 --- a/system/internal/repository/role_test.go +++ b/system/internal/repository/role_test.go @@ -9,8 +9,8 @@ import ( "github.com/pkg/errors" "github.com/titpetric/factory" - "github.com/crusttech/crust/internal/test" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/internal/test" + "github.com/cortezaproject/corteza-server/system/types" ) func TestRole(t *testing.T) { @@ -19,7 +19,7 @@ func TestRole(t *testing.T) { return } - db := factory.Database.MustGet() + db := factory.Database.MustGet("system") test.Error(t, db.Transaction(func() error { userRepo := User(context.Background(), db) diff --git a/system/internal/repository/user.go b/system/internal/repository/user.go index 9d47ebbcb..fcc67ed92 100644 --- a/system/internal/repository/user.go +++ b/system/internal/repository/user.go @@ -9,7 +9,7 @@ import ( "github.com/jmoiron/sqlx" "github.com/titpetric/factory" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/system/types" ) type ( diff --git a/system/internal/repository/user_test.go b/system/internal/repository/user_test.go index 9b815b20e..e85ae103a 100644 --- a/system/internal/repository/user_test.go +++ b/system/internal/repository/user_test.go @@ -9,8 +9,8 @@ import ( "github.com/pkg/errors" "github.com/titpetric/factory" - "github.com/crusttech/crust/internal/test" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/internal/test" + "github.com/cortezaproject/corteza-server/system/types" ) func TestUser(t *testing.T) { @@ -19,7 +19,7 @@ func TestUser(t *testing.T) { return } - db := factory.Database.MustGet() + db := factory.Database.MustGet("system") // Run tests in transaction to maintain DB state. test.Error(t, db.Transaction(func() error { diff --git a/system/internal/service/access_control.go b/system/internal/service/access_control.go index 1ba41c8a9..8522060ac 100644 --- a/system/internal/service/access_control.go +++ b/system/internal/service/access_control.go @@ -3,8 +3,8 @@ package service import ( "context" - "github.com/crusttech/crust/internal/permissions" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/internal/permissions" + "github.com/cortezaproject/corteza-server/system/types" ) type ( diff --git a/system/internal/service/application.go b/system/internal/service/application.go index 300167126..a924f4ce4 100644 --- a/system/internal/service/application.go +++ b/system/internal/service/application.go @@ -6,8 +6,8 @@ import ( "github.com/pkg/errors" "github.com/titpetric/factory" - "github.com/crusttech/crust/system/internal/repository" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/system/internal/repository" + "github.com/cortezaproject/corteza-server/system/types" ) type ( diff --git a/system/internal/service/auth.go b/system/internal/service/auth.go index 9674d74a2..a59b63231 100644 --- a/system/internal/service/auth.go +++ b/system/internal/service/auth.go @@ -13,10 +13,10 @@ import ( "go.uber.org/zap/zapcore" "golang.org/x/crypto/bcrypt" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/internal/rand" - "github.com/crusttech/crust/system/internal/repository" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/internal/logger" + "github.com/cortezaproject/corteza-server/internal/rand" + "github.com/cortezaproject/corteza-server/system/internal/repository" + "github.com/cortezaproject/corteza-server/system/types" ) type ( diff --git a/system/internal/service/auth_notification.go b/system/internal/service/auth_notification.go index 0425fa33e..59e52a2e4 100644 --- a/system/internal/service/auth_notification.go +++ b/system/internal/service/auth_notification.go @@ -9,8 +9,8 @@ import ( "go.uber.org/zap/zapcore" gomail "gopkg.in/mail.v2" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/internal/mail" + "github.com/cortezaproject/corteza-server/internal/logger" + "github.com/cortezaproject/corteza-server/internal/mail" ) type ( @@ -68,7 +68,7 @@ var (

If you have any questions, please contact {{ .SignatureEmail }}.

-

We hope you enjoy using Crust!

+

We hope you enjoy using Corteza!

Best regards,
{{ .SignatureName }}

@@ -87,7 +87,7 @@ var ( // @todo Temporary email template storage emailTemplates = map[string]string{ - "email-confirmation.en.subject": `[Crust] Confirm your email address`, + "email-confirmation.en.subject": `[Corteza] Confirm your email address`, "email-confirmation.en.html": emailTemplateHeader + `

Confirm your email address

Hello,

@@ -95,7 +95,7 @@ var (

You will be logged-in after successful confirmation.

` + emailTemplateFooter, - "password-reset.en.subject": `[Crust] Reset your password`, + "password-reset.en.subject": `[Corteza] Reset your password`, "password-reset.en.html": emailTemplateHeader + `

Reset your password

Hello,

diff --git a/system/internal/service/auth_settings.go b/system/internal/service/auth_settings.go index c1682a043..43ee59390 100644 --- a/system/internal/service/auth_settings.go +++ b/system/internal/service/auth_settings.go @@ -87,8 +87,8 @@ func (s authSettings) Format() map[string]interface{} { } switch label { - case "crust-iam": - label = "Crust Unify" + case "corteza-iam": + label = "Corteza Unify" case "facebook": label = "Facebook" case "gplus": diff --git a/system/internal/service/auth_test.go b/system/internal/service/auth_test.go index 90edbfea4..813befe9a 100644 --- a/system/internal/service/auth_test.go +++ b/system/internal/service/auth_test.go @@ -9,10 +9,10 @@ import ( "go.uber.org/zap" "golang.org/x/crypto/bcrypt" - "github.com/crusttech/crust/internal/test" - "github.com/crusttech/crust/system/internal/repository" - repomock "github.com/crusttech/crust/system/internal/repository/mocks" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/internal/test" + "github.com/cortezaproject/corteza-server/system/internal/repository" + repomock "github.com/cortezaproject/corteza-server/system/internal/repository/mocks" + "github.com/cortezaproject/corteza-server/system/types" ) // @todo this mockDB will be probably be used by other tests, move it to some common place diff --git a/system/internal/service/error.go b/system/internal/service/error.go index 64c7ceffc..bf77f2bfc 100644 --- a/system/internal/service/error.go +++ b/system/internal/service/error.go @@ -18,7 +18,7 @@ func (e serviceError) Error() string { } func (e serviceError) String() string { - return "crust.system.service." + string(e) + return "system.service." + string(e) } func (e serviceError) withStack() error { diff --git a/system/internal/service/main_test.go b/system/internal/service/main_test.go index 68973591f..98fb084df 100644 --- a/system/internal/service/main_test.go +++ b/system/internal/service/main_test.go @@ -7,25 +7,18 @@ import ( "os" "testing" - "github.com/namsral/flag" "github.com/titpetric/factory" "go.uber.org/zap/zapcore" - "github.com/crusttech/crust/internal/logger" - systemMigrate "github.com/crusttech/crust/system/db" + "github.com/cortezaproject/corteza-server/internal/logger" + systemMigrate "github.com/cortezaproject/corteza-server/system/db" ) func TestMain(m *testing.M) { logger.Init(zapcore.DebugLevel) - dsn := "" - flag.StringVar(&dsn, "db-dsn", "crust:crust@tcp(crust-db:3306)/crust?collation=utf8mb4_general_ci", "DSN for database connection") - flag.Parse() - - factory.Database.Add("default", dsn) - factory.Database.Add("system", dsn) - - db := factory.Database.MustGet() + factory.Database.Add("system", os.Getenv("SYSTEM_DB_DSN")) + db := factory.Database.MustGet("system") db.Profiler = &factory.Database.ProfilerStdout // migrate database schema diff --git a/system/internal/service/organisation.go b/system/internal/service/organisation.go index 92d28b91f..f4c0776c6 100644 --- a/system/internal/service/organisation.go +++ b/system/internal/service/organisation.go @@ -5,11 +5,9 @@ import ( "github.com/titpetric/factory" "go.uber.org/zap" - "go.uber.org/zap/zapcore" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/system/internal/repository" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/system/internal/repository" + "github.com/cortezaproject/corteza-server/system/types" ) type ( @@ -54,9 +52,9 @@ func (svc organisation) With(ctx context.Context) OrganisationService { } // log() returns zap's logger with requestID from current context and fields. -func (svc organisation) log(fields ...zapcore.Field) *zap.Logger { - return logger.AddRequestID(svc.ctx, svc.logger).With(fields...) -} +// func (svc organisation) log(fields ...zapcore.Field) *zap.Logger { +// return logger.AddRequestID(svc.ctx, svc.logger).With(fields...) +// } func (svc organisation) FindByID(id uint64) (*types.Organisation, error) { // @todo: permission check if current user can read organisation diff --git a/system/internal/service/role.go b/system/internal/service/role.go index fbf3bdc81..534c9abd9 100644 --- a/system/internal/service/role.go +++ b/system/internal/service/role.go @@ -6,11 +6,9 @@ import ( "github.com/pkg/errors" "github.com/titpetric/factory" "go.uber.org/zap" - "go.uber.org/zap/zapcore" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/system/internal/repository" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/system/internal/repository" + "github.com/cortezaproject/corteza-server/system/types" ) type ( @@ -73,9 +71,9 @@ func (svc role) With(ctx context.Context) RoleService { } // log() returns zap's logger with requestID from current context and fields. -func (svc role) log(fields ...zapcore.Field) *zap.Logger { - return logger.AddRequestID(svc.ctx, svc.logger).With(fields...) -} +// func (svc role) log(fields ...zapcore.Field) *zap.Logger { +// return logger.AddRequestID(svc.ctx, svc.logger).With(fields...) +// } func (svc role) FindByID(roleID uint64) (*types.Role, error) { return svc.findByID(roleID) diff --git a/system/internal/service/service.go b/system/internal/service/service.go index 0cf0110dd..d3432a193 100644 --- a/system/internal/service/service.go +++ b/system/internal/service/service.go @@ -5,10 +5,10 @@ import ( "go.uber.org/zap" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/internal/permissions" - internalSettings "github.com/crusttech/crust/internal/settings" - "github.com/crusttech/crust/system/internal/repository" + "github.com/cortezaproject/corteza-server/internal/logger" + "github.com/cortezaproject/corteza-server/internal/permissions" + internalSettings "github.com/cortezaproject/corteza-server/internal/settings" + "github.com/cortezaproject/corteza-server/system/internal/repository" ) type ( @@ -22,7 +22,9 @@ type ( ) var ( - permSvc permissionServicer + DefaultPermissions permissionServicer + DefaultIntSettings internalSettings.Service + DefaultLogger *zap.Logger DefaultAccessControl *accessControl @@ -39,17 +41,17 @@ var ( ) func Init(ctx context.Context) (err error) { - intSet := internalSettings.NewService(internalSettings.NewRepository(repository.DB(ctx), "sys_settings")) + DefaultIntSettings = internalSettings.NewService(internalSettings.NewRepository(repository.DB(ctx), "sys_settings")) DefaultLogger = logger.Default().Named("system.service") - permSvc = permissions.Service( + DefaultPermissions = permissions.Service( ctx, DefaultLogger, permissions.Repository(repository.DB(ctx), "sys_permission_rules")) - DefaultAccessControl = AccessControl(permSvc) + DefaultAccessControl = AccessControl(DefaultPermissions) - DefaultSettings = Settings(ctx, intSet) + DefaultSettings = Settings(ctx, DefaultIntSettings) DefaultUser = User(ctx) DefaultRole = Role(ctx) @@ -68,5 +70,5 @@ func Init(ctx context.Context) (err error) { } func Watchers(ctx context.Context) { - permSvc.Watch(ctx) + DefaultPermissions.Watch(ctx) } diff --git a/system/internal/service/settings.go b/system/internal/service/settings.go index ae9a5eb85..3bd9477d6 100644 --- a/system/internal/service/settings.go +++ b/system/internal/service/settings.go @@ -6,11 +6,9 @@ import ( "github.com/titpetric/factory" "go.uber.org/zap" - "go.uber.org/zap/zapcore" - "github.com/crusttech/crust/internal/logger" - internalSettings "github.com/crusttech/crust/internal/settings" - "github.com/crusttech/crust/system/internal/repository" + internalSettings "github.com/cortezaproject/corteza-server/internal/settings" + "github.com/cortezaproject/corteza-server/system/internal/repository" ) type ( @@ -62,9 +60,9 @@ func (svc settings) With(ctx context.Context) SettingsService { } // log() returns zap's logger with requestID from current context and fields. -func (svc settings) log(fields ...zapcore.Field) *zap.Logger { - return logger.AddRequestID(svc.ctx, svc.logger).With(fields...) -} +// func (svc settings) log(fields ...zapcore.Field) *zap.Logger { +// return logger.AddRequestID(svc.ctx, svc.logger).With(fields...) +// } func (svc settings) FindByPrefix(prefix string) (vv internalSettings.ValueSet, err error) { if !svc.ac.CanReadSettings(svc.ctx) { diff --git a/system/internal/service/user.go b/system/internal/service/user.go index 2db96c3c3..794629032 100644 --- a/system/internal/service/user.go +++ b/system/internal/service/user.go @@ -6,19 +6,15 @@ import ( "github.com/titpetric/factory" "go.uber.org/zap" - "go.uber.org/zap/zapcore" - internalAuth "github.com/crusttech/crust/internal/auth" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/system/internal/repository" - "github.com/crusttech/crust/system/types" + internalAuth "github.com/cortezaproject/corteza-server/internal/auth" + "github.com/cortezaproject/corteza-server/system/internal/repository" + "github.com/cortezaproject/corteza-server/system/types" ) const ( ErrUserInvalidCredentials = serviceError("UserInvalidCredentials") ErrUserLocked = serviceError("UserLocked") - - uuidLength = 36 ) type ( @@ -83,9 +79,9 @@ func (svc user) With(ctx context.Context) UserService { } // log() returns zap's logger with requestID from current context and fields. -func (svc user) log(fields ...zapcore.Field) *zap.Logger { - return logger.AddRequestID(svc.ctx, svc.logger).With(fields...) -} +// func (svc user) log(fields ...zapcore.Field) *zap.Logger { +// return logger.AddRequestID(svc.ctx, svc.logger).With(fields...) +// } func (svc user) FindByID(ID uint64) (*types.User, error) { if ID == 0 { diff --git a/system/provision.go b/system/provision.go deleted file mode 100644 index 006478710..000000000 --- a/system/provision.go +++ /dev/null @@ -1,26 +0,0 @@ -package service - -import ( - "context" - - "github.com/crusttech/crust/system/internal/service" -) - -// Provision orchestrates various tasks after deployment -// -func Provision(ctx context.Context) (err error) { - if err = resetDefaultPermissionRules(ctx); err != nil { - return - } - - // @todo move migration here - - return -} - -// Resets default permission rules for compose resources -func resetDefaultPermissionRules(ctx context.Context) error { - var ac = service.DefaultAccessControl - - return ac.Grant(ctx, ac.DefaultRules()...) -} diff --git a/system/rest/application.go b/system/rest/application.go index a96ebc2aa..f303deeb2 100644 --- a/system/rest/application.go +++ b/system/rest/application.go @@ -3,9 +3,9 @@ package rest import ( "context" - "github.com/crusttech/crust/system/internal/service" - "github.com/crusttech/crust/system/rest/request" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/system/internal/service" + "github.com/cortezaproject/corteza-server/system/rest/request" + "github.com/cortezaproject/corteza-server/system/types" "github.com/pkg/errors" ) diff --git a/system/rest/auth.go b/system/rest/auth.go index 8685f74d1..11edb4451 100644 --- a/system/rest/auth.go +++ b/system/rest/auth.go @@ -7,11 +7,11 @@ import ( "github.com/pkg/errors" "github.com/titpetric/factory/resputil" - "github.com/crusttech/crust/internal/auth" - "github.com/crusttech/crust/internal/payload" - "github.com/crusttech/crust/internal/payload/outgoing" - "github.com/crusttech/crust/system/internal/service" - "github.com/crusttech/crust/system/rest/request" + "github.com/cortezaproject/corteza-server/internal/auth" + "github.com/cortezaproject/corteza-server/internal/payload" + "github.com/cortezaproject/corteza-server/internal/payload/outgoing" + "github.com/cortezaproject/corteza-server/system/internal/service" + "github.com/cortezaproject/corteza-server/system/rest/request" ) var _ = errors.Wrap diff --git a/system/rest/auth_external.go b/system/rest/auth_external.go index bd12ed62e..ac5aeeea2 100644 --- a/system/rest/auth_external.go +++ b/system/rest/auth_external.go @@ -15,9 +15,9 @@ import ( "go.uber.org/zap" "go.uber.org/zap/zapcore" - "github.com/crusttech/crust/internal/auth" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/system/internal/service" + "github.com/cortezaproject/corteza-server/internal/auth" + "github.com/cortezaproject/corteza-server/internal/logger" + "github.com/cortezaproject/corteza-server/system/internal/service" ) type ( @@ -42,11 +42,11 @@ func (ctrl ExternalAuth) log(ctx context.Context, fields ...zapcore.Field) *zap. return logger.ContextValue(ctx).Named("external-auth").With(fields...) } -func (ctrl *ExternalAuth) MountRoutes(r chi.Router) { +func (ctrl *ExternalAuth) ApiServerRoutes(r chi.Router) { - // Make sure we're backwards compatible and redirect /oidc to /auth/external/openid-connect.crust-iam + // Make sure we're backwards compatible and redirect /oidc to /auth/external/openid-connect.corteza-iam r.Get("/oidc", func(w http.ResponseWriter, req *http.Request) { - http.Redirect(w, req, externalAuthBaseUrl+"/openid-connect.crust-iam", http.StatusMovedPermanently) + http.Redirect(w, req, externalAuthBaseUrl+"/openid-connect.corteza-iam", http.StatusMovedPermanently) }) // Copy provider from path (Chi URL param) to request context and return it diff --git a/system/rest/auth_internal.go b/system/rest/auth_internal.go index fbb9f4d3b..24a17efa9 100644 --- a/system/rest/auth_internal.go +++ b/system/rest/auth_internal.go @@ -5,12 +5,12 @@ import ( "github.com/pkg/errors" - "github.com/crusttech/crust/internal/auth" - "github.com/crusttech/crust/internal/payload" - "github.com/crusttech/crust/internal/payload/outgoing" - "github.com/crusttech/crust/system/internal/service" - "github.com/crusttech/crust/system/rest/request" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/internal/auth" + "github.com/cortezaproject/corteza-server/internal/payload" + "github.com/cortezaproject/corteza-server/internal/payload/outgoing" + "github.com/cortezaproject/corteza-server/system/internal/service" + "github.com/cortezaproject/corteza-server/system/rest/request" + "github.com/cortezaproject/corteza-server/system/types" ) var _ = errors.Wrap diff --git a/system/rest/handlers/application.go b/system/rest/handlers/application.go index f4d1bd8e0..967e33985 100644 --- a/system/rest/handlers/application.go +++ b/system/rest/handlers/application.go @@ -23,8 +23,8 @@ import ( "github.com/go-chi/chi" "github.com/titpetric/factory/resputil" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/system/rest/request" + "github.com/cortezaproject/corteza-server/internal/logger" + "github.com/cortezaproject/corteza-server/system/rest/request" ) // Internal API interface diff --git a/system/rest/handlers/auth.go b/system/rest/handlers/auth.go index 221c12d58..47441e849 100644 --- a/system/rest/handlers/auth.go +++ b/system/rest/handlers/auth.go @@ -23,8 +23,8 @@ import ( "github.com/go-chi/chi" "github.com/titpetric/factory/resputil" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/system/rest/request" + "github.com/cortezaproject/corteza-server/internal/logger" + "github.com/cortezaproject/corteza-server/system/rest/request" ) // Internal API interface diff --git a/system/rest/handlers/auth_internal.go b/system/rest/handlers/auth_internal.go index 984fdb223..0f1486e8a 100644 --- a/system/rest/handlers/auth_internal.go +++ b/system/rest/handlers/auth_internal.go @@ -23,8 +23,8 @@ import ( "github.com/go-chi/chi" "github.com/titpetric/factory/resputil" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/system/rest/request" + "github.com/cortezaproject/corteza-server/internal/logger" + "github.com/cortezaproject/corteza-server/system/rest/request" ) // Internal API interface diff --git a/system/rest/handlers/organisation.go b/system/rest/handlers/organisation.go index 5dccd0d43..58ad7ef78 100644 --- a/system/rest/handlers/organisation.go +++ b/system/rest/handlers/organisation.go @@ -23,8 +23,8 @@ import ( "github.com/go-chi/chi" "github.com/titpetric/factory/resputil" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/system/rest/request" + "github.com/cortezaproject/corteza-server/internal/logger" + "github.com/cortezaproject/corteza-server/system/rest/request" ) // Internal API interface diff --git a/system/rest/handlers/permissions.go b/system/rest/handlers/permissions.go index 348ff94a8..be6d2f21a 100644 --- a/system/rest/handlers/permissions.go +++ b/system/rest/handlers/permissions.go @@ -23,8 +23,8 @@ import ( "github.com/go-chi/chi" "github.com/titpetric/factory/resputil" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/system/rest/request" + "github.com/cortezaproject/corteza-server/internal/logger" + "github.com/cortezaproject/corteza-server/system/rest/request" ) // Internal API interface diff --git a/system/rest/handlers/role.go b/system/rest/handlers/role.go index c51fd7861..44aac6a91 100644 --- a/system/rest/handlers/role.go +++ b/system/rest/handlers/role.go @@ -23,8 +23,8 @@ import ( "github.com/go-chi/chi" "github.com/titpetric/factory/resputil" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/system/rest/request" + "github.com/cortezaproject/corteza-server/internal/logger" + "github.com/cortezaproject/corteza-server/system/rest/request" ) // Internal API interface diff --git a/system/rest/handlers/settings.go b/system/rest/handlers/settings.go index 324ac914c..41c81c7aa 100644 --- a/system/rest/handlers/settings.go +++ b/system/rest/handlers/settings.go @@ -23,8 +23,8 @@ import ( "github.com/go-chi/chi" "github.com/titpetric/factory/resputil" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/system/rest/request" + "github.com/cortezaproject/corteza-server/internal/logger" + "github.com/cortezaproject/corteza-server/system/rest/request" ) // Internal API interface diff --git a/system/rest/handlers/user.go b/system/rest/handlers/user.go index d97ba4e29..b3d612726 100644 --- a/system/rest/handlers/user.go +++ b/system/rest/handlers/user.go @@ -23,8 +23,8 @@ import ( "github.com/go-chi/chi" "github.com/titpetric/factory/resputil" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/system/rest/request" + "github.com/cortezaproject/corteza-server/internal/logger" + "github.com/cortezaproject/corteza-server/system/rest/request" ) // Internal API interface diff --git a/system/rest/organisation.go b/system/rest/organisation.go index 3c1a6da8a..c0a26a55e 100644 --- a/system/rest/organisation.go +++ b/system/rest/organisation.go @@ -5,9 +5,9 @@ import ( "github.com/pkg/errors" - "github.com/crusttech/crust/system/internal/service" - "github.com/crusttech/crust/system/rest/request" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/system/internal/service" + "github.com/cortezaproject/corteza-server/system/rest/request" + "github.com/cortezaproject/corteza-server/system/types" ) var _ = errors.Wrap diff --git a/system/rest/permissions.go b/system/rest/permissions.go index 78a55d6a3..d07b82163 100644 --- a/system/rest/permissions.go +++ b/system/rest/permissions.go @@ -5,9 +5,9 @@ import ( "github.com/titpetric/factory/resputil" - "github.com/crusttech/crust/internal/permissions" - "github.com/crusttech/crust/system/internal/service" - "github.com/crusttech/crust/system/rest/request" + "github.com/cortezaproject/corteza-server/internal/permissions" + "github.com/cortezaproject/corteza-server/system/internal/service" + "github.com/cortezaproject/corteza-server/system/rest/request" ) type ( diff --git a/system/rest/request/permissions.go b/system/rest/request/permissions.go index e270f9a08..4a0e7116f 100644 --- a/system/rest/request/permissions.go +++ b/system/rest/request/permissions.go @@ -26,7 +26,7 @@ import ( "github.com/go-chi/chi" "github.com/pkg/errors" - "github.com/crusttech/crust/internal/permissions" + "github.com/cortezaproject/corteza-server/internal/permissions" ) var _ = chi.URLParam diff --git a/system/rest/request/user.go b/system/rest/request/user.go index 17862197f..dc4efbc65 100644 --- a/system/rest/request/user.go +++ b/system/rest/request/user.go @@ -26,7 +26,7 @@ import ( "github.com/go-chi/chi" "github.com/pkg/errors" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/system/types" ) var _ = chi.URLParam diff --git a/system/rest/request/util.go b/system/rest/request/util.go index 4451032fd..7f96b3e5d 100644 --- a/system/rest/request/util.go +++ b/system/rest/request/util.go @@ -1,5 +1,7 @@ package request +//lint:file-ignore U1000 Ignore unused code, part of request pkg toolset + import ( "regexp" "strconv" @@ -9,7 +11,7 @@ import ( "github.com/pkg/errors" ) -var truthy = regexp.MustCompile("^\\s*(t(rue)?|y(es)?|1)\\s*$") +var truthy = regexp.MustCompile(`^\s*(t(rue)?|y(es)?|1)\s*$`) func parseJSONTextWithErr(s string) (types.JSONText, error) { result := &types.JSONText{} @@ -46,7 +48,7 @@ func parseUInt64(s string) uint64 { func parseUInt64A(values []string) []uint64 { var result []uint64 - if values != nil && len(values) > 0 { + if len(values) > 0 { for _, val := range values { result = append(result, parseUInt64(val)) } diff --git a/system/rest/role.go b/system/rest/role.go index 7a2b5c58a..04db2c4fc 100644 --- a/system/rest/role.go +++ b/system/rest/role.go @@ -5,10 +5,10 @@ import ( "github.com/pkg/errors" - "github.com/crusttech/crust/internal/payload" - "github.com/crusttech/crust/system/internal/service" - "github.com/crusttech/crust/system/rest/request" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/internal/payload" + "github.com/cortezaproject/corteza-server/system/internal/service" + "github.com/cortezaproject/corteza-server/system/rest/request" + "github.com/cortezaproject/corteza-server/system/types" ) var _ = errors.Wrap diff --git a/system/rest/router.go b/system/rest/router.go index b8fd0c8d5..8dc72e6be 100644 --- a/system/rest/router.go +++ b/system/rest/router.go @@ -3,30 +3,27 @@ package rest import ( "github.com/go-chi/chi" - "github.com/crusttech/crust/internal/auth" - "github.com/crusttech/crust/system/rest/handlers" + "github.com/cortezaproject/corteza-server/internal/auth" + "github.com/cortezaproject/corteza-server/system/rest/handlers" ) -func MountRoutes() func(chi.Router) { - // Initialize handers & controllers. - return func(r chi.Router) { - NewExternalAuth().MountRoutes(r) +func MountRoutes(r chi.Router) { + NewExternalAuth().ApiServerRoutes(r) - // Provide raw `/auth` handlers - handlers.NewAuth((Auth{}).New()).MountRoutes(r) + // Provide raw `/auth` handlers + handlers.NewAuth((Auth{}).New()).MountRoutes(r) - handlers.NewAuthInternal((AuthInternal{}).New()).MountRoutes(r) + handlers.NewAuthInternal((AuthInternal{}).New()).MountRoutes(r) - // Protect all _private_ routes - r.Group(func(r chi.Router) { - r.Use(auth.MiddlewareValidOnly) + // Protect all _private_ routes + r.Group(func(r chi.Router) { + r.Use(auth.MiddlewareValidOnly) - handlers.NewUser(User{}.New()).MountRoutes(r) - handlers.NewRole(Role{}.New()).MountRoutes(r) - handlers.NewOrganisation(Organisation{}.New()).MountRoutes(r) - handlers.NewPermissions(Permissions{}.New()).MountRoutes(r) - handlers.NewApplication(Application{}.New()).MountRoutes(r) - handlers.NewSettings(Settings{}.New()).MountRoutes(r) - }) - } + handlers.NewUser(User{}.New()).MountRoutes(r) + handlers.NewRole(Role{}.New()).MountRoutes(r) + handlers.NewOrganisation(Organisation{}.New()).MountRoutes(r) + handlers.NewPermissions(Permissions{}.New()).MountRoutes(r) + handlers.NewApplication(Application{}.New()).MountRoutes(r) + handlers.NewSettings(Settings{}.New()).MountRoutes(r) + }) } diff --git a/system/rest/settings.go b/system/rest/settings.go index 3d3713cec..ca8037bf6 100644 --- a/system/rest/settings.go +++ b/system/rest/settings.go @@ -5,9 +5,9 @@ import ( "github.com/pkg/errors" - "github.com/crusttech/crust/internal/settings" - "github.com/crusttech/crust/system/internal/service" - "github.com/crusttech/crust/system/rest/request" + "github.com/cortezaproject/corteza-server/internal/settings" + "github.com/cortezaproject/corteza-server/system/internal/service" + "github.com/cortezaproject/corteza-server/system/rest/request" ) var _ = errors.Wrap diff --git a/system/rest/user.go b/system/rest/user.go index 31b0d3a40..c0f516b1e 100644 --- a/system/rest/user.go +++ b/system/rest/user.go @@ -5,9 +5,9 @@ import ( "github.com/pkg/errors" - "github.com/crusttech/crust/system/internal/service" - "github.com/crusttech/crust/system/rest/request" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/system/internal/service" + "github.com/cortezaproject/corteza-server/system/rest/request" + "github.com/cortezaproject/corteza-server/system/types" ) var _ = errors.Wrap diff --git a/system/routes.go b/system/routes.go deleted file mode 100644 index 241bfbee7..000000000 --- a/system/routes.go +++ /dev/null @@ -1,37 +0,0 @@ -package service - -import ( - "context" - - "github.com/go-chi/chi" - - "github.com/crusttech/crust/internal/auth" - "github.com/crusttech/crust/internal/config" - "github.com/crusttech/crust/internal/middleware" - "github.com/crusttech/crust/system/rest" -) - -func Routes(ctx context.Context) *chi.Mux { - r := chi.NewRouter() - middleware.Mount(ctx, r, flags.http) - MountRoutes(ctx, r) - middleware.MountSystemRoutes(ctx, r, flags.http) - return r -} - -func MountRoutes(ctx context.Context, r chi.Router) { - r.Group(func(r chi.Router) { - r.Use( - auth.DefaultJwtHandler.Verifier(), - auth.DefaultJwtHandler.Authenticator(), - ) - - mountRoutes(r, flags.http, rest.MountRoutes()) - }) -} - -func mountRoutes(r chi.Router, opts *config.HTTP, mounts ...func(r chi.Router)) { - for _, mount := range mounts { - mount(r) - } -} diff --git a/system/routes_test.go b/system/routes_test.go deleted file mode 100644 index a634ffb89..000000000 --- a/system/routes_test.go +++ /dev/null @@ -1,343 +0,0 @@ -// +build integration-disabled - -package service - -import ( - "context" - "encoding/json" - "fmt" - "io" - "net/http" - "net/http/httptest" - "net/http/httputil" - "net/url" - "os" - "strings" - "testing" - "time" - - "github.com/dgrijalva/jwt-go" - "github.com/namsral/flag" - - "github.com/crusttech/crust/internal/auth" - "github.com/crusttech/crust/internal/test" - systemRepository "github.com/crusttech/crust/system/internal/repository" - systemTypes "github.com/crusttech/crust/system/types" -) - -type ( - jsonResponse struct { - Error struct { - Message string `json:"message"` - Trace string `json:"trace,omitempty"` - } `json:"error"` - } -) - -func TestUsers(t *testing.T) { - ctx := context.Background() - - // we need to set this due to using Init() - os.Setenv("SYSTEM_DB_DSN", "crust:crust@tcp(crust-db:3306)/crust?collation=utf8mb4_general_ci") - - mountFlags("system", Flags) - - // Initialize routes and exit on failure. - err := Init(ctx) - test.Assert(t, err == nil, "Error initializing: %+v", err) - - jwtSecret := "test-secret" - - jwtAuth, err := auth.JWT(jwtSecret, 600) - test.NoError(t, err, "Error initializing: %v") - - routes := Routes(ctx) - - // Send check request with invalid JWT token. - { - req, err := http.NewRequest("GET", "http://127.0.0.1/auth/check", nil) - test.Assert(t, err == nil, "Error creating request: %+v", err) - - token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ - "id": "zblj", - "nbf": time.Date(2015, 10, 10, 12, 0, 0, 0, time.UTC).Unix(), - }) - - jwtAuth.Encode() - - tokenString, err := token.SignedString([]byte(jwtSecret)) - test.Assert(t, err == nil, "Error creating JWT token: %+v", err) - - req.AddCookie(&http.Cookie{ - Name: "jwt", - Value: tokenString, - Domain: ".localhost", - Expires: time.Now().Add(time.Hour), - HttpOnly: true, - MaxAge: 50000, - Path: "/auth", - }) - - recorder := httptest.NewRecorder() - routes.ServeHTTP(recorder, req) - resp := recorder.Result() - - fmt.Println(">>> (request)") - fmt.Println(request(req)) - fmt.Println("----") - fmt.Println("<<< (response)") - fmt.Println(response(resp)) - - jr, err := decodeJson(resp.Body) - test.Assert(t, err == nil, "Error decoding response body: %+v", err) - test.Assert(t, jr.Error.Message == "failed to authorize request: signature is invalid", "Expected error 'failed to authorize request: signature is invalid' got: %+v", jr.Error.Message) - } - - // Send "Login" request without parameters. - { - req, err := http.NewRequest("POST", "http://localhost/auth/login", nil) - test.Assert(t, err == nil, "Error creating request: %+v", err) - - recorder := httptest.NewRecorder() - routes.ServeHTTP(recorder, req) - resp := recorder.Result() - - fmt.Println(">>> (request)") - fmt.Println(request(req)) - fmt.Println("----") - fmt.Println("<<< (response)") - fmt.Println(response(resp)) - - jr, err := decodeJson(resp.Body) - test.Assert(t, err == nil, "Error decoding response body: %+v", err) - test.Assert(t, jr.Error.Message == "missing form body", "Expected error 'missing form body' got: %+v", jr.Error.Message) - } - - // Send "Login" request with missing user. - { - jsonStr := `{"username":"test123","password":"test123"}` - - req, err := http.NewRequest("POST", "http://localhost/auth/login", strings.NewReader(jsonStr)) - req.Header.Set("Content-Type", "application/json") - - test.Assert(t, err == nil, "Error creating request: %+v", err) - - recorder := httptest.NewRecorder() - routes.ServeHTTP(recorder, req) - resp := recorder.Result() - - fmt.Println(">>> (request)") - fmt.Println(request(req)) - fmt.Println("----") - fmt.Println("<<< (response)") - fmt.Println(response(resp)) - - jr, err := decodeJson(resp.Body) - test.Assert(t, err == nil, "Error decoding response body: %+v", err) - test.Assert(t, jr.Error.Message == "crust.auth.repository.UserNotFound", "Expected error 'crust.auth.repository.UserNotFound' got: %+v", jr.Error.Message) - } - - // Create user. - user := &systemTypes.User{ - ID: 1337, - Username: "johndoe", - } - { - userAPI := systemRepository.User(context.Background(), nil) - _, err := userAPI.Create(user) - test.Assert(t, err == nil, "Error when inserting user: %+v", err) - } - - // Send "Login" request with existing user. - if false { - form := url.Values{} - form.Add("username", "johndoe") - form.Add("password", "johndoe123") - - req, err := http.NewRequest("POST", "http://localhost/auth/login", strings.NewReader(form.Encode())) - req.Header.Add("Content-Type", "application/x-www-form-urlencoded") - - test.Assert(t, err == nil, "Error creating request: %+v", err) - - recorder := httptest.NewRecorder() - routes.ServeHTTP(recorder, req) - resp := recorder.Result() - - fmt.Println(">>> (request)") - fmt.Println(request(req)) - fmt.Println("----") - fmt.Println("<<< (response)") - fmt.Println(response(resp)) - - c := resp.Cookies() - test.Assert(t, len(c) == 1, "Expected 1 cookie value, got: %+v", len(c)) - test.Assert(t, c[0].Value != "", "Expected non empty jwt token, got: %+v", c[0].Value) - - type jsonResponse struct { - Response struct { - UserID string `json:"userID"` - Username string `json:"username"` - } `json:"response"` - } - - var jr jsonResponse - err = json.NewDecoder(resp.Body).Decode(&jr) - test.Assert(t, err == nil, "Error decoding response body: %+v", err) - test.Assert(t, jr.Response.UserID != "0", "Expected userID not to be 0, got: %+v", jr.Response.UserID) - test.Assert(t, jr.Response.Username == "johndoe", "Expected username 'johndoe', got: %+v", jr.Response.Username) - - // Check JWT token after successful login. - req, err = http.NewRequest("GET", "http://localhost/auth/check", nil) - test.Assert(t, err == nil, "Error creating request: %+v", err) - - routes.ServeHTTP(recorder, req) - - resp = recorder.Result() - - fmt.Println(">>> (request)") - fmt.Println(request(req)) - fmt.Println("----") - fmt.Println("<<< (response)") - fmt.Println(response(resp)) - - test.Assert(t, resp.StatusCode == 200, "Expected http status code 200, got: %+v", resp.StatusCode) - test.Assert(t, len(c) == 1, "Expected 1 cookie value, got: %+v", len(c)) - test.Assert(t, c[0].Value != "", "Expected non empty jwt token, got: %+v", c[0].Value) - } - - // Send "Login" request with existing user. - { - jsonStr := `{"username": "johndoe", "password": "johndoe123"}` - - req, err := http.NewRequest("POST", "http://localhost/auth/login", strings.NewReader(jsonStr)) - req.Header.Add("Content-Type", "application/json") - - test.Assert(t, err == nil, "Error creating request: %+v", err) - - recorder := httptest.NewRecorder() - routes.ServeHTTP(recorder, req) - resp := recorder.Result() - - fmt.Println(">>> (request)") - fmt.Println(request(req)) - fmt.Println("----") - fmt.Println("<<< (response)") - fmt.Println(response(resp)) - - c := resp.Cookies() - test.Assert(t, len(c) == 1, "Expected 1 cookie value, got: %+v", len(c)) - test.Assert(t, c[0].Value != "", "Expected non empty jwt token, got: %+v", c[0].Value) - - type jsonResponse struct { - Response struct { - UserID string `json:"userID"` - Username string `json:"username"` - } `json:"response"` - } - - var jr jsonResponse - err = json.NewDecoder(resp.Body).Decode(&jr) - test.Assert(t, err == nil, "Error decoding response body: %+v", err) - test.Assert(t, jr.Response.UserID != "0", "Expected userID not to be 0, got: %+v", jr.Response.UserID) - test.Assert(t, jr.Response.Username == "johndoe", "Expected username 'johndoe', got: %+v", jr.Response.Username) - - // Check JWT token after successful login. - req, err = http.NewRequest("GET", "http://localhost/auth/check", nil) - test.Assert(t, err == nil, "Error creating request: %+v", err) - - routes.ServeHTTP(recorder, req) - - resp = recorder.Result() - - fmt.Println(">>> (request)") - fmt.Println(request(req)) - fmt.Println("----") - fmt.Println("<<< (response)") - fmt.Println(response(resp)) - - test.Assert(t, resp.StatusCode == 200, "Expected http status code 200, got: %+v", resp.StatusCode) - test.Assert(t, len(c) == 1, "Expected 1 cookie value, got: %+v", len(c)) - test.Assert(t, c[0].Value != "", "Expected non empty jwt token, got: %+v", c[0].Value) - } - - // Send "Logout" request and expect empty jwt token. - { - req, err := http.NewRequest("GET", "http://localhost/auth/logout", nil) - test.Assert(t, err == nil, "Error creating request: %+v", err) - - recorder := httptest.NewRecorder() - routes.ServeHTTP(recorder, req) - resp := recorder.Result() - - fmt.Println(">>> (request)") - fmt.Println(request(req)) - fmt.Println("----") - fmt.Println("<<< (response)") - fmt.Println(response(resp)) - - c := resp.Cookies() - - test.Assert(t, resp.StatusCode == 200, "Expected http status code 200, got: %+v", resp.StatusCode) - test.Assert(t, len(c) == 1, "Expected 1 cookie value, got: %+v", len(c)) - test.Assert(t, c[0].Value == "", "Expected empty jwt token, got: %+v", c[0].Value) - } - - // Send check request without JWT token. - { - req, err := http.NewRequest("GET", "http://127.0.0.1/auth/check", nil) - test.Assert(t, err == nil, "Error creating request: %+v", err) - - recorder := httptest.NewRecorder() - routes.ServeHTTP(recorder, req) - - resp := recorder.Result() - - fmt.Println(">>> (request)") - fmt.Println(request(req)) - fmt.Println("----") - fmt.Println("<<< (response)") - fmt.Println(response(resp)) - - jr, err := decodeJson(resp.Body) - test.Assert(t, err == nil, "Error decoding response body: %+v", err) - test.Assert(t, jr.Error.Message == "http: named cookie not present", "Expected error 'http: named cookie not present' got: %+v", jr.Error.Message) - } -} - -func request(req *http.Request) string { - b, err := httputil.DumpRequestOut(req, true) - if err != nil { - return ">>> Error: " + err.Error() - } - if b != nil { - return strings.TrimSpace(string(b)) - } - return "" -} - -func response(resp *http.Response) string { - b, err := httputil.DumpResponse(resp, true) - if err != nil { - return "<<< Error: " + err.Error() - } - if b != nil { - return strings.TrimSpace(string(b)) - } - return "" -} - -func mountFlags(prefix string, mountFlags ...func(...string)) { - for _, mount := range mountFlags { - mount(prefix) - } - flag.Parse() -} - -func decodeJson(r io.Reader) (jsonResponse, error) { - var ret jsonResponse - err := json.NewDecoder(r).Decode(&ret) - if err != nil { - return jsonResponse{}, err - } - return ret, nil -} diff --git a/system/service/init.go b/system/service/init.go index 35be2deab..3c4b78c57 100644 --- a/system/service/init.go +++ b/system/service/init.go @@ -3,7 +3,7 @@ package service import ( "context" - "github.com/crusttech/crust/system/internal/service" + "github.com/cortezaproject/corteza-server/system/internal/service" ) func Init(ctx context.Context) error { diff --git a/system/service/user.go b/system/service/user.go index f47145ebc..21cf88b43 100644 --- a/system/service/user.go +++ b/system/service/user.go @@ -5,8 +5,8 @@ import ( "io" "testing" - "github.com/crusttech/crust/system/internal/service" - "github.com/crusttech/crust/system/types" + "github.com/cortezaproject/corteza-server/system/internal/service" + "github.com/cortezaproject/corteza-server/system/types" ) type ( diff --git a/system/start.go b/system/start.go deleted file mode 100644 index da596d33c..000000000 --- a/system/start.go +++ /dev/null @@ -1,116 +0,0 @@ -package service - -import ( - "context" - "crypto/tls" - "fmt" - "net" - "net/http" - - "github.com/pkg/errors" - "github.com/titpetric/factory/resputil" - "go.uber.org/zap" - - "github.com/crusttech/crust/internal/auth" - "github.com/crusttech/crust/internal/db" - "github.com/crusttech/crust/internal/logger" - "github.com/crusttech/crust/internal/mail" - "github.com/crusttech/crust/internal/metrics" - "github.com/crusttech/crust/internal/settings" - migrate "github.com/crusttech/crust/system/db" - "github.com/crusttech/crust/system/internal/auth/external" - "github.com/crusttech/crust/system/internal/repository" - "github.com/crusttech/crust/system/service" -) - -func Init(ctx context.Context) (err error) { - // validate configuration - if err = flags.Validate(); err != nil { - return - } - - mail.SetupDialer(flags.smtp) - - if err = InitDatabase(ctx); err != nil { - return - } - - if flags.http.ClientTSLInsecure { - // This will allow HTTPS requests to insecure hosts (expired, wrong host, self signed, untrusted root...) - // With this enabled, features like OIDC auto-discovery should work on any of examples found on badssl.com. - // - // With SYSTEM_HTTP_CLIENT_TSL_INSECURE=0 (default) next command returns 404 error (expected) - // > ./system-cli external-auth auto-discovery foo-tsl-1 https://expired.badssl.com/ - // - // Without SYSTEM_HTTP_CLIENT_TSL_INSECURE=1 next command returns "x509: certificate has expired or is not yet valid" - // > ./system-cli external-auth auto-discovery foo-tsl-1 https://expired.badssl.com/ - // - http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} - } - - // configure resputil options - resputil.SetConfig(resputil.Options{ - Pretty: flags.http.Pretty, - Trace: flags.http.Tracing, - Logger: func(err error) { - // @todo: error logging - }, - }) - - // Use JWT secret for hmac signer for now - auth.DefaultSigner = auth.HmacSigner(flags.jwt.Secret) - auth.DefaultJwtHandler, err = auth.JWT(flags.jwt.Secret, flags.jwt.Expiry) - if err != nil { - return - } - - // Don't change this, it needs database connection - if err = service.Init(ctx); err != nil { - return - } - - return nil -} - -func InitDatabase(ctx context.Context) error { - // start/configure database connection - db, err := db.TryToConnect(ctx, "system", flags.db.DSN, flags.db.Profiler) - if err != nil { - return errors.Wrap(err, "could not connect to database") - } - - // migrate database schema - if err := migrate.Migrate(db); err != nil { - return err - } - - return nil -} - -func StartWatchers(ctx context.Context) { - service.Watchers(ctx) -} - -func StartRestAPI(ctx context.Context) error { - // Load settings from the database, - // for now, only at start-up time. - settingService := settings.NewService(settings.NewRepository(repository.DB(ctx), "sys_settings")).With(ctx) - - // Setup goth/external authentication - external.Init(settingService) - - logger.Default().Info("Starting HTTP server", zap.String("address", flags.http.Addr)) - listener, err := net.Listen("tcp", flags.http.Addr) - if err != nil { - return errors.Wrap(err, fmt.Sprintf("Can't listen on addr %s", flags.http.Addr)) - } - - if flags.monitor.Interval > 0 { - go metrics.NewMonitor(flags.monitor.Interval) - } - - go http.Serve(listener, Routes(ctx)) - <-ctx.Done() - - return nil -} diff --git a/system/system.go b/system/system.go new file mode 100644 index 000000000..eebd83817 --- /dev/null +++ b/system/system.go @@ -0,0 +1,167 @@ +package system + +import ( + "context" + + "github.com/go-chi/chi" + _ "github.com/joho/godotenv/autoload" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/titpetric/factory" + "go.uber.org/zap" + + "github.com/cortezaproject/corteza-server/internal/db" + "github.com/cortezaproject/corteza-server/internal/logger" + "github.com/cortezaproject/corteza-server/pkg/api" + "github.com/cortezaproject/corteza-server/pkg/cli" + "github.com/cortezaproject/corteza-server/pkg/cli/flags" + "github.com/cortezaproject/corteza-server/system/commands" + migrate "github.com/cortezaproject/corteza-server/system/db" + "github.com/cortezaproject/corteza-server/system/internal/service" + "github.com/cortezaproject/corteza-server/system/rest" +) + +const ( + system = "system" +) + +type ( + System struct { + log *zap.Logger + + // General + logOpt *flags.LogOpt + smtpOpt *flags.SMTPOpt + jwtOpt *flags.JWTOpt + httpClientOpt *flags.HttpClientOpt + + // System specific + dbOpt *flags.DBOpt + provisionOpt *flags.ProvisionOpt + } +) + +func init() { + logger.Init(zap.DebugLevel) +} + +func InitSystem() *System { + return &System{ + log: logger.Default().Named(system), + } +} + +// Command produces cobra.Command +func (m *System) Command(ctx context.Context) (cmd *cobra.Command) { + cmd = &cobra.Command{ + Use: "corteza-server-system", + TraverseChildren: true, + PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) { + cli.InitGeneralServices(m.logOpt, m.smtpOpt, m.jwtOpt, m.httpClientOpt) + + return m.StartServices(ctx) + }, + } + + m.BindGlobalFlags(cmd) + + srv := api.NewServer(m.log) + serveApiCmd := srv.Command(ctx, system, m.ApiServerPreRun) + + // Bind all flags we need for serving system + m.BindApiServerFlags(serveApiCmd) + + srv.MountRoutes(m.ApiServerRoutes) + + cmd.AddCommand( + serveApiCmd, + cli.SetupProvisionSubcommands(ctx, m), + ) + + m.AddCommands(cmd, ctx) + + return +} + +// AddCommands - other commands that this subservice needs +func (m *System) AddCommands(cmd *cobra.Command, ctx context.Context) { + cmd.AddCommand( + commands.Settings(ctx), + commands.Auth(ctx), + commands.Users(ctx), + commands.Roles(ctx), + ) +} + +// Binds all global flags +func (m *System) BindGlobalFlags(cmd *cobra.Command) { + m.logOpt = flags.Log(cmd) + m.smtpOpt = flags.SMTP(cmd) + m.jwtOpt = flags.JWT(cmd) + m.httpClientOpt = flags.HttpClient(cmd) +} + +// BindApiServerFlags sets & binds all API server flags +func (m *System) BindApiServerFlags(cmd *cobra.Command) { + m.dbOpt = flags.DB(cmd, system) + m.provisionOpt = flags.Provision(cmd, system) +} + +func (m *System) StartServices(ctx context.Context) (err error) { + _, err = db.TryToConnect(ctx, m.log, system, m.dbOpt.DSN, m.dbOpt.Profiler) + if err != nil { + return errors.Wrap(err, "could not connect to database") + } + + if m.provisionOpt.Database { + err = m.ProvisionMigrateDatabase(ctx) + if err != nil { + return + } + } + + err = service.Init(ctx) + if err != nil { + return + } + + return +} + +// ApiServerPreRun is executed before serve-api command runs REST API server +// +// Should initialize all that needs to run in the background +func (m System) ApiServerPreRun(ctx context.Context) error { + service.DefaultPermissions.Watch(ctx) + return nil +} + +// ApiServerRoutes mounts api server routes +func (m *System) ApiServerRoutes(r chi.Router) { + rest.MountRoutes(r) +} + +// ProvisionMigrateDatabase migrates database to new version +// +// This is ran by default on serve-api (when not explicitly disabled with --compose-provision-database=false) +// or on demand with "provision migrate-database" +func (m System) ProvisionMigrateDatabase(ctx context.Context) error { + var db, err = factory.Database.Get(system) + if err != nil { + return err + } + + db = db.With(ctx) + // Disable profiler for migrations + db.Profiler = nil + + return migrate.Migrate(db) +} + +// ProvisionAccessControl resets access-control rules for roles admin (2) and everyone (1) +// +// Run with emand with "provision access-control-rules" +func (m System) ProvisionAccessControl(ctx context.Context) error { + var ac = service.DefaultAccessControl + return ac.Grant(ctx, ac.DefaultRules()...) +} diff --git a/system/types/application.gen_test.go b/system/types/application.gen_test.go index 8f2142c31..cb2b68f2b 100644 --- a/system/types/application.gen_test.go +++ b/system/types/application.gen_test.go @@ -5,7 +5,7 @@ import ( "errors" - "github.com/crusttech/crust/internal/test" + "github.com/cortezaproject/corteza-server/internal/test" ) // Hello! This file is auto-generated. diff --git a/system/types/applications.go b/system/types/applications.go index cf7ac3b12..96ab71d9a 100644 --- a/system/types/applications.go +++ b/system/types/applications.go @@ -5,7 +5,7 @@ import ( "encoding/json" "time" - "github.com/crusttech/crust/internal/permissions" + "github.com/cortezaproject/corteza-server/internal/permissions" "github.com/pkg/errors" ) @@ -44,6 +44,7 @@ func (a Application) PermissionResource() permissions.Resource { } func (au *ApplicationUnify) Scan(value interface{}) error { + //lint:ignore S1034 This typecast is intentional, we need to get []byte out of a []uint8 switch value.(type) { case nil: au = nil diff --git a/system/types/credentials.gen_test.go b/system/types/credentials.gen_test.go index 51a0f5e8c..13bfd05b6 100644 --- a/system/types/credentials.gen_test.go +++ b/system/types/credentials.gen_test.go @@ -5,7 +5,7 @@ import ( "errors" - "github.com/crusttech/crust/internal/test" + "github.com/cortezaproject/corteza-server/internal/test" ) // Hello! This file is auto-generated. diff --git a/system/types/organisation.gen_test.go b/system/types/organisation.gen_test.go index 1ebeabca1..2dee8ffa3 100644 --- a/system/types/organisation.gen_test.go +++ b/system/types/organisation.gen_test.go @@ -5,7 +5,7 @@ import ( "errors" - "github.com/crusttech/crust/internal/test" + "github.com/cortezaproject/corteza-server/internal/test" ) // Hello! This file is auto-generated. diff --git a/system/types/organisation.go b/system/types/organisation.go index cde33c34c..d29146560 100644 --- a/system/types/organisation.go +++ b/system/types/organisation.go @@ -3,7 +3,7 @@ package types import ( "time" - "github.com/crusttech/crust/internal/permissions" + "github.com/cortezaproject/corteza-server/internal/permissions" ) type ( diff --git a/system/types/permission_resources.go b/system/types/permission_resources.go index ffd015606..951f8a61c 100644 --- a/system/types/permission_resources.go +++ b/system/types/permission_resources.go @@ -1,7 +1,7 @@ package types import ( - "github.com/crusttech/crust/internal/permissions" + "github.com/cortezaproject/corteza-server/internal/permissions" ) const SystemPermissionResource = permissions.Resource("system") diff --git a/system/types/role.gen_test.go b/system/types/role.gen_test.go index 6854d1535..b4c19a333 100644 --- a/system/types/role.gen_test.go +++ b/system/types/role.gen_test.go @@ -5,7 +5,7 @@ import ( "errors" - "github.com/crusttech/crust/internal/test" + "github.com/cortezaproject/corteza-server/internal/test" ) // Hello! This file is auto-generated. diff --git a/system/types/role.go b/system/types/role.go index 903bfcf5f..97fac3cdb 100644 --- a/system/types/role.go +++ b/system/types/role.go @@ -3,7 +3,7 @@ package types import ( "time" - "github.com/crusttech/crust/internal/permissions" + "github.com/cortezaproject/corteza-server/internal/permissions" ) type ( diff --git a/system/types/user.gen_test.go b/system/types/user.gen_test.go index 63da6c67a..75c44ff93 100644 --- a/system/types/user.gen_test.go +++ b/system/types/user.gen_test.go @@ -5,7 +5,7 @@ import ( "errors" - "github.com/crusttech/crust/internal/test" + "github.com/cortezaproject/corteza-server/internal/test" ) // Hello! This file is auto-generated. diff --git a/system/types/user.go b/system/types/user.go index d630bfeb2..5ac14e50f 100644 --- a/system/types/user.go +++ b/system/types/user.go @@ -7,7 +7,7 @@ import ( "github.com/pkg/errors" - "github.com/crusttech/crust/internal/permissions" + "github.com/cortezaproject/corteza-server/internal/permissions" ) type ( @@ -54,7 +54,7 @@ type ( const ( NormalUser UserKind = "" - BotUser = "bot" + BotUser UserKind = "bot" ) func (u *User) Valid() bool { @@ -79,6 +79,7 @@ func (u *User) PermissionResource() permissions.Resource { } func (meta *UserMeta) Scan(value interface{}) error { + //lint:ignore S1034 This typecast is intentional, we need to get []byte out of a []uint8 switch value.(type) { case nil: *meta = UserMeta{}