Fix all tests broken by compose/namespace change
This commit is contained in:
@@ -93,6 +93,10 @@ steps:
|
||||
CI: circleci
|
||||
AUTH_OIDC_ENABLED: 0
|
||||
AUTH_JWT_SECRET: bRxJ37sJ6Qu4
|
||||
DB_DSN: crust:crust@tcp(crust-db:3306)/crust?collation=utf8mb4_general_ci
|
||||
SYSTEM_DB_DSN: crust:crust@tcp(crust-db:3306)/crust?collation=utf8mb4_general_ci
|
||||
COMPOSE_DB_DSN: crust:crust@tcp(crust-db:3306)/crust?collation=utf8mb4_general_ci
|
||||
MESSAGING_DB_DSN: crust:crust@tcp(crust-db:3306)/crust?collation=utf8mb4_general_ci
|
||||
commands:
|
||||
- make mocks
|
||||
- make codegen
|
||||
@@ -103,11 +107,13 @@ steps:
|
||||
- go build -ldflags "-X github.com/crusttech/crust/internal/version.BuildTime=`date +%FT%T%z` -X github.com/crusttech/crust/internal/version.Version=`git describe --always --tags`" -o build/system-cli-$GOOS-$GOARCH cmd/system-cli/*.go
|
||||
# check all tests are able to build
|
||||
- wait-for-it.sh -t 60 --strict crust-db:3306 -- echo "Crust DB1 is up"
|
||||
- ./build/system-cli-$GOOS-$GOARCH roles reset
|
||||
- gotest -v --tags="migrations" ./system/db/...
|
||||
- gotest -v --tags="migrations" ./compose/db/...
|
||||
- gotest -v --tags="migrations" ./messaging/db/...
|
||||
- go test -run=^$ --tags="unit integration external" ./cmd/... ./internal/... ./compose/... ./messaging/... ./system/...
|
||||
- gotest -failfast --coverprofile=coverage.txt -v --tags="unit integration" ./internal/... ./system/... ./compose/... ./messaging/...
|
||||
|
||||
- name: coverage
|
||||
image: plugins/codecov
|
||||
settings:
|
||||
|
||||
@@ -116,7 +116,7 @@ func (r *namespace) Update(mod *types.Namespace) (*types.Namespace, error) {
|
||||
return mod, r.db().Replace(r.table(), mod)
|
||||
}
|
||||
|
||||
func (r *namespace) DeleteByID(id uint64) error {
|
||||
_, err := r.db().Exec("DELETE FROM "+r.table()+" WHERE id=?", id)
|
||||
func (r *namespace) DeleteByID(namespaceID uint64) error {
|
||||
_, err := r.db().Exec("UPDATE "+r.table()+" SET deleted_at = NOW() WHERE id = ?", namespaceID)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ type (
|
||||
With(ctx context.Context, db *factory.DB) PageRepository
|
||||
|
||||
FindByID(namespaceID, pageID uint64) (*types.Page, error)
|
||||
FindByModuleID(namespaceID, pageID uint64) (*types.Page, error)
|
||||
FindByModuleID(namespaceID, moduleID uint64) (*types.Page, error)
|
||||
Find(filter types.PageFilter) (set types.PageSet, f types.PageFilter, err error)
|
||||
|
||||
Create(mod *types.Page) (*types.Page, error)
|
||||
@@ -107,6 +107,8 @@ func (r page) Find(filter types.PageFilter) (set types.PageSet, f types.PageFilt
|
||||
|
||||
if filter.ParentID > 0 {
|
||||
query = query.Where("self_id = ?", filter.ParentID)
|
||||
} else if filter.Root {
|
||||
query = query.Where("self_id = 0")
|
||||
}
|
||||
|
||||
if f.Query != "" {
|
||||
@@ -171,6 +173,7 @@ func (r page) Create(mod *types.Page) (*types.Page, error) {
|
||||
func (r page) Update(mod *types.Page) (*types.Page, error) {
|
||||
now := time.Now()
|
||||
mod.UpdatedAt = &now
|
||||
|
||||
return mod, r.db().Replace(r.table(), mod)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,87 @@
|
||||
// +build unit
|
||||
// +build integration
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/crusttech/crust/compose/types"
|
||||
"github.com/crusttech/crust/internal/auth"
|
||||
"github.com/crusttech/crust/internal/test"
|
||||
systemTypes "github.com/crusttech/crust/system/types"
|
||||
)
|
||||
|
||||
func TestModuleGraph(t *testing.T) {
|
||||
// repository := Module().With(context.Background())
|
||||
func TestChart(t *testing.T) {
|
||||
ctx := context.WithValue(context.Background(), "testing", true)
|
||||
|
||||
user := &systemTypes.User{
|
||||
ID: 1337,
|
||||
Name: "John Crm Doe",
|
||||
Username: "johndoe",
|
||||
}
|
||||
|
||||
// Set Identity (required for permission checks).
|
||||
ctx = auth.SetIdentityToContext(ctx, user)
|
||||
|
||||
ns1, _ := createTestNamespaces(ctx, t)
|
||||
|
||||
svc := Chart().With(ctx)
|
||||
|
||||
// the chart object we're working with
|
||||
chart := &types.Chart{
|
||||
NamespaceID: ns1.ID,
|
||||
Name: "Test",
|
||||
}
|
||||
|
||||
{
|
||||
{
|
||||
m, err := svc.Update(chart)
|
||||
test.Assert(t, m == nil, "Expected empty return for invalid update, got %#v", m)
|
||||
test.Assert(t, err != nil, "Expected error when updating invalid content")
|
||||
}
|
||||
|
||||
// create chart
|
||||
m, err := svc.Create(chart)
|
||||
test.Assert(t, err == nil, "Error when creating chart: %+v", err)
|
||||
test.Assert(t, m.ID > 0, "Expected auto generated ID")
|
||||
|
||||
{
|
||||
_, err := svc.Create(chart)
|
||||
test.Assert(t, err == nil, "Unexpected error when creating chart, %+v", err)
|
||||
}
|
||||
|
||||
// fetch created chart
|
||||
{
|
||||
ms, err := svc.FindByID(m.NamespaceID, m.ID)
|
||||
test.Assert(t, err == nil, "Error when retrieving chart by id: %+v", err)
|
||||
test.Assert(t, ms.ID == m.ID, "Expected ID from database to match, %+v", errors.Errorf("%d != %d", m.ID, ms.ID))
|
||||
test.Assert(t, ms.Name == m.Name, "Expected Name from database to match, %+v", errors.Errorf("%s != %s", m.Name, ms.Name))
|
||||
}
|
||||
|
||||
// update created chart
|
||||
{
|
||||
m.UpdatedAt = nil
|
||||
m.Name = "Updated test"
|
||||
_, err := svc.Update(m)
|
||||
test.Assert(t, err == nil, "Error when updating chart, %+v", err)
|
||||
}
|
||||
|
||||
// re-fetch chart
|
||||
{
|
||||
ms, err := svc.FindByID(m.NamespaceID, m.ID)
|
||||
test.Assert(t, err == nil, "Error when retrieving chart by id: %+v", err)
|
||||
test.Assert(t, ms.ID == m.ID, "re-fetch: Expected ID from database to match, %d != %d", m.ID, ms.ID)
|
||||
test.Assert(t, ms.Name == m.Name, "Expected Name from database to match, %s != %s", m.Name, ms.Name)
|
||||
}
|
||||
|
||||
// delete chart
|
||||
{
|
||||
err := svc.DeleteByID(m.NamespaceID, m.ID)
|
||||
test.Assert(t, err == nil, "Error when deleting chart by id: %+v", err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
@@ -11,6 +12,8 @@ import (
|
||||
"github.com/titpetric/factory"
|
||||
|
||||
composeMigrate "github.com/crusttech/crust/compose/db"
|
||||
"github.com/crusttech/crust/compose/types"
|
||||
"github.com/crusttech/crust/internal/test"
|
||||
systemMigrate "github.com/crusttech/crust/system/db"
|
||||
systemService "github.com/crusttech/crust/system/service"
|
||||
)
|
||||
@@ -56,3 +59,15 @@ func TestMain(m *testing.M) {
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func createTestNamespaces(ctx context.Context, t *testing.T) (ns1 *types.Namespace, ns2 *types.Namespace) {
|
||||
var err error
|
||||
|
||||
ns1, err = Namespace().With(ctx).Create(&types.Namespace{Enabled: true, Name: "TestNamespace"})
|
||||
test.Assert(t, err == nil, "Error when creating namespace: %+v", err)
|
||||
|
||||
ns2, err = Namespace().With(ctx).Create(&types.Namespace{Enabled: true, Name: "TestNamespace"})
|
||||
test.Assert(t, err == nil, "Error when creating namespace: %+v", err)
|
||||
|
||||
return ns1, ns2
|
||||
}
|
||||
|
||||
@@ -100,6 +100,11 @@ func (svc *module) Find(filter types.ModuleFilter) (set types.ModuleSet, f types
|
||||
}
|
||||
|
||||
func (svc *module) Create(mod *types.Module) (*types.Module, error) {
|
||||
|
||||
if mod.NamespaceID == 0 {
|
||||
return nil, ErrNamespaceRequired.withStack()
|
||||
}
|
||||
|
||||
if !svc.prmSvc.CanCreateModule(crmNamespace()) {
|
||||
return nil, ErrNoCreatePermissions.withStack()
|
||||
}
|
||||
|
||||
@@ -24,11 +24,14 @@ func TestModule(t *testing.T) {
|
||||
// Set Identity (required for permission checks).
|
||||
ctx = auth.SetIdentityToContext(ctx, user)
|
||||
|
||||
ns1, _ := createTestNamespaces(ctx, t)
|
||||
|
||||
svc := Module().With(ctx)
|
||||
|
||||
// the module object we're working with
|
||||
module := &types.Module{
|
||||
Name: "Test",
|
||||
NamespaceID: ns1.ID,
|
||||
Name: "Test",
|
||||
Fields: types.ModuleFieldSet{
|
||||
&types.ModuleField{
|
||||
Name: "name",
|
||||
@@ -65,7 +68,7 @@ func TestModule(t *testing.T) {
|
||||
|
||||
// fetch created module
|
||||
{
|
||||
ms, err := svc.FindByID(m.ID)
|
||||
ms, err := svc.FindByID(m.NamespaceID, m.ID)
|
||||
test.Assert(t, err == nil, "Error when retrieving module by id: %+v", err)
|
||||
test.Assert(t, ms.ID == m.ID, "Expected ID from database to match, %d != %d", m.ID, ms.ID)
|
||||
test.Assert(t, ms.Name == m.Name, "Expected Name from database to match, %s != %s", m.Name, ms.Name)
|
||||
@@ -75,6 +78,7 @@ func TestModule(t *testing.T) {
|
||||
// update created module
|
||||
{
|
||||
m.Name = "Updated test"
|
||||
m.UpdatedAt = nil
|
||||
_, err := svc.Update(m)
|
||||
test.Assert(t, err == nil, "Error when updating module, %+v", err)
|
||||
}
|
||||
@@ -88,7 +92,7 @@ func TestModule(t *testing.T) {
|
||||
|
||||
// re-fetch module
|
||||
{
|
||||
ms, err := svc.FindByID(m.ID)
|
||||
ms, err := svc.FindByID(m.NamespaceID, m.ID)
|
||||
test.Assert(t, err == nil, "Error when retrieving module by id: %+v", err)
|
||||
test.Assert(t, ms.ID == m.ID, "Expected ID from database to match, %d != %d", m.ID, ms.ID)
|
||||
test.Assert(t, ms.Name == m.Name, "Expected Name from database to match, %s != %s", m.Name, ms.Name)
|
||||
@@ -96,7 +100,7 @@ func TestModule(t *testing.T) {
|
||||
|
||||
// fetch all modules
|
||||
{
|
||||
ms, err := svc.Find()
|
||||
ms, _, err := svc.Find(types.ModuleFilter{})
|
||||
test.Assert(t, err == nil, "Error when retrieving modules: %+v", err)
|
||||
test.Assert(t, len(ms) >= 1, "Expected at least one module, got %d", len(ms))
|
||||
prevModuleCount = len(ms)
|
||||
@@ -104,13 +108,13 @@ func TestModule(t *testing.T) {
|
||||
|
||||
// re-fetch module
|
||||
{
|
||||
err := svc.DeleteByID(m.ID)
|
||||
err := svc.DeleteByID(m.NamespaceID, m.ID)
|
||||
test.Assert(t, err == nil, "Error when deleting module by id: %+v", err)
|
||||
}
|
||||
|
||||
// fetch all modules
|
||||
{
|
||||
ms, err := svc.Find()
|
||||
ms, _, err := svc.Find(types.ModuleFilter{})
|
||||
test.Assert(t, err == nil, "Error when retrieving modules: %+v", err)
|
||||
test.Assert(t, len(ms) < prevModuleCount, "Expected modules count to decrease after deletion, %d < %d", len(ms), prevModuleCount)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// +build integration
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/crusttech/crust/compose/types"
|
||||
"github.com/crusttech/crust/internal/auth"
|
||||
"github.com/crusttech/crust/internal/test"
|
||||
systemTypes "github.com/crusttech/crust/system/types"
|
||||
)
|
||||
|
||||
func TestNamespace(t *testing.T) {
|
||||
ctx := context.WithValue(context.Background(), "testing", true)
|
||||
|
||||
user := &systemTypes.User{
|
||||
ID: 1337,
|
||||
Name: "John Crm Doe",
|
||||
Username: "johndoe",
|
||||
}
|
||||
|
||||
// Set Identity (required for permission checks).
|
||||
ctx = auth.SetIdentityToContext(ctx, user)
|
||||
|
||||
svc := Namespace().With(ctx)
|
||||
|
||||
// the namespace object we're working with
|
||||
namespace := &types.Namespace{
|
||||
Name: "Test",
|
||||
}
|
||||
|
||||
prevNamespaceCount := uint(0)
|
||||
|
||||
{
|
||||
{
|
||||
m, err := svc.Update(namespace)
|
||||
test.Assert(t, m == nil, "Expected empty return for invalid update, got %#v", m)
|
||||
test.Assert(t, err != nil, "Expected error when updating invalid content")
|
||||
}
|
||||
|
||||
// create namespace
|
||||
m, err := svc.Create(namespace)
|
||||
test.Assert(t, err == nil, "Error when creating namespace: %+v", err)
|
||||
test.Assert(t, m.ID > 0, "Expected auto generated ID")
|
||||
|
||||
// fetch created namespace
|
||||
{
|
||||
ms, err := svc.FindByID(m.ID)
|
||||
test.Assert(t, err == nil, "Error when retrieving namespace by id: %+v", err)
|
||||
test.Assert(t, ms.ID == m.ID, "Expected ID from database to match, %d != %d", m.ID, ms.ID)
|
||||
test.Assert(t, ms.Name == m.Name, "Expected Name from database to match, %s != %s", m.Name, ms.Name)
|
||||
}
|
||||
|
||||
// update created namespace
|
||||
{
|
||||
m.Name = "Updated test"
|
||||
m.UpdatedAt = nil
|
||||
_, err := svc.Update(m)
|
||||
test.Assert(t, err == nil, "Error when updating namespace, %+v", err)
|
||||
}
|
||||
|
||||
// re-fetch namespace
|
||||
{
|
||||
ms, err := svc.FindByID(m.ID)
|
||||
test.Assert(t, err == nil, "Error when retrieving namespace by id: %+v", err)
|
||||
test.Assert(t, ms.ID == m.ID, "Expected ID from database to match, %d != %d", m.ID, ms.ID)
|
||||
test.Assert(t, ms.Name == m.Name, "Expected Name from database to match, %s != %s", m.Name, ms.Name)
|
||||
}
|
||||
|
||||
// fetch all namespaces
|
||||
{
|
||||
_, f, err := svc.Find(types.NamespaceFilter{})
|
||||
test.Assert(t, err == nil, "Error when retrieving namespaces: %+v", err)
|
||||
test.Assert(t, f.Count > 0, "Expected at least one namespace, got %d", f.Count)
|
||||
prevNamespaceCount = f.Count
|
||||
}
|
||||
|
||||
// re-fetch namespace
|
||||
{
|
||||
err := svc.DeleteByID(m.ID)
|
||||
test.Assert(t, err == nil, "Error when deleting namespace by id: %+v", err)
|
||||
}
|
||||
|
||||
// fetch all namespaces
|
||||
{
|
||||
_, f, err := svc.Find(types.NamespaceFilter{})
|
||||
test.Assert(t, err == nil, "Error when retrieving namespaces: %+v", err)
|
||||
test.Assert(t, f.Count < prevNamespaceCount, "Expected namespaces count to decrease after deletion, %d < %d", f.Count, prevNamespaceCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,10 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
ErrModulePageExists serviceError = "ModulePageExists"
|
||||
)
|
||||
|
||||
func Page() PageService {
|
||||
return (&page{
|
||||
prmSvc: DefaultPermissions,
|
||||
@@ -76,17 +80,32 @@ func (svc *page) checkPermissions(p *types.Page, err error) (*types.Page, error)
|
||||
}
|
||||
|
||||
func (svc *page) FindBySelfID(namespaceID, parentID uint64) (pp types.PageSet, f types.PageFilter, err error) {
|
||||
if namespaceID == 0 {
|
||||
return nil, f, ErrNamespaceRequired.withStack()
|
||||
}
|
||||
|
||||
return svc.filterPageSetByPermission(svc.pageRepo.Find(types.PageFilter{
|
||||
NamespaceID: namespaceID,
|
||||
ParentID: parentID,
|
||||
|
||||
// This will enable parentID=0 query
|
||||
Root: true,
|
||||
}))
|
||||
}
|
||||
|
||||
func (svc *page) Find(filter types.PageFilter) (set types.PageSet, f types.PageFilter, err error) {
|
||||
if filter.NamespaceID == 0 {
|
||||
return nil, f, ErrNamespaceRequired.withStack()
|
||||
}
|
||||
|
||||
return svc.filterPageSetByPermission(svc.pageRepo.Find(filter))
|
||||
}
|
||||
|
||||
func (svc *page) Tree(namespaceID uint64) (pages types.PageSet, err error) {
|
||||
if namespaceID == 0 {
|
||||
return nil, ErrNamespaceRequired.withStack()
|
||||
}
|
||||
|
||||
var (
|
||||
tree types.PageSet
|
||||
filter = types.PageFilter{
|
||||
@@ -140,58 +159,70 @@ func (svc *page) Reorder(namespaceID, selfID uint64, pageIDs []uint64) error {
|
||||
return svc.pageRepo.Reorder(namespaceID, selfID, pageIDs)
|
||||
}
|
||||
|
||||
func (svc *page) Create(page *types.Page) (p *types.Page, err error) {
|
||||
validate := func() error {
|
||||
if !svc.prmSvc.CanCreatePage(crmNamespace()) {
|
||||
return errors.New("not allowed to create this page")
|
||||
}
|
||||
func (svc *page) Create(mod *types.Page) (p *types.Page, err error) {
|
||||
mod.ID = 0
|
||||
|
||||
if page.ModuleID > 0 {
|
||||
if p, err = svc.pageRepo.FindByModuleID(page.NamespaceID, page.ModuleID); err != nil {
|
||||
return err
|
||||
} else if p.ID > 0 {
|
||||
return errors.New("Page for module already exists")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
if mod.NamespaceID == 0 {
|
||||
return nil, ErrNamespaceRequired.withStack()
|
||||
}
|
||||
if err := validate(); err != nil {
|
||||
return nil, err
|
||||
|
||||
if !svc.prmSvc.CanCreatePage(crmNamespace()) {
|
||||
return nil, ErrNoCreatePermissions.withStack()
|
||||
}
|
||||
return p, svc.db.Transaction(func() (err error) {
|
||||
p, err = svc.pageRepo.Create(page)
|
||||
|
||||
if err = svc.checkModulePage(mod); err != nil {
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
p, err = svc.pageRepo.Create(mod)
|
||||
return
|
||||
}
|
||||
|
||||
func (svc *page) Update(page *types.Page) (p *types.Page, err error) {
|
||||
validate := func() error {
|
||||
if page.ID == 0 {
|
||||
return errors.New("Error when saving page, invalid ID")
|
||||
} else if p, err = svc.pageRepo.FindByID(page.NamespaceID, page.ID); err != nil {
|
||||
return errors.Wrap(err, "Error while loading page for update")
|
||||
} else {
|
||||
if !svc.prmSvc.CanUpdatePage(p) {
|
||||
return errors.New("not allowed to update this page")
|
||||
}
|
||||
}
|
||||
func (svc *page) Update(mod *types.Page) (p *types.Page, err error) {
|
||||
if mod.ID == 0 {
|
||||
return nil, ErrInvalidID.withStack()
|
||||
}
|
||||
|
||||
if page.ModuleID > 0 {
|
||||
if p, err = svc.pageRepo.FindByModuleID(page.NamespaceID, page.ModuleID); err != nil {
|
||||
return err
|
||||
} else if p.ID > 0 && page.ID != p.ID {
|
||||
return errors.New("Page for module already exists")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err := validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, svc.db.Transaction(func() (err error) {
|
||||
p, err = svc.pageRepo.Update(page)
|
||||
if p, err = svc.pageRepo.FindByID(mod.NamespaceID, mod.ID); err != nil {
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
if isStale(mod.UpdatedAt, p.UpdatedAt, p.CreatedAt) {
|
||||
return nil, ErrStaleData.withStack()
|
||||
}
|
||||
|
||||
if !svc.prmSvc.CanUpdatePage(p) {
|
||||
return nil, ErrNoUpdatePermissions.withStack()
|
||||
}
|
||||
|
||||
if err = svc.checkModulePage(mod); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
p.ModuleID = mod.ModuleID
|
||||
p.SelfID = mod.SelfID
|
||||
p.Blocks = mod.Blocks
|
||||
p.Title = mod.Title
|
||||
p.Description = mod.Description
|
||||
p.Visible = mod.Visible
|
||||
p.Weight = mod.Weight
|
||||
|
||||
p, err = svc.pageRepo.Update(p)
|
||||
return
|
||||
}
|
||||
|
||||
func (svc page) checkModulePage(mod *types.Page) error {
|
||||
if mod.ModuleID > 0 {
|
||||
if p, err := svc.pageRepo.FindByModuleID(mod.NamespaceID, mod.ModuleID); err != nil {
|
||||
if err.Error() != repository.ErrPageNotFound.Error() {
|
||||
return err
|
||||
}
|
||||
} else if p.ID > 0 && mod.ID != p.ID {
|
||||
return ErrModulePageExists
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *page) DeleteByID(namespaceID, pageID uint64) error {
|
||||
|
||||
@@ -27,12 +27,16 @@ func TestPage(t *testing.T) {
|
||||
// Set Identity (required for permission checks).
|
||||
ctx = auth.SetIdentityToContext(ctx, user)
|
||||
|
||||
repository := Page().With(ctx)
|
||||
ns1, _ := createTestNamespaces(ctx, t)
|
||||
|
||||
svc := Page().With(ctx)
|
||||
|
||||
// the page object we're working with
|
||||
var err error
|
||||
page := &types.Page{
|
||||
Title: "Test",
|
||||
ModuleID: 123,
|
||||
NamespaceID: ns1.ID,
|
||||
Title: "Test",
|
||||
ModuleID: 123,
|
||||
}
|
||||
(&page.Blocks).Scan([]byte("[]"))
|
||||
|
||||
@@ -40,104 +44,99 @@ func TestPage(t *testing.T) {
|
||||
|
||||
{
|
||||
{
|
||||
m, err := repository.Update(page)
|
||||
m, err := svc.Update(page)
|
||||
test.Assert(t, m == nil, "Expected empty return for invalid update, got %#v", m)
|
||||
test.Assert(t, err != nil, "Expected error when updating invalid content")
|
||||
}
|
||||
|
||||
// create page
|
||||
m, err := repository.Create(page)
|
||||
page, err = svc.Create(page)
|
||||
test.Assert(t, err == nil, "Error when creating page: %+v", err)
|
||||
test.Assert(t, m.ID > 0, "Expected auto generated ID")
|
||||
test.Assert(t, page.ID > 0, "Expected auto generated ID")
|
||||
|
||||
page.SelfID = m.ID
|
||||
var firstPageID = page.ID
|
||||
|
||||
page.SelfID = page.ID
|
||||
|
||||
{
|
||||
_, err := repository.Create(page)
|
||||
_, err = svc.Create(page)
|
||||
test.Assert(t, err != nil, "%+v", errors.Errorf("Expected error when creating duplicate moduleID page"))
|
||||
}
|
||||
|
||||
page.ModuleID = 0
|
||||
|
||||
{
|
||||
page.ModuleID = 0
|
||||
_, err := repository.Create(page)
|
||||
_, err = svc.Create(page)
|
||||
test.Assert(t, err == nil, "Unexpected error when creating page, %+v", err)
|
||||
}
|
||||
{
|
||||
_, err := repository.Create(page)
|
||||
_, err = svc.Create(page)
|
||||
test.Assert(t, err == nil, "Unexpected error when creating page, %+v", err)
|
||||
}
|
||||
|
||||
// fetch created page
|
||||
{
|
||||
ms, err := repository.FindByID(m.ID)
|
||||
p, err := svc.FindByID(page.NamespaceID, page.ID)
|
||||
test.Assert(t, err == nil, "Error when retrieving page by id: %+v", err)
|
||||
test.Assert(t, ms.ID == m.ID, "Expected ID from database to match, %+v", errors.Errorf("%d != %d", m.ID, ms.ID))
|
||||
test.Assert(t, ms.Title == m.Title, "Expected Title from database to match, %+v", errors.Errorf("%s != %s", m.Title, ms.Title))
|
||||
test.Assert(t, p.ID == page.ID, "Expected ID from database to match, %+v", errors.Errorf("%d != %d", page.ID, p.ID))
|
||||
test.Assert(t, p.Title == page.Title, "Expected Title from database to match, %+v", errors.Errorf("%s != %s", page.Title, p.Title))
|
||||
}
|
||||
|
||||
// update created page
|
||||
{
|
||||
m.Title = "Updated test"
|
||||
_, err := repository.Update(m)
|
||||
page.Title = "Updated test"
|
||||
page.UpdatedAt = nil
|
||||
_, err := svc.Update(page)
|
||||
test.Assert(t, err == nil, "Error when updating page, %+v", err)
|
||||
}
|
||||
|
||||
// re-fetch page
|
||||
{
|
||||
ms, err := repository.FindByID(m.ID)
|
||||
p, err := svc.FindByID(page.NamespaceID, page.ID)
|
||||
test.Assert(t, err == nil, "Error when retrieving page by id: %+v", err)
|
||||
test.Assert(t, ms.ID == m.ID, "re-fetch: Expected ID from database to match, %d != %d", m.ID, ms.ID)
|
||||
test.Assert(t, ms.Title == m.Title, "Expected Title from database to match, %s != %s", m.Title, ms.Title)
|
||||
}
|
||||
|
||||
// re-fetch page with moduleID
|
||||
{
|
||||
ms, err := repository.FindByModuleID(m.ModuleID)
|
||||
test.Assert(t, err == nil, "Error when retrieving page by id: %+v", err)
|
||||
test.Assert(t, ms.ID == m.ID, "fetch-module: Expected ID from database to match, %d != %d", m.ID, ms.ID)
|
||||
test.Assert(t, ms.Title == m.Title, "Expected Title from database to match, %s != %s", m.Title, ms.Title)
|
||||
test.Assert(t, p.ID == page.ID, "re-fetch: Expected ID from database to match, %d != %d", page.ID, p.ID)
|
||||
test.Assert(t, p.Title == page.Title, "Expected Title from database to match, %s != %s", page.Title, p.Title)
|
||||
}
|
||||
|
||||
// fetch all pages
|
||||
{
|
||||
ms, err := repository.FindBySelfID(0)
|
||||
p, _, err := svc.FindBySelfID(page.NamespaceID, 0)
|
||||
test.Assert(t, err == nil, "Error when retrieving pages: %+v", err)
|
||||
test.Assert(t, len(ms) >= 1, "Expected at least one page, got %d", len(ms))
|
||||
prevPageCount = len(ms)
|
||||
test.Assert(t, len(p) >= 1, "Expected at least one page, got %d", len(p))
|
||||
prevPageCount = len(p)
|
||||
}
|
||||
|
||||
// fetch all pages
|
||||
{
|
||||
ms, err := repository.FindBySelfID(m.ID)
|
||||
p, _, err := svc.FindBySelfID(page.NamespaceID, firstPageID)
|
||||
test.Assert(t, err == nil, "Error when retrieving pages: %+v", err)
|
||||
test.Assert(t, len(ms) == 2, "Expected two pages with selfID=%d, got %v", m.ID, spew.Sdump(ms))
|
||||
prevPageCount = len(ms)
|
||||
test.Assert(t, len(p) == 2, "Expected 2 pages with selfID=%d, got %v", page.ID, spew.Sdump(p))
|
||||
prevPageCount = len(p)
|
||||
|
||||
parent := m.ID
|
||||
ids := []uint64{ms[0].ID, ms[1].ID}
|
||||
ids := []uint64{p[0].ID, p[1].ID}
|
||||
|
||||
{
|
||||
err := repository.Reorder(parent, ids)
|
||||
err := svc.Reorder(page.NamespaceID, firstPageID, ids)
|
||||
test.Assert(t, err == nil, "Error when reordering pages: %+v", err)
|
||||
|
||||
ms, err = repository.FindBySelfID(m.ID)
|
||||
p, _, err = svc.FindBySelfID(page.NamespaceID, firstPageID)
|
||||
test.Assert(t, err == nil, "Error when retrieving pages: %+v", err)
|
||||
test.Assert(t, len(ms) == 2, "Expected two pages with selfID=%d, got %v", m.ID, spew.Sdump(ms))
|
||||
test.Assert(t, ms[0].Weight < ms[1].Weight, "Expected ascending order, %+v", errors.Errorf("%d < %d", ms[0].Weight, ms[1].Weight))
|
||||
test.Assert(t, len(p) == 2, "Expected 2 pages with selfID=%d, got %v", page.ID, spew.Sdump(p))
|
||||
test.Assert(t, p[0].Weight < p[1].Weight, "Expected ascending order, %+v", errors.Errorf("%d < %d", p[0].Weight, p[1].Weight))
|
||||
}
|
||||
}
|
||||
|
||||
// re-fetch page
|
||||
{
|
||||
err := repository.DeleteByID(m.ID)
|
||||
err := svc.DeleteByID(page.NamespaceID, page.ID)
|
||||
test.Assert(t, err == nil, "Error when deleting page by id: %+v", err)
|
||||
}
|
||||
|
||||
// fetch all pages
|
||||
{
|
||||
ms, err := repository.FindBySelfID(0)
|
||||
p, _, err := svc.FindBySelfID(page.NamespaceID, 0)
|
||||
test.Assert(t, err == nil, "Error when retrieving pages: %+v", err)
|
||||
test.Assert(t, len(ms) < prevPageCount, "Expected pages count to decrease after deletion, %d < %d", len(ms), prevPageCount)
|
||||
test.Assert(t, len(p) < prevPageCount, "Expected pages count to decrease after deletion, %d < %d", len(p), prevPageCount)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ type (
|
||||
Effective() (ee []effectivePermission, err error)
|
||||
|
||||
CanAccess() bool
|
||||
CanGrant() bool
|
||||
CanCreateNamespace() bool
|
||||
CanReadNamespace(r permissionResource) bool
|
||||
CanUpdateNamespace(r permissionResource) bool
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
// +build integration
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/crusttech/crust/compose/internal/repository"
|
||||
"github.com/crusttech/crust/compose/types"
|
||||
"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) {
|
||||
var err error
|
||||
ctx := context.WithValue(context.Background(), "testing", true)
|
||||
{
|
||||
user := &systemTypes.User{ID: 1337}
|
||||
ctx = auth.SetIdentityToContext(ctx, auth.NewIdentity(user.Identity()))
|
||||
}
|
||||
|
||||
// Create user with role and add it to context.
|
||||
userSvc := systemService.TestUser(t, ctx)
|
||||
user := &systemTypes.User{
|
||||
Name: "John Crm Doe",
|
||||
Username: "johndoe",
|
||||
}
|
||||
|
||||
_, err = userSvc.Create(user)
|
||||
NoError(t, err, "expected no error creating user, got %+v", err)
|
||||
|
||||
ctx = auth.SetIdentityToContext(ctx, user)
|
||||
|
||||
roleSvc := systemService.TestRole(t, 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)
|
||||
|
||||
// Insert `grant` permission for `compose`.
|
||||
{
|
||||
db := repository.DB(ctx)
|
||||
resources := rules.NewResources(ctx, db)
|
||||
|
||||
list := []rules.Rule{
|
||||
rules.Rule{Resource: types.PermissionResource, Operation: "grant", Value: rules.Allow},
|
||||
}
|
||||
|
||||
err := resources.Grant(role.ID, list)
|
||||
NoError(t, err, "expected no error, got %+v", err)
|
||||
}
|
||||
|
||||
// Generate services.
|
||||
cleanContext := auth.SetIdentityToContext(context.Background(), user)
|
||||
permissionsSvc := Permissions().With(cleanContext)
|
||||
systemRulesSvc := systemService.TestRules(t, ctx)
|
||||
|
||||
// Test `access` to compose service.
|
||||
ret := permissionsSvc.CanAccess()
|
||||
Assert(t, ret == false, "expected CanAccess == false, got %+v", ret)
|
||||
|
||||
// Add `access` to compose service.
|
||||
list := []rules.Rule{
|
||||
rules.Rule{Resource: types.PermissionResource, Operation: "access", Value: rules.Allow},
|
||||
}
|
||||
_, err = systemRulesSvc.Update(role.ID, list)
|
||||
NoError(t, err, "expected no error, got %+v", err)
|
||||
|
||||
// Test `access` to compose service.
|
||||
ret = permissionsSvc.CanAccess()
|
||||
Assert(t, ret == true, "expected CanAccess == true, got %+v", ret)
|
||||
}
|
||||
@@ -46,8 +46,8 @@ func Init() error {
|
||||
// Data is stale when new date does not match updatedAt or createdAt (before first update)
|
||||
func isStale(new *time.Time, updatedAt *time.Time, createdAt time.Time) bool {
|
||||
if new == nil {
|
||||
// Change to true to require stale-data-check.
|
||||
return true
|
||||
// Change to true for stale-data-check
|
||||
return false
|
||||
}
|
||||
|
||||
if updatedAt != nil {
|
||||
|
||||
@@ -77,6 +77,10 @@ func (svc trigger) Find(filter types.TriggerFilter) (set types.TriggerSet, f typ
|
||||
}
|
||||
|
||||
func (svc trigger) Create(mod *types.Trigger) (c *types.Trigger, err error) {
|
||||
if mod.NamespaceID == 0 {
|
||||
return nil, ErrNamespaceRequired.withStack()
|
||||
}
|
||||
|
||||
if !svc.prmSvc.CanCreateTrigger(crmNamespace()) {
|
||||
return nil, ErrNoCreatePermissions.withStack()
|
||||
}
|
||||
|
||||
@@ -26,12 +26,15 @@ func TestTrigger(t *testing.T) {
|
||||
// Set Identity (required for permission checks).
|
||||
ctx = auth.SetIdentityToContext(ctx, user)
|
||||
|
||||
ns1, _ := createTestNamespaces(ctx, t)
|
||||
|
||||
svc := Trigger().With(ctx)
|
||||
|
||||
// the trigger object we're working with
|
||||
trigger := &types.Trigger{
|
||||
Name: "Test",
|
||||
ModuleID: 123,
|
||||
NamespaceID: ns1.ID,
|
||||
Name: "Test",
|
||||
ModuleID: 123,
|
||||
}
|
||||
|
||||
{
|
||||
@@ -53,7 +56,7 @@ func TestTrigger(t *testing.T) {
|
||||
|
||||
// fetch created trigger
|
||||
{
|
||||
ms, err := svc.FindByID(m.ID)
|
||||
ms, err := svc.FindByID(m.NamespaceID, m.ID)
|
||||
test.Assert(t, err == nil, "Error when retrieving trigger by id: %+v", err)
|
||||
test.Assert(t, ms.ID == m.ID, "Expected ID from database to match, %+v", errors.Errorf("%d != %d", m.ID, ms.ID))
|
||||
test.Assert(t, ms.Name == m.Name, "Expected Name from database to match, %+v", errors.Errorf("%s != %s", m.Name, ms.Name))
|
||||
@@ -61,6 +64,7 @@ func TestTrigger(t *testing.T) {
|
||||
|
||||
// update created trigger
|
||||
{
|
||||
m.UpdatedAt = nil
|
||||
m.Name = "Updated test"
|
||||
_, err := svc.Update(m)
|
||||
test.Assert(t, err == nil, "Error when updating trigger, %+v", err)
|
||||
@@ -68,7 +72,7 @@ func TestTrigger(t *testing.T) {
|
||||
|
||||
// re-fetch trigger
|
||||
{
|
||||
ms, err := svc.FindByID(m.ID)
|
||||
ms, err := svc.FindByID(m.NamespaceID, m.ID)
|
||||
test.Assert(t, err == nil, "Error when retrieving trigger by id: %+v", err)
|
||||
test.Assert(t, ms.ID == m.ID, "re-fetch: Expected ID from database to match, %d != %d", m.ID, ms.ID)
|
||||
test.Assert(t, ms.Name == m.Name, "Expected Name from database to match, %s != %s", m.Name, ms.Name)
|
||||
@@ -76,7 +80,7 @@ func TestTrigger(t *testing.T) {
|
||||
|
||||
// delete trigger
|
||||
{
|
||||
err := svc.DeleteByID(m.ID)
|
||||
err := svc.DeleteByID(m.NamespaceID, m.ID)
|
||||
test.Assert(t, err == nil, "Error when deleting trigger by id: %+v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,8 @@ type (
|
||||
|
||||
PageFilter struct {
|
||||
NamespaceID uint64 `json:"namespaceID,string"`
|
||||
ParentID uint64 `json:"paentID,string"`
|
||||
ParentID uint64 `json:"parentID,string,omitempty"`
|
||||
Root bool `json:"root,omitempty"`
|
||||
Query string `json:"query"`
|
||||
Page uint `json:"page"`
|
||||
PerPage uint `json:"perPage"`
|
||||
|
||||
Reference in New Issue
Block a user