Skip to content

Commit 7bfd8c9

Browse files
committed
feat: support -1 and 0
1 parent 4f7e157 commit 7bfd8c9

File tree

8 files changed

+766
-16
lines changed

8 files changed

+766
-16
lines changed

spec/ParseGraphQLQueryComplexity.spec.js

Lines changed: 372 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,48 @@ describe('ParseGraphQL Query Complexity', () => {
151151
const result = await masterClient.query({ query });
152152
expect(result.data.users).toBeDefined();
153153
});
154+
155+
it('should allow queries with maintenance key even when exceeding fields limit', async () => {
156+
await reconfigureServer({
157+
maintenanceKey: 'maintenanceKey123',
158+
maxGraphQLQueryComplexity: {
159+
fields: 3,
160+
},
161+
});
162+
163+
const httpLinkWithMaintenance = createHttpLink({
164+
uri: 'http://localhost:13378/graphql',
165+
fetch: (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)),
166+
headers: {
167+
'X-Parse-Application-Id': 'test',
168+
'X-Parse-Maintenance-Key': 'maintenanceKey123',
169+
},
170+
});
171+
172+
const maintenanceClient = new ApolloClient({
173+
link: httpLinkWithMaintenance,
174+
cache: new InMemoryCache(),
175+
});
176+
177+
const query = gql`
178+
query {
179+
users {
180+
edges {
181+
node {
182+
objectId
183+
username
184+
createdAt
185+
updatedAt
186+
email
187+
}
188+
}
189+
}
190+
}
191+
`;
192+
193+
const result = await maintenanceClient.query({ query });
194+
expect(result.data.users).toBeDefined();
195+
});
154196
});
155197

