mirror of
https://github.com/pocketbase/pocketbase.git
synced 2024-11-24 17:07:00 +02:00
768 lines
26 KiB
Go
768 lines
26 KiB
Go
package apis_test
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/labstack/echo/v5"
|
|
"github.com/pocketbase/dbx"
|
|
"github.com/pocketbase/pocketbase/daos"
|
|
"github.com/pocketbase/pocketbase/models"
|
|
"github.com/pocketbase/pocketbase/tests"
|
|
"github.com/pocketbase/pocketbase/tools/types"
|
|
)
|
|
|
|
func TestAdminAuthWithPassword(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "empty data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/auth-with-password",
|
|
Body: strings.NewReader(``),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{"identity":{"code":"validation_required","message":"Cannot be blank."},"password":{"code":"validation_required","message":"Cannot be blank."}}`},
|
|
},
|
|
{
|
|
Name: "invalid data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/auth-with-password",
|
|
Body: strings.NewReader(`{`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "wrong email",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/auth-with-password",
|
|
Body: strings.NewReader(`{"identity":"missing@example.com","password":"1234567890"}`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{
|
|
"OnAdminBeforeAuthWithPasswordRequest": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "wrong password",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/auth-with-password",
|
|
Body: strings.NewReader(`{"identity":"test@example.com","password":"invalid"}`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{
|
|
"OnAdminBeforeAuthWithPasswordRequest": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "valid email/password (guest)",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/auth-with-password",
|
|
Body: strings.NewReader(`{"identity":"test@example.com","password":"1234567890"}`),
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"admin":{"id":"sywbhecnh46rhm0"`,
|
|
`"token":`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"OnAdminBeforeAuthWithPasswordRequest": 1,
|
|
"OnAdminAfterAuthWithPasswordRequest": 1,
|
|
"OnAdminAuthRequest": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "valid email/password (already authorized)",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/auth-with-password",
|
|
Body: strings.NewReader(`{"identity":"test@example.com","password":"1234567890"}`),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4MTYwMH0.han3_sG65zLddpcX2ic78qgy7FKecuPfOpFa8Dvi5Bg",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"admin":{"id":"sywbhecnh46rhm0"`,
|
|
`"token":`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"OnAdminBeforeAuthWithPasswordRequest": 1,
|
|
"OnAdminAfterAuthWithPasswordRequest": 1,
|
|
"OnAdminAuthRequest": 1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestAdminRequestPasswordReset(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "empty data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/request-password-reset",
|
|
Body: strings.NewReader(``),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{"email":{"code":"validation_required","message":"Cannot be blank."}}`},
|
|
},
|
|
{
|
|
Name: "invalid data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/request-password-reset",
|
|
Body: strings.NewReader(`{"email`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "missing admin",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/request-password-reset",
|
|
Body: strings.NewReader(`{"email":"missing@example.com"}`),
|
|
Delay: 100 * time.Millisecond,
|
|
ExpectedStatus: 204,
|
|
},
|
|
{
|
|
Name: "existing admin",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/request-password-reset",
|
|
Body: strings.NewReader(`{"email":"test@example.com"}`),
|
|
Delay: 100 * time.Millisecond,
|
|
ExpectedStatus: 204,
|
|
ExpectedEvents: map[string]int{
|
|
"OnModelBeforeUpdate": 1,
|
|
"OnModelAfterUpdate": 1,
|
|
"OnMailerBeforeAdminResetPasswordSend": 1,
|
|
"OnMailerAfterAdminResetPasswordSend": 1,
|
|
"OnAdminBeforeRequestPasswordResetRequest": 1,
|
|
"OnAdminAfterRequestPasswordResetRequest": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "existing admin (after already sent)",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/request-password-reset",
|
|
Body: strings.NewReader(`{"email":"test@example.com"}`),
|
|
Delay: 100 * time.Millisecond,
|
|
ExpectedStatus: 204,
|
|
BeforeTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
|
|
// simulate recent password request
|
|
admin, err := app.Dao().FindAdminByEmail("test@example.com")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
admin.LastResetSentAt = types.NowDateTime()
|
|
dao := daos.New(app.Dao().DB()) // new dao to ignore hooks
|
|
if err := dao.Save(admin); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestAdminConfirmPasswordReset(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "empty data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/confirm-password-reset",
|
|
Body: strings.NewReader(``),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{"password":{"code":"validation_required","message":"Cannot be blank."},"passwordConfirm":{"code":"validation_required","message":"Cannot be blank."},"token":{"code":"validation_required","message":"Cannot be blank."}}`},
|
|
},
|
|
{
|
|
Name: "invalid data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/confirm-password-reset",
|
|
Body: strings.NewReader(`{"password`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "expired token",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/confirm-password-reset",
|
|
Body: strings.NewReader(`{
|
|
"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImVtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImV4cCI6MTY0MDk5MTY2MX0.GLwCOsgWTTEKXTK-AyGW838de1OeZGIjfHH0FoRLqZg",
|
|
"password":"1234567890",
|
|
"passwordConfirm":"1234567890"
|
|
}`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{"token":{"code":"validation_invalid_token","message":"Invalid or expired token."}}}`},
|
|
},
|
|
{
|
|
Name: "valid token + invalid password",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/confirm-password-reset",
|
|
Body: strings.NewReader(`{
|
|
"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImVtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImV4cCI6MjIwODk4MTYwMH0.kwFEler6KSMKJNstuaSDvE1QnNdCta5qSnjaIQ0hhhc",
|
|
"password":"123456",
|
|
"passwordConfirm":"123456"
|
|
}`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{"password":{"code":"validation_length_out_of_range"`},
|
|
},
|
|
{
|
|
Name: "valid token + valid password",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/confirm-password-reset",
|
|
Body: strings.NewReader(`{
|
|
"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImVtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImV4cCI6MjIwODk4MTYwMH0.kwFEler6KSMKJNstuaSDvE1QnNdCta5qSnjaIQ0hhhc",
|
|
"password":"1234567891",
|
|
"passwordConfirm":"1234567891"
|
|
}`),
|
|
ExpectedStatus: 204,
|
|
ExpectedEvents: map[string]int{
|
|
"OnModelBeforeUpdate": 1,
|
|
"OnModelAfterUpdate": 1,
|
|
"OnAdminBeforeConfirmPasswordResetRequest": 1,
|
|
"OnAdminAfterConfirmPasswordResetRequest": 1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestAdminRefresh(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/auth-refresh",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as user",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/auth-refresh",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoUmVjb3JkIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyMjA4OTg1MjYxfQ.UwD8JvkbQtXpymT09d7J6fdA0aP9g4FJ1GPh_ggEkzc",
|
|
},
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin (expired token)",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/auth-refresh",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTY0MDk5MTY2MX0.I7w8iktkleQvC7_UIRpD7rNzcU4OnF7i7SFIUu6lD_4",
|
|
},
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin (valid token)",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins/auth-refresh",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"admin":{"id":"sywbhecnh46rhm0"`,
|
|
`"token":`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"OnAdminAuthRequest": 1,
|
|
"OnAdminBeforeAuthRefreshRequest": 1,
|
|
"OnAdminAfterAuthRefreshRequest": 1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestAdminsList(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized",
|
|
Method: http.MethodGet,
|
|
Url: "/api/admins",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as user",
|
|
Method: http.MethodGet,
|
|
Url: "/api/admins",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoUmVjb3JkIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyMjA4OTg1MjYxfQ.UwD8JvkbQtXpymT09d7J6fdA0aP9g4FJ1GPh_ggEkzc",
|
|
},
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin",
|
|
Method: http.MethodGet,
|
|
Url: "/api/admins",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"page":1`,
|
|
`"perPage":30`,
|
|
`"totalItems":3`,
|
|
`"items":[{`,
|
|
`"id":"sywbhecnh46rhm0"`,
|
|
`"id":"sbmbsdb40jyxf7h"`,
|
|
`"id":"9q2trqumvlyr3bd"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"OnAdminsListRequest": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as admin + paging and sorting",
|
|
Method: http.MethodGet,
|
|
Url: "/api/admins?page=2&perPage=1&sort=-created",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"page":2`,
|
|
`"perPage":1`,
|
|
`"totalItems":3`,
|
|
`"items":[{`,
|
|
`"id":"sbmbsdb40jyxf7h"`,
|
|
},
|
|
NotExpectedContent: []string{
|
|
`"tokenKey"`,
|
|
`"passwordHash"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"OnAdminsListRequest": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as admin + invalid filter",
|
|
Method: http.MethodGet,
|
|
Url: "/api/admins?filter=invalidfield~'test2'",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin + valid filter",
|
|
Method: http.MethodGet,
|
|
Url: "/api/admins?filter=email~'test3'",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"page":1`,
|
|
`"perPage":30`,
|
|
`"totalItems":1`,
|
|
`"items":[{`,
|
|
`"id":"9q2trqumvlyr3bd"`,
|
|
},
|
|
NotExpectedContent: []string{
|
|
`"tokenKey"`,
|
|
`"passwordHash"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"OnAdminsListRequest": 1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestAdminView(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized",
|
|
Method: http.MethodGet,
|
|
Url: "/api/admins/sbmbsdb40jyxf7h",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as user",
|
|
Method: http.MethodGet,
|
|
Url: "/api/admins/sbmbsdb40jyxf7h",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoUmVjb3JkIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyMjA4OTg1MjYxfQ.UwD8JvkbQtXpymT09d7J6fdA0aP9g4FJ1GPh_ggEkzc",
|
|
},
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin + nonexisting admin id",
|
|
Method: http.MethodGet,
|
|
Url: "/api/admins/nonexisting",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 404,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin + existing admin id",
|
|
Method: http.MethodGet,
|
|
Url: "/api/admins/sbmbsdb40jyxf7h",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":"sbmbsdb40jyxf7h"`,
|
|
},
|
|
NotExpectedContent: []string{
|
|
`"tokenKey"`,
|
|
`"passwordHash"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"OnAdminViewRequest": 1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestAdminDelete(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized",
|
|
Method: http.MethodDelete,
|
|
Url: "/api/admins/sbmbsdb40jyxf7h",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as user",
|
|
Method: http.MethodDelete,
|
|
Url: "/api/admins/sbmbsdb40jyxf7h",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoUmVjb3JkIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyMjA4OTg1MjYxfQ.UwD8JvkbQtXpymT09d7J6fdA0aP9g4FJ1GPh_ggEkzc",
|
|
},
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin + missing admin id",
|
|
Method: http.MethodDelete,
|
|
Url: "/api/admins/missing",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 404,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin + existing admin id",
|
|
Method: http.MethodDelete,
|
|
Url: "/api/admins/sbmbsdb40jyxf7h",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 204,
|
|
ExpectedEvents: map[string]int{
|
|
"OnModelBeforeDelete": 1,
|
|
"OnModelAfterDelete": 1,
|
|
"OnAdminBeforeDeleteRequest": 1,
|
|
"OnAdminAfterDeleteRequest": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as admin - try to delete the only remaining admin",
|
|
Method: http.MethodDelete,
|
|
Url: "/api/admins/sywbhecnh46rhm0",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
BeforeTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
|
|
// delete all admins except the authorized one
|
|
adminModel := &models.Admin{}
|
|
_, err := app.Dao().DB().Delete(adminModel.TableName(), dbx.Not(dbx.HashExp{
|
|
"id": "sywbhecnh46rhm0",
|
|
})).Execute()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
ExpectedEvents: map[string]int{
|
|
"OnAdminBeforeDeleteRequest": 1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestAdminCreate(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized (while having at least 1 existing admin)",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "unauthorized (while having 0 existing admins)",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins",
|
|
Body: strings.NewReader(`{"email":"testnew@example.com","password":"1234567890","passwordConfirm":"1234567890","avatar":3}`),
|
|
BeforeTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
|
|
// delete all admins
|
|
_, err := app.Dao().DB().NewQuery("DELETE FROM {{_admins}}").Execute()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":`,
|
|
`"email":"testnew@example.com"`,
|
|
`"avatar":3`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"OnModelBeforeCreate": 1,
|
|
"OnModelAfterCreate": 1,
|
|
"OnAdminBeforeCreateRequest": 1,
|
|
"OnAdminAfterCreateRequest": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as user",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoUmVjb3JkIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyMjA4OTg1MjYxfQ.UwD8JvkbQtXpymT09d7J6fdA0aP9g4FJ1GPh_ggEkzc",
|
|
},
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin + empty data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins",
|
|
Body: strings.NewReader(``),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{"email":{"code":"validation_required","message":"Cannot be blank."},"password":{"code":"validation_required","message":"Cannot be blank."}}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin + invalid data format",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins",
|
|
Body: strings.NewReader(`{`),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin + invalid data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins",
|
|
Body: strings.NewReader(`{
|
|
"email":"test@example.com",
|
|
"password":"1234",
|
|
"passwordConfirm":"4321",
|
|
"avatar":99
|
|
}`),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"avatar":{"code":"validation_max_less_equal_than_required"`,
|
|
`"email":{"code":"validation_admin_email_exists"`,
|
|
`"password":{"code":"validation_length_out_of_range"`,
|
|
`"passwordConfirm":{"code":"validation_values_mismatch"`,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as admin + valid data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/admins",
|
|
Body: strings.NewReader(`{
|
|
"email":"testnew@example.com",
|
|
"password":"1234567890",
|
|
"passwordConfirm":"1234567890",
|
|
"avatar":3
|
|
}`),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":`,
|
|
`"email":"testnew@example.com"`,
|
|
`"avatar":3`,
|
|
},
|
|
NotExpectedContent: []string{
|
|
`"password"`,
|
|
`"passwordConfirm"`,
|
|
`"tokenKey"`,
|
|
`"passwordHash"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"OnModelBeforeCreate": 1,
|
|
"OnModelAfterCreate": 1,
|
|
"OnAdminBeforeCreateRequest": 1,
|
|
"OnAdminAfterCreateRequest": 1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestAdminUpdate(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized",
|
|
Method: http.MethodPatch,
|
|
Url: "/api/admins/sbmbsdb40jyxf7h",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as user",
|
|
Method: http.MethodPatch,
|
|
Url: "/api/admins/sbmbsdb40jyxf7h",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoUmVjb3JkIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyMjA4OTg1MjYxfQ.UwD8JvkbQtXpymT09d7J6fdA0aP9g4FJ1GPh_ggEkzc",
|
|
},
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin + missing admin",
|
|
Method: http.MethodPatch,
|
|
Url: "/api/admins/missing",
|
|
Body: strings.NewReader(``),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 404,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin + empty data",
|
|
Method: http.MethodPatch,
|
|
Url: "/api/admins/sbmbsdb40jyxf7h",
|
|
Body: strings.NewReader(``),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":"sbmbsdb40jyxf7h"`,
|
|
`"email":"test2@example.com"`,
|
|
`"avatar":2`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"OnModelBeforeUpdate": 1,
|
|
"OnModelAfterUpdate": 1,
|
|
"OnAdminBeforeUpdateRequest": 1,
|
|
"OnAdminAfterUpdateRequest": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as admin + invalid formatted data",
|
|
Method: http.MethodPatch,
|
|
Url: "/api/admins/sbmbsdb40jyxf7h",
|
|
Body: strings.NewReader(`{`),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin + invalid data",
|
|
Method: http.MethodPatch,
|
|
Url: "/api/admins/sbmbsdb40jyxf7h",
|
|
Body: strings.NewReader(`{
|
|
"email":"test@example.com",
|
|
"password":"1234",
|
|
"passwordConfirm":"4321",
|
|
"avatar":99
|
|
}`),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"avatar":{"code":"validation_max_less_equal_than_required"`,
|
|
`"email":{"code":"validation_admin_email_exists"`,
|
|
`"password":{"code":"validation_length_out_of_range"`,
|
|
`"passwordConfirm":{"code":"validation_values_mismatch"`,
|
|
},
|
|
},
|
|
{
|
|
Method: http.MethodPatch,
|
|
Url: "/api/admins/sbmbsdb40jyxf7h",
|
|
Body: strings.NewReader(`{
|
|
"email":"testnew@example.com",
|
|
"password":"1234567891",
|
|
"passwordConfirm":"1234567891",
|
|
"avatar":5
|
|
}`),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhZG1pbiIsImV4cCI6MjIwODk4NTI2MX0.M1m--VOqGyv0d23eeUc0r9xE8ZzHaYVmVFw1VZW6gT8",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":"sbmbsdb40jyxf7h"`,
|
|
`"email":"testnew@example.com"`,
|
|
`"avatar":5`,
|
|
},
|
|
NotExpectedContent: []string{
|
|
`"password"`,
|
|
`"passwordConfirm"`,
|
|
`"tokenKey"`,
|
|
`"passwordHash"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"OnModelBeforeUpdate": 1,
|
|
"OnModelAfterUpdate": 1,
|
|
"OnAdminBeforeUpdateRequest": 1,
|
|
"OnAdminAfterUpdateRequest": 1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|