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
This commit is contained in:
Denis Arh
2019-05-24 12:40:12 +02:00
parent 4c166d92c6
commit 908e232ac4
82 changed files with 570 additions and 1002 deletions
-41
View File
@@ -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)
}
}
-83
View File
@@ -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)
}
}
+18 -17
View File
@@ -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)
}
},
+11
View File
@@ -0,0 +1,11 @@
package commands
import (
"fmt"
"os"
)
func exit(err error) {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
+81
View File
@@ -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
}
@@ -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
@@ -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)
}
},
}
+7 -3
View File
@@ -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")
}
+4 -14
View File
@@ -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)
}
-54
View File
@@ -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(),
}
}
+2 -2
View File
@@ -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) {
+1 -1
View File
@@ -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) {
+3 -1
View File
@@ -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"},
})
+2 -4
View File
@@ -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 {
+1 -1
View File
@@ -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"
)
+9 -10
View File
@@ -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)
}
@@ -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)
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"github.com/titpetric/factory"
"github.com/crusttech/crust/system/types"
"github.com/cortezaproject/corteza-server/system/types"
)
type (
@@ -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)
+1 -1
View File
@@ -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 {
+3 -10
View File
@@ -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
@@ -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
+5 -4
View File
@@ -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
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"github.com/titpetric/factory"
"github.com/crusttech/crust/system/types"
"github.com/cortezaproject/corteza-server/system/types"
)
type (
@@ -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 {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"github.com/titpetric/factory"
"github.com/crusttech/crust/internal/auth"
"github.com/cortezaproject/corteza-server/internal/auth"
)
type (
@@ -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) {
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"github.com/titpetric/factory"
"github.com/crusttech/crust/system/types"
"github.com/cortezaproject/corteza-server/system/types"
)
type (
+3 -3
View File
@@ -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)
+1 -1
View File
@@ -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 (
+3 -3
View File
@@ -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 {
+2 -2
View File
@@ -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 (
+2 -2
View File
@@ -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 (
+4 -4
View File
@@ -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 (
+5 -5
View File
@@ -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 (
<tr>
<td style="padding:30px;border-top: 1px solid #F3F3F5">
<p>If you have any questions, please contact <a href="mailto:{{ .SignatureEmail }}" style="color:#1397CB;">{{ .SignatureEmail }}</a>.</p>
<p>We hope you enjoy using Crust!</p>
<p>We hope you enjoy using Corteza!</p>
<p>Best regards, <br>
{{ .SignatureName }}</p>
</td>
@@ -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 +
`<h2 style="color: #1397CB;text-align: center;">Confirm your email address</h2>
<p>Hello,</p>
@@ -95,7 +95,7 @@ var (
<p>You will be logged-in after successful confirmation.</p>` +
emailTemplateFooter,
"password-reset.en.subject": `[Crust] Reset your password`,
"password-reset.en.subject": `[Corteza] Reset your password`,
"password-reset.en.html": emailTemplateHeader +
`<h2 style="color: #1397CB;text-align: center;">Reset your password</h2>
<p>Hello,</p>
+2 -2
View File
@@ -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":
+4 -4
View File
@@ -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
+1 -1
View File
@@ -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 {
+4 -11
View File
@@ -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
+5 -7
View File
@@ -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
+5 -7
View File
@@ -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)
+12 -10
View File
@@ -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)
}
+5 -7
View File
@@ -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) {
+6 -10
View File
@@ -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 {
-26
View File
@@ -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()...)
}
+3 -3
View File
@@ -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"
)
+5 -5
View File
@@ -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
+6 -6
View File
@@ -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
+6 -6
View File
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+3 -3
View File
@@ -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
+3 -3
View File
@@ -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 (
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+4 -2
View File
@@ -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))
}
+4 -4
View File
@@ -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
+17 -20
View File
@@ -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)
})
}
+3 -3
View File
@@ -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
+3 -3
View File
@@ -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
-37
View File
@@ -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)
}
}
-343
View File
@@ -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
}
+1 -1
View File
@@ -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 {
+2 -2
View File
@@ -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 (
-116
View File
@@ -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
}
+167
View File
@@ -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()...)
}
+1 -1
View File
@@ -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.
+2 -1
View File
@@ -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
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -3,7 +3,7 @@ package types
import (
"time"
"github.com/crusttech/crust/internal/permissions"
"github.com/cortezaproject/corteza-server/internal/permissions"
)
type (
+1 -1
View File
@@ -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")
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -3,7 +3,7 @@ package types
import (
"time"
"github.com/crusttech/crust/internal/permissions"
"github.com/cortezaproject/corteza-server/internal/permissions"
)
type (
+1 -1
View File
@@ -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.
+3 -2
View File
@@ -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{}