Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 127 lines (84 sloc) 6.37 kB
d084cd6 @mikermcneil Update policies.md
mikermcneil authored
1 # Policies (ACL)
37dae74 @buttondownben bump versions
buttondownben authored
2 > _**Note:** You are viewing the Sails.js v0.9.x documentation. If you're looking for information on v0.8.x, please visit [here](http://08x.sailsjs.org)._
effcd0c @dcbartlett Updating
dcbartlett authored
3
602f7d0 @rachaelshaw Update policies.md
rachaelshaw authored
4 So, you don’t want your mom to access your secret stash of ... code? Here's how you can make that happen.
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
5
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
6 ## What Are Policies?
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
7
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
8 Policies in Sails are versatile tools for authorization and access control-- they let you allow or deny access to your controllers down to a fine level of granularity. For example, if you were building Dropbox, before letting a user upload a file to a folder, you might check that she `isAuthenticated`, then ensure that she `canWrite` (has write permissions on the folder.) Finally, you'd want to check that the folder she's uploading into `hasEnoughSpace`.
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
9
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
10 Policies can be used for anything: HTTP BasicAuth, 3rd party single-sign-on, OAuth 2.0, or your own custom authorization/authentication scheme.
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
11
12
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
13 ## Writing Your First Policy
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
14
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
15 Policies are files defined in the `api/policies` folder in your Sails app. Each policy file should contain a single function.
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
16
9e6a3ad @rachaelshaw Update policies.md
rachaelshaw authored
17 When it comes down to it, policies are really just Connect/Express middleware functions which run **before** your controllers. You can chain as many of them together as you like-- in fact they're designed to be used this way. Ideally, each middleware function should really check just *one thing*.
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
18
19 For example, the `canWrite` policy mentioned above might look something like this:
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
20
21 ```javascript
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
22 // policies/canWrite.js
23 module.exports = function canWrite (req, res, next) {
24 var targetFolderId = req.param('id');
25 var userId = req.session.user.id;
26
27 Permission
28 .findOneByFolderId( targetFolderId )
29 .exec( function foundPermission (err, permission) {
30
31 // Unexpected error occurred-- skip to the app's default error (500) handler
32 if (err) return next(err);
33
34 // No permission exists linking this user to this folder. Maybe they got removed from it? Maybe they never had permission in the first place? Who cares?
35 if ( ! permission ) return res.redirect('/notAllowed');
36
37 // OK, so a permission was found. Let's be sure it's a "write".
38 if ( permission.type !== 'write' ) return res.redirect('/notAllowed');
39
40 // If we made it all the way down here, looks like everything's ok, so we'll let the user through
41 next();
42 });
43 };
44 ```
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
45
46
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
47 ## How do I protect my controllers with policies?
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
48
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
49 Sails has a built in ACL (access control list) located in `config/policies.js`. This file is used to map policies to your controllers.
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
50
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
51 This file is *declarative*, meaning it describes *what* the permissions for your app should look like, not *how* they should work. Declarative programming has many benefits, but in particular, it is both conventional and adaptable. This makes it easier for new developers to jump in and understand what's going on, plus it makes your app more flexible as your requirements inevitably change over time.
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
52
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
53 You can apply one or more policies to a given controller or action. Any file in your `/policies` folder (e.g. `authenticated.js`) is referable in your ACL (`config/policies.js`) by its filename minus the extension, (e.g. `'authenticated'`).
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
54
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
55 Additionally, there are a few special, built-in policy mappings:
56 + `true`: public access (allows anyone to get to the mapped controller/action)
57 + `false`: **NO** access (allows **no-one** to access the mapped controller/action)
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
58
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
59 `'*': true` is the default policy for all controllers and actions. In production, it's good practice to set this to `false` to prevent access to any logic you might have inadvertently exposed.
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
60
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
61 ### Here’s an example of adding some policies to a controller:
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
62 ```javascript
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
63 RabbitController: {
64
65 // Apply the `false` policy as the default for all of RabbitController's actions
66 // (`false` prevents all access, which ensures that nothing bad happens to our rabbits)
67 '*': false,
68
69 // For the action `nurture`, apply the 'isRabbitMother' policy
70 // (this overrides `false` above)
71 nurture : 'isRabbitMother',
72
73 // Apply the `isNiceToAnimals` AND `hasRabbitFood` policies
74 // before letting any users feed our rabbits
75 feed : ['isNiceToAnimals', 'hasRabbitFood']
76 }
77 ```
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
78
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
79 Here’s what the `isNiceToAnimals` policy from above might look like: (this file would be located at `policies/isNiceToAnimals.js`)
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
80
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
81 We’ll make some educated guesses about whether our system will consider this user someone who is nice to animals.
82 ```javascript
83 module.exports = function isNiceToAnimals (req, res, next) {
84
85 // `req.session` contains a set of data specific to the user making this request.
86 // It's kind of like our app's "memory" of the current user.
87
88 // If our user has a history of animal cruelty, not only will we
89 // prevent her from going even one step further (`return`),
90 // we'll go ahead and redirect her to PETA (`res.redirect`).
91 if ( req.session.user.hasHistoryOfAnimalCruelty ) {
92 return res.redirect('http://PETA.org');
93 }
94
95 // If the user has been seen frowning at puppies, we have to assume that
96 // they might end up being mean to them, so we'll
97 if ( req.session.user.frownsAtPuppies ) {
98 return res.redirect('http://www.dailypuppy.com/');
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
99 }
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
100
101 // Finally, if the user has a clean record, we'll call the `next()` function
102 // to let them through to the next policy or our controller
103 next();
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
104 };
105 ```
106
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
107 #### Besides protecting rabbits (while a noble cause, no doubt), here are a few other use cases for policies:
108 + cookie-based authentication
109 + role-based access control
110 + limiting file uploads based on MB quotas
111 + any other kind of authentication scheme you can imagine
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
112
113
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
114 ## What about me? I'm using Passport?!
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
115
e19111b @silenceisgolden Update policies.md
silenceisgolden authored
116 Passport works great with Sails! In general, since Sails uses Connect/Express at its core, all of the Connect/Express-oriented things work pretty well. In fact, Sails has no problem interpreting most Express middleware to work with socket.io.
88b56d3 @mikermcneil Update policies.md
mikermcneil authored
117
e19111b @silenceisgolden Update policies.md
silenceisgolden authored
118 There are a few good examples of this floating around.
119
120 [Using Passport.JS with Sails.JS](http://jethrokuan.github.io/2013/12/19/Using-Passport-With-Sails-JS.html)
121
122 Here's a good one (hasn't been tested in v0.9.x yet): https://gist.github.com/theangryangel/5060446
3dee60c @dcbartlett Changed filenames to coordinate with website.
dcbartlett authored
123
124
125
d084cd6 @mikermcneil Update policies.md
mikermcneil authored
126 [![githalytics.com alpha](https://cruel-carlota.pagodabox.com/8acf2fc2ca0aca8a3018e355ad776ed7 "githalytics.com")](http://githalytics.com/balderdashy/sails/wiki/policies)
Something went wrong with that request. Please try again.