156198
describe('maxGraphQLQueryComplexity.depth', () => {
@@ -660,5 +702,335 @@ describe('ParseGraphQL Query Complexity', () => {
660702
expect(deepResult.errors[0].message).toContain('Query depth exceeds maximum allowed depth');
661703
});
662704
});
705+
706+
describe('Skipping validation with -1', () => {
707+
it('should skip depth validation when depth is -1', async () => {
708+
await reconfigureServer({
709+
maxGraphQLQueryComplexity: {
710+
depth: -1,
711+
fields: 50,
712+
},
713+
});
714+
715+
// Very deep query that would normally fail
716+
const query = gql`
717+
query {
718+
users {
719+
edges {
720+
node {
721+
objectId
722+
username
723+
createdAt
724+
updatedAt
725+
email
726+
emailVerified
727+
username
728+
}
729+
}
730+
}
731+
}
732+
`;
733+
734+
const result = await apolloClient.query({ query });
735+
expect(result.data.users).toBeDefined();
736+
});
737+
738+
it('should skip fields validation when fields is -1', async () => {
739+
await reconfigureServer({
740+
maxGraphQLQueryComplexity: {
741+
depth: 10,
742+
fields: -1,
743+
},
744+
});
745+
746+
// Many fields query that would normally fail
747+
const query = gql`
748+
query {
749+
users {
750+
edges {
751+
node {
752+
objectId
753+
username
754+
createdAt
755+
updatedAt
756+
email
757+
emailVerified
758+
}
759+
}
760+
}
761+
}
762+
`;
763+
764+
const result = await apolloClient.query({ query });
765+
expect(result.data.users).toBeDefined();
766+
});
767+
768+
it('should skip both validations when both are -1', async () => {
769+
await reconfigureServer({
770+
maxGraphQLQueryComplexity: {
771+
depth: -1,
772+
fields: -1,
773+
},
774+
});
775+
776+
// Very complex query
777+
const query = gql`
778+
query {
779+
users {
780+
edges {
781+
node {
782+
objectId
783+
username
784+
createdAt
785+
updatedAt
786+
email
787+
emailVerified
788+
}
789+
}
790+
}
791+
}
792+
`;
793+
794+
const result = await apolloClient.query({ query });
795+
expect(result.data.users).toBeDefined();
796+
});
797+
798+
it('should enforce fields limit when depth is -1', async () => {
799+
await reconfigureServer({
800+
maxGraphQLQueryComplexity: {
801+
depth: -1,
802+
fields: 3,
803+
},
804+
});
805+
806+
const query = gql`
807+
query {
808+
users {
809+
edges {
810+
node {
811+
objectId
812+
username
813+
createdAt
814+
updatedAt
815+
}
816+
}
817+
}
818+
}
819+
`;
820+
821+
try {
822+
await apolloClient.query({ query });
823+
fail('Should have thrown an error');
824+
} catch (error) {
825+
expect(error.networkError.result.errors[0].message).toContain('Number of fields selected exceeds maximum allowed');
826+
}
827+
});
828+
});
829+
830+
describe('Restricting with depth 0', () => {
831+
it('should reject all queries when depth is 0', async () => {
832+
await reconfigureServer({
833+
maxGraphQLQueryComplexity: {
834+
depth: 0,
835+
},
836+
});
837+
838+
const query = gql`
839+
query {
840+
users {
841+
edges {
842+
node {
843+
objectId
844+
}
845+
}
846+
}
847+
}
848+
`;
849+
850+
try {
851+
await apolloClient.query({ query });
852+
fail('Should have thrown an error');
853+
} catch (error) {
854+
expect(error.networkError.result.errors[0].message).toContain('Query depth exceeds maximum allowed depth');
855+
}
856+
});
857+
858+
it('should reject all queries when fields is 0', async () => {
859+
await reconfigureServer({
860+
maxGraphQLQueryComplexity: {
861+
fields: 0,
862+
},
863+
});
864+
865+
const query = gql`
866+
query {
867+
users {
868+
edges {
869+
node {
870+
objectId
871+
}
872+
}
873+
}
874+
}
875+
`;
876+
877+
try {
878+
await apolloClient.query({ query });
879+
fail('Should have thrown an error');
880+
} catch (error) {
881+
expect(error.networkError.result.errors[0].message).toContain('Number of fields selected exceeds maximum allowed');
882+
}
883+
});
884+
885+
it('should allow master key even with depth 0', async () => {
886+
await reconfigureServer({
887+
maxGraphQLQueryComplexity: {
888+
depth: 0,
889+
},
890+
});
891+
892+
const httpLinkWithMaster = createHttpLink({
893+
uri: 'http://localhost:13378/graphql',
894+
fetch: (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)),
895+
headers: {
896+
'X-Parse-Application-Id': 'test',
897+
'X-Parse-Master-Key': 'test',
898+
},
899+
});
900+
901+
const masterClient = new ApolloClient({
902+
link: httpLinkWithMaster,
903+
cache: new InMemoryCache(),
904+
});
905+
906+
const query = gql`
907+
query {
908+
users {
909+
edges {
910+
node {
911+
objectId
912+
}
913+
}
914+
}
915+
}
916+
`;
917+
918+
const result = await masterClient.query({ query });
919+
expect(result.data.users).toBeDefined();
920+
});
921+
922+
it('should allow master key even with fields 0', async () => {
923+
await reconfigureServer({
924+
maxGraphQLQueryComplexity: {
925+
fields: 0,
926+
},
927+
});
928+
929+
const httpLinkWithMaster = createHttpLink({
930+
uri: 'http://localhost:13378/graphql',
931+
fetch: (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)),
932+
headers: {
933+
'X-Parse-Application-Id': 'test',
934+
'X-Parse-Master-Key': 'test',
935+
},
936+
});
937+
938+
const masterClient = new ApolloClient({
939+
link: httpLinkWithMaster,
940+
cache: new InMemoryCache(),
941+
});
942+
943+
const query = gql`
944+
query {
945+
users {
946+
edges {
947+
node {
948+
objectId
949+
}
950+
}
951+
}
952+
}
953+
`;
954+
955+
const result = await masterClient.query({ query });
956+
expect(result.data.users).toBeDefined();
957+
});
958+
959+
it('should allow maintenance key even with depth 0', async () => {
960+
await reconfigureServer({
961+
maintenanceKey: 'maintenanceKey123',
962+
maxGraphQLQueryComplexity: {
963+
depth: 0,
964+
},
965+
});
966+
967+
const httpLinkWithMaintenance = createHttpLink({
968+
uri: 'http://localhost:13378/graphql',
969+
fetch: (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)),
970+
headers: {
971+
'X-Parse-Application-Id': 'test',
972+
'X-Parse-Maintenance-Key': 'maintenanceKey123',
973+
},
974+
});
975+
976+
const maintenanceClient = new ApolloClient({
977+
link: httpLinkWithMaintenance,
978+
cache: new InMemoryCache(),
979+
});
980+
981+
const query = gql`
982+
query {
983+
users {
984+
edges {
985+
node {
986+
objectId
987+
}
988+
}
989+
}
990+
}
991+
`;
992+
993+
const result = await maintenanceClient.query({ query });
994+
expect(result.data.users).toBeDefined();
995+
});
996+
997+
it('should allow maintenance key even with fields 0', async () => {
998+
await reconfigureServer({
999+
maintenanceKey: 'maintenanceKey123',
1000+
maxGraphQLQueryComplexity: {
1001+
fields: 0,
1002+
},
1003+
});
1004+
1005+
const httpLinkWithMaintenance = createHttpLink({
1006+
uri: 'http://localhost:13378/graphql',
1007+
fetch: (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)),
1008+
headers: {
1009+
'X-Parse-Application-Id': 'test',
1010+
'X-Parse-Maintenance-Key': 'maintenanceKey123',
1011+
},
1012+
});
1013+
1014+
const maintenanceClient = new ApolloClient({
1015+
link: httpLinkWithMaintenance,
1016+
cache: new InMemoryCache(),
1017+
});
1018+
1019+
const query = gql`
1020+
query {
1021+
users {
1022+
edges {
1023+
node {
1024+
objectId
1025+
}
1026+
}
1027+
}
1028+
}
1029+
`;
1030+
1031+
const result = await maintenanceClient.query({ query });
1032+
expect(result.data.users).toBeDefined();
1033+
});
1034+
});
6631035
});
6641036

0 commit comments

Comments
 (0)