Skip to content

Commit 8ee829f

Browse files
Moumoulsdavimacedo
authored andcommitted
GraphQL: 3rd Party LoginWith Support (parse-community#6371)
* wip * wip * tested
1 parent d0428bf commit 8ee829f

File tree

2 files changed

+154
-6
lines changed

2 files changed

+154
-6
lines changed

spec/ParseGraphQLServer.spec.js

+60-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const req = require('../lib/request');
44
const fetch = require('node-fetch');
55
const FormData = require('form-data');
66
const ws = require('ws');
7+
require('./helper');
78
const pluralize = require('pluralize');
89
const { getMainDefinition } = require('apollo-utilities');
910
const { ApolloLink, split } = require('apollo-link');
@@ -907,7 +908,7 @@ describe('ParseGraphQLServer', () => {
907908
.map(field => field.name)
908909
.sort();
909910

910-
expect(inputFields).toEqual(['clientMutationId', 'userFields']);
911+
expect(inputFields).toEqual(['clientMutationId', 'fields']);
911912
});
912913

913914
it('should have clientMutationId in sign up mutation payload', async () => {
@@ -7114,7 +7115,7 @@ describe('ParseGraphQLServer', () => {
71147115
variables: {
71157116
input: {
71167117
clientMutationId,
7117-
userFields: {
7118+
fields: {
71187119
username: 'user1',
71197120
password: 'user1',
71207121
someField: 'someValue',
@@ -7129,6 +7130,63 @@ describe('ParseGraphQLServer', () => {
71297130
expect(typeof result.data.signUp.viewer.sessionToken).toBe('string');
71307131
});
71317132

7133+
it('should login with user', async () => {
7134+
const clientMutationId = uuidv4();
7135+
const userSchema = new Parse.Schema('_User');
7136+
parseServer = await global.reconfigureServer({
7137+
publicServerURL: 'http://localhost:13377/parse',
7138+
auth: {
7139+
myAuth: {
7140+
module: global.mockCustomAuthenticator('parse', 'graphql'),
7141+
},
7142+
},
7143+
});
7144+
7145+
userSchema.addString('someField');
7146+
await userSchema.update();
7147+
await parseGraphQLServer.parseGraphQLSchema.databaseController.schemaCache.clear();
7148+
const result = await apolloClient.mutate({
7149+
mutation: gql`
7150+
mutation LogInWith($input: LogInWithInput!) {
7151+
logInWith(input: $input) {
7152+
clientMutationId
7153+
viewer {
7154+
sessionToken
7155+
user {
7156+
someField
7157+
}
7158+
}
7159+
}
7160+
}
7161+
`,
7162+
variables: {
7163+
input: {
7164+
clientMutationId,
7165+
authData: {
7166+
myAuth: {
7167+
id: 'parse',
7168+
password: 'graphql',
7169+
},
7170+
},
7171+
fields: {
7172+
someField: 'someValue',
7173+
},
7174+
},
7175+
},
7176+
});
7177+
7178+
expect(result.data.logInWith.clientMutationId).toEqual(
7179+
clientMutationId
7180+
);
7181+
expect(result.data.logInWith.viewer.sessionToken).toBeDefined();
7182+
expect(result.data.logInWith.viewer.user.someField).toEqual(
7183+
'someValue'
7184+
);
7185+
expect(typeof result.data.logInWith.viewer.sessionToken).toBe(
7186+
'string'
7187+
);
7188+
});
7189+
71327190
it('should log the user in', async () => {
71337191
const clientMutationId = uuidv4();
71347192
const user = new Parse.User();

src/GraphQL/loaders/usersMutations.js

+94-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1-
import { GraphQLNonNull, GraphQLString, GraphQLBoolean } from 'graphql';
1+
import {
2+
GraphQLNonNull,
3+
GraphQLString,
4+
GraphQLBoolean,
5+
GraphQLInputObjectType,
6+
} from 'graphql';
27
import { mutationWithClientMutationId } from 'graphql-relay';
38
import UsersRouter from '../../Routers/UsersRouter';
49
import * as objectsMutations from '../helpers/objectsMutations';
10+
import { OBJECT } from './defaultGraphQLTypes';
511
import { getUserFromSessionToken } from './usersQueries';
612

713
const usersRouter = new UsersRouter();
@@ -16,7 +22,7 @@ const load = parseGraphQLSchema => {
1622
description:
1723
'The signUp mutation can be used to create and sign up a new user.',
1824
inputFields: {
19-
userFields: {
25+
fields: {
2026
descriptions:
2127
'These are the fields of the new user to be created and signed up.',
2228
type:
@@ -32,12 +38,12 @@ const load = parseGraphQLSchema => {
3238
},
3339
mutateAndGetPayload: async (args, context, mutationInfo) => {
3440
try {
35-
const { userFields } = args;
41+
const { fields } = args;
3642
const { config, auth, info } = context;
3743

3844
const { sessionToken } = await objectsMutations.createObject(
3945
'_User',
40-
userFields,
46+
fields,
4147
config,
4248
auth,
4349
info
@@ -67,6 +73,90 @@ const load = parseGraphQLSchema => {
6773
);
6874
parseGraphQLSchema.addGraphQLType(signUpMutation.type, true, true);
6975
parseGraphQLSchema.addGraphQLMutation('signUp', signUpMutation, true, true);
76+
const logInWithMutation = mutationWithClientMutationId({
77+
name: 'LogInWith',
78+
description:
79+
'The logInWith mutation can be used to signup, login user with 3rd party authentication system. This mutation create a user if the authData do not correspond to an existing one.',
80+
inputFields: {
81+
authData: {
82+
descriptions: 'This is the auth data of your custom auth provider',
83+
type: new GraphQLNonNull(OBJECT),
84+
},
85+
fields: {
86+
descriptions:
87+
'These are the fields of the user to be created/updated and logged in.',
88+
type: new GraphQLInputObjectType({
89+
name: 'UserLoginWithInput',
90+
fields: () => {
91+
const classGraphQLCreateFields = parseGraphQLSchema.parseClassTypes[
92+
'_User'
93+
].classGraphQLCreateType.getFields();
94+
return Object.keys(classGraphQLCreateFields).reduce(
95+
(fields, fieldName) => {
96+
if (
97+
fieldName !== 'password' &&
98+
fieldName !== 'username' &&
99+
fieldName !== 'authData'
100+
) {
101+
fields[fieldName] = classGraphQLCreateFields[fieldName];
102+
}
103+
return fields;
104+
},
105+
{}
106+
);
107+
},
108+
}),
109+
},
110+
},
111+
outputFields: {
112+
viewer: {
113+
description:
114+
'This is the new user that was created, signed up and returned as a viewer.',
115+
type: new GraphQLNonNull(parseGraphQLSchema.viewerType),
116+
},
117+
},
118+
mutateAndGetPayload: async (args, context, mutationInfo) => {
119+
try {
120+
const { fields, authData } = args;
121+
const { config, auth, info } = context;
122+
123+
const { sessionToken } = await objectsMutations.createObject(
124+
'_User',
125+
{ ...fields, authData },
126+
config,
127+
auth,
128+
info
129+
);
130+
131+
info.sessionToken = sessionToken;
132+
133+
return {
134+
viewer: await getUserFromSessionToken(
135+
config,
136+
info,
137+
mutationInfo,
138+
'viewer.user.',
139+
true
140+
),
141+
};
142+
} catch (e) {
143+
parseGraphQLSchema.handleError(e);
144+
}
145+
},
146+
});
147+
148+
parseGraphQLSchema.addGraphQLType(
149+
logInWithMutation.args.input.type.ofType,
150+
true,
151+
true
152+
);
153+
parseGraphQLSchema.addGraphQLType(logInWithMutation.type, true, true);
154+
parseGraphQLSchema.addGraphQLMutation(
155+
'logInWith',
156+
logInWithMutation,
157+
true,
158+
true
159+
);
70160

71161
const logInMutation = mutationWithClientMutationId({
72162
name: 'LogIn',

0 commit comments

Comments
 (0)