2020-12-08 00:45:51 +01:00
import { GraphQLNonNull , GraphQLString , GraphQLBoolean , GraphQLInputObjectType } from 'graphql' ;
2019-12-01 21:43:08 -08:00
import { mutationWithClientMutationId } from 'graphql-relay' ;
2021-10-11 14:51:28 +02:00
import deepcopy from 'deepcopy' ;
2019-06-19 17:19:47 -07:00
import UsersRouter from '../../Routers/UsersRouter' ;
2019-09-01 22:11:03 -07:00
import * as objectsMutations from '../helpers/objectsMutations' ;
2020-01-28 03:57:26 +01:00
import { OBJECT } from './defaultGraphQLTypes' ;
2019-08-12 10:38:59 +02:00
import { getUserFromSessionToken } from './usersQueries' ;
2020-10-09 17:40:30 +02:00
import { transformTypes } from '../transformers/mutation' ;
2021-03-29 10:15:41 +05:30
import Parse from 'parse/node' ;
2019-06-19 17:19:47 -07:00
const usersRouter = new UsersRouter ( ) ;
const load = parseGraphQLSchema => {
2019-07-25 20:46:25 +01:00
if ( parseGraphQLSchema . isUsersClassDisabled ) {
return ;
}
2019-06-19 17:19:47 -07:00
2019-12-01 21:43:08 -08:00
const signUpMutation = mutationWithClientMutationId ( {
name : 'SignUp' ,
2020-12-08 00:45:51 +01:00
description : 'The signUp mutation can be used to create and sign up a new user.' ,
2019-12-01 21:43:08 -08:00
inputFields : {
2020-01-28 03:57:26 +01:00
fields : {
2020-12-08 00:45:51 +01:00
descriptions : 'These are the fields of the new user to be created and signed up.' ,
type : parseGraphQLSchema . parseClassTypes [ '_User' ] . classGraphQLCreateType ,
2019-06-19 17:19:47 -07:00
} ,
2019-12-01 21:43:08 -08:00
} ,
outputFields : {
viewer : {
2020-12-08 00:45:51 +01:00
description : 'This is the new user that was created, signed up and returned as a viewer.' ,
2019-12-01 21:43:08 -08:00
type : new GraphQLNonNull ( parseGraphQLSchema . viewerType ) ,
} ,
} ,
mutateAndGetPayload : async ( args , context , mutationInfo ) => {
try {
2021-10-11 14:51:28 +02:00
const { fields } = deepcopy ( args ) ;
2019-12-01 21:43:08 -08:00
const { config , auth , info } = context ;
2019-08-17 11:02:19 -07:00
2020-10-09 17:40:30 +02:00
const parseFields = await transformTypes ( 'create' , fields , {
className : '_User' ,
parseGraphQLSchema ,
req : { config , auth , info } ,
} ) ;
2020-07-17 18:50:41 +02:00
const { sessionToken , objectId } = await objectsMutations . createObject (
2019-12-01 21:43:08 -08:00
'_User' ,
2020-10-09 17:40:30 +02:00
parseFields ,
2019-12-01 21:43:08 -08:00
config ,
auth ,
info
) ;
2019-08-17 11:02:19 -07:00
2020-07-17 18:50:41 +02:00
context . info . sessionToken = sessionToken ;
2019-08-17 11:02:19 -07:00
2019-12-01 21:43:08 -08:00
return {
2020-12-08 00:45:51 +01:00
viewer : await getUserFromSessionToken ( context , mutationInfo , 'viewer.user.' , objectId ) ,
2019-12-01 21:43:08 -08:00
} ;
} catch ( e ) {
parseGraphQLSchema . handleError ( e ) ;
}
2019-06-19 17:19:47 -07:00
} ,
2019-12-01 21:43:08 -08:00
} ) ;
2020-12-08 00:45:51 +01:00
parseGraphQLSchema . addGraphQLType ( signUpMutation . args . input . type . ofType , true , true ) ;
2019-12-01 21:43:08 -08:00
parseGraphQLSchema . addGraphQLType ( signUpMutation . type , true , true ) ;
parseGraphQLSchema . addGraphQLMutation ( 'signUp' , signUpMutation , true , true ) ;
2020-01-28 03:57:26 +01:00
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 : {
2020-12-08 00:45:51 +01:00
descriptions : 'These are the fields of the user to be created/updated and logged in.' ,
2020-01-28 03:57:26 +01:00
type : new GraphQLInputObjectType ( {
name : 'UserLoginWithInput' ,
fields : ( ) => {
const classGraphQLCreateFields = parseGraphQLSchema . parseClassTypes [
'_User'
] . classGraphQLCreateType . getFields ( ) ;
2020-12-08 00:45:51 +01:00
return Object . keys ( classGraphQLCreateFields ) . reduce ( ( fields , fieldName ) => {
if (
fieldName !== 'password' &&
fieldName !== 'username' &&
fieldName !== 'authData'
) {
fields [ fieldName ] = classGraphQLCreateFields [ fieldName ] ;
}
return fields ;
} , { } ) ;
2020-01-28 03:57:26 +01:00
} ,
} ) ,
} ,
} ,
outputFields : {
viewer : {
2020-12-08 00:45:51 +01:00
description : 'This is the new user that was created, signed up and returned as a viewer.' ,
2020-01-28 03:57:26 +01:00
type : new GraphQLNonNull ( parseGraphQLSchema . viewerType ) ,
} ,
} ,
mutateAndGetPayload : async ( args , context , mutationInfo ) => {
try {
2021-10-11 14:51:28 +02:00
const { fields , authData } = deepcopy ( args ) ;
2020-01-28 03:57:26 +01:00
const { config , auth , info } = context ;
2020-10-09 17:40:30 +02:00
const parseFields = await transformTypes ( 'create' , fields , {
className : '_User' ,
parseGraphQLSchema ,
req : { config , auth , info } ,
} ) ;
2020-07-17 18:50:41 +02:00
const { sessionToken , objectId } = await objectsMutations . createObject (
2020-01-28 03:57:26 +01:00
'_User' ,
2020-10-09 17:40:30 +02:00
{ ... parseFields , authData } ,
2020-01-28 03:57:26 +01:00
config ,
auth ,
info
) ;
2020-07-17 18:50:41 +02:00
context . info . sessionToken = sessionToken ;
2020-01-28 03:57:26 +01:00
return {
2020-12-08 00:45:51 +01:00
viewer : await getUserFromSessionToken ( context , mutationInfo , 'viewer.user.' , objectId ) ,
2020-01-28 03:57:26 +01:00
} ;
} catch ( e ) {
parseGraphQLSchema . handleError ( e ) ;
}
} ,
} ) ;
2020-12-08 00:45:51 +01:00
parseGraphQLSchema . addGraphQLType ( logInWithMutation . args . input . type . ofType , true , true ) ;
2020-01-28 03:57:26 +01:00
parseGraphQLSchema . addGraphQLType ( logInWithMutation . type , true , true ) ;
2020-12-08 00:45:51 +01:00
parseGraphQLSchema . addGraphQLMutation ( 'logInWith' , logInWithMutation , true , true ) ;
2019-08-17 11:02:19 -07:00
2019-12-01 21:43:08 -08:00
const logInMutation = mutationWithClientMutationId ( {
name : 'LogIn' ,
description : 'The logIn mutation can be used to log in an existing user.' ,
inputFields : {
username : {
description : 'This is the username used to log in the user.' ,
type : new GraphQLNonNull ( GraphQLString ) ,
} ,
password : {
description : 'This is the password used to log in the user.' ,
type : new GraphQLNonNull ( GraphQLString ) ,
2019-08-17 11:02:19 -07:00
} ,
2019-12-01 21:43:08 -08:00
} ,
outputFields : {
viewer : {
2020-12-08 00:45:51 +01:00
description : 'This is the existing user that was logged in and returned as a viewer.' ,
2019-12-01 21:43:08 -08:00
type : new GraphQLNonNull ( parseGraphQLSchema . viewerType ) ,
} ,
} ,
mutateAndGetPayload : async ( args , context , mutationInfo ) => {
try {
2021-10-11 14:51:28 +02:00
const { username , password } = deepcopy ( args ) ;
2019-12-01 21:43:08 -08:00
const { config , auth , info } = context ;
2020-07-17 18:50:41 +02:00
const { sessionToken , objectId } = (
2020-01-04 21:50:00 +01:00
await usersRouter . handleLogIn ( {
body : {
username ,
password ,
} ,
query : { } ,
config ,
auth ,
info ,
} )
) . response ;
2019-12-01 21:43:08 -08:00
2020-07-17 18:50:41 +02:00
context . info . sessionToken = sessionToken ;
2019-12-01 21:43:08 -08:00
return {
2020-12-08 00:45:51 +01:00
viewer : await getUserFromSessionToken ( context , mutationInfo , 'viewer.user.' , objectId ) ,
2019-12-01 21:43:08 -08:00
} ;
} catch ( e ) {
parseGraphQLSchema . handleError ( e ) ;
}
2019-06-19 17:19:47 -07:00
} ,
2019-12-01 21:43:08 -08:00
} ) ;
2020-12-08 00:45:51 +01:00
parseGraphQLSchema . addGraphQLType ( logInMutation . args . input . type . ofType , true , true ) ;
2019-12-01 21:43:08 -08:00
parseGraphQLSchema . addGraphQLType ( logInMutation . type , true , true ) ;
parseGraphQLSchema . addGraphQLMutation ( 'logIn' , logInMutation , true , true ) ;
2019-08-17 11:02:19 -07:00
2019-12-01 21:43:08 -08:00
const logOutMutation = mutationWithClientMutationId ( {
name : 'LogOut' ,
description : 'The logOut mutation can be used to log out an existing user.' ,
outputFields : {
2020-12-08 00:45:51 +01:00
ok : {
description : "It's always true." ,
type : new GraphQLNonNull ( GraphQLBoolean ) ,
2019-12-01 21:43:08 -08:00
} ,
} ,
2020-12-08 00:45:51 +01:00
mutateAndGetPayload : async ( _args , context ) => {
2019-12-01 21:43:08 -08:00
try {
const { config , auth , info } = context ;
2019-08-17 11:02:19 -07:00
2019-12-01 21:43:08 -08:00
await usersRouter . handleLogOut ( {
config ,
auth ,
info ,
} ) ;
2019-08-17 11:02:19 -07:00
2020-12-08 00:45:51 +01:00
return { ok : true } ;
2019-12-01 21:43:08 -08:00
} catch ( e ) {
parseGraphQLSchema . handleError ( e ) ;
}
2019-06-19 17:19:47 -07:00
} ,
2019-12-01 21:43:08 -08:00
} ) ;
2020-12-08 00:45:51 +01:00
parseGraphQLSchema . addGraphQLType ( logOutMutation . args . input . type . ofType , true , true ) ;
2019-12-01 21:43:08 -08:00
parseGraphQLSchema . addGraphQLType ( logOutMutation . type , true , true ) ;
parseGraphQLSchema . addGraphQLMutation ( 'logOut' , logOutMutation , true , true ) ;
2020-01-04 21:50:00 +01:00
const resetPasswordMutation = mutationWithClientMutationId ( {
name : 'ResetPassword' ,
description :
'The resetPassword mutation can be used to reset the password of an existing user.' ,
inputFields : {
email : {
descriptions : 'Email of the user that should receive the reset email' ,
type : new GraphQLNonNull ( GraphQLString ) ,
} ,
} ,
outputFields : {
ok : {
description : "It's always true." ,
type : new GraphQLNonNull ( GraphQLBoolean ) ,
} ,
} ,
mutateAndGetPayload : async ( { email } , context ) => {
const { config , auth , info } = context ;
await usersRouter . handleResetRequest ( {
body : {
email ,
} ,
config ,
auth ,
info ,
} ) ;
return { ok : true } ;
} ,
} ) ;
2020-12-08 00:45:51 +01:00
parseGraphQLSchema . addGraphQLType ( resetPasswordMutation . args . input . type . ofType , true , true ) ;
2020-01-04 21:50:00 +01:00
parseGraphQLSchema . addGraphQLType ( resetPasswordMutation . type , true , true ) ;
2020-12-08 00:45:51 +01:00
parseGraphQLSchema . addGraphQLMutation ( 'resetPassword' , resetPasswordMutation , true , true ) ;
2020-01-04 21:50:00 +01:00
2021-03-29 10:15:41 +05:30
const confirmResetPasswordMutation = mutationWithClientMutationId ( {
name : 'ConfirmResetPassword' ,
description :
'The confirmResetPassword mutation can be used to reset the password of an existing user.' ,
inputFields : {
username : {
descriptions : 'Username of the user that have received the reset email' ,
type : new GraphQLNonNull ( GraphQLString ) ,
} ,
password : {
descriptions : 'New password of the user' ,
type : new GraphQLNonNull ( GraphQLString ) ,
} ,
token : {
descriptions : 'Reset token that was emailed to the user' ,
type : new GraphQLNonNull ( GraphQLString ) ,
} ,
} ,
outputFields : {
ok : {
description : "It's always true." ,
type : new GraphQLNonNull ( GraphQLBoolean ) ,
} ,
} ,
mutateAndGetPayload : async ( { username , password , token } , context ) => {
const { config } = context ;
if ( ! username ) {
throw new Parse . Error ( Parse . Error . USERNAME _MISSING , 'you must provide a username' ) ;
}
if ( ! password ) {
throw new Parse . Error ( Parse . Error . PASSWORD _MISSING , 'you must provide a password' ) ;
}
if ( ! token ) {
throw new Parse . Error ( Parse . Error . OTHER _CAUSE , 'you must provide a token' ) ;
}
const userController = config . userController ;
await userController . updatePassword ( username , token , password ) ;
return { ok : true } ;
} ,
} ) ;
parseGraphQLSchema . addGraphQLType (
confirmResetPasswordMutation . args . input . type . ofType ,
true ,
true
) ;
parseGraphQLSchema . addGraphQLType ( confirmResetPasswordMutation . type , true , true ) ;
parseGraphQLSchema . addGraphQLMutation (
'confirmResetPassword' ,
confirmResetPasswordMutation ,
true ,
true
) ;
2020-01-04 21:50:00 +01:00
const sendVerificationEmailMutation = mutationWithClientMutationId ( {
name : 'SendVerificationEmail' ,
description :
'The sendVerificationEmail mutation can be used to send the verification email again.' ,
inputFields : {
email : {
2020-12-08 00:45:51 +01:00
descriptions : 'Email of the user that should receive the verification email' ,
2020-01-04 21:50:00 +01:00
type : new GraphQLNonNull ( GraphQLString ) ,
} ,
} ,
outputFields : {
ok : {
description : "It's always true." ,
type : new GraphQLNonNull ( GraphQLBoolean ) ,
} ,
} ,
mutateAndGetPayload : async ( { email } , context ) => {
try {
const { config , auth , info } = context ;
await usersRouter . handleVerificationEmailRequest ( {
body : {
email ,
} ,
config ,
auth ,
info ,
} ) ;
return { ok : true } ;
} catch ( e ) {
parseGraphQLSchema . handleError ( e ) ;
}
} ,
} ) ;
parseGraphQLSchema . addGraphQLType (
sendVerificationEmailMutation . args . input . type . ofType ,
true ,
true
) ;
2020-12-08 00:45:51 +01:00
parseGraphQLSchema . addGraphQLType ( sendVerificationEmailMutation . type , true , true ) ;
2020-01-04 21:50:00 +01:00
parseGraphQLSchema . addGraphQLMutation (
'sendVerificationEmail' ,
sendVerificationEmailMutation ,
true ,
true
) ;
2019-06-19 17:19:47 -07:00
} ;
export { load } ;