Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
191 lines
6.9 KiB
Plaintext
191 lines
6.9 KiB
Plaintext
import { status as httpStatus } from 'http-status';
|
|
import { buildAfterOperation } from '../../collections/operations/utilities/buildAfterOperation.js';
|
|
import { buildBeforeOperation } from '../../collections/operations/utilities/buildBeforeOperation.js';
|
|
import { APIError, Forbidden } from '../../errors/index.js';
|
|
import { appendNonTrashedFilter } from '../../utilities/appendNonTrashedFilter.js';
|
|
import { commitTransaction } from '../../utilities/commitTransaction.js';
|
|
import { initTransaction } from '../../utilities/initTransaction.js';
|
|
import { killTransaction } from '../../utilities/killTransaction.js';
|
|
import { getFieldsToSign } from '../getFieldsToSign.js';
|
|
import { jwtSign } from '../jwt.js';
|
|
import { addSessionToUser, revokeSession } from '../sessions.js';
|
|
import { authenticateLocalStrategy } from '../strategies/local/authenticate.js';
|
|
import { generatePasswordSaltHash } from '../strategies/local/generatePasswordSaltHash.js';
|
|
export const resetPasswordOperation = async (args)=>{
|
|
const { collection: { config: collectionConfig }, data, depth, overrideAccess, req: { payload: { secret }, payload }, req } = args;
|
|
if (!Object.prototype.hasOwnProperty.call(data, 'token') || !Object.prototype.hasOwnProperty.call(data, 'password')) {
|
|
throw new APIError('Missing required data.', httpStatus.BAD_REQUEST);
|
|
}
|
|
if (collectionConfig.auth.disableLocalStrategy) {
|
|
throw new Forbidden(req.t);
|
|
}
|
|
let sid;
|
|
let user = null;
|
|
try {
|
|
const shouldCommit = await initTransaction(req);
|
|
args = await buildBeforeOperation({
|
|
args,
|
|
collection: args.collection.config,
|
|
operation: 'resetPassword',
|
|
overrideAccess
|
|
});
|
|
// /////////////////////////////////////
|
|
// Reset Password
|
|
// /////////////////////////////////////
|
|
const where = appendNonTrashedFilter({
|
|
enableTrash: Boolean(collectionConfig.trash),
|
|
trash: false,
|
|
where: {
|
|
resetPasswordExpiration: {
|
|
greater_than: new Date().toISOString()
|
|
},
|
|
resetPasswordToken: {
|
|
equals: data.token
|
|
}
|
|
}
|
|
});
|
|
user = await payload.db.findOne({
|
|
collection: collectionConfig.slug,
|
|
req,
|
|
where
|
|
});
|
|
if (!user) {
|
|
throw new APIError('Token is either invalid or has expired.', httpStatus.FORBIDDEN);
|
|
}
|
|
// TODO: replace this method
|
|
const { hash, salt } = await generatePasswordSaltHash({
|
|
collection: collectionConfig,
|
|
password: data.password,
|
|
req
|
|
});
|
|
user.salt = salt;
|
|
user.hash = hash;
|
|
user.resetPasswordExpiration = new Date().toISOString();
|
|
if (collectionConfig.auth.verify) {
|
|
user._verified = Boolean(user._verified);
|
|
}
|
|
// /////////////////////////////////////
|
|
// beforeValidate - Collection
|
|
// /////////////////////////////////////
|
|
if (collectionConfig.hooks?.beforeValidate?.length) {
|
|
for (const hook of collectionConfig.hooks.beforeValidate){
|
|
await hook({
|
|
collection: args.collection?.config,
|
|
context: req.context,
|
|
data: user,
|
|
operation: 'update',
|
|
req
|
|
});
|
|
}
|
|
}
|
|
// /////////////////////////////////////
|
|
// Update new password
|
|
// /////////////////////////////////////
|
|
// Ensure updatedAt date is always updated
|
|
user.updatedAt = new Date().toISOString();
|
|
const doc = await payload.db.updateOne({
|
|
id: user.id,
|
|
collection: collectionConfig.slug,
|
|
data: user,
|
|
req
|
|
});
|
|
await authenticateLocalStrategy({
|
|
doc,
|
|
password: data.password
|
|
});
|
|
const fieldsToSignArgs = {
|
|
collectionConfig,
|
|
email: user.email,
|
|
user
|
|
};
|
|
const session = await addSessionToUser({
|
|
collectionConfig,
|
|
payload,
|
|
req,
|
|
user
|
|
});
|
|
sid = session.sid;
|
|
if (sid) {
|
|
fieldsToSignArgs.sid = sid;
|
|
}
|
|
const fieldsToSign = getFieldsToSign(fieldsToSignArgs);
|
|
// /////////////////////////////////////
|
|
// beforeLogin - Collection
|
|
// /////////////////////////////////////
|
|
let userBeforeLogin = user;
|
|
if (collectionConfig.hooks?.beforeLogin?.length) {
|
|
for (const hook of collectionConfig.hooks.beforeLogin){
|
|
userBeforeLogin = await hook({
|
|
collection: args.collection?.config,
|
|
context: args.req.context,
|
|
req: args.req,
|
|
user: userBeforeLogin
|
|
}) || userBeforeLogin;
|
|
}
|
|
}
|
|
const { token } = await jwtSign({
|
|
fieldsToSign,
|
|
secret,
|
|
tokenExpiration: collectionConfig.auth.tokenExpiration
|
|
});
|
|
req.user = userBeforeLogin;
|
|
// /////////////////////////////////////
|
|
// afterLogin - Collection
|
|
// /////////////////////////////////////
|
|
if (collectionConfig.hooks?.afterLogin?.length) {
|
|
for (const hook of collectionConfig.hooks.afterLogin){
|
|
userBeforeLogin = await hook({
|
|
collection: args.collection?.config,
|
|
context: args.req.context,
|
|
req: args.req,
|
|
token,
|
|
user: userBeforeLogin
|
|
}) || userBeforeLogin;
|
|
}
|
|
}
|
|
const fullUser = await payload.findByID({
|
|
id: user.id,
|
|
collection: collectionConfig.slug,
|
|
depth,
|
|
overrideAccess,
|
|
req,
|
|
trash: false
|
|
});
|
|
if (shouldCommit) {
|
|
await commitTransaction(req);
|
|
}
|
|
if (fullUser) {
|
|
fullUser.collection = collectionConfig.slug;
|
|
fullUser._strategy = 'local-jwt';
|
|
}
|
|
let result = {
|
|
token,
|
|
user: fullUser
|
|
};
|
|
// /////////////////////////////////////
|
|
// afterOperation - Collection
|
|
// /////////////////////////////////////
|
|
result = await buildAfterOperation({
|
|
args,
|
|
collection: args.collection?.config,
|
|
operation: 'resetPassword',
|
|
overrideAccess,
|
|
result
|
|
});
|
|
return result;
|
|
} catch (error) {
|
|
if (sid) {
|
|
await revokeSession({
|
|
collectionConfig,
|
|
payload,
|
|
req,
|
|
sid,
|
|
user
|
|
});
|
|
}
|
|
await killTransaction(req);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
//# sourceMappingURL=resetPassword.js.map |