diff --git a/crm/service/main_test.go b/crm/service/main_test.go index d08cf3c1a..36df969f9 100644 --- a/crm/service/main_test.go +++ b/crm/service/main_test.go @@ -15,11 +15,6 @@ import ( ) func TestMain(m *testing.M) { - if testing.Short() { - log.Println("skipping test in short mode.") - return - } - // @todo this is a very optimistic initialization, make it more robust godotenv.Load("../../.env") diff --git a/crm/service/permissions_test.go b/crm/service/permissions_test.go index d4006e53a..0759035eb 100644 --- a/crm/service/permissions_test.go +++ b/crm/service/permissions_test.go @@ -8,6 +8,7 @@ import ( "github.com/crusttech/crust/internal/rules" . "github.com/crusttech/crust/internal/test" + "github.com/crusttech/crust/crm/repository" systemService "github.com/crusttech/crust/system/service" systemTypes "github.com/crusttech/crust/system/types" ) @@ -41,6 +42,19 @@ func TestPermissions(t *testing.T) { // Set Identity. ctx = auth.SetIdentityToContext(ctx, user) + // Insert `grant` permission for `compose`. + { + db := repository.DB(ctx) + resources := rules.NewResources(ctx, db) + + list := []rules.Rule{ + rules.Rule{Resource: "compose", Operation: "grant", Value: rules.Allow}, + } + + err := resources.Grant(role.ID, list) + NoError(t, err, "expected no error, got %v", err) + } + // Generate services. permissionsSvc := Permissions().With(ctx) systemPermissionSvc := systemService.Permissions().With(ctx) diff --git a/internal/rules/main_test.go b/internal/rules/main_test.go index e63e9f4dd..5f09020e6 100644 --- a/internal/rules/main_test.go +++ b/internal/rules/main_test.go @@ -26,10 +26,6 @@ func TestMain(m *testing.M) { flag.StringVar(&dsn, p("db-dsn"), "crust:crust@tcp(db1:3306)/crust?collation=utf8mb4_general_ci", "DSN for database connection") flag.Parse() - if testing.Short() { - return - } - factory.Database.Add("default", dsn) db := factory.Database.MustGet() diff --git a/messaging/repository/main_test.go b/messaging/repository/main_test.go index aa7fed35e..7229532c9 100644 --- a/messaging/repository/main_test.go +++ b/messaging/repository/main_test.go @@ -29,10 +29,6 @@ func TestMain(m *testing.M) { flag.StringVar(&dsn, p("db-dsn"), "crust:crust@tcp(db1:3306)/crust?collation=utf8mb4_general_ci", "DSN for database connection") flag.Parse() - if testing.Short() { - return - } - factory.Database.Add("default", dsn) db := factory.Database.MustGet() diff --git a/messaging/service/main_test.go b/messaging/service/main_test.go index 436517ee1..7986b4422 100644 --- a/messaging/service/main_test.go +++ b/messaging/service/main_test.go @@ -32,10 +32,6 @@ func TestMain(m *testing.M) { flag.StringVar(&dsn, p("db-dsn"), "crust:crust@tcp(db1:3306)/crust?collation=utf8mb4_general_ci", "DSN for database connection") flag.Parse() - if testing.Short() { - return - } - factory.Database.Add("default", dsn) db := factory.Database.MustGet() diff --git a/messaging/service/permissions_test.go b/messaging/service/permissions_test.go index bc2366e3a..14bf7e2dc 100644 --- a/messaging/service/permissions_test.go +++ b/messaging/service/permissions_test.go @@ -7,6 +7,8 @@ import ( "github.com/crusttech/crust/internal/auth" "github.com/crusttech/crust/internal/rules" . "github.com/crusttech/crust/internal/test" + + "github.com/crusttech/crust/messaging/repository" "github.com/crusttech/crust/messaging/types" systemService "github.com/crusttech/crust/system/service" systemTypes "github.com/crusttech/crust/system/types" @@ -41,6 +43,19 @@ func TestPermissions(t *testing.T) { // Set Identity. ctx = auth.SetIdentityToContext(ctx, user) + // Insert `grant` permission for `messaging`. + { + db := repository.DB(ctx) + resources := rules.NewResources(ctx, db) + + list := []rules.Rule{ + rules.Rule{Resource: "messaging", Operation: "grant", Value: rules.Allow}, + } + + err := resources.Grant(role.ID, list) + NoError(t, err, "expected no error, got %v", err) + } + // Generate services. channelSvc := (&channel{ usr: systemService.User(), diff --git a/system/repository/main_test.go b/system/repository/main_test.go index d3e362f76..4b42d82f5 100644 --- a/system/repository/main_test.go +++ b/system/repository/main_test.go @@ -28,10 +28,6 @@ func TestMain(m *testing.M) { flag.StringVar(&dsn, p("db-dsn"), "crust:crust@tcp(db1:3306)/crust?collation=utf8mb4_general_ci", "DSN for database connection") flag.Parse() - if testing.Short() { - return - } - factory.Database.Add("default", dsn) db := factory.Database.MustGet() diff --git a/system/service/main_test.go b/system/service/main_test.go index b84b0c449..c5edb8624 100644 --- a/system/service/main_test.go +++ b/system/service/main_test.go @@ -32,10 +32,6 @@ func TestMain(m *testing.M) { flag.StringVar(&dsn, p("db-dsn"), "crust:crust@tcp(db1:3306)/crust?collation=utf8mb4_general_ci", "DSN for database connection") flag.Parse() - if testing.Short() { - return - } - factory.Database.Add("default", dsn) db := factory.Database.MustGet() diff --git a/system/service/permissions.go b/system/service/permissions.go index 2b0138c94..22166efc5 100644 --- a/system/service/permissions.go +++ b/system/service/permissions.go @@ -2,12 +2,19 @@ package service import ( "context" + "strings" + + "github.com/pkg/errors" "github.com/crusttech/crust/internal/rules" "github.com/crusttech/crust/system/repository" "github.com/crusttech/crust/system/types" ) +const ( + delimiter = ":" +) + type ( permissions struct { db db @@ -67,6 +74,10 @@ func (p *permissions) Update(roleID uint64, rules []rules.Rule) (interface{}, er if err != nil { return nil, err } + err = p.checkServiceAccess(rule.Resource) + if err != nil { + return nil, err + } } err := p.resources.Grant(roleID, rules) if err != nil { @@ -78,3 +89,13 @@ func (p *permissions) Update(roleID uint64, rules []rules.Rule) (interface{}, er func (p *permissions) Delete(roleID uint64) (interface{}, error) { return nil, p.resources.Delete(roleID) } + +func (p *permissions) checkServiceAccess(resource string) error { + service := strings.Split(resource, delimiter)[0] + + grant := p.resources.Check(service, "grant") + if grant == rules.Allow { + return nil + } + return errors.Errorf("No grant permissions for: %v", service) +} diff --git a/system/service/permissions_test.go b/system/service/permissions_test.go index 6389d14ba..ceab22040 100644 --- a/system/service/permissions_test.go +++ b/system/service/permissions_test.go @@ -9,8 +9,9 @@ import ( internalAuth "github.com/crusttech/crust/internal/auth" "github.com/crusttech/crust/internal/rules" . "github.com/crusttech/crust/internal/test" - systemRepos "github.com/crusttech/crust/system/repository" - systemTypes "github.com/crusttech/crust/system/types" + + "github.com/crusttech/crust/system/repository" + "github.com/crusttech/crust/system/types" ) func TestPermission(t *testing.T) { @@ -21,8 +22,8 @@ func TestPermission(t *testing.T) { ctx := context.TODO() // Create user for test. - userRepo := systemRepos.User(ctx, factory.Database.MustGet()) - user := &systemTypes.User{ + userRepo := repository.User(ctx, factory.Database.MustGet()) + user := &types.User{ Name: "John Doe", Username: "johndoe", SatosaID: "1234", @@ -34,8 +35,8 @@ func TestPermission(t *testing.T) { NoError(t, err, "expected no error creating user, got %v", err) // Create role for test and add user - roleRepo := systemRepos.Role(ctx, factory.Database.MustGet()) - role := &systemTypes.Role{ + roleRepo := repository.Role(ctx, factory.Database.MustGet()) + role := &types.Role{ Name: "Test role v1", } _, err = roleRepo.Create(role) @@ -50,6 +51,29 @@ func TestPermission(t *testing.T) { // Create permission service. permissionSvc := Permissions().With(ctx) + // Update rules for test role, with error. + { + list := []rules.Rule{ + rules.Rule{Resource: "messaging:channel:1", Operation: "message.update.all", Value: rules.Allow}, + } + _, err := permissionSvc.Update(role.ID, list) + Error(t, err, "expected error == No Allow permissions for: messaging") + } + + // Insert `grant` permission for `messaging` and `system`. + { + db := repository.DB(ctx) + resources := rules.NewResources(ctx, db) + + list := []rules.Rule{ + rules.Rule{Resource: "system", Operation: "grant", Value: rules.Allow}, + rules.Rule{Resource: "messaging", Operation: "grant", Value: rules.Allow}, + } + + err := resources.Grant(role.ID, list) + NoError(t, err, "expected no error, got %v", err) + } + // Update rules for test role. { list := []rules.Rule{ @@ -61,7 +85,7 @@ func TestPermission(t *testing.T) { rules.Rule{Resource: "messaging:channel", Operation: "message.update.all", Value: rules.Allow}, } _, err := permissionSvc.Update(role.ID, list) - NoError(t, err, "expected no error, setting rules") + NoError(t, err, "expected no error, got %v", err) } // Update with invalid roles @@ -94,23 +118,23 @@ func TestPermission(t *testing.T) { // Read rules for test role. { ret, err := permissionSvc.Read(role.ID) - NoError(t, err, "expected no error, setting rules") + NoError(t, err, "expected no error, got %v", err) rules := ret.([]rules.Rule) - Assert(t, len(rules) == 5, "expected len(rules) == 5, got %v", len(rules)) + Assert(t, len(rules) == 7, "expected len(rules) == 7, got %v", len(rules)) } // Delete rules for test role. { _, err := permissionSvc.Delete(role.ID) - NoError(t, err, "expected no error, setting rules") + NoError(t, err, "expected no error, got %v", err) } // Read rules for test role. { ret, err := permissionSvc.Read(role.ID) - NoError(t, err, "expected no error, setting rules") + NoError(t, err, "expected no error, got %v", err) rules := ret.([]rules.Rule) @@ -120,9 +144,9 @@ func TestPermission(t *testing.T) { // List defined permissions. { ret, err := permissionSvc.List() - NoError(t, err, "expected no error, setting rules") + NoError(t, err, "expected no error, got %v", err) - perms := ret.([]systemTypes.Permission) + perms := ret.([]types.Permission) Assert(t, len(perms) > 0, "expected len(rules) > 0, got %v", len(perms)) } diff --git a/system/service/validation.go b/system/service/validation.go index 1e0e055f5..5b62230ce 100644 --- a/system/service/validation.go +++ b/system/service/validation.go @@ -87,7 +87,6 @@ var ( ) func validatePermission(resource string, operation string) error { - delimiter := ":" resourceParts := strings.Split(resource, delimiter) if len(resourceParts) < 1 { return errors.Errorf("Invalid resource format, expected >= 1, got %d", len(resourceParts))