Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(GraphQL): Mutations with Auth on interfaces should work correctly. #6839

Merged
merged 10 commits into from
Nov 5, 2020
244 changes: 244 additions & 0 deletions graphql/e2e/auth/add_mutation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,250 @@ func (m *Movie) delete(t *testing.T, user, role string) {
require.Nil(t, gqlResponse.Errors)
}

func (a *Author) delete(t *testing.T) {
getParams := &common.GraphQLParams{
Query: `
mutation deleteAuthor($ids: [ID!]) {
deleteAuthor(filter:{id:$ids}) {
msg
}
}
`,
Variables: map[string]interface{}{"ids": []string{a.Id}},
}
gqlResponse := getParams.ExecuteAsPost(t, graphqlURL)
require.Nil(t, gqlResponse.Errors)
}

func (q *Question) delete(t *testing.T, user string) {
getParams := &common.GraphQLParams{
Headers: common.GetJWTForInterfaceAuth(t, user, "", q.Answered, metaInfo),
Query: `
mutation deleteQuestion($ids: [ID!]) {
deleteQuestion(filter:{id:$ids}) {
msg
}
}
`,
Variables: map[string]interface{}{"ids": []string{q.Id}},
}
gqlResponse := getParams.ExecuteAsPost(t, graphqlURL)
require.Nil(t, gqlResponse.Errors)
}

func (f *FbPost) delete(t *testing.T, user, role string) {
getParams := &common.GraphQLParams{
Headers: common.GetJWT(t, user, role, metaInfo),
Query: `
mutation deleteFbPost($ids: [ID!]) {
deleteFbPost(filter:{id:$ids}) {
msg
}
}
`,
Variables: map[string]interface{}{"ids": []string{f.Id}},
}
gqlResponse := getParams.ExecuteAsPost(t, graphqlURL)
require.Nil(t, gqlResponse.Errors)
}

func TestAuth_AddOnTypeWithRBACRuleOnInterface(t *testing.T) {
testCases := []TestCase{{
user: "[email protected]",
role: "ADMIN",
variables: map[string]interface{}{"fbpost": &FbPost{
Text: "New FbPost",
Author: &Author{
Name: "[email protected]",
},
Sender: &Author{
Name: "[email protected]",
},
Receiver: &Author{
Name: "[email protected]",
},
PostCount: 5,
}},
expectedError: false,
result: `{"addFbPost":{"fbPost":[{"id":"0x15f","text":"New FbPost","author":{"id":"0x15e","name":"[email protected]"},"sender":{"id":"0x15d","name":"[email protected]"},"receiver":{"id":"0x160","name":"[email protected]"}}]}}`,
}, {
user: "[email protected]",
role: "USER",
variables: map[string]interface{}{"fbpost": &FbPost{
Text: "New FbPost",
Author: &Author{
Name: "[email protected]",
},
Sender: &Author{
Name: "[email protected]",
},
Receiver: &Author{
Name: "[email protected]",
},
PostCount: 5,
}},
expectedError: true,
},
}

query := `
mutation addFbPost($fbpost: AddFbPostInput!) {
addFbPost(input: [$fbpost]) {
fbPost {
id
text
author {
id
name
}
sender {
id
name
}
receiver {
id
name
}
}
}
}
`

var expected, result struct {
AddFbPost struct {
FbPost []*FbPost
}
}

for _, tcase := range testCases {
params := &common.GraphQLParams{
Headers: common.GetJWT(t, tcase.user, tcase.role, metaInfo),
Query: query,
Variables: tcase.variables,
}

gqlResponse := params.ExecuteAsPost(t, graphqlURL)
if tcase.expectedError {
require.Equal(t, len(gqlResponse.Errors), 1)
require.Contains(t, gqlResponse.Errors[0].Message, "authorization failed")
continue
}

require.Nil(t, gqlResponse.Errors)

err := json.Unmarshal([]byte(tcase.result), &expected)
require.NoError(t, err)

err = json.Unmarshal(gqlResponse.Data, &result)
require.NoError(t, err)

opt := cmpopts.IgnoreFields(FbPost{}, "Id")
opt1 := cmpopts.IgnoreFields(Author{}, "Id")
if diff := cmp.Diff(expected, result, opt, opt1); diff != "" {
t.Errorf("result mismatch (-want +got):\n%s", diff)
}

for _, i := range result.AddFbPost.FbPost {
i.Author.delete(t)
i.Sender.delete(t)
i.Receiver.delete(t)
i.delete(t, tcase.user, tcase.role)
}
}
}

