UNPKG

13.5 kBJavaScriptView Raw
1/* eslint-env mocha */
2'use strict'
3
4const Code = require('code')
5const expect = Code.expect
6const nock = require('nock')
7const Rbac = require('../lib/index')
8
9describe('RBAC', function () {
10 let getPermission
11
12 before(function () {
13 getPermission = function (id) {
14 return new Promise((resolve, reject) => {
15 const users = [
16 ['users:create', 'users:remove'], // user 0
17 ['users:read'], // user 1
18 ['users:eat', 'users:sleep', 'users:rave', 'users:repeat'] // user 2
19 ]
20 if (users[id]) {
21 resolve(users[id])
22 } else {
23 reject(new Error('Inexistent User'))
24 }
25 })
26 }
27
28 const opts = {
29 reqheaders: {
30 authorization: 'Bearer abcd'
31 }
32 }
33
34 nock('http://www.example.com', opts)
35 .post('/authorize', { permissions: ['users:create'] })
36 .times(1000)
37 .reply(401)
38
39 .post('/authorize', { permissions: ['users:read'] })
40 .times(1000)
41 .reply(200, {
42 id: 1000 // remote authorization can return claims about the principal
43 })
44
45 .post('/authorize', { permissions: ['users:read', 'users:void'] })
46 .times(1000)
47 .reply(200)
48
49 .post('/authorize', { permissions: ['users:read:and', 'users:create:and'] })
50 .times(1000)
51 .reply(200)
52
53 .post('/authorize')
54 .times(1000)
55 .reply(401)
56 })
57
58 describe('- UNIT Tests', () => {
59 it('should Rbac throw if opts.getPermission is not specified', function () {
60 expect(() => new Rbac({ some: 'prop' })).to.throw(TypeError)
61 })
62
63 it('should Rbac throw if opts.remoteAuth is specified and opts.remoteAuth.url is not', function () {
64 expect(() => new Rbac({ remoteAuth: {} })).to.throw(TypeError)
65 })
66 })
67
68 // "authorize" method START
69 describe('- Rbac.authorize', () => {
70 it('should throw if permissions is not an array', function (done) {
71 const rbac = new Rbac({ getPermission: getPermission })
72 rbac
73 .authorize(1, { permissions: 'users:create', checkType: null })
74 .then(() => Code.fail('Rbac.authorize should fail'))
75 .catch((err) => {
76 expect(err).to.be.an.error('Invalid permissions value: must be an array')
77 done()
78 })
79 })
80
81 it('should throw if permissions are more than one', function (done) {
82 const rbac = new Rbac({ getPermission: getPermission })
83 rbac
84 .authorize(1, { permissions: ['users:read', 'users:create'], checkType: null })
85 .then(() => Code.fail('Rbac.authorize should fail'))
86 .catch((err) => {
87 expect(err).to.be.an.error()
88 expect(err.message).to.include('Invalid permissions:checkType combination.')
89 done()
90 })
91 })
92
93 it("should fail if user isn't allowed the existing permission", function (done) {
94 const rbac = new Rbac({ getPermission: getPermission })
95 rbac
96 .authorize(1, { permissions: ['users:create'], checkType: null })
97 .then(() => Code.fail('Rbac.authorize should fail'))
98 .catch((err) => {
99 expect(err).to.be.an.error('Permission denied.')
100 done()
101 })
102 })
103
104 it('should pass if user is allowed the existing permission', function (done) {
105 const rbac = new Rbac({ getPermission: getPermission })
106 rbac
107 .authorize(1, { permissions: ['users:read'], checkType: null })
108 .then(() => done())
109 .catch(done)
110 })
111 })
112 // "authorize" method END
113
114 // "authorize "OR" method START
115 describe('- Rbac.authorize OR', () => {
116 it('should fail if the number of permissions is less than 2', function (done) {
117 const rbac = new Rbac({ getPermission: getPermission })
118 rbac
119 .authorize(1, { permissions: ['users:create'], checkType: 'OR' })
120 .then(done)
121 .catch((err) => {
122 expect(err).to.be.an.error()
123 expect(err.message).to.include('Invalid permissions:checkType combination.')
124 done()
125 })
126 })
127
128 it('should fail if the user has none of the permissions', function (done) {
129 const rbac = new Rbac({ getPermission: getPermission })
130 rbac
131 .authorize(1, { permissions: ['users:milkyway', 'users:blackhole'], checkType: 'OR' })
132 .then(done)
133 .catch((err) => {
134 expect(err).to.be.an.error('Permission denied.')
135 done()
136 })
137 })
138
139 it('should pass if the user has at least one permission', function (done) {
140 const rbac = new Rbac({ getPermission: getPermission })
141 rbac
142 .authorize(1, { permissions: ['users:read', 'users:andromeda'], checkType: 'OR' })
143 .then(() => done())
144 .catch(done)
145 })
146 })
147 // "authorize "OR" method END
148
149 // "authorize "AND" method START
150 describe('- Rbac.authorize AND', () => {
151 it('should fail if the number of permissions is less than 2', function (done) {
152 const rbac = new Rbac({ getPermission: getPermission })
153 rbac
154 .authorize(1, { permissions: ['users:create'], checkType: 'AND' })
155 .then(done)
156 .catch((err) => {
157 expect(err).to.be.an.error()
158 expect(err.message).to.include('Invalid permissions:checkType combination.')
159 done()
160 })
161 })
162
163 it.skip('should fail if the user has none of the permissions', function (done) {
164 const rbac = new Rbac({ getPermission: getPermission })
165 rbac
166 .authorize(0, { permissions: ['users:milkyway', 'users:blackhole'], checkType: 'AND' })
167 .then(done)
168 .catch((err) => {
169 expect(err).to.be.an.error('Permission denied.')
170 done()
171 })
172 })
173
174 it.skip('should fail if the user has just one of the permissions', function (done) {
175 const rbac = new Rbac({ getPermission: getPermission })
176 rbac
177 .authorize(0, { permissions: ['users:create', 'users:blackhole'], checkType: 'AND' })
178 .then(done)
179 .catch((err) => {
180 expect(err).to.be.an.error('Permission denied.')
181 done()
182 })
183 })
184
185 it.skip('should pass if the user has all permissions', function (done) {
186 const rbac = new Rbac({ getPermission: getPermission })
187 rbac
188 .authorize(0, { permissions: ['users:create', 'users:remove'], checkType: 'AND' })
189 .then(() => done())
190 .catch(done)
191 })
192 })
193 // "authorize "AND" method END
194
195 // "Rbac.express.authorizeRemote" method START
196 describe('- Rbac.express.authorizeRemote', () => {
197 it("should fail if user isn't allowed the existing permission", function (done) {
198 const rbac = new Rbac({
199 remoteAuth: {
200 url: 'http://www.example.com/authorize',
201 headers: {
202 authorization: 'Bearer abcd'
203 }
204 }
205 })
206 rbac
207 .authorizeRemote('users:create')
208 .then(() => Code.fail('Rbac.authorize should fail'))
209 .catch((err) => {
210 expect(err.statusCode).to.equal(401)
211 done()
212 })
213 })
214
215 it('should pass if user is allowed the existing permission', function (done) {
216 const rbac = new Rbac({
217 remoteAuth: {
218 url: 'http://www.example.com/authorize',
219 headers: {
220 authorization: 'Bearer abcd'
221 }
222 }
223 })
224 rbac
225 .authorizeRemote('users:read')
226 .then(() => done())
227 .catch(done)
228 })
229
230 it("should fail if user isn't allowed the existing permission remotely", function (done) {
231 const rbac = new Rbac({
232 remoteAuth: {
233 url: 'http://www.example.com/authorize'
234 }
235 })
236 const middleware = rbac
237 .express
238 .authorizeRemote('users:create')
239
240 const req = {
241 headers: {
242 authorization: 'Bearer abcd'
243 }
244 }
245
246 middleware(req, null, (err) => {
247 expect(err).to.be.an.error()
248 expect(err.isBoom).to.exist().and.be.true()
249 expect(err.output.statusCode).to.exist().and.equal(401)
250 done()
251 })
252 })
253 })
254 // "Rbac.express.authorizeRemote" method END
255
256 // "Rbac.express.authorizeRemoteOr" method START
257 describe('- Rbac.express.authorizeRemoteOr', () => {
258 it("should fail if user isn't allowed the existing permission", function (done) {
259 const rbac = new Rbac({
260 remoteAuth: {
261 url: 'http://www.example.com/authorize',
262 headers: {
263 authorization: 'Bearer abcd'
264 }
265 }
266 })
267 rbac
268 .authorizeRemoteOr(['users:milkyway', 'users:blackhole'])
269 .then(() => Code.fail('Rbac.authorize should fail'))
270 .catch((err) => {
271 expect(err.statusCode).to.equal(401)
272 done()
273 })
274 })
275
276 it('should pass if user is allowed at least one permission', function (done) {
277 const rbac = new Rbac({
278 remoteAuth: {
279 url: 'http://www.example.com/authorize',
280 headers: {
281 authorization: 'Bearer abcd'
282 }
283 }
284 })
285 rbac
286 .authorizeRemoteOr(['users:read', 'users:void'])
287 .then(() => done())
288 .catch(done)
289 })
290
291 it("should fail if user isn't allowed the existing permission remotely", function (done) {
292 const rbac = new Rbac({
293 remoteAuth: {
294 url: 'http://www.example.com/authorize'
295 }
296 })
297 const middleware = rbac
298 .express
299 .authorizeRemoteOr(['users:void', 'users:blank'])
300
301 const req = {
302 headers: {
303 authorization: 'Bearer abcd'
304 }
305 }
306
307 middleware(req, null, (err) => {
308 expect(err).to.be.an.error()
309 expect(err.isBoom).to.exist().and.be.true()
310 expect(err.output.statusCode).to.exist().and.equal(401)
311 done()
312 })
313 })
314 })
315 // "Rbac.express.authorizeRemoteOr" method END
316
317 // "Rbac.express.authorizeRemoteAnd" method START
318 describe('- Rbac.express.authorizeRemoteAnd', () => {
319 it("should fail if user isn't allowed the existing permission", function (done) {
320 const rbac = new Rbac({
321 remoteAuth: {
322 url: 'http://www.example.com/authorize',
323 headers: {
324 authorization: 'Bearer abcd'
325 }
326 }
327 })
328 rbac
329 .authorizeRemoteAnd(['users:milkyway', 'users:blackhole'])
330 .then(() => Code.fail('Rbac.authorize should fail'))
331 .catch((err) => {
332 expect(err.statusCode).to.equal(401)
333 done()
334 })
335 })
336
337 it("should fail if user is doens't have all permissions", function (done) {
338 const rbac = new Rbac({
339 remoteAuth: {
340 url: 'http://www.example.com/authorize',
341 headers: {
342 authorization: 'Bearer abcd'
343 }
344 }
345 })
346 rbac
347 .authorizeRemoteAnd(['users:read', 'users:blackhole'])
348 .then(() => Code.fail('Rbac.authorize should fail'))
349 .catch((err) => {
350 expect(err.statusCode).to.equal(401)
351 done()
352 })
353 })
354
355 it("should fail if user isn't allowed any of the permissions", function (done) {
356 const rbac = new Rbac({
357 remoteAuth: {
358 url: 'http://www.example.com/authorize'
359 }
360 })
361 const middleware = rbac
362 .express
363 .authorizeRemoteOr(['users:void', 'users:blank'])
364
365 const req = {
366 headers: {
367 authorization: 'Bearer abcd'
368 }
369 }
370
371 middleware(req, null, (err) => {
372 expect(err).to.be.an.error()
373 expect(err.isBoom).to.exist().and.be.true()
374 expect(err.output.statusCode).to.exist().and.equal(401)
375 done()
376 })
377 })
378
379 it('should pass if user is allowed all permissions', function (done) {
380 const rbac = new Rbac({
381 remoteAuth: {
382 url: 'http://www.example.com/authorize',
383 headers: {
384 authorization: 'Bearer abcd'
385 }
386 }
387 })
388 rbac
389 .authorizeRemoteOr(['users:read:and', 'users:create:and'])
390 .then(() => done())
391 .catch(done)
392 })
393 })
394 // "Rbac.express.authorizeRemoteAnd" method END
395
396 // "Rbac.express.authorize" method START
397 describe('- Rbac.express.authorize', () => {
398 it("should fail if user isn't allowed the existing permission", function (done) {
399 const rbac = new Rbac({ getPermission: getPermission })
400 const middleware = rbac
401 .express
402 .authorize('users:create')
403
404 const req = {
405 user: {
406 id: 1
407 }
408 }
409
410 middleware(req, null, (err) => {
411 expect(err).to.be.an.error()
412 expect(err.isBoom).to.exist().and.be.true()
413 expect(err.output.statusCode).to.exist().and.equal(401)
414 done()
415 })
416 })
417
418 it('should pass if user is allowed the existing permission', function (done) {
419 const rbac = new Rbac({ getPermission: getPermission })
420 const middleware = rbac
421 .express
422 .authorize('users:read')
423
424 const req = {
425 user: {
426 id: 1
427 }
428 }
429
430 middleware(req, null, (err) => {
431 expect(err).to.be.undefined()
432 done()
433 })
434 })
435
436 it('should allow for userId being set', function (done) {
437 const rbac = new Rbac({
438 getPermission: getPermission,
439 getReqId: (req) => req.some.prop
440 })
441 const middleware = rbac
442 .express
443 .authorize('users:read')
444
445 const req = {
446 some: {
447 prop: 1
448 }
449 }
450
451 middleware(req, null, (err) => {
452 expect(err).to.be.undefined()
453 done()
454 })
455 })
456 })
457// "Rbac.express.authorize" method END
458})