Skip to content

Commit a3a00d4

Browse files
sadakchapArul-
authored andcommitted
GraphQL: reset password with emailed token (parse-community#7290)
* renamed "resetPassword" to "requestResetPassword" & created new "resetPassword" mutation * added new route to handle resetPassword in UsersRouter.js * updated resetPassword test to "requestResetPassword" mutation * updated "resetPassword" mutation args description * changed token arg description to rerun the tests * directly using updatePassword for resetPassword * removed handleResetPassword from UsersRouter.js file * added test case for reset Password * changed mutation names to "resetPassword" & "confirmResetPassword" * changed mutation names in test also
1 parent 011c045 commit a3a00d4

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

spec/ParseGraphQLServer.spec.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7086,6 +7086,77 @@ describe('ParseGraphQLServer', () => {
70867086
expect(result.data.resetPassword.clientMutationId).toEqual(clientMutationId);
70877087
expect(result.data.resetPassword.ok).toBeTruthy();
70887088
});
7089+
7090+
it('should reset password', async () => {
7091+
const clientMutationId = uuidv4();
7092+
let resetPasswordToken;
7093+
const emailAdapter = {
7094+
sendVerificationEmail: () => {},
7095+
sendPasswordResetEmail: ({ link }) => {
7096+
resetPasswordToken = link.split('token=')[1].split('&')[0];
7097+
},
7098+
sendMail: () => {},
7099+
};
7100+
parseServer = await global.reconfigureServer({
7101+
appName: 'test',
7102+
emailAdapter: emailAdapter,
7103+
publicServerURL: 'http://localhost:13377/parse',
7104+
auth: {
7105+
myAuth: {
7106+
module: global.mockCustomAuthenticator('parse', 'graphql'),
7107+
},
7108+
},
7109+
});
7110+
const user = new Parse.User();
7111+
user.setUsername('user1');
7112+
user.setPassword('user1');
7113+
user.setEmail('[email protected]');
7114+
await user.signUp();
7115+
await Parse.User.logOut();
7116+
await Parse.User.requestPasswordReset('[email protected]');
7117+
await apolloClient.mutate({
7118+
mutation: gql`
7119+
mutation ConfirmResetPassword($input: ConfirmResetPasswordInput!) {
7120+
confirmResetPassword(input: $input) {
7121+
clientMutationId
7122+
ok
7123+
}
7124+
}
7125+
`,
7126+
variables: {
7127+
input: {
7128+
clientMutationId,
7129+
username: 'user1',
7130+
password: 'newPassword',
7131+
token: resetPasswordToken,
7132+
},
7133+
},
7134+
});
7135+
const result = await apolloClient.mutate({
7136+
mutation: gql`
7137+
mutation LogInUser($input: LogInInput!) {
7138+
logIn(input: $input) {
7139+
clientMutationId
7140+
viewer {
7141+
sessionToken
7142+
}
7143+
}
7144+
}
7145+
`,
7146+
variables: {
7147+
input: {
7148+
clientMutationId,
7149+
username: 'user1',
7150+
password: 'newPassword',
7151+
},
7152+
},
7153+
});
7154+
7155+
expect(result.data.logIn.clientMutationId).toEqual(clientMutationId);
7156+
expect(result.data.logIn.viewer.sessionToken).toBeDefined();
7157+
expect(typeof result.data.logIn.viewer.sessionToken).toBe('string');
7158+
});
7159+
70897160
it('should send verification email again', async () => {
70907161
const clientMutationId = uuidv4();
70917162
const emailAdapter = {

src/GraphQL/loaders/usersMutations.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as objectsMutations from '../helpers/objectsMutations';
55
import { OBJECT } from './defaultGraphQLTypes';
66
import { getUserFromSessionToken } from './usersQueries';
77
import { transformTypes } from '../transformers/mutation';
8+
import Parse from 'parse/node';
89

910
const usersRouter = new UsersRouter();
1011

@@ -250,6 +251,61 @@ const load = parseGraphQLSchema => {
250251
parseGraphQLSchema.addGraphQLType(resetPasswordMutation.type, true, true);
251252
parseGraphQLSchema.addGraphQLMutation('resetPassword', resetPasswordMutation, true, true);
252253

254+
const confirmResetPasswordMutation = mutationWithClientMutationId({
255+
name: 'ConfirmResetPassword',
256+
description:
257+
'The confirmResetPassword mutation can be used to reset the password of an existing user.',
258+
inputFields: {
259+
username: {
260+
descriptions: 'Username of the user that have received the reset email',
261+
type: new GraphQLNonNull(GraphQLString),
262+
},
263+
password: {
264+
descriptions: 'New password of the user',
265+
type: new GraphQLNonNull(GraphQLString),
266+
},
267+
token: {
268+
descriptions: 'Reset token that was emailed to the user',
269+
type: new GraphQLNonNull(GraphQLString),
270+
},
271+
},
272+
outputFields: {
273+
ok: {
274+
description: "It's always true.",
275+
type: new GraphQLNonNull(GraphQLBoolean),
276+
},
277+
},
278+
mutateAndGetPayload: async ({ username, password, token }, context) => {
279+
const { config } = context;
280+
if (!username) {
281+
throw new Parse.Error(Parse.Error.USERNAME_MISSING, 'you must provide a username');
282+
}
283+
if (!password) {
284+
throw new Parse.Error(Parse.Error.PASSWORD_MISSING, 'you must provide a password');
285+
}
286+
if (!token) {
287+
throw new Parse.Error(Parse.Error.OTHER_CAUSE, 'you must provide a token');
288+
}
289+
290+
const userController = config.userController;
291+
await userController.updatePassword(username, token, password);
292+
return { ok: true };
293+
},
294+
});
295+
296+
parseGraphQLSchema.addGraphQLType(
297+
confirmResetPasswordMutation.args.input.type.ofType,
298+
true,
299+
true
300+
);
301+
parseGraphQLSchema.addGraphQLType(confirmResetPasswordMutation.type, true, true);
302+
parseGraphQLSchema.addGraphQLMutation(
303+
'confirmResetPassword',
304+
confirmResetPasswordMutation,
305+
true,
306+
true
307+
);
308+
253309
const sendVerificationEmailMutation = mutationWithClientMutationId({
254310
name: 'SendVerificationEmail',
255311
description:

0 commit comments

Comments
 (0)