Merge pull request #684 from Marco129/client-class-creation
Add allowClientClassCreation option
This commit is contained in:
@@ -73,6 +73,20 @@ describe('rest create', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('handles create on non-existent class when disabled client class creation', (done) => {
|
||||||
|
var customConfig = Object.assign({}, config, {allowClientClassCreation: false});
|
||||||
|
rest.create(customConfig, auth.nobody(customConfig), 'ClientClassCreation', {})
|
||||||
|
.then(() => {
|
||||||
|
fail('Should throw an error');
|
||||||
|
done();
|
||||||
|
}, (err) => {
|
||||||
|
expect(err.code).toEqual(Parse.Error.OPERATION_FORBIDDEN);
|
||||||
|
expect(err.message).toEqual('This user is not allowed to access ' +
|
||||||
|
'non-existent class: ClientClassCreation');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('handles user signup', (done) => {
|
it('handles user signup', (done) => {
|
||||||
var user = {
|
var user = {
|
||||||
username: 'asdf',
|
username: 'asdf',
|
||||||
|
|||||||
@@ -95,6 +95,20 @@ describe('rest query', () => {
|
|||||||
}).catch((error) => { console.log(error); });
|
}).catch((error) => { console.log(error); });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('query non-existent class when disabled client class creation', (done) => {
|
||||||
|
var customConfig = Object.assign({}, config, {allowClientClassCreation: false});
|
||||||
|
rest.find(customConfig, auth.nobody(customConfig), 'ClientClassCreation', {})
|
||||||
|
.then(() => {
|
||||||
|
fail('Should throw an error');
|
||||||
|
done();
|
||||||
|
}, (err) => {
|
||||||
|
expect(err.code).toEqual(Parse.Error.OPERATION_FORBIDDEN);
|
||||||
|
expect(err.message).toEqual('This user is not allowed to access ' +
|
||||||
|
'non-existent class: ClientClassCreation');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('query with wrongly encoded parameter', (done) => {
|
it('query with wrongly encoded parameter', (done) => {
|
||||||
rest.create(config, nobody, 'TestParameterEncode', {foo: 'bar'}
|
rest.create(config, nobody, 'TestParameterEncode', {foo: 'bar'}
|
||||||
).then(() => {
|
).then(() => {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export class Config {
|
|||||||
this.fileKey = cacheInfo.fileKey;
|
this.fileKey = cacheInfo.fileKey;
|
||||||
this.facebookAppIds = cacheInfo.facebookAppIds;
|
this.facebookAppIds = cacheInfo.facebookAppIds;
|
||||||
this.enableAnonymousUsers = cacheInfo.enableAnonymousUsers;
|
this.enableAnonymousUsers = cacheInfo.enableAnonymousUsers;
|
||||||
|
this.allowClientClassCreation = cacheInfo.allowClientClassCreation;
|
||||||
this.database = DatabaseAdapter.getDatabaseConnection(applicationId);
|
this.database = DatabaseAdapter.getDatabaseConnection(applicationId);
|
||||||
this.hooksController = cacheInfo.hooksController;
|
this.hooksController = cacheInfo.hooksController;
|
||||||
this.filesController = cacheInfo.filesController;
|
this.filesController = cacheInfo.filesController;
|
||||||
|
|||||||
@@ -115,6 +115,8 @@ RestQuery.prototype.execute = function() {
|
|||||||
return this.getUserAndRoleACL();
|
return this.getUserAndRoleACL();
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return this.redirectClassNameForKey();
|
return this.redirectClassNameForKey();
|
||||||
|
}).then(() => {
|
||||||
|
return this.validateClientClassCreation();
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return this.replaceSelect();
|
return this.replaceSelect();
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
@@ -161,6 +163,25 @@ RestQuery.prototype.redirectClassNameForKey = function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Validates this operation against the allowClientClassCreation config.
|
||||||
|
RestQuery.prototype.validateClientClassCreation = function() {
|
||||||
|
if (this.config.allowClientClassCreation === false && !this.auth.isMaster) {
|
||||||
|
return this.config.database.loadSchema().then((schema) => {
|
||||||
|
return schema.hasClass(this.className)
|
||||||
|
}).then((hasClass) => {
|
||||||
|
if (hasClass === true) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN,
|
||||||
|
'This user is not allowed to access ' +
|
||||||
|
'non-existent class: ' + this.className);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Replaces a $inQuery clause by running the subquery, if there is an
|
// Replaces a $inQuery clause by running the subquery, if there is an
|
||||||
// $inQuery clause.
|
// $inQuery clause.
|
||||||
// The $inQuery clause turns into an $in with values that are just
|
// The $inQuery clause turns into an $in with values that are just
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ function RestWrite(config, auth, className, query, data, originalData) {
|
|||||||
RestWrite.prototype.execute = function() {
|
RestWrite.prototype.execute = function() {
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
return this.getUserAndRoleACL();
|
return this.getUserAndRoleACL();
|
||||||
|
}).then(() => {
|
||||||
|
return this.validateClientClassCreation();
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return this.validateSchema();
|
return this.validateSchema();
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
@@ -105,6 +107,25 @@ RestWrite.prototype.getUserAndRoleACL = function() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Validates this operation against the allowClientClassCreation config.
|
||||||
|
RestWrite.prototype.validateClientClassCreation = function() {
|
||||||
|
if (this.config.allowClientClassCreation === false && !this.auth.isMaster) {
|
||||||
|
return this.config.database.loadSchema().then((schema) => {
|
||||||
|
return schema.hasClass(this.className)
|
||||||
|
}).then((hasClass) => {
|
||||||
|
if (hasClass === true) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN,
|
||||||
|
'This user is not allowed to access ' +
|
||||||
|
'non-existent class: ' + this.className);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Validates this operation against the schema.
|
// Validates this operation against the schema.
|
||||||
RestWrite.prototype.validateSchema = function() {
|
RestWrite.prototype.validateSchema = function() {
|
||||||
return this.config.database.validateObject(this.className, this.data, this.query);
|
return this.config.database.validateObject(this.className, this.data, this.query);
|
||||||
|
|||||||
@@ -85,6 +85,16 @@ export default {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"allowClientClassCreation": {
|
||||||
|
env: "PARSE_SERVER_ALLOW_CLIENT_CLASS_CREATION",
|
||||||
|
help: "Enable (or disable) client class creation, defaults to true",
|
||||||
|
action: function(opt) {
|
||||||
|
if (opt == "true" || opt == "1") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
"mountPath": {
|
"mountPath": {
|
||||||
env: "PARSE_SERVER_MOUNT_PATH",
|
env: "PARSE_SERVER_MOUNT_PATH",
|
||||||
help: "Mount path for the server, defaults to /parse",
|
help: "Mount path for the server, defaults to /parse",
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ function ParseServer({
|
|||||||
fileKey = 'invalid-file-key',
|
fileKey = 'invalid-file-key',
|
||||||
facebookAppIds = [],
|
facebookAppIds = [],
|
||||||
enableAnonymousUsers = true,
|
enableAnonymousUsers = true,
|
||||||
|
allowClientClassCreation = true,
|
||||||
oauth = {},
|
oauth = {},
|
||||||
serverURL = requiredParameter('You must provide a serverURL!'),
|
serverURL = requiredParameter('You must provide a serverURL!'),
|
||||||
maxUploadSize = '20mb'
|
maxUploadSize = '20mb'
|
||||||
@@ -139,6 +140,7 @@ function ParseServer({
|
|||||||
loggerController: loggerController,
|
loggerController: loggerController,
|
||||||
hooksController: hooksController,
|
hooksController: hooksController,
|
||||||
enableAnonymousUsers: enableAnonymousUsers,
|
enableAnonymousUsers: enableAnonymousUsers,
|
||||||
|
allowClientClassCreation: allowClientClassCreation,
|
||||||
oauth: oauth,
|
oauth: oauth,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user