forked from canada-ca/tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreset-password.js
More file actions
143 lines (128 loc) · 4.42 KB
/
Copy pathreset-password.js
File metadata and controls
143 lines (128 loc) · 4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import { GraphQLNonNull, GraphQLString } from 'graphql'
import { mutationWithClientMutationId } from 'graphql-relay'
import { t } from '@lingui/macro'
import { resetPasswordUnion } from '../unions'
const { AUTHENTICATED_KEY } = process.env
export const resetPassword = new mutationWithClientMutationId({
name: 'ResetPassword',
description: 'This mutation allows the user to take the token they received in their email to reset their password.',
inputFields: () => ({
password: {
type: new GraphQLNonNull(GraphQLString),
description: 'The users new password.',
},
confirmPassword: {
type: new GraphQLNonNull(GraphQLString),
description: 'A confirmation password to confirm the new password.',
},
resetToken: {
type: new GraphQLNonNull(GraphQLString),
description: 'The JWT found in the url, redirected from the email they received.',
},
}),
outputFields: () => ({
result: {
type: resetPasswordUnion,
description: '`ResetPasswordUnion` returning either a `ResetPasswordResult`, or `ResetPasswordError` object.',
resolve: (payload) => payload,
},
}),
mutateAndGetPayload: async (
args,
{
i18n,
query,
collections,
transaction,
auth: { verifyToken, bcrypt },
loaders: { loadUserByKey },
validators: { cleanseInput },
},
) => {
// Cleanse input
const password = cleanseInput(args.password)
const confirmPassword = cleanseInput(args.confirmPassword)
const resetToken = cleanseInput(args.resetToken)
// Check if reset token is valid
const tokenParameters = verifyToken({ token: resetToken, secret: String(AUTHENTICATED_KEY) })
// Check to see if user id exists in token params !!!
if (tokenParameters.userKey === 'undefined' || typeof tokenParameters.userKey === 'undefined') {
console.warn(
`When resetting password user attempted to verify account, but userKey is not located in the token parameters.`,
)
return {
_type: 'error',
code: 400,
description: i18n._(t`Incorrect token value. Please request a new email.`),
}
}
// Check if user exists
const user = await loadUserByKey.load(tokenParameters.userKey)
// Replace with userRequired()
if (typeof user === 'undefined') {
console.warn(
`A user attempted to reset the password for ${tokenParameters.userKey}, however there is no associated account.`,
)
return {
_type: 'error',
code: 400,
description: i18n._(t`Unable to reset password. Please try again.`),
}
}
// Check to see if newly submitted passwords match
if (password !== confirmPassword) {
console.warn(
`User: ${user._key} attempted to reset their password, however the submitted passwords do not match.`,
)
return {
_type: 'error',
code: 400,
description: i18n._(t`New passwords do not match.`),
}
}
// Check to see if password meets GoC requirements
if (password.length < 12) {
console.warn(
`User: ${user._key} attempted to reset their password, however the submitted password is not long enough.`,
)
return {
_type: 'error',
code: 400,
description: i18n._(t`Password does not meet requirements.`),
}
}
// Update users password in db
const hashedPassword = bcrypt.hashSync(password, 10)
// Setup Transaction
const trx = await transaction(collections)
try {
await trx.step(
() => query`
WITH users
FOR user IN users
UPDATE ${user._key}
WITH {
password: ${hashedPassword},
failedLoginAttempts: 0
} IN users
`,
)
} catch (err) {
console.error(`Trx step error occurred when user: ${user._key} attempted to reset their password: ${err}`)
await trx.abort()
throw new Error(i18n._(t`Unable to reset password. Please try again.`))
}
try {
await trx.commit()
} catch (err) {
console.error(`Trx commit error occurred while user: ${user._key} attempted to authenticate: ${err}`)
await trx.abort()
throw new Error(i18n._(t`Unable to reset password. Please try again.`))
}
console.info(`User: ${user._key} successfully reset their password.`)
return {
_type: 'regular',
status: i18n._(t`Password was successfully reset.`),
}
},
})