Skip to content

GraphQL: 3rd Party LoginWith Support #6371

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

Merged
merged 3 commits into from
Jan 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 60 additions & 2 deletions spec/ParseGraphQLServer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const req = require('../lib/request');
const fetch = require('node-fetch');
const FormData = require('form-data');
const ws = require('ws');
require('./helper');
const pluralize = require('pluralize');
const { getMainDefinition } = require('apollo-utilities');
const { ApolloLink, split } = require('apollo-link');
Expand Down Expand Up @@ -907,7 +908,7 @@ describe('ParseGraphQLServer', () => {
.map(field => field.name)
.sort();

expect(inputFields).toEqual(['clientMutationId', 'userFields']);
expect(inputFields).toEqual(['clientMutationId', 'fields']);
});

it('should have clientMutationId in sign up mutation payload', async () => {
Expand Down Expand Up @@ -7114,7 +7115,7 @@ describe('ParseGraphQLServer', () => {
variables: {
input: {
clientMutationId,
userFields: {
fields: {
username: 'user1',
password: 'user1',
someField: 'someValue',
Expand All @@ -7129,6 +7130,63 @@ describe('ParseGraphQLServer', () => {
expect(typeof result.data.signUp.viewer.sessionToken).toBe('string');
});

it('should login with user', async () => {
const clientMutationId = uuidv4();
const userSchema = new Parse.Schema('_User');
parseServer = await global.reconfigureServer({
publicServerURL: 'http://localhost:13377/parse',
auth: {
myAuth: {
module: global.mockCustomAuthenticator('parse', 'graphql'),
},
},
});

userSchema.addString('someField');
await userSchema.update();
await parseGraphQLServer.parseGraphQLSchema.databaseController.schemaCache.clear();
const result = await apolloClient.mutate({
mutation: gql`
mutation LogInWith($input: LogInWithInput!) {
logInWith(input: $input) {
clientMutationId
viewer {
sessionToken
user {
someField
}
}
}
}
`,
variables: {
input: {
clientMutationId,
authData: {
myAuth: {
id: 'parse',
password: 'graphql',
},
},
fields: {
someField: 'someValue',
},
},
},
});

expect(result.data.logInWith.clientMutationId).toEqual(
clientMutationId
);
expect(result.data.logInWith.viewer.sessionToken).toBeDefined();
expect(result.data.logInWith.viewer.user.someField).toEqual(
'someValue'
);
expect(typeof result.data.logInWith.viewer.sessionToken).toBe(
'string'
);
});

it('should log the user in', async () => {
const clientMutationId = uuidv4();
const user = new Parse.User();
Expand Down
98 changes: 94 additions & 4 deletions src/GraphQL/loaders/usersMutations.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { GraphQLNonNull, GraphQLString, GraphQLBoolean } from 'graphql';
import {
GraphQLNonNull,
GraphQLString,
GraphQLBoolean,
GraphQLInputObjectType,
} from 'graphql';
import { mutationWithClientMutationId } from 'graphql-relay';
import UsersRouter from '../../Routers/UsersRouter';
import * as objectsMutations from '../helpers/objectsMutations';
import { OBJECT } from './defaultGraphQLTypes';
import { getUserFromSessionToken } from './usersQueries';

const usersRouter = new UsersRouter();
Expand All @@ -16,7 +22,7 @@ const load = parseGraphQLSchema => {
description:
'The signUp mutation can be used to create and sign up a new user.',
inputFields: {
userFields: {
fields: {
descriptions:
'These are the fields of the new user to be created and signed up.',
type:
Expand All @@ -32,12 +38,12 @@ const load = parseGraphQLSchema => {
},
mutateAndGetPayload: async (args, context, mutationInfo) => {
try {
const { userFields } = args;
const { fields } = args;
const { config, auth, info } = context;

const { sessionToken } = await objectsMutations.createObject(
'_User',
userFields,
fields,
config,
auth,
info
Expand Down Expand Up @@ -67,6 +73,90 @@ const load = parseGraphQLSchema => {
);
parseGraphQLSchema.addGraphQLType(signUpMutation.type, true, true);
parseGraphQLSchema.addGraphQLMutation('signUp', signUpMutation, true, true);
const logInWithMutation = mutationWithClientMutationId({
name: 'LogInWith',
description:
'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.',
inputFields: {
authData: {
descriptions: 'This is the auth data of your custom auth provider',
type: new GraphQLNonNull(OBJECT),
},
fields: {
descriptions:
'These are the fields of the user to be created/updated and logged in.',
type: new GraphQLInputObjectType({
name: 'UserLoginWithInput',
fields: () => {
const classGraphQLCreateFields = parseGraphQLSchema.parseClassTypes[
'_User'
].classGraphQLCreateType.getFields();
return Object.keys(classGraphQLCreateFields).reduce(
(fields, fieldName) => {
if (
fieldName !== 'password' &&
fieldName !== 'username' &&
fieldName !== 'authData'
) {
fields[fieldName] = classGraphQLCreateFields[fieldName];
}
return fields;
},
{}
);
},
}),
},
},
outputFields: {
viewer: {
description:
'This is the new user that was created, signed up and returned as a viewer.',
type: new GraphQLNonNull(parseGraphQLSchema.viewerType),
},
},
mutateAndGetPayload: async (args, context, mutationInfo) => {
try {
const { fields, authData } = args;
const { config, auth, info } = context;

const { sessionToken } = await objectsMutations.createObject(
'_User',
{ ...fields, authData },
config,
auth,
info
);

info.sessionToken = sessionToken;

return {
viewer: await getUserFromSessionToken(
config,
info,
mutationInfo,
'viewer.user.',
true
),
};
} catch (e) {
parseGraphQLSchema.handleError(e);
}
},
});

parseGraphQLSchema.addGraphQLType(
logInWithMutation.args.input.type.ofType,
true,
true
);
parseGraphQLSchema.addGraphQLType(logInWithMutation.type, true, true);
parseGraphQLSchema.addGraphQLMutation(
'logInWith',
logInWithMutation,
true,
true
);

const logInMutation = mutationWithClientMutationId({
name: 'LogIn',
Expand Down