feat: Add conditional email verification via dynamic Parse Server options verifyUserEmails, sendUserEmailVerification that now accept functions (#8425)

This commit is contained in:
Daniel
2023-06-20 20:10:25 +10:00
committed by GitHub
parent 3710da7379
commit 44acd6d9ed
11 changed files with 341 additions and 82 deletions

View File

@@ -113,6 +113,9 @@ RestWrite.prototype.execute = function () {
.then(() => {
return this.validateAuthData();
})
.then(() => {
return this.checkRestrictedFields();
})
.then(() => {
return this.runBeforeSaveTrigger();
})
@@ -603,17 +606,23 @@ RestWrite.prototype.handleAuthData = async function (authData) {
}
};
// The non-third-party parts of User transformation
RestWrite.prototype.transformUser = function () {
var promise = Promise.resolve();
RestWrite.prototype.checkRestrictedFields = async function () {
if (this.className !== '_User') {
return promise;
return;
}
if (!this.auth.isMaintenance && !this.auth.isMaster && 'emailVerified' in this.data) {
const error = `Clients aren't allowed to manually update email verification.`;
throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error);
}
};
// The non-third-party parts of User transformation
RestWrite.prototype.transformUser = function () {
var promise = Promise.resolve();
if (this.className !== '_User') {
return promise;
}
// Do not cleanup session if objectId is not set
if (this.query && this.objectId()) {
@@ -751,8 +760,14 @@ RestWrite.prototype._validateEmail = function () {
Object.keys(this.data.authData)[0] === 'anonymous')
) {
// We updated the email, send a new validation
this.storage['sendVerificationEmail'] = true;
this.config.userController.setEmailVerifyToken(this.data);
const { originalObject, updatedObject } = this.buildParseObjects();
const request = {
original: originalObject,
object: updatedObject,
master: this.auth.isMaster,
ip: this.config.ip,
};
return this.config.userController.setEmailVerifyToken(this.data, request, this.storage);
}
});
};
@@ -864,7 +879,7 @@ RestWrite.prototype._validatePasswordHistory = function () {
return Promise.resolve();
};
RestWrite.prototype.createSessionTokenIfNeeded = function () {
RestWrite.prototype.createSessionTokenIfNeeded = async function () {
if (this.className !== '_User') {
return;
}
@@ -878,13 +893,31 @@ RestWrite.prototype.createSessionTokenIfNeeded = function () {
}
if (
!this.storage.authProvider && // signup call, with
this.config.preventLoginWithUnverifiedEmail && // no login without verification
this.config.preventLoginWithUnverifiedEmail === true && // no login without verification
this.config.verifyUserEmails
) {
// verification is on
this.storage.rejectSignup = true;
return;
}
if (!this.storage.authProvider && this.config.verifyUserEmails) {
let shouldPreventUnverifedLogin = this.config.preventLoginWithUnverifiedEmail;
if (typeof this.config.preventLoginWithUnverifiedEmail === 'function') {
const { originalObject, updatedObject } = this.buildParseObjects();
const request = {
original: originalObject,
object: updatedObject,
master: this.auth.isMaster,
ip: this.config.ip,
};
shouldPreventUnverifedLogin = await Promise.resolve(
this.config.preventLoginWithUnverifiedEmail(request)
);
}
if (shouldPreventUnverifedLogin === true) {
return;
}
}
return this.createSessionToken();
};
@@ -1010,7 +1043,7 @@ RestWrite.prototype.handleFollowup = function () {
if (this.storage && this.storage['sendVerificationEmail']) {
delete this.storage['sendVerificationEmail'];
// Fire and forget!
this.config.userController.sendVerificationEmail(this.data);
this.config.userController.sendVerificationEmail(this.data, { auth: this.auth });
return this.handleFollowup.bind(this);
}
};