adds update, adds way to disable email within forgotPassword operation

This commit is contained in:
James
2020-08-14 10:04:48 -04:00
parent 6c881e3c48
commit b53dbc1a27
14 changed files with 87 additions and 21 deletions

View File

@@ -2,8 +2,9 @@ function forgotPassword(collection) {
async function resolver(_, args, context) {
const options = {
collection,
data: args,
data: { email: args.email },
req: context.req,
disableEmail: args.disableEmail,
};
await this.operations.collections.auth.forgotPassword(options);

View File

@@ -29,6 +29,7 @@ async function forgotPassword(args) {
Model,
},
data,
disableEmail,
} = options;
let token = await crypto.randomBytes(20);
@@ -43,19 +44,21 @@ async function forgotPassword(args) {
await user.save();
const html = `You are receiving this because you (or someone else) have requested the reset of the password for your account.
Please click on the following link, or paste this into your browser to complete the process:
<a href="${config.serverURL}${config.routes.admin}/reset/${token}">
${config.serverURL}${config.routes.admin}/reset/${token}
</a>
If you did not request this, please ignore this email and your password will remain unchanged.`;
if (!disableEmail) {
const html = `You are receiving this because you (or someone else) have requested the reset of the password for your account.
Please click on the following link, or paste this into your browser to complete the process:
<a href="${config.serverURL}${config.routes.admin}/reset/${token}">
${config.serverURL}${config.routes.admin}/reset/${token}
</a>
If you did not request this, please ignore this email and your password will remain unchanged.`;
email({
from: `"${config.email.fromName}" <${config.email.fromAddress}>`,
to: data.email,
subject: 'Password Reset',
html,
});
email({
from: `"${config.email.fromName}" <${config.email.fromAddress}>`,
to: data.email,
subject: 'Password Reset',
html,
});
}
// /////////////////////////////////////
// 3. Execute after forgot password hook

View File

@@ -118,6 +118,8 @@ async function register(args) {
// /////////////////////////////////////
// 8. Return user
// /////////////////////////////////////
result = JSON.stringify(result);
result = JSON.parse(result);
return result;
}

View File

@@ -48,7 +48,10 @@ async function update(args) {
user.setLocale(locale, fallbackLocale);
}
const originalDoc = user.toJSON({ virtuals: true });
let originalDoc = user.toJSON({ virtuals: true });
originalDoc = JSON.stringify(originalDoc);
originalDoc = JSON.parse(originalDoc);
let { data } = args;
@@ -153,6 +156,8 @@ async function update(args) {
// /////////////////////////////////////
// 11. Return user
// /////////////////////////////////////
user = JSON.stringify(user);
user = JSON.parse(user);
return user;
}

View File

@@ -5,7 +5,8 @@ async function forgotPasswordHandler(req, res, next) {
await this.operations.collections.auth.forgotPassword({
req,
collection: req.collection,
data: req.body,
data: { email: req.body.email },
disableEmail: req.body.disableEmail,
});
return res.status(httpStatus.OK)

View File

@@ -215,6 +215,7 @@ function registerCollections() {
type: new GraphQLNonNull(GraphQLBoolean),
args: {
email: { type: new GraphQLNonNull(GraphQLString) },
disableEmail: { type: GraphQLBoolean },
},
resolve: forgotPassword(collection),
};

View File

@@ -162,6 +162,9 @@ async function create(args) {
// 9. Return results
// /////////////////////////////////////
result = JSON.stringify(result);
result = JSON.parse(result);
return result;
}

View File

@@ -134,6 +134,9 @@ async function find(args) {
// 7. Return results
// /////////////////////////////////////
afterReadResult = JSON.stringify(afterReadResult);
afterReadResult = JSON.parse(afterReadResult);
return afterReadResult;
}

View File

@@ -107,6 +107,9 @@ async function findByID(args) {
// 6. Return results
// /////////////////////////////////////
result = JSON.stringify(result);
result = JSON.parse(result);
return result;
}

View File

@@ -0,0 +1,26 @@
async function update(options) {
const {
collection: collectionSlug,
depth,
locale,
fallbackLocale,
data,
} = options;
const collection = this.collections[collectionSlug];
return this.operations.collections.update({
depth,
data,
collection,
overrideAccess: true,
req: {
payloadAPI: 'local',
locale,
fallbackLocale,
payload: this,
},
});
}
module.exports = update;

View File

@@ -62,7 +62,10 @@ async function update(args) {
doc.setLocale(locale, fallbackLocale);
}
const originalDoc = doc.toJSON({ virtuals: true });
let originalDoc = doc.toJSON({ virtuals: true });
originalDoc = JSON.stringify(originalDoc);
originalDoc = JSON.parse(originalDoc);
let { data } = args;
@@ -199,6 +202,9 @@ async function update(args) {
// 11. Return updated document
// /////////////////////////////////////
doc = JSON.stringify(doc);
doc = JSON.parse(doc);
return doc;
}

View File

@@ -91,15 +91,20 @@ const optionsToValidatorMap = {
return true;
},
richText: (value) => {
richText: (value, options) => {
//! Need better way to share an empty text node
//! it is used here and in field-types/RichText
const emptyRichTextNode = [{
children: [{ text: '' }],
}];
const blankSlateJSNode = JSON.stringify(emptyRichTextNode);
if (value && JSON.stringify(value) !== blankSlateJSNode) return true;
return 'This field is required.';
if (options.required) {
const blankSlateJSNode = JSON.stringify(emptyRichTextNode);
if (value && JSON.stringify(value) !== blankSlateJSNode) return true;
return 'This field is required.';
}
return true;
},
checkbox: (value, options = {}) => {
if ((value && typeof value !== 'boolean')

View File

@@ -96,6 +96,7 @@ class Payload {
this.create = this.create.bind(this);
this.find = this.find.bind(this);
this.findByID = this.findByID.bind(this);
this.update = this.update.bind(this);
this.register = this.register.bind(this);
this.login = this.login.bind(this);
this.forgotPassword = this.forgotPassword.bind(this);
@@ -133,6 +134,12 @@ class Payload {
return findByID(options);
}
async update(options) {
let { update } = localOperations;
update = update.bind(this);
return update(options);
}
async register(options) {
let { register } = localOperations.auth;
register = register.bind(this);

View File

@@ -1,5 +1,5 @@
const globalTeardown = async () => {
const serverClosePromise = new Promise(resolve => global.PAYLOAD_SERVER.close(resolve));
const serverClosePromise = new Promise((resolve) => global.PAYLOAD_SERVER.close(resolve));
await serverClosePromise;
};