Add record procedure exec capabilities
This will allow us to perform bulk operations on record & record-values
This commit is contained in:
@@ -121,6 +121,11 @@ func newHelper(t *testing.T) helper {
|
||||
return h
|
||||
}
|
||||
|
||||
// Returns context w/ security details
|
||||
func (h helper) secCtx() context.Context {
|
||||
return auth.SetIdentityToContext(context.Background(), h.cUser)
|
||||
}
|
||||
|
||||
// apitest basics, initialize, set handler, add auth
|
||||
func (h helper) apiInit() *apitest.APITest {
|
||||
InitApp()
|
||||
|
||||
@@ -17,10 +17,10 @@ func (h helper) repoModule() repository.ModuleRepository {
|
||||
return repository.Module(context.Background(), db())
|
||||
}
|
||||
|
||||
func (h helper) repoMakeModule(ns *types.Namespace, name string) *types.Module {
|
||||
func (h helper) repoMakeModule(ns *types.Namespace, name string, ff ...*types.ModuleField) *types.Module {
|
||||
m, err := h.
|
||||
repoModule().
|
||||
Create(&types.Module{Name: name, NamespaceID: ns.ID})
|
||||
Create(&types.Module{Name: name, NamespaceID: ns.ID, Fields: ff})
|
||||
h.a.NoError(err)
|
||||
|
||||
return m
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/steinfletcher/apitest"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/compose/rest/request"
|
||||
"github.com/cortezaproject/corteza-server/compose/service"
|
||||
"github.com/cortezaproject/corteza-server/compose/types"
|
||||
"github.com/cortezaproject/corteza-server/pkg/rh"
|
||||
"github.com/cortezaproject/corteza-server/tests/helpers"
|
||||
)
|
||||
|
||||
func (h helper) apiSendRecordExec(nsID, modID uint64, proc string, args []request.ProcedureArg) *apitest.Response {
|
||||
payload, err := json.Marshal(request.RecordExec{Args: args})
|
||||
h.a.NoError(err)
|
||||
|
||||
return h.apiInit().
|
||||
Post(fmt.Sprintf("/namespace/%d/module/%d/record/exec/%s", nsID, modID, proc)).
|
||||
JSON(string(payload)).
|
||||
Expect(h.t)
|
||||
}
|
||||
|
||||
func TestRecordExecUnknownProcedure(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
|
||||
h.apiInit().
|
||||
Post("/namespace/0/module/0/record/exec/test-unexisting-proc").
|
||||
Expect(t).
|
||||
Status(http.StatusOK).
|
||||
Assert(helpers.AssertError("unknown procedure")).
|
||||
End()
|
||||
}
|
||||
|
||||
func TestRecordExec(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
|
||||
h.allow(types.ModulePermissionResource.AppendWildcard(), "record.update")
|
||||
|
||||
module := h.repoMakeRecordModuleWithFields(
|
||||
"record testing module",
|
||||
&types.ModuleField{Name: "position", Kind: "Number"},
|
||||
&types.ModuleField{Name: "handle"},
|
||||
&types.ModuleField{Name: "category"},
|
||||
)
|
||||
|
||||
makeRecord := func(position int, handle, cat string) *types.Record {
|
||||
return h.repoMakeRecord(module,
|
||||
&types.RecordValue{Name: "position", Value: strconv.Itoa(position)},
|
||||
&types.RecordValue{Name: "handle", Value: handle},
|
||||
&types.RecordValue{Name: "category", Value: cat},
|
||||
)
|
||||
}
|
||||
|
||||
assertSort := func(expectedHandles string) {
|
||||
// Using record service for fetching to avoid value pre-fetching etc..
|
||||
set, _, err := service.DefaultRecord.With(h.secCtx()).Find(types.RecordFilter{
|
||||
ModuleID: module.ID,
|
||||
NamespaceID: module.NamespaceID,
|
||||
Sort: "position ASC",
|
||||
PageFilter: rh.PageFilter{},
|
||||
})
|
||||
|
||||
h.a.NoError(err)
|
||||
h.a.NotNil(set)
|
||||
|
||||
actualHandles := ""
|
||||
_ = set.Walk(func(r *types.Record) error {
|
||||
v := r.Values.FilterByName("handle")
|
||||
|
||||
if len(v) == 1 {
|
||||
actualHandles += v[0].Value
|
||||
} else {
|
||||
actualHandles += strconv.Itoa(len(v))
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
h.a.Equal(expectedHandles, actualHandles)
|
||||
}
|
||||
|
||||
var (
|
||||
aRec = makeRecord(1, "a", "CAT1")
|
||||
bRec = makeRecord(2, "b", "CAT1")
|
||||
cRec = makeRecord(3, "c", "CAT1")
|
||||
dRec = makeRecord(4, "d", "CAT2")
|
||||
eRec = makeRecord(5, "e", "CAT2")
|
||||
fRec = makeRecord(6, "f", "CAT2")
|
||||
gRec = makeRecord(7, "g", "CAT3")
|
||||
hRec = makeRecord(8, "h", "CAT3")
|
||||
iRec = makeRecord(9, "i", "CAT3")
|
||||
)
|
||||
|
||||
// map handle to record ID so we can use it for reordering
|
||||
rr := map[string]string{
|
||||
"a": strconv.FormatUint(aRec.ID, 10),
|
||||
"b": strconv.FormatUint(bRec.ID, 10),
|
||||
"c": strconv.FormatUint(cRec.ID, 10),
|
||||
"d": strconv.FormatUint(dRec.ID, 10),
|
||||
"e": strconv.FormatUint(eRec.ID, 10),
|
||||
"f": strconv.FormatUint(fRec.ID, 10),
|
||||
"g": strconv.FormatUint(gRec.ID, 10),
|
||||
"h": strconv.FormatUint(hRec.ID, 10),
|
||||
"i": strconv.FormatUint(iRec.ID, 10),
|
||||
}
|
||||
|
||||
assertSort("abcdefghi")
|
||||
|
||||
h.apiSendRecordExec(module.NamespaceID, module.ID, "organize", request.ProcedureArgs{
|
||||
{"recordID", rr["a"]},
|
||||
{"sortingField", "position"},
|
||||
{"sortingValue", "5"}}).
|
||||
Status(http.StatusOK).
|
||||
Assert(helpers.AssertNoErrors).
|
||||
End()
|
||||
|
||||
assertSort("bcdeafghi")
|
||||
|
||||
h.apiSendRecordExec(module.NamespaceID, module.ID, "organize", request.ProcedureArgs{
|
||||
{"recordID", rr["i"]},
|
||||
{"sortingField", "position"},
|
||||
{"sortingValue", "0"}}).
|
||||
Status(http.StatusOK).
|
||||
Assert(helpers.AssertNoErrors).
|
||||
End()
|
||||
|
||||
assertSort("ibcdeafgh")
|
||||
|
||||
h.apiSendRecordExec(module.NamespaceID, module.ID, "organize", request.ProcedureArgs{
|
||||
{"recordID", rr["b"]},
|
||||
{"sortingFilter", "category = 'CAT1'"},
|
||||
{"sortingField", "position"},
|
||||
{"sortingValue", "5"}}).
|
||||
Status(http.StatusOK).
|
||||
Assert(helpers.AssertNoErrors).
|
||||
End()
|
||||
|
||||
assertSort("idecbfgah")
|
||||
|
||||
h.apiSendRecordExec(module.NamespaceID, module.ID, "organize", request.ProcedureArgs{
|
||||
{"recordID", rr["b"]},
|
||||
{"valueField", "category"},
|
||||
{"value", "CAT2"},
|
||||
{"sortingValue", "5"}}).
|
||||
Status(http.StatusOK).
|
||||
Assert(helpers.AssertNoErrors).
|
||||
End()
|
||||
|
||||
assertSort("idecbfgah")
|
||||
rsv, err := h.repoRecord().LoadValues([]string{"category"}, []uint64{bRec.ID})
|
||||
h.a.NoError(err)
|
||||
h.a.NotNil(rsv)
|
||||
h.a.Len(rsv.FilterByName("category"), 1)
|
||||
h.a.Equal("CAT2", rsv.FilterByName("category")[0].Value)
|
||||
}
|
||||
@@ -18,45 +18,40 @@ func (h helper) repoRecord() repository.RecordRepository {
|
||||
return repository.Record(context.Background(), db())
|
||||
}
|
||||
|
||||
func (h helper) repoMakeRecordModuleWithFields(name string) *types.Module {
|
||||
func (h helper) repoMakeRecordModuleWithFields(name string, ff ...*types.ModuleField) *types.Module {
|
||||
namespace := h.repoMakeNamespace("record testing namespace")
|
||||
|
||||
h.allow(types.NamespacePermissionResource.AppendWildcard(), "read")
|
||||
h.allow(types.ModulePermissionResource.AppendWildcard(), "read")
|
||||
h.allow(types.ModulePermissionResource.AppendWildcard(), "record.read")
|
||||
|
||||
m, err := h.
|
||||
repoModule().
|
||||
Create(&types.Module{
|
||||
Name: name,
|
||||
NamespaceID: namespace.ID,
|
||||
Fields: types.ModuleFieldSet{
|
||||
&types.ModuleField{
|
||||
Name: "name",
|
||||
},
|
||||
&types.ModuleField{
|
||||
Name: "email",
|
||||
},
|
||||
&types.ModuleField{
|
||||
Name: "options",
|
||||
Multi: true,
|
||||
},
|
||||
&types.ModuleField{
|
||||
Name: "description",
|
||||
},
|
||||
&types.ModuleField{
|
||||
Name: "another_record",
|
||||
Kind: "Record",
|
||||
},
|
||||
if len(ff) == 0 {
|
||||
// Default fields
|
||||
ff = types.ModuleFieldSet{
|
||||
&types.ModuleField{
|
||||
Name: "name",
|
||||
},
|
||||
})
|
||||
&types.ModuleField{
|
||||
Name: "email",
|
||||
},
|
||||
&types.ModuleField{
|
||||
Name: "options",
|
||||
Multi: true,
|
||||
},
|
||||
&types.ModuleField{
|
||||
Name: "description",
|
||||
},
|
||||
&types.ModuleField{
|
||||
Name: "another_record",
|
||||
Kind: "Record",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
h.a.NoError(err)
|
||||
|
||||
return m
|
||||
return h.repoMakeModule(namespace, name, ff...)
|
||||
}
|
||||
|
||||
func (h helper) repoMakeRecord(module *types.Module, name string) *types.Record {
|
||||
func (h helper) repoMakeRecord(module *types.Module, rvs ...*types.RecordValue) *types.Record {
|
||||
record, err := h.
|
||||
repoRecord().
|
||||
Create(&types.Record{
|
||||
@@ -68,6 +63,9 @@ func (h helper) repoMakeRecord(module *types.Module, name string) *types.Record
|
||||
})
|
||||
h.a.NoError(err)
|
||||
|
||||
err = h.repoRecord().UpdateValues(record.ID, rvs)
|
||||
h.a.NoError(err)
|
||||
|
||||
return record
|
||||
}
|
||||
|
||||
@@ -75,7 +73,7 @@ func TestRecordRead(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
|
||||
module := h.repoMakeRecordModuleWithFields("record testing module")
|
||||
record := h.repoMakeRecord(module, "some-record")
|
||||
record := h.repoMakeRecord(module)
|
||||
|
||||
h.apiInit().
|
||||
Get(fmt.Sprintf("/namespace/%d/module/%d/record/%d", module.NamespaceID, module.ID, record.ID)).
|
||||
@@ -91,8 +89,8 @@ func TestRecordList(t *testing.T) {
|
||||
|
||||
module := h.repoMakeRecordModuleWithFields("record testing module")
|
||||
|
||||
h.repoMakeRecord(module, "app")
|
||||
h.repoMakeRecord(module, "app")
|
||||
h.repoMakeRecord(module)
|
||||
h.repoMakeRecord(module)
|
||||
|
||||
h.apiInit().
|
||||
Get(fmt.Sprintf("/namespace/%d/module/%d/record/", module.NamespaceID, module.ID)).
|
||||
@@ -109,7 +107,7 @@ func TestRecordCreateForbidden(t *testing.T) {
|
||||
|
||||
h.apiInit().
|
||||
Post(fmt.Sprintf("/namespace/%d/module/%d/record/", module.NamespaceID, module.ID)).
|
||||
FormData("name", "some-record").
|
||||
FormData("name").
|
||||
Expect(t).
|
||||
Status(http.StatusOK).
|
||||
Assert(helpers.AssertError("compose.service.NoCreatePermissions")).
|
||||
@@ -124,7 +122,7 @@ func TestRecordCreate(t *testing.T) {
|
||||
|
||||
h.apiInit().
|
||||
Post(fmt.Sprintf("/namespace/%d/module/%d/record/", module.NamespaceID, module.ID)).
|
||||
FormData("name", "some-record").
|
||||
FormData("name").
|
||||
Expect(t).
|
||||
Status(http.StatusOK).
|
||||
Assert(helpers.AssertNoErrors).
|
||||
@@ -135,7 +133,7 @@ func TestRecordUpdateForbidden(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
|
||||
module := h.repoMakeRecordModuleWithFields("record testing module")
|
||||
record := h.repoMakeRecord(module, "some-record")
|
||||
record := h.repoMakeRecord(module)
|
||||
|
||||
h.apiInit().
|
||||
Post(fmt.Sprintf("/namespace/%d/module/%d/record/%d", module.NamespaceID, module.ID, record.ID)).
|
||||
@@ -150,7 +148,7 @@ func TestRecordUpdate(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
|
||||
module := h.repoMakeRecordModuleWithFields("record testing module")
|
||||
record := h.repoMakeRecord(module, "some-record")
|
||||
record := h.repoMakeRecord(module)
|
||||
h.allow(types.ModulePermissionResource.AppendWildcard(), "record.update")
|
||||
|
||||
h.apiInit().
|
||||
@@ -171,7 +169,7 @@ func TestRecordDeleteForbidden(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
|
||||
module := h.repoMakeRecordModuleWithFields("record testing module")
|
||||
record := h.repoMakeRecord(module, "some-record")
|
||||
record := h.repoMakeRecord(module)
|
||||
|
||||
h.apiInit().
|
||||
Delete(fmt.Sprintf("/namespace/%d/module/%d/record/%d", module.NamespaceID, module.ID, record.ID)).
|
||||
@@ -185,7 +183,7 @@ func TestRecordDelete(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
|
||||
module := h.repoMakeRecordModuleWithFields("record testing module")
|
||||
record := h.repoMakeRecord(module, "some-record")
|
||||
record := h.repoMakeRecord(module)
|
||||
|
||||
h.allow(types.ModulePermissionResource.AppendWildcard(), "record.delete")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user