Skip to content

Commit ba63d03

Browse files
authored
Fix(GraphQL): Add support for using auth with secret directive (#6907) (#6920)
* Fix(GraphQL): Add support for using auth with secret directive (#6907) * Add password field in auth directive * Add query resolving tests * Add e2e tests * Address feedback (cherry picked from commit 3311923) * Fix failing auth tests (#6923) (cherry picked from commit 74fb2c7)
1 parent 5f865cc commit ba63d03

File tree

61 files changed

+751
-196
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+751
-196
lines changed

graphql/e2e/auth/add_mutation_test.go

+19
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ func TestAuth_AddOnTypeWithRBACRuleOnInterface(t *testing.T) {
159159
role: "ADMIN",
160160
variables: map[string]interface{}{"fbpost": &FbPost{
161161
Text: "New FbPost",
162+
Pwd: "password",
162163
Author: &Author{
163164
164165
},
@@ -177,6 +178,7 @@ func TestAuth_AddOnTypeWithRBACRuleOnInterface(t *testing.T) {
177178
role: "USER",
178179
variables: map[string]interface{}{"fbpost": &FbPost{
179180
Text: "New FbPost",
181+
Pwd: "password",
180182
Author: &Author{
181183
182184
},
@@ -264,6 +266,7 @@ func TestAuth_AddOnTypeWithGraphTraversalRuleOnInterface(t *testing.T) {
264266
ans: true,
265267
variables: map[string]interface{}{"question": &Question{
266268
Text: "A Question",
269+
Pwd: "password",
267270
Author: &Author{
268271
269272
},
@@ -275,6 +278,7 @@ func TestAuth_AddOnTypeWithGraphTraversalRuleOnInterface(t *testing.T) {
275278
ans: false,
276279
variables: map[string]interface{}{"question": &Question{
277280
Text: "A Question",
281+
Pwd: "password",
278282
Author: &Author{
279283
Name: "user1",
280284
},
@@ -287,6 +291,7 @@ func TestAuth_AddOnTypeWithGraphTraversalRuleOnInterface(t *testing.T) {
287291
ans: true,
288292
variables: map[string]interface{}{"question": &Question{
289293
Text: "A Question",
294+
Pwd: "password",
290295
Author: &Author{
291296
Name: "user1",
292297
},
@@ -361,6 +366,7 @@ func TestAddDeepFilter(t *testing.T) {
361366
Name: "column_add_1",
362367
InProject: &Project{
363368
Name: "project_add_1",
369+
Pwd: "password1",
364370
},
365371
}},
366372
}, {
@@ -372,10 +378,12 @@ func TestAddDeepFilter(t *testing.T) {
372378
Name: "column_add_2",
373379
InProject: &Project{
374380
Name: "project_add_2",
381+
Pwd: "password2",
375382
Roles: []*Role{{
376383
Permission: "ADMIN",
377384
AssignedTo: []*common.User{{
378385
Username: "user2",
386+
Password: "password",
379387
}},
380388
}},
381389
},
@@ -388,15 +396,18 @@ func TestAddDeepFilter(t *testing.T) {
388396
Name: "column_add_3",
389397
InProject: &Project{
390398
Name: "project_add_4",
399+
Pwd: "password4",
391400
Roles: []*Role{{
392401
Permission: "ADMIN",
393402
AssignedTo: []*common.User{{
394403
Username: "user6",
404+
Password: "password",
395405
}},
396406
}, {
397407
Permission: "VIEW",
398408
AssignedTo: []*common.User{{
399409
Username: "user6",
410+
Password: "password",
400411
}},
401412
}},
402413
},
@@ -468,6 +479,7 @@ func TestAddOrRBACFilter(t *testing.T) {
468479
result: `{"addProject": {"project":[{"name":"project_add_1"}]}}`,
469480
variables: map[string]interface{}{"project": &Project{
470481
Name: "project_add_1",
482+
Pwd: "password1",
471483
}},
472484
}, {
473485
// Test case fails as the role isn't assigned to the correct user
@@ -476,10 +488,12 @@ func TestAddOrRBACFilter(t *testing.T) {
476488
result: ``,
477489
variables: map[string]interface{}{"project": &Project{
478490
Name: "project_add_2",
491+
Pwd: "password2",
479492
Roles: []*Role{{
480493
Permission: "ADMIN",
481494
AssignedTo: []*common.User{{
482495
Username: "user2",
496+
Password: "password",
483497
}},
484498
}},
485499
}},
@@ -489,15 +503,18 @@ func TestAddOrRBACFilter(t *testing.T) {
489503
result: `{"addProject": {"project":[{"name":"project_add_3"}]}}`,
490504
variables: map[string]interface{}{"project": &Project{
491505
Name: "project_add_3",
506+
Pwd: "password3",
492507
Roles: []*Role{{
493508
Permission: "ADMIN",
494509
AssignedTo: []*common.User{{
495510
Username: "user7",
511+
Password: "password",
496512
}},
497513
}, {
498514
Permission: "VIEW",
499515
AssignedTo: []*common.User{{
500516
Username: "user7",
517+
Password: "password",
501518
}},
502519
}},
503520
}},
@@ -817,13 +834,15 @@ func TestAddRBACFilter(t *testing.T) {
817834
result: `{"addLog": {"log":[{"logs":"log_add_1"}]}}`,
818835
variables: map[string]interface{}{"issue": &Log{
819836
Logs: "log_add_1",
837+
Pwd: "password1",
820838
}},
821839
}, {
822840
user: "user1",
823841
role: "USER",
824842
result: ``,
825843
variables: map[string]interface{}{"issue": &Log{
826844
Logs: "log_add_2",
845+
Pwd: "password2",
827846
}},
828847
}}
829848

graphql/e2e/auth/auth_test.go

+155
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import (
2424
"strings"
2525
"testing"
2626

27+
"github.com/google/go-cmp/cmp/cmpopts"
28+
2729
"github.com/dgraph-io/dgraph/graphql/e2e/common"
2830
"github.com/dgraph-io/dgraph/testutil"
2931
"github.com/dgrijalva/jwt-go/v4"
@@ -76,6 +78,7 @@ type Question struct {
7678
Text string `json:"text,omitempty"`
7779
Answered bool `json:"answered,omitempty"`
7880
Author *Author `json:"author,omitempty"`
81+
Pwd string `json:"pwd,omitempty"`
7982
}
8083

8184
type Answer struct {
@@ -91,12 +94,14 @@ type FbPost struct {
9194
Sender *Author `json:"sender,omitempty"`
9295
Receiver *Author `json:"receiver,omitempty"`
9396
PostCount int `json:"postCount,omitempty"`
97+
Pwd string `json:"pwd,omitempty"`
9498
}
9599

96100
type Log struct {
97101
Id string `json:"id,omitempty"`
98102
Logs string `json:"logs,omitempty"`
99103
Random string `json:"random,omitempty"`
104+
Pwd string `json:"pwd,omitempty"`
100105
}
101106

102107
type ComplexLog struct {
@@ -130,6 +135,7 @@ type Project struct {
130135
Name string `json:"name,omitempty"`
131136
Roles []*Role `json:"roles,omitempty"`
132137
Columns []*Column `json:"columns,omitempty"`
138+
Pwd string `json:"pwd,omitempty"`
133139
}
134140

135141
type Student struct {
@@ -1615,3 +1621,152 @@ func TestChildCountQueryWithOtherFields(t *testing.T) {
16151621
})
16161622
}
16171623
}
1624+
1625+
func checkLogPassword(t *testing.T, logID, pwd, role string) *common.GraphQLResponse {
1626+
// Check Log Password for given logID, pwd, role
1627+
checkLogParamsFalse := &common.GraphQLParams{
1628+
Headers: common.GetJWT(t, "SomeUser", role, metaInfo),
1629+
Query: `query checkLogPassword($name: ID!, $pwd: String!) {
1630+
checkLogPassword(id: $name, pwd: $pwd) { id }
1631+
}`,
1632+
Variables: map[string]interface{}{
1633+
"name": logID,
1634+
"pwd": pwd,
1635+
},
1636+
}
1637+
1638+
gqlResponse := checkLogParamsFalse.ExecuteAsPost(t, graphqlURL)
1639+
common.RequireNoGQLErrors(t, gqlResponse)
1640+
return gqlResponse
1641+
}
1642+
1643+
func deleteLog(t *testing.T, logID string) {
1644+
deleteLogParams := &common.GraphQLParams{
1645+
Query: `
1646+
mutation DelLog($logID: ID!) {
1647+
deleteLog(filter:{id:[$logID]}) {
1648+
numUids
1649+
}
1650+
}
1651+
`,
1652+
Variables: map[string]interface{}{"logID": logID},
1653+
Headers: common.GetJWT(t, "SomeUser", "ADMIN", metaInfo),
1654+
}
1655+
gqlResponse := deleteLogParams.ExecuteAsPost(t, graphqlURL)
1656+
require.Nil(t, gqlResponse.Errors)
1657+
}
1658+
1659+
func deleteUser(t *testing.T, username string) {
1660+
deleteUserParams := &common.GraphQLParams{
1661+
Headers: common.GetJWT(t, username, "ADMIN", metaInfo),
1662+
Query: `
1663+
mutation DelUser($username: String!) {
1664+
deleteUser(filter:{username: {eq: $username } } ) {
1665+
numUids
1666+
}
1667+
}
1668+
`,
1669+
Variables: map[string]interface{}{"username": username},
1670+
}
1671+
gqlResponse := deleteUserParams.ExecuteAsPost(t, graphqlURL)
1672+
require.Nil(t, gqlResponse.Errors)
1673+
}
1674+
1675+
func TestAuthWithSecretDirective(t *testing.T) {
1676+
1677+
// Check that no auth rule is applied to checkUserPassword query.
1678+
newUser := &common.User{
1679+
Username: "Test User",
1680+
Password: "password",
1681+
IsPublic: true,
1682+
}
1683+
1684+
addUserParams := &common.GraphQLParams{
1685+
Query: `mutation addUser($user: [AddUserInput!]!) {
1686+
addUser(input: $user) {
1687+
user {
1688+
username
1689+
}
1690+
}
1691+
}`,
1692+
Variables: map[string]interface{}{"user": []*common.User{newUser}},
1693+
}
1694+
1695+
gqlResponse := addUserParams.ExecuteAsPost(t, graphqlURL)
1696+
require.Equal(t, `{"addUser":{"user":[{"username":"Test User"}]}}`,
1697+
string(gqlResponse.Data))
1698+
1699+
checkUserParams := &common.GraphQLParams{
1700+
Query: `query checkUserPassword($name: String!, $pwd: String!) {
1701+
checkUserPassword(username: $name, password: $pwd) {
1702+
username
1703+
isPublic
1704+
}
1705+
}`,
1706+
Variables: map[string]interface{}{
1707+
"name": newUser.Username,
1708+
"pwd": newUser.Password,
1709+
},
1710+
}
1711+
1712+
gqlResponse = checkUserParams.ExecuteAsPost(t, graphqlURL)
1713+
common.RequireNoGQLErrors(t, gqlResponse)
1714+
1715+
var result struct {
1716+
CheckUserPassword *common.User `json:"checkUserPassword,omitempty"`
1717+
}
1718+
1719+
err := json.Unmarshal([]byte(gqlResponse.Data), &result)
1720+
require.Nil(t, err)
1721+
1722+
opt := cmpopts.IgnoreFields(common.User{}, "Password")
1723+
if diff := cmp.Diff(newUser, result.CheckUserPassword, opt); diff != "" {
1724+
t.Errorf("result mismatch (-want +got):\n%s", diff)
1725+
}
1726+
deleteUser(t, newUser.Username)
1727+
1728+
// Check that checkLogPassword works with RBAC rule
1729+
newLog := &Log{
1730+
Pwd: "password",
1731+
}
1732+
1733+
addLogParams := &common.GraphQLParams{
1734+
Headers: common.GetJWT(t, "Random", "ADMIN", metaInfo),
1735+
Query: `mutation addLog($log: [AddLogInput!]!) {
1736+
addLog(input: $log) {
1737+
log {
1738+
id
1739+
}
1740+
}
1741+
}`,
1742+
Variables: map[string]interface{}{"log": []*Log{newLog}},
1743+
}
1744+
1745+
gqlResponse = addLogParams.ExecuteAsPost(t, graphqlURL)
1746+
var addLogResult struct {
1747+
AddLog struct {
1748+
Log []*Log
1749+
}
1750+
}
1751+
1752+
err = json.Unmarshal([]byte(gqlResponse.Data), &addLogResult)
1753+
require.Nil(t, err)
1754+
// Id of the created log
1755+
logID := addLogResult.AddLog.Log[0].Id
1756+
1757+
// checkLogPassword with RBAC rule true should work
1758+
gqlResponse = checkLogPassword(t, logID, newLog.Pwd, "Admin")
1759+
var resultLog struct {
1760+
CheckLogPassword *Log `json:"checkLogPassword,omitempty"`
1761+
}
1762+
1763+
err = json.Unmarshal([]byte(gqlResponse.Data), &resultLog)
1764+
require.Nil(t, err)
1765+
1766+
require.Equal(t, resultLog.CheckLogPassword.Id, logID)
1767+
1768+
// checkLogPassword with RBAC rule false should not work
1769+
gqlResponse = checkLogPassword(t, logID, newLog.Pwd, "USER")
1770+
require.JSONEq(t, `{"checkLogPassword": null}`, string(gqlResponse.Data))
1771+
deleteLog(t, logID)
1772+
}

graphql/e2e/auth/delete_mutation_test.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ func (l *Log) add(t *testing.T, user, role string) {
2929
getParams := &common.GraphQLParams{
3030
Headers: common.GetJWT(t, user, role, metaInfo),
3131
Query: `
32-
mutation addLog($log: AddLogInput!) {
33-
addLog(input: [$log]) {
32+
mutation addLog($pwd: String!, $logs: String, $random: String) {
33+
addLog(input: [{pwd: $pwd, logs: $logs, random: $random}]) {
3434
numUids
3535
}
3636
}
3737
`,
38-
Variables: map[string]interface{}{"log": l},
38+
Variables: map[string]interface{}{"pwd": "password", "logs": l.Logs, "random": l.Random},
3939
}
4040
gqlResponse := getParams.ExecuteAsPost(t, graphqlURL)
4141
require.Nil(t, gqlResponse.Errors)
@@ -93,13 +93,13 @@ func (q *Question) add(t *testing.T, user string, ans bool) {
9393
getParams := &common.GraphQLParams{
9494
Headers: common.GetJWTForInterfaceAuth(t, user, "", ans, metaInfo),
9595
Query: `
96-
mutation addQuestion($text: String!,$id: ID!, $ans: Boolean ){
97-
addQuestion(input: [{text: $text, author: {id: $id}, answered: $ans }]){
96+
mutation addQuestion($text: String!,$id: ID!, $ans: Boolean, $pwd: String! ){
97+
addQuestion(input: [{text: $text, author: {id: $id}, answered: $ans, pwd: $pwd }]){
9898
numUids
9999
}
100100
}
101101
`,
102-
Variables: map[string]interface{}{"text": q.Text, "ans": q.Answered, "id": q.Author.Id},
102+
Variables: map[string]interface{}{"text": q.Text, "ans": q.Answered, "id": q.Author.Id, "pwd": "password"},
103103
}
104104
gqlResponse := getParams.ExecuteAsPost(t, graphqlURL)
105105
require.Nil(t, gqlResponse.Errors)
@@ -109,13 +109,13 @@ func (a *Answer) add(t *testing.T, user string) {
109109
getParams := &common.GraphQLParams{
110110
Headers: common.GetJWT(t, user, "", metaInfo),
111111
Query: `
112-
mutation addAnswer($text: String!,$id: ID!){
113-
addAnswer(input: [{text: $text, author: {id: $id}}]){
112+
mutation addAnswer($text: String!,$id: ID!, $pwd: String!){
113+
addAnswer(input: [{text: $text, pwd: $pwd, author: {id: $id}}]){
114114
numUids
115115
}
116116
}
117117
`,
118-
Variables: map[string]interface{}{"text": a.Text, "id": a.Author.Id},
118+
Variables: map[string]interface{}{"text": a.Text, "id": a.Author.Id, "pwd": "password"},
119119
}
120120
gqlResponse := getParams.ExecuteAsPost(t, graphqlURL)
121121
require.Nil(t, gqlResponse.Errors)
@@ -125,13 +125,13 @@ func (f *FbPost) add(t *testing.T, user, role string) {
125125
getParams := &common.GraphQLParams{
126126
Headers: common.GetJWT(t, user, role, metaInfo),
127127
Query: `
128-
mutation addFbPost($text: String!,$id1: ID!,$id2:ID!, $id3: ID!, $postCount: Int! ){
129-
addFbPost(input: [{text: $text, author: {id: $id1},sender: {id: $id2}, receiver: {id: $id3}, postCount: $postCount }]){
128+
mutation addFbPost($text: String!,$id1: ID!,$id2:ID!, $id3: ID!, $postCount: Int!, $pwd: String! ){
129+
addFbPost(input: [{text: $text, author: {id: $id1},sender: {id: $id2}, receiver: {id: $id3}, postCount: $postCount, pwd: $pwd }]){
130130
numUids
131131
}
132132
}
133133
`,
134-
Variables: map[string]interface{}{"text": f.Text, "id1": f.Author.Id, "id2": f.Sender.Id, "id3": f.Receiver.Id, "postCount": f.PostCount},
134+
Variables: map[string]interface{}{"text": f.Text, "id1": f.Author.Id, "id2": f.Sender.Id, "id3": f.Receiver.Id, "postCount": f.PostCount, "pwd": "password"},
135135
}
136136
gqlResponse := getParams.ExecuteAsPost(t, graphqlURL)
137137
require.Nil(t, gqlResponse.Errors)

0 commit comments

Comments
 (0)