3
0

add(crm): check service access permissions

This commit is contained in:
Mitja Zivkovic
2019-02-26 11:09:01 +01:00
parent fd511e703e
commit 8804379981
6 changed files with 154 additions and 15 deletions

18
crm/rest/middleware.go Normal file
View File

@@ -0,0 +1,18 @@
package rest
import (
"net/http"
"github.com/crusttech/crust/crm/service"
)
func middlewareAllowedAccess(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !service.DefaultPermissions.With(r.Context()).CanAccessCompose() {
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})
}

View File

@@ -16,11 +16,12 @@ func MountRoutes() func(chi.Router) {
notification = Notification{}.New()
)
// Initialize handers & controllers.
// Initialize handlers & controllers.
return func(r chi.Router) {
// Protect all _private_ routes
r.Group(func(r chi.Router) {
r.Use(auth.MiddlewareValidOnly)
r.Use(middlewareAllowedAccess)
handlers.NewPage(page).MountRoutes(r)
handlers.NewModule(module).MountRoutes(r)

View File

@@ -63,20 +63,6 @@ func TestMain(m *testing.M) {
os.Exit(m.Run())
}
func db() *factory.DB {
return factory.Database.MustGet()
}
func must(t *testing.T, err error, message ...string) {
prefix := "Error"
if len(message) > 0 {
prefix = message[0]
}
if err != nil {
t.Fatalf(prefix+": %+v", err)
}
}
func assert(t *testing.T, ok bool, format string, args ...interface{}) bool {
if !ok {
t.Fatalf(format, args...)

View File

@@ -0,0 +1,64 @@
package service
import (
"context"
"github.com/crusttech/crust/crm/repository"
internalRules "github.com/crusttech/crust/internal/rules"
systemService "github.com/crusttech/crust/system/service"
)
type (
permissions struct {
db db
ctx context.Context
prm systemService.PermissionsService
}
// Fallback option
Fallback func() bool
PermissionsService interface {
With(context.Context) PermissionsService
CanAccessCompose() bool
}
)
func Permissions() PermissionsService {
return (&permissions{
prm: systemService.DefaultPermissions,
}).With(context.Background())
}
func (p *permissions) With(ctx context.Context) PermissionsService {
db := repository.DB(ctx)
return &permissions{
db: db,
ctx: ctx,
prm: p.prm.With(ctx),
}
}
func (p *permissions) CanAccessCompose() bool {
return p.checkAccess("compose", "access")
}
func (p *permissions) checkAccess(resource string, operation string, fbs ...Fallback) bool {
access := p.prm.Check(resource, operation)
switch access {
case internalRules.Allow:
return true
case internalRules.Deny:
return false
default:
for _, fb := range fbs {
if fb() == true {
return true
}
}
return false
}
}

View File

@@ -0,0 +1,62 @@
package service
import (
"context"
"testing"
"github.com/crusttech/crust/internal/auth"
"github.com/crusttech/crust/internal/rules"
. "github.com/crusttech/crust/internal/test"
systemService "github.com/crusttech/crust/system/service"
systemTypes "github.com/crusttech/crust/system/types"
)
func TestPermissions(t *testing.T) {
ctx := context.TODO()
// Create user with role and add it to context.
userSvc := systemService.User().With(ctx)
user := &systemTypes.User{
Name: "John Crm Doe",
Username: "johndoe",
SatosaID: "12345",
}
err := user.GeneratePassword("johndoe")
NoError(t, err, "expected no error generating password, got %v", err)
_, err = userSvc.Create(user)
NoError(t, err, "expected no error creating user, got %v", err)
roleSvc := systemService.Role().With(ctx)
role := &systemTypes.Role{
Name: "Test role v1",
}
role, err = roleSvc.Create(role)
NoError(t, err, "expected no error creating role, got %v", err)
err = roleSvc.MemberAdd(role.ID, user.ID)
NoError(t, err, "expected no error adding user to role, got %v", err)
// Set Identity.
ctx = auth.SetIdentityToContext(ctx, user)
// Generate services.
permissionsSvc := Permissions().With(ctx)
systemPermissionSvc := systemService.Permissions().With(ctx)
// Test `access` to compose service.
ret := permissionsSvc.CanAccessCompose()
Assert(t, ret == false, "expected CanAccessCompose == false, got %v", ret)
// Add `access` to compose service.
list := []rules.Rule{
rules.Rule{Resource: "compose", Operation: "access", Value: rules.Allow},
}
_, err = systemPermissionSvc.Update(role.ID, list)
NoError(t, err, "expected no error, got %v", err)
// Test `access` to compose service.
ret = permissionsSvc.CanAccessCompose()
Assert(t, ret == true, "expected CanAccessCompose == true, got %v", ret)
}

View File

@@ -4,6 +4,12 @@ import (
"sync"
)
type (
db interface {
Transaction(callback func() error) error
}
)
var (
o sync.Once
DefaultRecord RecordService
@@ -12,6 +18,7 @@ var (
DefaultChart ChartService
DefaultPage PageService
DefaultNotification NotificationService
DefaultPermissions PermissionsService
)
func Init() {
@@ -22,5 +29,6 @@ func Init() {
DefaultPage = Page()
DefaultChart = Chart()
DefaultNotification = Notification()
DefaultPermissions = Permissions()
})
}