mirror of
https://github.com/pocketbase/pocketbase.git
synced 2025-02-16 01:19:46 +02:00
1515 lines
53 KiB
Go
1515 lines
53 KiB
Go
package apis_test
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/pocketbase/pocketbase/core"
|
|
"github.com/pocketbase/pocketbase/tests"
|
|
"github.com/pocketbase/pocketbase/tools/list"
|
|
)
|
|
|
|
func TestCollectionsList(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized",
|
|
Method: http.MethodGet,
|
|
URL: "/api/collections",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as regular user",
|
|
Method: http.MethodGet,
|
|
URL: "/api/collections",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyNTI0NjA0NDYxLCJyZWZyZXNoYWJsZSI6dHJ1ZX0.ZT3F0Z3iM-xbGgSG3LEKiEzHrPHr8t8IuHLZGGNuxLo",
|
|
},
|
|
ExpectedStatus: 403,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as superuser",
|
|
Method: http.MethodGet,
|
|
URL: "/api/collections",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"page":1`,
|
|
`"perPage":30`,
|
|
`"totalItems":16`,
|
|
`"items":[{`,
|
|
`"name":"` + core.CollectionNameSuperusers + `"`,
|
|
`"name":"` + core.CollectionNameAuthOrigins + `"`,
|
|
`"name":"` + core.CollectionNameExternalAuths + `"`,
|
|
`"name":"` + core.CollectionNameMFAs + `"`,
|
|
`"name":"` + core.CollectionNameOTPs + `"`,
|
|
`"name":"users"`,
|
|
`"name":"nologin"`,
|
|
`"name":"clients"`,
|
|
`"name":"demo1"`,
|
|
`"name":"demo2"`,
|
|
`"name":"demo3"`,
|
|
`"name":"demo4"`,
|
|
`"name":"demo5"`,
|
|
`"name":"numeric_id_view"`,
|
|
`"name":"view1"`,
|
|
`"name":"view2"`,
|
|
`"type":"auth"`,
|
|
`"type":"base"`,
|
|
`"type":"view"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionsListRequest": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + paging and sorting",
|
|
Method: http.MethodGet,
|
|
URL: "/api/collections?page=2&perPage=2&sort=-created",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"page":2`,
|
|
`"perPage":2`,
|
|
`"totalItems":16`,
|
|
`"items":[{`,
|
|
`"name":"` + core.CollectionNameMFAs + `"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionsListRequest": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + invalid filter",
|
|
Method: http.MethodGet,
|
|
URL: "/api/collections?filter=invalidfield~'demo2'",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + valid filter",
|
|
Method: http.MethodGet,
|
|
URL: "/api/collections?filter=name~'demo'",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"page":1`,
|
|
`"perPage":30`,
|
|
`"totalItems":5`,
|
|
`"items":[{`,
|
|
`"name":"demo1"`,
|
|
`"name":"demo2"`,
|
|
`"name":"demo3"`,
|
|
`"name":"demo4"`,
|
|
`"name":"demo5"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionsListRequest": 1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestCollectionView(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized",
|
|
Method: http.MethodGet,
|
|
URL: "/api/collections/demo1",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as regular user",
|
|
Method: http.MethodGet,
|
|
URL: "/api/collections/demo1",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyNTI0NjA0NDYxLCJyZWZyZXNoYWJsZSI6dHJ1ZX0.ZT3F0Z3iM-xbGgSG3LEKiEzHrPHr8t8IuHLZGGNuxLo",
|
|
},
|
|
ExpectedStatus: 403,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + nonexisting collection identifier",
|
|
Method: http.MethodGet,
|
|
URL: "/api/collections/missing",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 404,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + using the collection name",
|
|
Method: http.MethodGet,
|
|
URL: "/api/collections/demo1",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":"wsmn24bux7wo113"`,
|
|
`"name":"demo1"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionViewRequest": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + using the collection id",
|
|
Method: http.MethodGet,
|
|
URL: "/api/collections/wsmn24bux7wo113",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":"wsmn24bux7wo113"`,
|
|
`"name":"demo1"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionViewRequest": 1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestCollectionDelete(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ensureDeletedFiles := func(app *tests.TestApp, collectionId string) {
|
|
storageDir := filepath.Join(app.DataDir(), "storage", collectionId)
|
|
|
|
entries, _ := os.ReadDir(storageDir)
|
|
if len(entries) != 0 {
|
|
t.Errorf("Expected empty/deleted dir, found %d", len(entries))
|
|
}
|
|
}
|
|
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized",
|
|
Method: http.MethodDelete,
|
|
URL: "/api/collections/demo1",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as regular user",
|
|
Method: http.MethodDelete,
|
|
URL: "/api/collections/demo1",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyNTI0NjA0NDYxLCJyZWZyZXNoYWJsZSI6dHJ1ZX0.ZT3F0Z3iM-xbGgSG3LEKiEzHrPHr8t8IuHLZGGNuxLo",
|
|
},
|
|
ExpectedStatus: 403,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + nonexisting collection identifier",
|
|
Method: http.MethodDelete,
|
|
URL: "/api/collections/missing",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 404,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + using the collection name",
|
|
Method: http.MethodDelete,
|
|
URL: "/api/collections/demo5",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
Delay: 100 * time.Millisecond,
|
|
ExpectedStatus: 204,
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionDeleteRequest": 1,
|
|
"OnCollectionDelete": 1,
|
|
"OnCollectionDeleteExecute": 1,
|
|
"OnCollectionAfterDeleteSuccess": 1,
|
|
"OnModelDelete": 1,
|
|
"OnModelDeleteExecute": 1,
|
|
"OnModelAfterDeleteSuccess": 1,
|
|
},
|
|
AfterTestFunc: func(t testing.TB, app *tests.TestApp, res *http.Response) {
|
|
ensureDeletedFiles(app, "9n89pl5vkct6330")
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + using the collection id",
|
|
Method: http.MethodDelete,
|
|
URL: "/api/collections/9n89pl5vkct6330",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
Delay: 100 * time.Millisecond,
|
|
ExpectedStatus: 204,
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionDeleteRequest": 1,
|
|
"OnCollectionDelete": 1,
|
|
"OnCollectionDeleteExecute": 1,
|
|
"OnCollectionAfterDeleteSuccess": 1,
|
|
"OnModelDelete": 1,
|
|
"OnModelDeleteExecute": 1,
|
|
"OnModelAfterDeleteSuccess": 1,
|
|
},
|
|
AfterTestFunc: func(t testing.TB, app *tests.TestApp, res *http.Response) {
|
|
ensureDeletedFiles(app, "9n89pl5vkct6330")
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + trying to delete a system collection",
|
|
Method: http.MethodDelete,
|
|
URL: "/api/collections/" + core.CollectionNameMFAs,
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionDeleteRequest": 1,
|
|
"OnCollectionDelete": 1,
|
|
"OnCollectionDeleteExecute": 1,
|
|
"OnCollectionAfterDeleteError": 1,
|
|
"OnModelDelete": 1,
|
|
"OnModelDeleteExecute": 1,
|
|
"OnModelAfterDeleteError": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + trying to delete a referenced collection",
|
|
Method: http.MethodDelete,
|
|
URL: "/api/collections/demo2",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionDeleteRequest": 1,
|
|
"OnCollectionDelete": 1,
|
|
"OnCollectionDeleteExecute": 1,
|
|
"OnCollectionAfterDeleteError": 1,
|
|
"OnModelDelete": 1,
|
|
"OnModelDeleteExecute": 1,
|
|
"OnModelAfterDeleteError": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + deleting a view",
|
|
Method: http.MethodDelete,
|
|
URL: "/api/collections/view2",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 204,
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionDeleteRequest": 1,
|
|
"OnCollectionDelete": 1,
|
|
"OnCollectionDeleteExecute": 1,
|
|
"OnCollectionAfterDeleteSuccess": 1,
|
|
"OnModelDelete": 1,
|
|
"OnModelDeleteExecute": 1,
|
|
"OnModelAfterDeleteSuccess": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "OnCollectionAfterDeleteSuccessRequest error response",
|
|
Method: http.MethodDelete,
|
|
URL: "/api/collections/view2",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
|
app.OnCollectionDeleteRequest().BindFunc(func(e *core.CollectionRequestEvent) error {
|
|
return errors.New("error")
|
|
})
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionDeleteRequest": 1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestCollectionCreate(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as regular user",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
Body: strings.NewReader(`{"name":"new","type":"base","fields":[{"type":"text","name":"test"}]}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyNTI0NjA0NDYxLCJyZWZyZXNoYWJsZSI6dHJ1ZX0.ZT3F0Z3iM-xbGgSG3LEKiEzHrPHr8t8IuHLZGGNuxLo",
|
|
},
|
|
ExpectedStatus: 403,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + empty data",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
Body: strings.NewReader(``),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"name":{"code":"validation_required"`,
|
|
},
|
|
NotExpectedContent: []string{
|
|
`"fields":{`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionCreateRequest": 1,
|
|
"OnCollectionCreate": 1,
|
|
"OnCollectionAfterCreateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelCreate": 1,
|
|
"OnModelAfterCreateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + invalid data (eg. existing name)",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
Body: strings.NewReader(`{"name":"demo1","type":"base","fields":[{"type":"text","name":""}]}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"fields":{`,
|
|
`"name":{"code":"validation_collection_name_exists"`,
|
|
`"name":{"code":"validation_required"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionCreateRequest": 1,
|
|
"OnCollectionCreate": 1,
|
|
"OnCollectionAfterCreateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelCreate": 1,
|
|
"OnModelAfterCreateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + valid data",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
Body: strings.NewReader(`{"name":"new","type":"base","fields":[{"type":"text","id":"12345789","name":"test"}]}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":`,
|
|
`"name":"new"`,
|
|
`"type":"base"`,
|
|
`"system":false`,
|
|
// ensures that id field was prepended
|
|
`"fields":[{"autogeneratePattern":"[a-z0-9]{15}","hidden":false,"id":"text3208210256","max":15,"min":15,"name":"id","pattern":"^[a-z0-9]+$","presentable":false,"primaryKey":true,"required":true,"system":true,"type":"text"},{"autogeneratePattern":"","hidden":false,"id":"12345789","max":0,"min":0,"name":"test","pattern":"","presentable":false,"primaryKey":false,"required":false,"system":false,"type":"text"}]`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionCreateRequest": 1,
|
|
"OnCollectionCreate": 1,
|
|
"OnCollectionCreateExecute": 1,
|
|
"OnCollectionAfterCreateSuccess": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelCreate": 1,
|
|
"OnModelCreateExecute": 1,
|
|
"OnModelAfterCreateSuccess": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "creating auth collection (default settings merge test)",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
Body: strings.NewReader(`{
|
|
"name":"new",
|
|
"type":"auth",
|
|
"emailChangeToken":{"duration":123},
|
|
"fields":[
|
|
{"type":"text","id":"12345789","name":"test"},
|
|
{"type":"text","name":"tokenKey","system":true,"required":false,"min":10}
|
|
]
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":`,
|
|
`"name":"new"`,
|
|
`"type":"auth"`,
|
|
`"system":false`,
|
|
`"passwordAuth":{"enabled":true,"identityFields":["email"]}`,
|
|
`"authRule":""`,
|
|
`"manageRule":null`,
|
|
`"name":"test"`,
|
|
`"name":"id"`,
|
|
`"name":"tokenKey"`,
|
|
`"name":"password"`,
|
|
`"name":"email"`,
|
|
`"name":"emailVisibility"`,
|
|
`"name":"verified"`,
|
|
`"duration":123`,
|
|
// should overwrite the user required option but keep the min value
|
|
`{"autogeneratePattern":"","hidden":true,"id":"text2504183744","max":0,"min":10,"name":"tokenKey","pattern":"","presentable":false,"primaryKey":false,"required":true,"system":true,"type":"text"}`,
|
|
},
|
|
NotExpectedContent: []string{
|
|
`"secret":"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionCreateRequest": 1,
|
|
"OnCollectionCreate": 1,
|
|
"OnCollectionCreateExecute": 1,
|
|
"OnCollectionAfterCreateSuccess": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelCreate": 1,
|
|
"OnModelCreateExecute": 1,
|
|
"OnModelAfterCreateSuccess": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "creating base collection with reserved auth fields",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
Body: strings.NewReader(`{
|
|
"name":"new",
|
|
"type":"base",
|
|
"fields":[
|
|
{"type":"text","name":"email"},
|
|
{"type":"text","name":"username"},
|
|
{"type":"text","name":"verified"},
|
|
{"type":"text","name":"emailVisibility"},
|
|
{"type":"text","name":"lastResetSentAt"},
|
|
{"type":"text","name":"lastVerificationSentAt"},
|
|
{"type":"text","name":"tokenKey"},
|
|
{"type":"text","name":"passwordHash"},
|
|
{"type":"text","name":"password"},
|
|
{"type":"text","name":"passwordConfirm"},
|
|
{"type":"text","name":"oldPassword"}
|
|
]
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"name":"new"`,
|
|
`"type":"base"`,
|
|
`"fields":[{`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionCreateRequest": 1,
|
|
"OnCollectionCreate": 1,
|
|
"OnCollectionCreateExecute": 1,
|
|
"OnCollectionAfterCreateSuccess": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelCreate": 1,
|
|
"OnModelCreateExecute": 1,
|
|
"OnModelAfterCreateSuccess": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "trying to create base collection with reserved system fields",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
Body: strings.NewReader(`{
|
|
"name":"new",
|
|
"type":"base",
|
|
"fields":[
|
|
{"type":"text","name":"id"},
|
|
{"type":"text","name":"expand"},
|
|
{"type":"text","name":"collectionId"},
|
|
{"type":"text","name":"collectionName"}
|
|
]
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{"fields":{`,
|
|
`"1":{"name":{"code":"validation_not_in_invalid`,
|
|
`"2":{"name":{"code":"validation_not_in_invalid`,
|
|
`"3":{"name":{"code":"validation_not_in_invalid`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionCreateRequest": 1,
|
|
"OnCollectionCreate": 1,
|
|
"OnCollectionAfterCreateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelCreate": 1,
|
|
"OnModelAfterCreateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "trying to create auth collection with reserved auth fields",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
Body: strings.NewReader(`{
|
|
"name":"new",
|
|
"type":"auth",
|
|
"fields":[
|
|
{"type":"text","name":"oldPassword"},
|
|
{"type":"text","name":"passwordConfirm"}
|
|
]
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{"fields":{`,
|
|
`"1":{"name":{"code":"validation_reserved_field_name`,
|
|
`"2":{"name":{"code":"validation_reserved_field_name`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionCreateRequest": 1,
|
|
"OnCollectionCreate": 1,
|
|
"OnCollectionAfterCreateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelCreate": 1,
|
|
"OnModelAfterCreateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "OnCollectionCreateRequest error response",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
Body: strings.NewReader(`{"name":"new","type":"base"}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
|
app.OnCollectionCreateRequest().BindFunc(func(e *core.CollectionRequestEvent) error {
|
|
return errors.New("error")
|
|
})
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionCreateRequest": 1,
|
|
},
|
|
},
|
|
|
|
// view
|
|
// -----------------------------------------------------------
|
|
{
|
|
Name: "trying to create view collection with invalid options",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
Body: strings.NewReader(`{
|
|
"name":"new",
|
|
"type":"view",
|
|
"fields":[{"type":"text","id":"12345789","name":"ignored!@#$"}],
|
|
"viewQuery":"invalid"
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"viewQuery":{"code":"validation_invalid_view_query`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionCreateRequest": 1,
|
|
"OnCollectionCreate": 1,
|
|
"OnCollectionAfterCreateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelCreate": 1,
|
|
"OnModelAfterCreateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "creating view collection",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
Body: strings.NewReader(`{
|
|
"name":"new",
|
|
"type":"view",
|
|
"fields":[{"type":"text","id":"12345789","name":"ignored!@#$"}],
|
|
"viewQuery": "select 1 as id from ` + core.CollectionNameSuperusers + `"
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"name":"new"`,
|
|
`"type":"view"`,
|
|
`"fields":[{"autogeneratePattern":"","hidden":false,"id":"text3208210256","max":0,"min":0,"name":"id","pattern":"^[a-z0-9]+$","presentable":false,"primaryKey":true,"required":true,"system":true,"type":"text"}]`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionCreateRequest": 1,
|
|
"OnCollectionCreate": 1,
|
|
"OnCollectionCreateExecute": 1,
|
|
"OnCollectionAfterCreateSuccess": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelCreate": 1,
|
|
"OnModelCreateExecute": 1,
|
|
"OnModelAfterCreateSuccess": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
|
|
// indexes
|
|
// -----------------------------------------------------------
|
|
{
|
|
Name: "creating base collection with invalid indexes",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
Body: strings.NewReader(`{
|
|
"name":"new",
|
|
"type":"base",
|
|
"fields":[
|
|
{"type":"text","name":"test"}
|
|
],
|
|
"indexes": [
|
|
"create index idx_test1 on new (test)",
|
|
"create index idx_test2 on new (missing)"
|
|
]
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"indexes":{"1":{"code":"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionCreateRequest": 1,
|
|
"OnCollectionCreate": 1,
|
|
"OnCollectionCreateExecute": 1,
|
|
"OnCollectionAfterCreateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelCreate": 1,
|
|
"OnModelCreateExecute": 1,
|
|
"OnModelAfterCreateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "creating base collection with index name from another collection",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
Body: strings.NewReader(`{
|
|
"name":"new",
|
|
"type":"base",
|
|
"fields":[
|
|
{"type":"text","name":"test"}
|
|
],
|
|
"indexes": [
|
|
"create index exist_test on new (test)"
|
|
]
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
|
demo1, err := app.FindCollectionByNameOrId("demo1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
demo1.AddIndex("exist_test", false, "updated", "")
|
|
if err = app.Save(demo1); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"indexes":{`,
|
|
`"0":{"code":"validation_existing_index_name"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionCreateRequest": 1,
|
|
"OnCollectionCreate": 1,
|
|
"OnCollectionAfterCreateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelCreate": 1,
|
|
"OnModelAfterCreateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "creating base collection with 2 indexes using the same name",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
Body: strings.NewReader(`{
|
|
"name":"new",
|
|
"type":"base",
|
|
"indexes": [
|
|
"create index duplicate_idx on new (created)",
|
|
"create index duplicate_idx on new (updated)"
|
|
]
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"indexes":{`,
|
|
`"1":{"code":"validation_duplicated_index_name"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionCreateRequest": 1,
|
|
"OnCollectionCreate": 1,
|
|
"OnCollectionAfterCreateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelCreate": 1,
|
|
"OnModelAfterCreateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "creating base collection with valid indexes (+ random table name)",
|
|
Method: http.MethodPost,
|
|
URL: "/api/collections",
|
|
Body: strings.NewReader(`{
|
|
"name":"new",
|
|
"type":"base",
|
|
"fields":[
|
|
{"type":"text","name":"test"}
|
|
],
|
|
"indexes": [
|
|
"create index idx_test1 on new (test)",
|
|
"create index idx_test2 on anything (id, test)"
|
|
]
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"name":"new"`,
|
|
`"type":"base"`,
|
|
`"indexes":[`,
|
|
`idx_test1`,
|
|
`idx_test2`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionCreateRequest": 1,
|
|
"OnCollectionCreate": 1,
|
|
"OnCollectionCreateExecute": 1,
|
|
"OnCollectionAfterCreateSuccess": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelCreate": 1,
|
|
"OnModelCreateExecute": 1,
|
|
"OnModelAfterCreateSuccess": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
AfterTestFunc: func(t testing.TB, app *tests.TestApp, res *http.Response) {
|
|
indexes, err := app.TableIndexes("new")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
expected := []string{"idx_test1", "idx_test2"}
|
|
if len(indexes) != len(expected) {
|
|
t.Fatalf("Expected %d indexes, got %d\n%v", len(expected), len(indexes), indexes)
|
|
}
|
|
for name := range indexes {
|
|
if !list.ExistInSlice(name, expected) {
|
|
t.Fatalf("Missing index %q", name)
|
|
}
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestCollectionUpdate(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/demo1",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as regular user",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/demo1",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyNTI0NjA0NDYxLCJyZWZyZXNoYWJsZSI6dHJ1ZX0.ZT3F0Z3iM-xbGgSG3LEKiEzHrPHr8t8IuHLZGGNuxLo",
|
|
},
|
|
ExpectedStatus: 403,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + missing collection",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/missing",
|
|
Body: strings.NewReader(`{}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 404,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + empty body",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/demo1",
|
|
Body: strings.NewReader(`{}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":"wsmn24bux7wo113"`,
|
|
`"name":"demo1"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionUpdateRequest": 1,
|
|
"OnCollectionUpdate": 1,
|
|
"OnCollectionUpdateExecute": 1,
|
|
"OnCollectionAfterUpdateSuccess": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelUpdate": 1,
|
|
"OnModelUpdateExecute": 1,
|
|
"OnModelAfterUpdateSuccess": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "OnCollectionAfterUpdateSuccessRequest error response",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/demo1",
|
|
Body: strings.NewReader(`{}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
|
app.OnCollectionUpdateRequest().BindFunc(func(e *core.CollectionRequestEvent) error {
|
|
return errors.New("error")
|
|
})
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionUpdateRequest": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + invalid data (eg. existing name)",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/demo1",
|
|
Body: strings.NewReader(`{
|
|
"name":"demo2",
|
|
"type":"auth"
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"name":{"code":"validation_collection_name_exists"`,
|
|
`"type":{"code":"validation_collection_type_change"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionUpdateRequest": 1,
|
|
"OnCollectionUpdate": 1,
|
|
"OnCollectionAfterUpdateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelUpdate": 1,
|
|
"OnModelAfterUpdateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as superuser + valid data",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/demo1",
|
|
Body: strings.NewReader(`{"name":"new"}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":`,
|
|
`"name":"new"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionUpdateRequest": 1,
|
|
"OnCollectionUpdate": 1,
|
|
"OnCollectionUpdateExecute": 1,
|
|
"OnCollectionAfterUpdateSuccess": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelUpdate": 1,
|
|
"OnModelUpdateExecute": 1,
|
|
"OnModelAfterUpdateSuccess": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
AfterTestFunc: func(t testing.TB, app *tests.TestApp, res *http.Response) {
|
|
// check if the record table was renamed
|
|
if !app.HasTable("new") {
|
|
t.Fatal("Couldn't find record table 'new'.")
|
|
}
|
|
},
|
|
},
|
|
{
|
|
Name: "trying to update collection with reserved fields",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/demo1",
|
|
Body: strings.NewReader(`{
|
|
"name":"new",
|
|
"fields":[
|
|
{"type":"text","name":"id","id":"_pbf_text_id_"},
|
|
{"type":"text","name":"created"},
|
|
{"type":"text","name":"updated"},
|
|
{"type":"text","name":"expand"},
|
|
{"type":"text","name":"collectionId"},
|
|
{"type":"text","name":"collectionName"}
|
|
]
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{"fields":{`,
|
|
`"3":{"name":{"code":"validation_not_in_invalid`,
|
|
`"4":{"name":{"code":"validation_not_in_invalid`,
|
|
`"5":{"name":{"code":"validation_not_in_invalid`,
|
|
},
|
|
NotExpectedContent: []string{
|
|
`"0":`,
|
|
`"1":`,
|
|
`"2":`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionUpdateRequest": 1,
|
|
"OnCollectionUpdate": 1,
|
|
"OnCollectionAfterUpdateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelUpdate": 1,
|
|
"OnModelAfterUpdateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "trying to update collection with changed/removed system fields",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/demo1",
|
|
Body: strings.NewReader(`{
|
|
"name":"new",
|
|
"fields":[
|
|
{"type":"text","name":"created"}
|
|
]
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{"fields":{`,
|
|
`"code":"validation_system_field_change"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionUpdateRequest": 1,
|
|
"OnCollectionUpdate": 1,
|
|
"OnCollectionAfterUpdateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelUpdate": 1,
|
|
"OnModelAfterUpdateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "trying to update auth collection with invalid options",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/users",
|
|
Body: strings.NewReader(`{
|
|
"passwordAuth":{"identityFields": ["missing"]}
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"passwordAuth":{"identityFields":{"code":"validation_missing_field"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionUpdateRequest": 1,
|
|
"OnCollectionUpdate": 1,
|
|
"OnCollectionAfterUpdateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelUpdate": 1,
|
|
"OnModelAfterUpdateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
|
|
// view
|
|
// -----------------------------------------------------------
|
|
{
|
|
Name: "trying to update view collection with invalid options",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/view1",
|
|
Body: strings.NewReader(`{
|
|
"fields":[{"type":"text","id":"12345789","name":"ignored!@#$"}],
|
|
"viewQuery":"invalid"
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"viewQuery":{"code":"validation_invalid_view_query"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionUpdateRequest": 1,
|
|
"OnCollectionUpdate": 1,
|
|
"OnCollectionAfterUpdateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelUpdate": 1,
|
|
"OnModelAfterUpdateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "updating view collection",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/view2",
|
|
Body: strings.NewReader(`{
|
|
"name":"view2_update",
|
|
"fields":[{"type":"text","id":"12345789","name":"ignored!@#$"}],
|
|
"viewQuery": "select 2 as id, created, updated, email from ` + core.CollectionNameSuperusers + `"
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"name":"view2_update"`,
|
|
`"type":"view"`,
|
|
`"fields":[{`,
|
|
`"name":"email"`,
|
|
`"name":"id"`,
|
|
`"name":"created"`,
|
|
`"name":"updated"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionUpdateRequest": 1,
|
|
"OnCollectionUpdate": 1,
|
|
"OnCollectionUpdateExecute": 1,
|
|
"OnCollectionAfterUpdateSuccess": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelUpdate": 1,
|
|
"OnModelUpdateExecute": 1,
|
|
"OnModelAfterUpdateSuccess": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
|
|
// indexes
|
|
// -----------------------------------------------------------
|
|
{
|
|
Name: "updating base collection with invalid indexes",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/demo2",
|
|
Body: strings.NewReader(`{
|
|
"indexes": [
|
|
"create unique idx_test1 on demo1 (text)",
|
|
"create index idx_test2 on demo2 (id, title)"
|
|
]
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"indexes":{"0":{"code":"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionUpdateRequest": 1,
|
|
"OnCollectionUpdate": 1,
|
|
"OnCollectionAfterUpdateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelUpdate": 1,
|
|
"OnModelAfterUpdateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
|
|
{
|
|
Name: "updating base collection with index name from another collection",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/demo2",
|
|
Body: strings.NewReader(`{
|
|
"indexes": [
|
|
"create index exist_test on new (test)"
|
|
]
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
|
demo1, err := app.FindCollectionByNameOrId("demo1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
demo1.AddIndex("exist_test", false, "updated", "")
|
|
if err = app.Save(demo1); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"indexes":{`,
|
|
`"0":{"code":"validation_existing_index_name"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionUpdateRequest": 1,
|
|
"OnCollectionUpdate": 1,
|
|
"OnCollectionAfterUpdateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelUpdate": 1,
|
|
"OnModelAfterUpdateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "updating base collection with 2 indexes using the same name",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/demo2",
|
|
Body: strings.NewReader(`{
|
|
"indexes": [
|
|
"create index duplicate_idx on new (created)",
|
|
"create index duplicate_idx on new (updated)"
|
|
]
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"indexes":{`,
|
|
`"1":{"code":"validation_duplicated_index_name"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionUpdateRequest": 1,
|
|
"OnCollectionUpdate": 1,
|
|
"OnCollectionAfterUpdateError": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelUpdate": 1,
|
|
"OnModelAfterUpdateError": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
},
|
|
|
|
{
|
|
Name: "updating base collection with valid indexes (+ random table name)",
|
|
Method: http.MethodPatch,
|
|
URL: "/api/collections/demo2",
|
|
Body: strings.NewReader(`{
|
|
"indexes": [
|
|
"create unique index idx_test1 on demo2 (title)",
|
|
"create index idx_test2 on anything (active)"
|
|
]
|
|
}`),
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"name":"demo2"`,
|
|
`"indexes":[`,
|
|
`idx_test1`,
|
|
`idx_test2`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnCollectionUpdateRequest": 1,
|
|
"OnCollectionUpdate": 1,
|
|
"OnCollectionUpdateExecute": 1,
|
|
"OnCollectionAfterUpdateSuccess": 1,
|
|
"OnCollectionValidate": 1,
|
|
"OnModelUpdate": 1,
|
|
"OnModelUpdateExecute": 1,
|
|
"OnModelAfterUpdateSuccess": 1,
|
|
"OnModelValidate": 1,
|
|
},
|
|
AfterTestFunc: func(t testing.TB, app *tests.TestApp, res *http.Response) {
|
|
indexes, err := app.TableIndexes("demo2")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
expected := []string{"idx_test1", "idx_test2"}
|
|
if len(indexes) != len(expected) {
|
|
t.Fatalf("Expected %d indexes, got %d\n%v", len(expected), len(indexes), indexes)
|
|
}
|
|
for name := range indexes {
|
|
if !list.ExistInSlice(name, expected) {
|
|
t.Fatalf("Missing index %q", name)
|
|
}
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestCollectionScaffolds(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized",
|
|
Method: http.MethodGet,
|
|
URL: "/api/collections/meta/scaffolds",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as regular user",
|
|
Method: http.MethodGet,
|
|
URL: "/api/collections/meta/scaffolds",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyNTI0NjA0NDYxLCJyZWZyZXNoYWJsZSI6dHJ1ZX0.ZT3F0Z3iM-xbGgSG3LEKiEzHrPHr8t8IuHLZGGNuxLo",
|
|
},
|
|
ExpectedStatus: 403,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as superuser",
|
|
Method: http.MethodGet,
|
|
URL: "/api/collections/meta/scaffolds",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":""`,
|
|
`"name":""`,
|
|
`"auth":{`,
|
|
`"base":{`,
|
|
`"view":{`,
|
|
`"type":"auth"`,
|
|
`"type":"base"`,
|
|
`"type":"view"`,
|
|
`"fields":[{`,
|
|
`"fields":[{`,
|
|
`"id":"text3208210256"`,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestCollectionTruncate(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized",
|
|
Method: http.MethodDelete,
|
|
URL: "/api/collections/demo5/truncate",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as regular user",
|
|
Method: http.MethodDelete,
|
|
URL: "/api/collections/demo5/truncate",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyNTI0NjA0NDYxLCJyZWZyZXNoYWJsZSI6dHJ1ZX0.ZT3F0Z3iM-xbGgSG3LEKiEzHrPHr8t8IuHLZGGNuxLo",
|
|
},
|
|
ExpectedStatus: 403,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
{
|
|
Name: "authorized as superuser",
|
|
Method: http.MethodDelete,
|
|
URL: "/api/collections/demo5/truncate",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 204,
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnModelDelete": 2,
|
|
"OnModelDeleteExecute": 2,
|
|
"OnModelAfterDeleteSuccess": 2,
|
|
"OnRecordDelete": 2,
|
|
"OnRecordDeleteExecute": 2,
|
|
"OnRecordAfterDeleteSuccess": 2,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as superuser but collection with required cascade delete references",
|
|
Method: http.MethodDelete,
|
|
URL: "/api/collections/demo3/truncate",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{
|
|
"*": 0,
|
|
"OnModelDelete": 2,
|
|
"OnModelDeleteExecute": 2,
|
|
"OnModelAfterDeleteError": 2,
|
|
"OnModelUpdate": 2,
|
|
"OnModelUpdateExecute": 2,
|
|
"OnModelAfterUpdateError": 2,
|
|
"OnRecordDelete": 2,
|
|
"OnRecordDeleteExecute": 2,
|
|
"OnRecordAfterDeleteError": 2,
|
|
"OnRecordUpdate": 2,
|
|
"OnRecordUpdateExecute": 2,
|
|
"OnRecordAfterUpdateError": 2,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as superuser trying to truncate view collection",
|
|
Method: http.MethodDelete,
|
|
URL: "/api/collections/view2/truncate",
|
|
Headers: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{"*": 0},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|