Allow accessType per remote method

This commit is contained in:
Raymond Feng 2014-12-12 08:50:17 -08:00
parent 1fec88fbb9
commit 16210e0f79
2 changed files with 52 additions and 1 deletions

View File

@ -314,6 +314,25 @@ Model._getAccessTypeForMethod = function(method) {
var ACL = Model._ACL(); var ACL = Model._ACL();
// Check the explicit setting of accessType
if (method.accessType) {
assert(method.accessType === ACL.READ ||
method.accessType === ACL.WRITE ||
method.accessType === ACL.EXECUTE, 'invalid accessType ' +
method.accessType +
'. It must be "READ", "WRITE", or "EXECUTE"');
return method.accessType;
}
// Default GET requests to READ
var verb = method.http && method.http.verb;
if (typeof verb === 'string') {
verb = verb.toUpperCase();
}
if (verb === 'GET' || verb === 'HEAD') {
return ACL.READ;
}
switch (method.name) { switch (method.name) {
case'create': case'create':
return ACL.WRITE; return ACL.WRITE;
@ -406,6 +425,7 @@ Model.belongsToRemoting = function(relationName, relation, define) {
isStatic: false, isStatic: false,
http: {verb: 'get', path: '/' + pathName}, http: {verb: 'get', path: '/' + pathName},
accepts: {arg: 'refresh', type: 'boolean', http: {source: 'query'}}, accepts: {arg: 'refresh', type: 'boolean', http: {source: 'query'}},
accessType: 'READ',
description: 'Fetches belongsTo relation ' + relationName, description: 'Fetches belongsTo relation ' + relationName,
returns: {arg: relationName, type: modelName, root: true} returns: {arg: relationName, type: modelName, root: true}
}, fn); }, fn);
@ -419,6 +439,7 @@ Model.hasOneRemoting = function(relationName, relation, define) {
http: {verb: 'get', path: '/' + pathName}, http: {verb: 'get', path: '/' + pathName},
accepts: {arg: 'refresh', type: 'boolean', http: {source: 'query'}}, accepts: {arg: 'refresh', type: 'boolean', http: {source: 'query'}},
description: 'Fetches hasOne relation ' + relationName, description: 'Fetches hasOne relation ' + relationName,
accessType: 'READ',
returns: {arg: relationName, type: relation.modelTo.modelName, root: true} returns: {arg: relationName, type: relation.modelTo.modelName, root: true}
}, fn); }, fn);
}; };
@ -445,6 +466,7 @@ Model.hasManyRemoting = function(relationName, relation, define) {
description: 'Foreign key for ' + relationName, required: true, description: 'Foreign key for ' + relationName, required: true,
http: {source: 'path'}}, http: {source: 'path'}},
description: 'Find a related item by id for ' + relationName, description: 'Find a related item by id for ' + relationName,
accessType: 'READ',
returns: {arg: 'result', type: toModelName, root: true}, returns: {arg: 'result', type: toModelName, root: true},
rest: {after: convertNullToNotFoundError} rest: {after: convertNullToNotFoundError}
}, findByIdFunc); }, findByIdFunc);
@ -457,6 +479,7 @@ Model.hasManyRemoting = function(relationName, relation, define) {
description: 'Foreign key for ' + relationName, required: true, description: 'Foreign key for ' + relationName, required: true,
http: {source: 'path'}}, http: {source: 'path'}},
description: 'Delete a related item by id for ' + relationName, description: 'Delete a related item by id for ' + relationName,
accessType: 'WRITE',
returns: [] returns: []
}, destroyByIdFunc); }, destroyByIdFunc);
@ -471,6 +494,7 @@ Model.hasManyRemoting = function(relationName, relation, define) {
{arg: 'data', type: toModelName, http: {source: 'body'}} {arg: 'data', type: toModelName, http: {source: 'body'}}
], ],
description: 'Update a related item by id for ' + relationName, description: 'Update a related item by id for ' + relationName,
accessType: 'WRITE',
returns: {arg: 'result', type: toModelName, root: true} returns: {arg: 'result', type: toModelName, root: true}
}, updateByIdFunc); }, updateByIdFunc);
@ -491,6 +515,7 @@ Model.hasManyRemoting = function(relationName, relation, define) {
description: 'Foreign key for ' + relationName, required: true, description: 'Foreign key for ' + relationName, required: true,
http: {source: 'path'}}].concat(accepts), http: {source: 'path'}}].concat(accepts),
description: 'Add a related item by id for ' + relationName, description: 'Add a related item by id for ' + relationName,
accessType: 'WRITE',
returns: {arg: relationName, type: modelThrough.modelName, root: true} returns: {arg: relationName, type: modelThrough.modelName, root: true}
}, addFunc); }, addFunc);
@ -502,6 +527,7 @@ Model.hasManyRemoting = function(relationName, relation, define) {
description: 'Foreign key for ' + relationName, required: true, description: 'Foreign key for ' + relationName, required: true,
http: {source: 'path'}}, http: {source: 'path'}},
description: 'Remove the ' + relationName + ' relation to an item by id', description: 'Remove the ' + relationName + ' relation to an item by id',
accessType: 'WRITE',
returns: [] returns: []
}, removeFunc); }, removeFunc);
@ -515,6 +541,7 @@ Model.hasManyRemoting = function(relationName, relation, define) {
description: 'Foreign key for ' + relationName, required: true, description: 'Foreign key for ' + relationName, required: true,
http: {source: 'path'}}, http: {source: 'path'}},
description: 'Check the existence of ' + relationName + ' relation to an item by id', description: 'Check the existence of ' + relationName + ' relation to an item by id',
accessType: 'READ',
returns: {arg: 'exists', type: 'boolean', root: true}, returns: {arg: 'exists', type: 'boolean', root: true},
rest: { rest: {
// After hook to map exists to 200/404 for HEAD // After hook to map exists to 200/404 for HEAD
@ -556,6 +583,7 @@ Model.scopeRemoting = function(scopeName, scope, define) {
http: {verb: 'get', path: '/' + pathName}, http: {verb: 'get', path: '/' + pathName},
accepts: {arg: 'filter', type: 'object'}, accepts: {arg: 'filter', type: 'object'},
description: 'Queries ' + scopeName + ' of ' + this.modelName + '.', description: 'Queries ' + scopeName + ' of ' + this.modelName + '.',
accessType: 'READ',
returns: {arg: scopeName, type: [toModelName], root: true} returns: {arg: scopeName, type: [toModelName], root: true}
}); });
@ -564,13 +592,15 @@ Model.scopeRemoting = function(scopeName, scope, define) {
http: {verb: 'post', path: '/' + pathName}, http: {verb: 'post', path: '/' + pathName},
accepts: {arg: 'data', type: toModelName, http: {source: 'body'}}, accepts: {arg: 'data', type: toModelName, http: {source: 'body'}},
description: 'Creates a new instance in ' + scopeName + ' of this model.', description: 'Creates a new instance in ' + scopeName + ' of this model.',
accessType: 'WRITE',
returns: {arg: 'data', type: toModelName, root: true} returns: {arg: 'data', type: toModelName, root: true}
}); });
define('__delete__' + scopeName, { define('__delete__' + scopeName, {
isStatic: isStatic, isStatic: isStatic,
http: {verb: 'delete', path: '/' + pathName}, http: {verb: 'delete', path: '/' + pathName},
description: 'Deletes all ' + scopeName + ' of this model.' description: 'Deletes all ' + scopeName + ' of this model.',
accessType: 'WRITE'
}); });
define('__count__' + scopeName, { define('__count__' + scopeName, {
@ -578,6 +608,7 @@ Model.scopeRemoting = function(scopeName, scope, define) {
http: {verb: 'get', path: '/' + pathName + '/count'}, http: {verb: 'get', path: '/' + pathName + '/count'},
accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'}, accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'},
description: 'Counts ' + scopeName + ' of ' + this.modelName + '.', description: 'Counts ' + scopeName + ' of ' + this.modelName + '.',
accessType: 'READ',
returns: {arg: 'count', type: 'number'} returns: {arg: 'count', type: 'number'}
}); });
@ -653,6 +684,7 @@ Model.nestRemoting = function(relationName, options, cb) {
opts.accepts = acceptArgs.concat(method.accepts || []); opts.accepts = acceptArgs.concat(method.accepts || []);
opts.returns = [].concat(method.returns || []); opts.returns = [].concat(method.returns || []);
opts.description = method.description; opts.description = method.description;
opts.accessType = method.accessType;
opts.rest = extend({}, method.rest || {}); opts.rest = extend({}, method.rest || {});
opts.rest.delegateTo = method; opts.rest.delegateTo = method;

View File

@ -485,6 +485,7 @@ PersistedModel.setupRemoting = function() {
setRemoting(PersistedModel, 'create', { setRemoting(PersistedModel, 'create', {
description: 'Create a new instance of the model and persist it into the data source', description: 'Create a new instance of the model and persist it into the data source',
accessType: 'WRITE',
accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}}, accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}},
returns: {arg: 'data', type: typeName, root: true}, returns: {arg: 'data', type: typeName, root: true},
http: {verb: 'post', path: '/'} http: {verb: 'post', path: '/'}
@ -493,6 +494,7 @@ PersistedModel.setupRemoting = function() {
setRemoting(PersistedModel, 'upsert', { setRemoting(PersistedModel, 'upsert', {
aliases: ['updateOrCreate'], aliases: ['updateOrCreate'],
description: 'Update an existing model instance or insert a new one into the data source', description: 'Update an existing model instance or insert a new one into the data source',
accessType: 'WRITE',
accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}}, accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}},
returns: {arg: 'data', type: typeName, root: true}, returns: {arg: 'data', type: typeName, root: true},
http: {verb: 'put', path: '/'} http: {verb: 'put', path: '/'}
@ -500,6 +502,7 @@ PersistedModel.setupRemoting = function() {
setRemoting(PersistedModel, 'exists', { setRemoting(PersistedModel, 'exists', {
description: 'Check whether a model instance exists in the data source', description: 'Check whether a model instance exists in the data source',
accessType: 'READ',
accepts: {arg: 'id', type: 'any', description: 'Model id', required: true}, accepts: {arg: 'id', type: 'any', description: 'Model id', required: true},
returns: {arg: 'exists', type: 'boolean'}, returns: {arg: 'exists', type: 'boolean'},
http: [ http: [
@ -529,6 +532,7 @@ PersistedModel.setupRemoting = function() {
setRemoting(PersistedModel, 'findById', { setRemoting(PersistedModel, 'findById', {
description: 'Find a model instance by id from the data source', description: 'Find a model instance by id from the data source',
accessType: 'READ',
accepts: { accepts: {
arg: 'id', type: 'any', description: 'Model id', required: true, arg: 'id', type: 'any', description: 'Model id', required: true,
http: {source: 'path'} http: {source: 'path'}
@ -540,6 +544,7 @@ PersistedModel.setupRemoting = function() {
setRemoting(PersistedModel, 'find', { setRemoting(PersistedModel, 'find', {
description: 'Find all instances of the model matched by filter from the data source', description: 'Find all instances of the model matched by filter from the data source',
accessType: 'READ',
accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, orderBy, offset, and limit'}, accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, orderBy, offset, and limit'},
returns: {arg: 'data', type: [typeName], root: true}, returns: {arg: 'data', type: [typeName], root: true},
http: {verb: 'get', path: '/'} http: {verb: 'get', path: '/'}
@ -547,6 +552,7 @@ PersistedModel.setupRemoting = function() {
setRemoting(PersistedModel, 'findOne', { setRemoting(PersistedModel, 'findOne', {
description: 'Find first instance of the model matched by filter from the data source', description: 'Find first instance of the model matched by filter from the data source',
accessType: 'READ',
accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, orderBy, offset, and limit'}, accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, orderBy, offset, and limit'},
returns: {arg: 'data', type: typeName, root: true}, returns: {arg: 'data', type: typeName, root: true},
http: {verb: 'get', path: '/findOne'}, http: {verb: 'get', path: '/findOne'},
@ -555,6 +561,7 @@ PersistedModel.setupRemoting = function() {
setRemoting(PersistedModel, 'destroyAll', { setRemoting(PersistedModel, 'destroyAll', {
description: 'Delete all matching records', description: 'Delete all matching records',
accessType: 'WRITE',
accepts: {arg: 'where', type: 'object', description: 'filter.where object'}, accepts: {arg: 'where', type: 'object', description: 'filter.where object'},
http: {verb: 'del', path: '/'}, http: {verb: 'del', path: '/'},
shared: false shared: false
@ -563,6 +570,7 @@ PersistedModel.setupRemoting = function() {
setRemoting(PersistedModel, 'updateAll', { setRemoting(PersistedModel, 'updateAll', {
aliases: ['update'], aliases: ['update'],
description: 'Update instances of the model matched by where from the data source', description: 'Update instances of the model matched by where from the data source',
accessType: 'WRITE',
accepts: [ accepts: [
{arg: 'where', type: 'object', http: {source: 'query'}, {arg: 'where', type: 'object', http: {source: 'query'},
description: 'Criteria to match model instances'}, description: 'Criteria to match model instances'},
@ -575,6 +583,7 @@ PersistedModel.setupRemoting = function() {
setRemoting(PersistedModel, 'deleteById', { setRemoting(PersistedModel, 'deleteById', {
aliases: ['destroyById', 'removeById'], aliases: ['destroyById', 'removeById'],
description: 'Delete a model instance by id from the data source', description: 'Delete a model instance by id from the data source',
accessType: 'WRITE',
accepts: {arg: 'id', type: 'any', description: 'Model id', required: true, accepts: {arg: 'id', type: 'any', description: 'Model id', required: true,
http: {source: 'path'}}, http: {source: 'path'}},
http: {verb: 'del', path: '/:id'} http: {verb: 'del', path: '/:id'}
@ -582,6 +591,7 @@ PersistedModel.setupRemoting = function() {
setRemoting(PersistedModel, 'count', { setRemoting(PersistedModel, 'count', {
description: 'Count instances of the model matched by where from the data source', description: 'Count instances of the model matched by where from the data source',
accessType: 'READ',
accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'}, accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'},
returns: {arg: 'count', type: 'number'}, returns: {arg: 'count', type: 'number'},
http: {verb: 'get', path: '/count'} http: {verb: 'get', path: '/count'}
@ -589,6 +599,7 @@ PersistedModel.setupRemoting = function() {
setRemoting(PersistedModel.prototype, 'updateAttributes', { setRemoting(PersistedModel.prototype, 'updateAttributes', {
description: 'Update attributes for a model instance and persist it into the data source', description: 'Update attributes for a model instance and persist it into the data source',
accessType: 'WRITE',
accepts: {arg: 'data', type: 'object', http: {source: 'body'}, description: 'An object of model property name/value pairs'}, accepts: {arg: 'data', type: 'object', http: {source: 'body'}, description: 'An object of model property name/value pairs'},
returns: {arg: 'data', type: typeName, root: true}, returns: {arg: 'data', type: typeName, root: true},
http: {verb: 'put', path: '/'} http: {verb: 'put', path: '/'}
@ -597,6 +608,7 @@ PersistedModel.setupRemoting = function() {
if (options.trackChanges) { if (options.trackChanges) {
setRemoting(PersistedModel, 'diff', { setRemoting(PersistedModel, 'diff', {
description: 'Get a set of deltas and conflicts since the given checkpoint', description: 'Get a set of deltas and conflicts since the given checkpoint',
accessType: 'READ',
accepts: [ accepts: [
{arg: 'since', type: 'number', description: 'Find deltas since this checkpoint'}, {arg: 'since', type: 'number', description: 'Find deltas since this checkpoint'},
{arg: 'remoteChanges', type: 'array', description: 'an array of change objects', {arg: 'remoteChanges', type: 'array', description: 'an array of change objects',
@ -609,6 +621,7 @@ PersistedModel.setupRemoting = function() {
setRemoting(PersistedModel, 'changes', { setRemoting(PersistedModel, 'changes', {
description: 'Get the changes to a model since a given checkpoint.' + description: 'Get the changes to a model since a given checkpoint.' +
'Provide a filter object to reduce the number of results returned.', 'Provide a filter object to reduce the number of results returned.',
accessType: 'READ',
accepts: [ accepts: [
{arg: 'since', type: 'number', description: 'Only return changes since this checkpoint'}, {arg: 'since', type: 'number', description: 'Only return changes since this checkpoint'},
{arg: 'filter', type: 'object', description: 'Only include changes that match this filter'} {arg: 'filter', type: 'object', description: 'Only include changes that match this filter'}
@ -619,18 +632,21 @@ PersistedModel.setupRemoting = function() {
setRemoting(PersistedModel, 'checkpoint', { setRemoting(PersistedModel, 'checkpoint', {
description: 'Create a checkpoint.', description: 'Create a checkpoint.',
accessType: 'WRITE',
returns: {arg: 'checkpoint', type: 'object', root: true}, returns: {arg: 'checkpoint', type: 'object', root: true},
http: {verb: 'post', path: '/checkpoint'} http: {verb: 'post', path: '/checkpoint'}
}); });
setRemoting(PersistedModel, 'currentCheckpoint', { setRemoting(PersistedModel, 'currentCheckpoint', {
description: 'Get the current checkpoint.', description: 'Get the current checkpoint.',
accessType: 'READ',
returns: {arg: 'checkpoint', type: 'object', root: true}, returns: {arg: 'checkpoint', type: 'object', root: true},
http: {verb: 'get', path: '/checkpoint'} http: {verb: 'get', path: '/checkpoint'}
}); });
setRemoting(PersistedModel, 'createUpdates', { setRemoting(PersistedModel, 'createUpdates', {
description: 'Create an update list from a delta list', description: 'Create an update list from a delta list',
accessType: 'WRITE',
accepts: {arg: 'deltas', type: 'array', http: {source: 'body'}}, accepts: {arg: 'deltas', type: 'array', http: {source: 'body'}},
returns: {arg: 'updates', type: 'array', root: true}, returns: {arg: 'updates', type: 'array', root: true},
http: {verb: 'post', path: '/create-updates'} http: {verb: 'post', path: '/create-updates'}
@ -638,17 +654,20 @@ PersistedModel.setupRemoting = function() {
setRemoting(PersistedModel, 'bulkUpdate', { setRemoting(PersistedModel, 'bulkUpdate', {
description: 'Run multiple updates at once. Note: this is not atomic.', description: 'Run multiple updates at once. Note: this is not atomic.',
accessType: 'WRITE',
accepts: {arg: 'updates', type: 'array'}, accepts: {arg: 'updates', type: 'array'},
http: {verb: 'post', path: '/bulk-update'} http: {verb: 'post', path: '/bulk-update'}
}); });
setRemoting(PersistedModel, 'rectifyAllChanges', { setRemoting(PersistedModel, 'rectifyAllChanges', {
description: 'Rectify all Model changes.', description: 'Rectify all Model changes.',
accessType: 'WRITE',
http: {verb: 'post', path: '/rectify-all'} http: {verb: 'post', path: '/rectify-all'}
}); });
setRemoting(PersistedModel, 'rectifyChange', { setRemoting(PersistedModel, 'rectifyChange', {
description: 'Tell loopback that a change to the model with the given id has occurred.', description: 'Tell loopback that a change to the model with the given id has occurred.',
accessType: 'WRITE',
accepts: {arg: 'id', type: 'any', http: {source: 'path'}}, accepts: {arg: 'id', type: 'any', http: {source: 'path'}},
http: {verb: 'post', path: '/:id/rectify-change'} http: {verb: 'post', path: '/:id/rectify-change'}
}); });