Now we have a feature branch for our server side updates. Let's get to work tidying things up.
To begin with, Sails offers some really handy Blueprint APIs to expose the data in your framework. The blueprints offer several types of apis: rest, shortcut, actions.
Our application will be exposing our PARequest resource using a REST API. So that blueprint is going to be very handy for us in our project.
The shortcut api is useful for development, in that it exposes the resource operations (find, create, update, destroy) in a way that you can easily type in a uri in a web browser and interact with the data. For testing purposes, this is really handy otherwise you need to use another tool like Postman to interact with your REST api.
But in our application we don't want to leave the shortcut api active. So let's close this down:
// your api/controllers/PARequestController.js
var fs = require('fs');
var path = require('path');
var fixtureData = null;
module.exports = {
_config: {
model: "parequest",
actions: true,
shortcuts: false, // <---- turn these off.
rest: true
},The Actions blueprint will expose a route for each of the actions found on your Controller. So if we added a PARequestController.flush() method, then the actions blueprint would expose a get /opstool-process-approval/parequest/flush route that you can call as well.
I'm not planning on creating any unique Actions on my PARequestController so let's turn that off:
// your api/controllers/PARequestController.js
var fs = require('fs');
var path = require('path');
var fixtureData = null;
module.exports = {
_config: {
model: "parequest",
actions: false, // <---- now turn these off.
shortcuts: false,
rest: true
},Now, in addition to the Blueprint APIs, we need to also close down our create and destroy methods.
According to our design document, our external interface should only be allowed to find a list of pending approvals, and update an approval's status. The external client application is not supposed to be able to create or destroy or do anything else a RESTful route might enable:. So, let's close those interfaces down:
// [plugin]/config/policies.js
module.exports = {
'opstool-process-approval/PARequestController': {
create: false,
add: false,
populate: false,
remove: false,
destroy: false
}
};Now access to those operations on our controller are no longer allowed.
So, wanna test those out without having to use another app to submit the REST api calls? Yeah, me too. Change the shortcuts back on:
// your api/controllers/PARequestController.js
module.exports = {
_config: {
model: "parequest", // all lowercase model name
actions: false,
shortcuts: true, // <------ enable this
rest: true
},Now restart sails:
# sails root directory
$ sails liftnow open a web browser and type in the following url: localhost:1337/opstool-process-approval/parequest/find. You should see our list of fixtures we sent back. So the find method is working.
now enter: localhost:1337/opstool-process-approval/parequest/create
You should see a forbidden message in your browser.
same for: localhost:1337/opstool-process-approval/parequest/destroy
shoot! I updated my code without writing the tests first. Looks like I got ahead of myself, and it certainly wont be the last time. So let's just write our Tests now and get back to work.
Let's update our tests/controller/PARequestController.js to now make sure we can not get to the create or delete routes:
it('should not be able to access our REST create route: ', function(done) {
request
.post('/opstool-process-approval/parequest')
.set('Accept', 'application/json')
.expect(403) // should return a forbidden
.end(function(err, res){
assert.isNull(err, ' --> there should be no error.');
done(err);
});
});
it('should not be able to access our REST delete route: ', function(done) {
request
.delete('/opstool-process-approval/parequest')
.set('Accept', 'application/json')
.expect(403) // should return a forbidden
.end(function(err, res){
assert.isNull(err, ' --> there should be no error.');
done(err);
});
});NOTE:
deleteis a reserved keyword in javascript, so it would be better if you wrote the request as:request['delete']('/opstool-process-approval/parequest')
Now run your tests:
$ npm test
> opstool-process-approval@0.0.0 test /sails/node_modules/opstool-process-approval
> make test
․․․․․․․․
8 passing (12s)
Note: our sails server actually spits out a few logging messages that I removed in this example. Don't worry if your actual output looks slightly different.
That looks good. Now write a test that expects a failure when attempting to access a shortcut route:
it('should not be able to access our shortcut route for find: ', function(done) {
request
.get('/opstool-process-approval/parequest/find')
.set('Accept', 'application/json')
.expect('Content-Type', /json/) // should return json
.expect(404) // should return a not found
.end(function(err, res){
assert.isNull(err, ' --> there should be no error.');
done(err);
});
});and now run your test:
$ npm test
> opstool-process-approval@0.0.0 test /sails/node_modules/opstool-process-approval
> make test
․․․․․․․․․
8 passing (12s)
1 failing
1) PARequestController should not be able to access our shortcut route for find: :
Uncaught AssertionError: --> there should be no error.: expected [Error: expected 404 "Not Found", got 200 "OK"] to equal null
at Function.assert.isNull (node_modules/chai/lib/chai/interface/assert.js:388:32)
at Test.<anonymous> (test/controllers/PARequestController.js:66:24)
at Test.assert (node_modules/ad-utils/node_modules/supertest/lib/test.js:156:6)
at Server.assert (node_modules/ad-utils/node_modules/supertest/lib/test.js:127:12)
at net.js:1419:10
make: *** [test] Error 1
npm ERR! Test failed. See above for more details.That looks right. We expected an error, but we got a 200 instead.
Now go back and disable the shortcuts:
// your api/controllers/PARequestController.js
module.exports = {
_config: {
model: "parequest",
actions: false,
shortcuts: false, // <------ disable this
rest: true
},and now run our tests again:
$ npm test
> opstool-process-approval@0.0.0 test /sails/node_modules/opstool-process-approval
> make test
․․․․․․․․․
9 passing (13s)
OK, save these changes in your new feature branch:
# from your [plugin] root:
$ git add .
$ git commit -m '+ADD: locked down unused PARequest APIs'< step 4 : Create our Server Side Feature branch step 6 : limit access to the find() operation >