Sanitizes RestWrite.data before passing to inflated object
This commit is contained in:
@@ -905,7 +905,7 @@ describe('Parse.User testing', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
var getMockMyOauthProvider = function() {
|
var getMockMyOauthProvider = function() {
|
||||||
return {
|
return {
|
||||||
authData: {
|
authData: {
|
||||||
@@ -1329,7 +1329,7 @@ describe('Parse.User testing', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("link multiple providers", (done) => {
|
it("link multiple providers", (done) => {
|
||||||
var provider = getMockFacebookProvider();
|
var provider = getMockFacebookProvider();
|
||||||
var mockProvider = getMockMyOauthProvider();
|
var mockProvider = getMockMyOauthProvider();
|
||||||
@@ -1351,7 +1351,7 @@ describe('Parse.User testing', () => {
|
|||||||
ok(model._isLinked("facebook"), "User should be linked to facebook");
|
ok(model._isLinked("facebook"), "User should be linked to facebook");
|
||||||
ok(model._isLinked("myoauth"), "User should be linked to myoauth");
|
ok(model._isLinked("myoauth"), "User should be linked to myoauth");
|
||||||
done();
|
done();
|
||||||
},
|
},
|
||||||
error: function(error) {
|
error: function(error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
fail('SHould not fail');
|
fail('SHould not fail');
|
||||||
@@ -1437,9 +1437,9 @@ describe('Parse.User testing', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have authData in beforeSave and afterSave', (done) => {
|
it('should have authData in beforeSave and afterSave', (done) => {
|
||||||
|
|
||||||
Parse.Cloud.beforeSave('_User', (request, response) => {
|
Parse.Cloud.beforeSave('_User', (request, response) => {
|
||||||
let authData = request.object.get('authData');
|
let authData = request.object.get('authData');
|
||||||
expect(authData).not.toBeUndefined();
|
expect(authData).not.toBeUndefined();
|
||||||
@@ -1451,7 +1451,7 @@ describe('Parse.User testing', () => {
|
|||||||
}
|
}
|
||||||
response.success();
|
response.success();
|
||||||
});
|
});
|
||||||
|
|
||||||
Parse.Cloud.afterSave('_User', (request, response) => {
|
Parse.Cloud.afterSave('_User', (request, response) => {
|
||||||
let authData = request.object.get('authData');
|
let authData = request.object.get('authData');
|
||||||
expect(authData).not.toBeUndefined();
|
expect(authData).not.toBeUndefined();
|
||||||
@@ -1463,7 +1463,7 @@ describe('Parse.User testing', () => {
|
|||||||
}
|
}
|
||||||
response.success();
|
response.success();
|
||||||
});
|
});
|
||||||
|
|
||||||
var provider = getMockFacebookProvider();
|
var provider = getMockFacebookProvider();
|
||||||
Parse.User._registerAuthenticationProvider(provider);
|
Parse.User._registerAuthenticationProvider(provider);
|
||||||
Parse.User._logInWith("facebook", {
|
Parse.User._logInWith("facebook", {
|
||||||
@@ -1970,9 +1970,9 @@ describe('Parse.User testing', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sometimes the authData still has null on that keys
|
// Sometimes the authData still has null on that keys
|
||||||
// https://github.com/ParsePlatform/parse-server/issues/935
|
// https://github.com/ParsePlatform/parse-server/issues/935
|
||||||
it('should cleanup null authData keys', (done) => {
|
it('should cleanup null authData keys', (done) => {
|
||||||
let database = new Config(Parse.applicationId).database;
|
let database = new Config(Parse.applicationId).database;
|
||||||
database.create('_User', {
|
database.create('_User', {
|
||||||
@@ -2003,8 +2003,26 @@ describe('Parse.User testing', () => {
|
|||||||
done();
|
done();
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
fail('this should not fail');
|
fail('this should not fail');
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
|
it('should aftersave with full object', (done) => {
|
||||||
|
var hit = 0;
|
||||||
|
Parse.Cloud.afterSave('_User', (req, res) => {
|
||||||
|
hit++;
|
||||||
|
expect(req.object.get('username')).toEqual('User');
|
||||||
|
res.success();
|
||||||
|
});
|
||||||
|
let user = new Parse.User()
|
||||||
|
user.setUsername('User');
|
||||||
|
user.setPassword('pass');
|
||||||
|
user.signUp().then(()=> {
|
||||||
|
user.set('hello', 'world');
|
||||||
|
return user.save();
|
||||||
|
}).then(() => {
|
||||||
|
Parse.Cloud._removeHook('Triggers', 'afterSave', '_User');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ function RestWrite(config, auth, className, query, data, originalData) {
|
|||||||
throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'objectId ' +
|
throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'objectId ' +
|
||||||
'is an invalid field name.');
|
'is an invalid field name.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the operation is complete, this.response may have several
|
// When the operation is complete, this.response may have several
|
||||||
// fields.
|
// fields.
|
||||||
// response: the actual data to be returned
|
// response: the actual data to be returned
|
||||||
@@ -136,7 +136,7 @@ RestWrite.prototype.runBeforeTrigger = function() {
|
|||||||
if (this.response) {
|
if (this.response) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid doing any setup for triggers if there is no 'beforeSave' trigger for this class.
|
// Avoid doing any setup for triggers if there is no 'beforeSave' trigger for this class.
|
||||||
if (!triggers.triggerExists(this.className, triggers.Types.beforeSave, this.config.applicationId)) {
|
if (!triggers.triggerExists(this.className, triggers.Types.beforeSave, this.config.applicationId)) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
@@ -154,7 +154,7 @@ RestWrite.prototype.runBeforeTrigger = function() {
|
|||||||
// This is an update for existing object.
|
// This is an update for existing object.
|
||||||
originalObject = triggers.inflate(extraData, this.originalData);
|
originalObject = triggers.inflate(extraData, this.originalData);
|
||||||
}
|
}
|
||||||
updatedObject.set(Parse._decode(undefined, this.data));
|
updatedObject.set(this.sanitizedData());
|
||||||
|
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
return triggers.maybeRunTrigger(triggers.Types.beforeSave, this.auth, updatedObject, originalObject, this.config.applicationId);
|
return triggers.maybeRunTrigger(triggers.Types.beforeSave, this.auth, updatedObject, originalObject, this.config.applicationId);
|
||||||
@@ -254,14 +254,14 @@ RestWrite.prototype.findUsersWithAuthData = function(authData) {
|
|||||||
}, []).filter((q) => {
|
}, []).filter((q) => {
|
||||||
return typeof q !== undefined;
|
return typeof q !== undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
let findPromise = Promise.resolve([]);
|
let findPromise = Promise.resolve([]);
|
||||||
if (query.length > 0) {
|
if (query.length > 0) {
|
||||||
findPromise = this.config.database.find(
|
findPromise = this.config.database.find(
|
||||||
this.className,
|
this.className,
|
||||||
{'$or': query}, {})
|
{'$or': query}, {})
|
||||||
}
|
}
|
||||||
|
|
||||||
return findPromise;
|
return findPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,9 +276,9 @@ RestWrite.prototype.handleAuthData = function(authData) {
|
|||||||
throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED,
|
throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED,
|
||||||
'this auth is already used');
|
'this auth is already used');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.storage['authProvider'] = Object.keys(authData).join(',');
|
this.storage['authProvider'] = Object.keys(authData).join(',');
|
||||||
|
|
||||||
if (results.length == 0) {
|
if (results.length == 0) {
|
||||||
this.data.username = cryptoUtils.newToken();
|
this.data.username = cryptoUtils.newToken();
|
||||||
} else if (!this.query) {
|
} else if (!this.query) {
|
||||||
@@ -404,7 +404,7 @@ RestWrite.prototype.transformUser = function() {
|
|||||||
|
|
||||||
// Handles any followup logic
|
// Handles any followup logic
|
||||||
RestWrite.prototype.handleFollowup = function() {
|
RestWrite.prototype.handleFollowup = function() {
|
||||||
|
|
||||||
if (this.storage && this.storage['clearSessions']) {
|
if (this.storage && this.storage['clearSessions']) {
|
||||||
var sessionQuery = {
|
var sessionQuery = {
|
||||||
user: {
|
user: {
|
||||||
@@ -417,7 +417,7 @@ RestWrite.prototype.handleFollowup = function() {
|
|||||||
this.config.database.destroy('_Session', sessionQuery)
|
this.config.database.destroy('_Session', sessionQuery)
|
||||||
.then(this.handleFollowup.bind(this));
|
.then(this.handleFollowup.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.storage && this.storage['sendVerificationEmail']) {
|
if (this.storage && this.storage['sendVerificationEmail']) {
|
||||||
delete this.storage['sendVerificationEmail'];
|
delete this.storage['sendVerificationEmail'];
|
||||||
// Fire and forget!
|
// Fire and forget!
|
||||||
@@ -695,7 +695,7 @@ RestWrite.prototype.runDatabaseOperation = function() {
|
|||||||
throw new Parse.Error(Parse.Error.SESSION_MISSING,
|
throw new Parse.Error(Parse.Error.SESSION_MISSING,
|
||||||
'cannot modify user ' + this.query.objectId);
|
'cannot modify user ' + this.query.objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.className === '_Product' && this.data.download) {
|
if (this.className === '_Product' && this.data.download) {
|
||||||
this.data.downloadName = this.data.download.name;
|
this.data.downloadName = this.data.download.name;
|
||||||
}
|
}
|
||||||
@@ -722,7 +722,7 @@ RestWrite.prototype.runDatabaseOperation = function() {
|
|||||||
ACL[this.data.objectId] = { read: true, write: true };
|
ACL[this.data.objectId] = { read: true, write: true };
|
||||||
ACL['*'] = { read: true, write: false };
|
ACL['*'] = { read: true, write: false };
|
||||||
this.data.ACL = ACL;
|
this.data.ACL = ACL;
|
||||||
}
|
}
|
||||||
// Run a create
|
// Run a create
|
||||||
return this.config.database.create(this.className, this.data, this.runOptions)
|
return this.config.database.create(this.className, this.data, this.runOptions)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -770,7 +770,7 @@ RestWrite.prototype.runAfterTrigger = function() {
|
|||||||
// Build the inflated object, different from beforeSave, originalData is not empty
|
// Build the inflated object, different from beforeSave, originalData is not empty
|
||||||
// since developers can change data in the beforeSave.
|
// since developers can change data in the beforeSave.
|
||||||
let updatedObject = triggers.inflate(extraData, this.originalData);
|
let updatedObject = triggers.inflate(extraData, this.originalData);
|
||||||
updatedObject.set(Parse._decode(undefined, this.data));
|
updatedObject.set(this.sanitizedData());
|
||||||
updatedObject._handleSaveResponse(this.response.response, this.response.status || 200);
|
updatedObject._handleSaveResponse(this.response.response, this.response.status || 200);
|
||||||
|
|
||||||
triggers.maybeRunTrigger(triggers.Types.afterSave, this.auth, updatedObject, originalObject, this.config.applicationId);
|
triggers.maybeRunTrigger(triggers.Types.afterSave, this.auth, updatedObject, originalObject, this.config.applicationId);
|
||||||
@@ -789,5 +789,17 @@ RestWrite.prototype.objectId = function() {
|
|||||||
return this.data.objectId || this.query.objectId;
|
return this.data.objectId || this.query.objectId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Returns a copy of the data and delete bad keys (_auth_data, _hashed_password...)
|
||||||
|
RestWrite.prototype.sanitizedData = function() {
|
||||||
|
let data = Object.keys(this.data).reduce((data, key) => {
|
||||||
|
// Regexp comes from Parse.Object.prototype.validate
|
||||||
|
if (!(/^[A-Za-z][0-9A-Za-z_]*$/).test(key)) {
|
||||||
|
delete data[key];
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}, deepcopy(this.data));
|
||||||
|
return Parse._decode(undefined, data);
|
||||||
|
}
|
||||||
|
|
||||||
export default RestWrite;
|
export default RestWrite;
|
||||||
module.exports = RestWrite;
|
module.exports = RestWrite;
|
||||||
|
|||||||
Reference in New Issue
Block a user