mirror of
https://github.com/pocketbase/pocketbase.git
synced 2024-11-24 17:07:00 +02:00
892 lines
31 KiB
Go
892 lines
31 KiB
Go
package apis_test
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/labstack/echo/v5"
|
|
"github.com/pocketbase/pocketbase/tests"
|
|
)
|
|
|
|
func TestUsersAuthMethods(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Method: http.MethodGet,
|
|
Url: "/api/users/auth-methods",
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"emailPassword":true`,
|
|
`"authProviders":[{`,
|
|
`"authProviders":[{`,
|
|
`"name":"gitlab"`,
|
|
`"state":`,
|
|
`"codeVerifier":`,
|
|
`"codeChallenge":`,
|
|
`"codeChallengeMethod":`,
|
|
`"authUrl":`,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestUserEmailAuth(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "authorized as user",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/auth-via-email",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "User eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjRkMDE5N2NjLTJiNGEtM2Y4My1hMjZiLWQ3N2JjODQyM2QzYyIsInR5cGUiOiJ1c2VyIiwiZXhwIjoxODkzNDc0MDAwfQ.Wq5ac1q1f5WntIzEngXk22ydMj-eFgvfSRg7dhmPKic",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/auth-via-email",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "invalid body format",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/auth-via-email",
|
|
Body: strings.NewReader(`{"email`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "invalid data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/auth-via-email",
|
|
Body: strings.NewReader(`{"email":"","password":""}`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"email":{`,
|
|
`"password":{`,
|
|
},
|
|
},
|
|
{
|
|
Name: "disabled email/pass auth with valid data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/auth-via-email",
|
|
Body: strings.NewReader(`{"email":"test@example.com","password":"123456"}`),
|
|
BeforeFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
|
|
app.Settings().EmailAuth.Enabled = false
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "valid data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/auth-via-email",
|
|
Body: strings.NewReader(`{"email":"test2@example.com","password":"123456"}`),
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"token"`,
|
|
`"user"`,
|
|
`"id":"7bc84d27-6ba2-b42a-383f-4197cc3d3d0c"`,
|
|
`"email":"test2@example.com"`,
|
|
`"verified":false`, // unverified user should be able to authenticate
|
|
},
|
|
ExpectedEvents: map[string]int{"OnUserAuthRequest": 1},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestUserRequestPasswordReset(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "empty data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/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/users/request-password-reset",
|
|
Body: strings.NewReader(`{"email`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "missing user",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/request-password-reset",
|
|
Body: strings.NewReader(`{"email":"missing@example.com"}`),
|
|
ExpectedStatus: 204,
|
|
},
|
|
{
|
|
Name: "existing user",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/request-password-reset",
|
|
Body: strings.NewReader(`{"email":"test@example.com"}`),
|
|
ExpectedStatus: 204,
|
|
// usually this events are fired but since the submit is
|
|
// executed in a separate go routine they are fired async
|
|
// ExpectedEvents: map[string]int{
|
|
// "OnModelBeforeUpdate": 1,
|
|
// "OnModelAfterUpdate": 1,
|
|
// "OnMailerBeforeUserResetPasswordSend": 1,
|
|
// "OnMailerAfterUserResetPasswordSend": 1,
|
|
// },
|
|
},
|
|
{
|
|
Name: "existing user (after already sent)",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/request-password-reset",
|
|
Body: strings.NewReader(`{"email":"test@example.com"}`),
|
|
ExpectedStatus: 204,
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestUserConfirmPasswordReset(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "empty data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/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 format",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/confirm-password-reset",
|
|
Body: strings.NewReader(`{"password`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "expired token",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/confirm-password-reset",
|
|
Body: strings.NewReader(`{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoidXNlciIsImlkIjoiNGQwMTk3Y2MtMmI0YS0zZjgzLWEyNmItZDc3YmM4NDIzZDNjIiwiZW1haWwiOiJ0ZXN0QGV4YW1wbGUuY29tIiwiZXhwIjoxNjQxMDMxMjAwfQ.t2lVe0ny9XruQsSFQdXqBi0I85i6vIUAQjFXZY5HPxc","password":"123456789","passwordConfirm":"123456789"}`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"token":{`,
|
|
`"code":"validation_invalid_token"`,
|
|
},
|
|
},
|
|
{
|
|
Name: "valid token and data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/confirm-password-reset",
|
|
Body: strings.NewReader(`{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoidXNlciIsImlkIjoiNGQwMTk3Y2MtMmI0YS0zZjgzLWEyNmItZDc3YmM4NDIzZDNjIiwiZW1haWwiOiJ0ZXN0QGV4YW1wbGUuY29tIiwiZXhwIjoxODYxOTU2MDAwfQ.V1gEbY4caEIF6IhQAJ8KZD4RvOGvTCFuYg1fTRSvhe0","password":"123456789","passwordConfirm":"123456789"}`),
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"token":`,
|
|
`"user":`,
|
|
`"id":"4d0197cc-2b4a-3f83-a26b-d77bc8423d3c"`,
|
|
`"email":"test@example.com"`,
|
|
},
|
|
ExpectedEvents: map[string]int{"OnUserAuthRequest": 1, "OnModelAfterUpdate": 1, "OnModelBeforeUpdate": 1},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestUserRequestVerification(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
// empty data
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/request-verification",
|
|
Body: strings.NewReader(``),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{"email":{"code":"validation_required","message":"Cannot be blank."}}`},
|
|
},
|
|
// invalid data
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/request-verification",
|
|
Body: strings.NewReader(`{"email`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
// missing user
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/request-verification",
|
|
Body: strings.NewReader(`{"email":"missing@example.com"}`),
|
|
ExpectedStatus: 204,
|
|
},
|
|
// existing already verified user
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/request-verification",
|
|
Body: strings.NewReader(`{"email":"test@example.com"}`),
|
|
ExpectedStatus: 204,
|
|
},
|
|
// existing unverified user
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/request-verification",
|
|
Body: strings.NewReader(`{"email":"test2@example.com"}`),
|
|
ExpectedStatus: 204,
|
|
// usually this events are fired but since the submit is
|
|
// executed in a separate go routine they are fired async
|
|
// ExpectedEvents: map[string]int{
|
|
// "OnModelBeforeUpdate": 1,
|
|
// "OnModelAfterUpdate": 1,
|
|
// "OnMailerBeforeUserVerificationSend": 1,
|
|
// "OnMailerAfterUserVerificationSend": 1,
|
|
// },
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestUserConfirmVerification(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
// empty data
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/confirm-verification",
|
|
Body: strings.NewReader(``),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":`,
|
|
`"token":{"code":"validation_required"`,
|
|
},
|
|
},
|
|
// invalid data
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/confirm-verification",
|
|
Body: strings.NewReader(`{"token`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
// expired token
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/confirm-verification",
|
|
Body: strings.NewReader(`{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoidXNlciIsImlkIjoiN2JjODRkMjctNmJhMi1iNDJhLTM4M2YtNDE5N2NjM2QzZDBjIiwiZW1haWwiOiJ0ZXN0MkBleGFtcGxlLmNvbSIsImV4cCI6MTY0MTAzMTIwMH0.YCqyREksfqn7cWu-innNNTbWQCr9DgYr7dduM2wxrtQ"}`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"token":{`,
|
|
`"code":"validation_invalid_token"`,
|
|
},
|
|
},
|
|
// valid token
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/confirm-verification",
|
|
Body: strings.NewReader(`{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXBlIjoidXNlciIsImlkIjoiN2JjODRkMjctNmJhMi1iNDJhLTM4M2YtNDE5N2NjM2QzZDBjIiwiZW1haWwiOiJ0ZXN0MkBleGFtcGxlLmNvbSIsImV4cCI6MTg2MTk1NjAwMH0.OsxRKuZrNTnwyVjvCwB4jY8TbT-NPZ-UFCpRhCvuv2U"}`),
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"token":`,
|
|
`"user":`,
|
|
`"id":"7bc84d27-6ba2-b42a-383f-4197cc3d3d0c"`,
|
|
`"email":"test2@example.com"`,
|
|
`"verified":true`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"OnUserAuthRequest": 1,
|
|
"OnModelAfterUpdate": 1,
|
|
"OnModelBeforeUpdate": 1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestUserRequestEmailChange(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
// unauthorized
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/request-email-change",
|
|
Body: strings.NewReader(`{"newEmail":"change@example.com"}`),
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
// authorized as admin
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/request-email-change",
|
|
Body: strings.NewReader(`{"newEmail":"change@example.com"}`),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
|
},
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
// invalid data
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/request-email-change",
|
|
Body: strings.NewReader(`{"newEmail`),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "User eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjRkMDE5N2NjLTJiNGEtM2Y4My1hMjZiLWQ3N2JjODQyM2QzYyIsInR5cGUiOiJ1c2VyIiwiZXhwIjoxODkzNDc0MDAwfQ.Wq5ac1q1f5WntIzEngXk22ydMj-eFgvfSRg7dhmPKic",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
// empty data
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/request-email-change",
|
|
Body: strings.NewReader(``),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "User eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjRkMDE5N2NjLTJiNGEtM2Y4My1hMjZiLWQ3N2JjODQyM2QzYyIsInR5cGUiOiJ1c2VyIiwiZXhwIjoxODkzNDc0MDAwfQ.Wq5ac1q1f5WntIzEngXk22ydMj-eFgvfSRg7dhmPKic",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":`,
|
|
`"newEmail":{"code":"validation_required"`,
|
|
},
|
|
},
|
|
// valid data (existing email)
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/request-email-change",
|
|
Body: strings.NewReader(`{"newEmail":"test2@example.com"}`),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "User eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjRkMDE5N2NjLTJiNGEtM2Y4My1hMjZiLWQ3N2JjODQyM2QzYyIsInR5cGUiOiJ1c2VyIiwiZXhwIjoxODkzNDc0MDAwfQ.Wq5ac1q1f5WntIzEngXk22ydMj-eFgvfSRg7dhmPKic",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":`,
|
|
`"newEmail":{"code":"validation_user_email_exists"`,
|
|
},
|
|
},
|
|
// valid data (new email)
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/request-email-change",
|
|
Body: strings.NewReader(`{"newEmail":"change@example.com"}`),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "User eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjRkMDE5N2NjLTJiNGEtM2Y4My1hMjZiLWQ3N2JjODQyM2QzYyIsInR5cGUiOiJ1c2VyIiwiZXhwIjoxODkzNDc0MDAwfQ.Wq5ac1q1f5WntIzEngXk22ydMj-eFgvfSRg7dhmPKic",
|
|
},
|
|
ExpectedStatus: 204,
|
|
ExpectedEvents: map[string]int{
|
|
"OnMailerBeforeUserChangeEmailSend": 1,
|
|
"OnMailerAfterUserChangeEmailSend": 1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestUserConfirmEmailChange(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
// empty data
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/confirm-email-change",
|
|
Body: strings.NewReader(``),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":`,
|
|
`"token":{"code":"validation_required"`,
|
|
`"password":{"code":"validation_required"`,
|
|
},
|
|
},
|
|
// invalid data
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/confirm-email-change",
|
|
Body: strings.NewReader(`{"token`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
// expired token and correct password
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/confirm-email-change",
|
|
Body: strings.NewReader(`{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjdiYzg0ZDI3LTZiYTItYjQyYS0zODNmLTQxOTdjYzNkM2QwYyIsInR5cGUiOiJ1c2VyIiwiZW1haWwiOiJ0ZXN0MkBleGFtcGxlLmNvbSIsIm5ld0VtYWlsIjoiY2hhbmdlQGV4YW1wbGUuY29tIiwiZXhwIjoxNjQwOTkxNjAwfQ.DOqNtSDcXbWix8OsK13X-tjfWi6jZNlAzIZiwG_YDOs","password":"123456"}`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"token":{`,
|
|
`"code":"validation_invalid_token"`,
|
|
},
|
|
},
|
|
// valid token and incorrect password
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/confirm-email-change",
|
|
Body: strings.NewReader(`{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjdiYzg0ZDI3LTZiYTItYjQyYS0zODNmLTQxOTdjYzNkM2QwYyIsInR5cGUiOiJ1c2VyIiwiZW1haWwiOiJ0ZXN0MkBleGFtcGxlLmNvbSIsIm5ld0VtYWlsIjoiY2hhbmdlQGV4YW1wbGUuY29tIiwiZXhwIjoxODkzNDUyNDAwfQ.aWMQJ_c49yFbzHO5TNhlkbKRokQ_isc2RbLGuSJx44c","password":"654321"}`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"password":{`,
|
|
`"code":"validation_invalid_password"`,
|
|
},
|
|
},
|
|
// valid token and correct password
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/confirm-email-change",
|
|
Body: strings.NewReader(`{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjdiYzg0ZDI3LTZiYTItYjQyYS0zODNmLTQxOTdjYzNkM2QwYyIsInR5cGUiOiJ1c2VyIiwiZW1haWwiOiJ0ZXN0MkBleGFtcGxlLmNvbSIsIm5ld0VtYWlsIjoiY2hhbmdlQGV4YW1wbGUuY29tIiwiZXhwIjoxODkzNDUyNDAwfQ.aWMQJ_c49yFbzHO5TNhlkbKRokQ_isc2RbLGuSJx44c","password":"123456"}`),
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"token":`,
|
|
`"user":`,
|
|
`"id":"7bc84d27-6ba2-b42a-383f-4197cc3d3d0c"`,
|
|
`"email":"change@example.com"`,
|
|
`"verified":true`,
|
|
},
|
|
ExpectedEvents: map[string]int{"OnUserAuthRequest": 1, "OnModelAfterUpdate": 1, "OnModelBeforeUpdate": 1},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestUserRefresh(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
// unauthorized
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/refresh",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
// authorized as admin
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/refresh",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
|
},
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
// authorized as user
|
|
{
|
|
Method: http.MethodPost,
|
|
Url: "/api/users/refresh",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "User eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjRkMDE5N2NjLTJiNGEtM2Y4My1hMjZiLWQ3N2JjODQyM2QzYyIsInR5cGUiOiJ1c2VyIiwiZXhwIjoxODkzNDc0MDAwfQ.Wq5ac1q1f5WntIzEngXk22ydMj-eFgvfSRg7dhmPKic",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"token":`,
|
|
`"user":`,
|
|
`"id":"4d0197cc-2b4a-3f83-a26b-d77bc8423d3c"`,
|
|
},
|
|
ExpectedEvents: map[string]int{"OnUserAuthRequest": 1},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestUsersList(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
// unauthorized
|
|
{
|
|
Method: http.MethodGet,
|
|
Url: "/api/users",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
// authorized as user
|
|
{
|
|
Method: http.MethodGet,
|
|
Url: "/api/users",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "User eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjRkMDE5N2NjLTJiNGEtM2Y4My1hMjZiLWQ3N2JjODQyM2QzYyIsInR5cGUiOiJ1c2VyIiwiZXhwIjoxODkzNDc0MDAwfQ.Wq5ac1q1f5WntIzEngXk22ydMj-eFgvfSRg7dhmPKic",
|
|
},
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
// authorized as admin
|
|
{
|
|
Method: http.MethodGet,
|
|
Url: "/api/users",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"page":1`,
|
|
`"perPage":30`,
|
|
`"totalItems":3`,
|
|
`"items":[{`,
|
|
`"id":"4d0197cc-2b4a-3f83-a26b-d77bc8423d3c"`,
|
|
`"id":"7bc84d27-6ba2-b42a-383f-4197cc3d3d0c"`,
|
|
`"id":"97cc3d3d-6ba2-383f-b42a-7bc84d27410c"`,
|
|
},
|
|
ExpectedEvents: map[string]int{"OnUsersListRequest": 1},
|
|
},
|
|
// authorized as admin + paging and sorting
|
|
{
|
|
Method: http.MethodGet,
|
|
Url: "/api/users?page=2&perPage=2&sort=-created",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"page":2`,
|
|
`"perPage":2`,
|
|
`"totalItems":3`,
|
|
`"items":[{`,
|
|
`"id":"4d0197cc-2b4a-3f83-a26b-d77bc8423d3c"`,
|
|
},
|
|
ExpectedEvents: map[string]int{"OnUsersListRequest": 1},
|
|
},
|
|
// authorized as admin + invalid filter
|
|
{
|
|
Method: http.MethodGet,
|
|
Url: "/api/users?filter=invalidfield~'test2'",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
// authorized as admin + valid filter
|
|
{
|
|
Method: http.MethodGet,
|
|
Url: "/api/users?filter=verified=true",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"page":1`,
|
|
`"perPage":30`,
|
|
`"totalItems":2`,
|
|
`"items":[{`,
|
|
`"id":"4d0197cc-2b4a-3f83-a26b-d77bc8423d3c"`,
|
|
`"id":"97cc3d3d-6ba2-383f-b42a-7bc84d27410c"`,
|
|
},
|
|
ExpectedEvents: map[string]int{"OnUsersListRequest": 1},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestUserView(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized",
|
|
Method: http.MethodGet,
|
|
Url: "/api/users/4d0197cc-2b4a-3f83-a26b-d77bc8423d3c",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin + nonexisting user id",
|
|
Method: http.MethodGet,
|
|
Url: "/api/users/00000000-0000-0000-0000-d77bc8423d3c",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
|
},
|
|
ExpectedStatus: 404,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin + existing user id",
|
|
Method: http.MethodGet,
|
|
Url: "/api/users/4d0197cc-2b4a-3f83-a26b-d77bc8423d3c",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":"4d0197cc-2b4a-3f83-a26b-d77bc8423d3c"`,
|
|
},
|
|
ExpectedEvents: map[string]int{"OnUserViewRequest": 1},
|
|
},
|
|
{
|
|
Name: "authorized as user - trying to view another user",
|
|
Method: http.MethodGet,
|
|
Url: "/api/users/7bc84d27-6ba2-b42a-383f-4197cc3d3d0c",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "User eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjRkMDE5N2NjLTJiNGEtM2Y4My1hMjZiLWQ3N2JjODQyM2QzYyIsInR5cGUiOiJ1c2VyIiwiZXhwIjoxODkzNDc0MDAwfQ.Wq5ac1q1f5WntIzEngXk22ydMj-eFgvfSRg7dhmPKic",
|
|
},
|
|
ExpectedStatus: 403,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as user - owner",
|
|
Method: http.MethodGet,
|
|
Url: "/api/users/4d0197cc-2b4a-3f83-a26b-d77bc8423d3c",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "User eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjRkMDE5N2NjLTJiNGEtM2Y4My1hMjZiLWQ3N2JjODQyM2QzYyIsInR5cGUiOiJ1c2VyIiwiZXhwIjoxODkzNDc0MDAwfQ.Wq5ac1q1f5WntIzEngXk22ydMj-eFgvfSRg7dhmPKic",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":"4d0197cc-2b4a-3f83-a26b-d77bc8423d3c"`,
|
|
},
|
|
ExpectedEvents: map[string]int{"OnUserViewRequest": 1},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestUserDelete(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized",
|
|
Method: http.MethodDelete,
|
|
Url: "/api/users/4d0197cc-2b4a-3f83-a26b-d77bc8423d3c",
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin + nonexisting user id",
|
|
Method: http.MethodDelete,
|
|
Url: "/api/users/00000000-0000-0000-0000-d77bc8423d3c",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
|
},
|
|
ExpectedStatus: 404,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin + existing user id",
|
|
Method: http.MethodDelete,
|
|
Url: "/api/users/4d0197cc-2b4a-3f83-a26b-d77bc8423d3c",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
|
},
|
|
ExpectedStatus: 204,
|
|
ExpectedEvents: map[string]int{
|
|
"OnUserBeforeDeleteRequest": 1,
|
|
"OnUserAfterDeleteRequest": 1,
|
|
"OnModelBeforeDelete": 2, // cascade delete to related Record model
|
|
"OnModelAfterDelete": 2, // cascade delete to related Record model
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as user - trying to delete another user",
|
|
Method: http.MethodDelete,
|
|
Url: "/api/users/7bc84d27-6ba2-b42a-383f-4197cc3d3d0c",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "User eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjRkMDE5N2NjLTJiNGEtM2Y4My1hMjZiLWQ3N2JjODQyM2QzYyIsInR5cGUiOiJ1c2VyIiwiZXhwIjoxODkzNDc0MDAwfQ.Wq5ac1q1f5WntIzEngXk22ydMj-eFgvfSRg7dhmPKic",
|
|
},
|
|
ExpectedStatus: 403,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as user - owner",
|
|
Method: http.MethodDelete,
|
|
Url: "/api/users/4d0197cc-2b4a-3f83-a26b-d77bc8423d3c",
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "User eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjRkMDE5N2NjLTJiNGEtM2Y4My1hMjZiLWQ3N2JjODQyM2QzYyIsInR5cGUiOiJ1c2VyIiwiZXhwIjoxODkzNDc0MDAwfQ.Wq5ac1q1f5WntIzEngXk22ydMj-eFgvfSRg7dhmPKic",
|
|
},
|
|
ExpectedStatus: 204,
|
|
ExpectedEvents: map[string]int{
|
|
"OnUserBeforeDeleteRequest": 1,
|
|
"OnUserAfterDeleteRequest": 1,
|
|
"OnModelBeforeDelete": 2, // cascade delete to related Record model
|
|
"OnModelAfterDelete": 2, // cascade delete to related Record model
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestUserCreate(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "empty data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users",
|
|
Body: strings.NewReader(``),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"email":{"code":"validation_required"`,
|
|
`"password":{"code":"validation_required"`,
|
|
},
|
|
},
|
|
{
|
|
Name: "invalid data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users",
|
|
Body: strings.NewReader(`{"email":"test@example.com","password":"1234","passwordConfirm":"4321"}`),
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"email":{"code":"validation_user_email_exists"`,
|
|
`"password":{"code":"validation_length_out_of_range"`,
|
|
`"passwordConfirm":{"code":"validation_values_mismatch"`,
|
|
},
|
|
},
|
|
{
|
|
Name: "valid data but with disabled email/pass auth",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users",
|
|
Body: strings.NewReader(`{"email":"newuser@example.com","password":"123456789","passwordConfirm":"123456789"}`),
|
|
BeforeFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
|
|
app.Settings().EmailAuth.Enabled = false
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "valid data",
|
|
Method: http.MethodPost,
|
|
Url: "/api/users",
|
|
Body: strings.NewReader(`{"email":"newuser@example.com","password":"123456789","passwordConfirm":"123456789"}`),
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":`,
|
|
`"email":"newuser@example.com"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"OnUserBeforeCreateRequest": 1,
|
|
"OnUserAfterCreateRequest": 1,
|
|
"OnModelBeforeCreate": 2, // +1 for the created profile record
|
|
"OnModelAfterCreate": 2, // +1 for the created profile record
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|
|
|
|
func TestUserUpdate(t *testing.T) {
|
|
scenarios := []tests.ApiScenario{
|
|
{
|
|
Name: "unauthorized",
|
|
Method: http.MethodPatch,
|
|
Url: "/api/users/4d0197cc-2b4a-3f83-a26b-d77bc8423d3c",
|
|
Body: strings.NewReader(`{"email":"new@example.com"}`),
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as user (owner)",
|
|
Method: http.MethodPatch,
|
|
Url: "/api/users/4d0197cc-2b4a-3f83-a26b-d77bc8423d3c",
|
|
Body: strings.NewReader(`{"email":"new@example.com"}`),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "User eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjRkMDE5N2NjLTJiNGEtM2Y4My1hMjZiLWQ3N2JjODQyM2QzYyIsInR5cGUiOiJ1c2VyIiwiZXhwIjoxODkzNDc0MDAwfQ.Wq5ac1q1f5WntIzEngXk22ydMj-eFgvfSRg7dhmPKic",
|
|
},
|
|
ExpectedStatus: 401,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin - invalid/missing user id",
|
|
Method: http.MethodPatch,
|
|
Url: "/api/users/invalid",
|
|
Body: strings.NewReader(``),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
|
},
|
|
ExpectedStatus: 404,
|
|
ExpectedContent: []string{`"data":{}`},
|
|
},
|
|
{
|
|
Name: "authorized as admin - empty data",
|
|
Method: http.MethodPatch,
|
|
Url: "/api/users/4d0197cc-2b4a-3f83-a26b-d77bc8423d3c",
|
|
Body: strings.NewReader(``),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":"4d0197cc-2b4a-3f83-a26b-d77bc8423d3c"`,
|
|
`"email":"test@example.com"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"OnUserBeforeUpdateRequest": 1,
|
|
"OnUserAfterUpdateRequest": 1,
|
|
"OnModelBeforeUpdate": 1,
|
|
"OnModelAfterUpdate": 1,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as admin - invalid data",
|
|
Method: http.MethodPatch,
|
|
Url: "/api/users/4d0197cc-2b4a-3f83-a26b-d77bc8423d3c",
|
|
Body: strings.NewReader(`{"email":"test2@example.com"}`),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
|
},
|
|
ExpectedStatus: 400,
|
|
ExpectedContent: []string{
|
|
`"data":{`,
|
|
`"email":{"code":"validation_user_email_exists"`,
|
|
},
|
|
},
|
|
{
|
|
Name: "authorized as admin - valid data",
|
|
Method: http.MethodPatch,
|
|
Url: "/api/users/4d0197cc-2b4a-3f83-a26b-d77bc8423d3c",
|
|
Body: strings.NewReader(`{"email":"new@example.com"}`),
|
|
RequestHeaders: map[string]string{
|
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
|
},
|
|
ExpectedStatus: 200,
|
|
ExpectedContent: []string{
|
|
`"id":"4d0197cc-2b4a-3f83-a26b-d77bc8423d3c"`,
|
|
`"email":"new@example.com"`,
|
|
},
|
|
ExpectedEvents: map[string]int{
|
|
"OnUserBeforeUpdateRequest": 1,
|
|
"OnUserAfterUpdateRequest": 1,
|
|
"OnModelBeforeUpdate": 1,
|
|
"OnModelAfterUpdate": 1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
scenario.Test(t)
|
|
}
|
|
}
|