func TestAuth_AddOnTypeWithGraphTraversalRuleOnInterface(t *testing.T) {
testCases := []TestCase{{
user: "[email protected]",
ans: true,
variables: map[string]interface{}{"question": &Question{
Text: "A Question",
Author: &Author{
Name: "[email protected]",
},
Answered: true,
}},
result: `{"addQuestion": {"question": [{"id": "0x123", "text": "A Question", "author": {"id": "0x124", "name": "[email protected]"}}]}}`,
}, {
user: "user1",
ans: false,
variables: map[string]interface{}{"question": &Question{
Text: "A Question",
Author: &Author{
Name: "user1",
},
Answered: true,
}},
expectedError: true,
},
{
user: "user2",
ans: true,
variables: map[string]interface{}{"question": &Question{
Text: "A Question",
Author: &Author{
Name: "user1",
},
Answered: true,
}},
expectedError: true,
},
}

query := `
mutation addQuestion($question: AddQuestionInput!) {
addQuestion(input: [$question]) {
question {
id
text
author {
id
name
}
}
}
}
`
var expected, result struct {
AddQuestion struct {
Question []*Question
}
}

for _, tcase := range testCases {
params := &common.GraphQLParams{
Headers: common.GetJWTForInterfaceAuth(t, tcase.user, tcase.role, tcase.ans, metaInfo),
Query: query,
Variables: tcase.variables,
}

gqlResponse := params.ExecuteAsPost(t, graphqlURL)
if tcase.expectedError {
require.Equal(t, len(gqlResponse.Errors), 1)
require.Contains(t, gqlResponse.Errors[0].Message, "authorization failed")
continue
}

require.Nil(t, gqlResponse.Errors)

err := json.Unmarshal([]byte(tcase.result), &expected)
require.NoError(t, err)

err = json.Unmarshal(gqlResponse.Data, &result)
require.NoError(t, err)
opt := cmpopts.IgnoreFields(Question{}, "Id")
opt1 := cmpopts.IgnoreFields(Author{}, "Id")
if diff := cmp.Diff(expected, result, opt, opt1); diff != "" {
t.Errorf("result mismatch (-want +got):\n%s", diff)
}

for _, i := range result.AddQuestion.Question {
i.Author.delete(t)
i.delete(t, tcase.user)
}
}
}

func TestAddDeepFilter(t *testing.T) {
// Column can only be added if the user has ADMIN role attached to the corresponding project.
testCases := []TestCase{{
Expand Down
39 changes: 31 additions & 8 deletions graphql/e2e/auth/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,34 @@ type Author struct {
Posts []*Question `json:"posts,omitempty"`
}

type Post struct {
Id string `json:"id,omitempty"`
Text string `json:"text,omitempty"`
Author *Author `json:"author,omitempty"`
}

type Question struct {
Id string `json:"id,omitempty"`
Text string `json:"text,omitempty"`
Answered bool `json:"answered,omitempty"`
Author *Author `json:"author,omitempty"`
}

type Answer struct {
Id string `json:"id,omitempty"`
Text string `json:"text,omitempty"`
Author *Author `json:"author,omitempty"`
}

type FbPost struct {
Id string `json:"id,omitempty"`
Text string `json:"text,omitempty"`
Author *Author `json:"author,omitempty"`
Sender *Author `json:"sender,omitempty"`
Receiver *Author `json:"receiver,omitempty"`
PostCount int `json:"postCount,omitempty"`
}

type Log struct {
Id string `json:"id,omitempty"`
Logs string `json:"logs,omitempty"`
Expand Down Expand Up @@ -128,14 +150,15 @@ type TaskOccurrence struct {
}

type TestCase struct {
user string
role string
ans bool
result string
name string
filter map[string]interface{}
variables map[string]interface{}
query string
user string
role string
ans bool
result string
name string
filter map[string]interface{}
variables map[string]interface{}
query string
expectedError bool
}

type uidResult struct {
Expand Down
Loading