Improve email verification (#3681)
* Removed hidden keys from users/me. * Ensured that general users cannot update email verified flag. * Updated tests to reflect email verification changes.
This commit is contained in:
committed by
Florent Vilmart
parent
81a55e655d
commit
877ef78b5e
@@ -2818,4 +2818,121 @@ describe('Parse.User testing', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not allow updates to emailVerified', done => {
|
||||||
|
var emailAdapter = {
|
||||||
|
sendVerificationEmail: () => {},
|
||||||
|
sendPasswordResetEmail: () => Promise.resolve(),
|
||||||
|
sendMail: () => Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = new Parse.User();
|
||||||
|
user.set({
|
||||||
|
username: 'hello',
|
||||||
|
password: 'world',
|
||||||
|
email: "test@email.com"
|
||||||
|
})
|
||||||
|
|
||||||
|
reconfigureServer({
|
||||||
|
appName: 'unused',
|
||||||
|
verifyUserEmails: true,
|
||||||
|
emailAdapter: emailAdapter,
|
||||||
|
publicServerURL: "http://localhost:8378/1"
|
||||||
|
}).then(() => {
|
||||||
|
return user.signUp();
|
||||||
|
}).then(() => {
|
||||||
|
return Parse.User.current().set('emailVerified', true).save();
|
||||||
|
}).then(() => {
|
||||||
|
fail("Should not be able to update emailVerified");
|
||||||
|
done();
|
||||||
|
}).catch((err) => {
|
||||||
|
expect(err.message).toBe("Clients aren't allowed to manually update email verification.");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not retrieve hidden fields', done => {
|
||||||
|
|
||||||
|
var emailAdapter = {
|
||||||
|
sendVerificationEmail: () => {},
|
||||||
|
sendPasswordResetEmail: () => Promise.resolve(),
|
||||||
|
sendMail: () => Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = new Parse.User();
|
||||||
|
user.set({
|
||||||
|
username: 'hello',
|
||||||
|
password: 'world',
|
||||||
|
email: "test@email.com"
|
||||||
|
})
|
||||||
|
|
||||||
|
reconfigureServer({
|
||||||
|
appName: 'unused',
|
||||||
|
verifyUserEmails: true,
|
||||||
|
emailAdapter: emailAdapter,
|
||||||
|
publicServerURL: "http://localhost:8378/1"
|
||||||
|
}).then(() => {
|
||||||
|
return user.signUp();
|
||||||
|
}).then(() => rp({
|
||||||
|
method: 'GET',
|
||||||
|
url: 'http://localhost:8378/1/users/me',
|
||||||
|
json: true,
|
||||||
|
headers: {
|
||||||
|
'X-Parse-Application-Id': Parse.applicationId,
|
||||||
|
'X-Parse-Session-Token': Parse.User.current().getSessionToken(),
|
||||||
|
'X-Parse-REST-API-Key': 'rest'
|
||||||
|
},
|
||||||
|
})).then((res) => {
|
||||||
|
expect(res.emailVerified).toBe(false);
|
||||||
|
expect(res._email_verify_token).toBeUndefined();
|
||||||
|
done()
|
||||||
|
}).then(() => rp({
|
||||||
|
method: 'GET',
|
||||||
|
url: 'http://localhost:8378/1/users/' + Parse.User.current().id,
|
||||||
|
json: true,
|
||||||
|
headers: {
|
||||||
|
'X-Parse-Application-Id': Parse.applicationId,
|
||||||
|
'X-Parse-REST-API-Key': 'rest'
|
||||||
|
},
|
||||||
|
})).then((res) => {
|
||||||
|
expect(res.emailVerified).toBe(false);
|
||||||
|
expect(res._email_verify_token).toBeUndefined();
|
||||||
|
done()
|
||||||
|
}).catch((err) => {
|
||||||
|
fail(JSON.stringify(err));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not allow updates to hidden fields', done => {
|
||||||
|
var emailAdapter = {
|
||||||
|
sendVerificationEmail: () => {},
|
||||||
|
sendPasswordResetEmail: () => Promise.resolve(),
|
||||||
|
sendMail: () => Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = new Parse.User();
|
||||||
|
user.set({
|
||||||
|
username: 'hello',
|
||||||
|
password: 'world',
|
||||||
|
email: "test@email.com"
|
||||||
|
})
|
||||||
|
|
||||||
|
reconfigureServer({
|
||||||
|
appName: 'unused',
|
||||||
|
verifyUserEmails: true,
|
||||||
|
emailAdapter: emailAdapter,
|
||||||
|
publicServerURL: "http://localhost:8378/1"
|
||||||
|
}).then(() => {
|
||||||
|
return user.signUp();
|
||||||
|
}).then(() => {
|
||||||
|
return Parse.User.current().set('_email_verify_token', 'bad').save();
|
||||||
|
}).then(() => {
|
||||||
|
fail("Should not be able to update email verification token");
|
||||||
|
done();
|
||||||
|
}).catch((err) => {
|
||||||
|
expect(err).toBeDefined();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -349,6 +349,11 @@ RestWrite.prototype.transformUser = function() {
|
|||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!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);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.query) {
|
if (this.query) {
|
||||||
// If we're updating a _User object, we need to clear out the cache for that user. Find all their
|
// If we're updating a _User object, we need to clear out the cache for that user. Find all their
|
||||||
// session tokens, and remove them from the cache.
|
// session tokens, and remove them from the cache.
|
||||||
|
|||||||
@@ -57,6 +57,17 @@ export class UsersRouter extends ClassesRouter {
|
|||||||
const user = response.results[0].user;
|
const user = response.results[0].user;
|
||||||
// Send token back on the login, because SDKs expect that.
|
// Send token back on the login, because SDKs expect that.
|
||||||
user.sessionToken = sessionToken;
|
user.sessionToken = sessionToken;
|
||||||
|
|
||||||
|
// Remove hidden properties.
|
||||||
|
for (var key in user) {
|
||||||
|
if (user.hasOwnProperty(key)) {
|
||||||
|
// Regexp comes from Parse.Object.prototype.validate
|
||||||
|
if (key !== "__type" && !(/^[A-Za-z][0-9A-Za-z_]*$/).test(key)) {
|
||||||
|
delete user[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return { response: user };
|
return { response: user };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user