UNPKG

14 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 id not a Number or not convertible to a Number', function (done) {
71 const rbac = new Rbac({ getPermission: getPermission })
72 rbac
73 .authorize('Not a Number', { permissions: 'users:create', checkType: null })
74 .then(() => Code.fail('Rbac.authorize should fail'))
75 .catch((err) => {
76 expect(err).to.be.an.error('Invalid userId value: must be a number.')
77 done()
78 })
79 })
80
81 it('should throw if permissions is not an array', function (done) {
82 const rbac = new Rbac({ getPermission: getPermission })
83 rbac
84 .authorize(1, { permissions: 'users:create', checkType: null })
85 .then(() => Code.fail('Rbac.authorize should fail'))
86 .catch((err) => {
87 expect(err).to.be.an.error('Invalid permissions value: must be an array')
88 done()
89 })
90 })
91
92 it('should throw if permissions are more than one', function (done) {
93 const rbac = new Rbac({ getPermission: getPermission })
94 rbac
95 .authorize(1, { permissions: ['users:read', 'users:create'], checkType: null })
96 .then(() => Code.fail('Rbac.authorize should fail'))
97 .catch((err) => {
98 expect(err).to.be.an.error()
99 expect(err.message).to.include('Invalid permissions:checkType combination.')
100 done()
101 })
102 })
103
104 it("should fail if user isn't allowed the existing permission", function (done) {
105 const rbac = new Rbac({ getPermission: getPermission })
106 rbac
107 .authorize(1, { permissions: ['users:create'], checkType: null })
108 .then(() => Code.fail('Rbac.authorize should fail'))
109 .catch((err) => {
110 expect(err).to.be.an.error('Permission denied.')
111 done()
112 })
113 })
114
115 it('should pass if user is allowed the existing permission', function (done) {
116 const rbac = new Rbac({ getPermission: getPermission })
117 rbac
118 .authorize(1, { permissions: ['users:read'], checkType: null })
119 .then(() => done())
120 .catch(done)
121 })
122 })
123 // "authorize" method END
124
125 // "authorize "OR" method START
126 describe('- Rbac.authorize OR', () => {
127 it('should fail if the number of permissions is less than 2', function (done) {
128 const rbac = new Rbac({ getPermission: getPermission })
129 rbac
130 .authorize(1, { permissions: ['users:create'], checkType: 'OR' })
131 .then(done)
132 .catch((err) => {
133 expect(err).to.be.an.error()
134 expect(err.message).to.include('Invalid permissions:checkType combination.')
135 done()
136 })
137 })
138
139 it('should fail if the user has none of the permissions', function (done) {
140 const rbac = new Rbac({ getPermission: getPermission })
141 rbac
142 .authorize(1, { permissions: ['users:milkyway', 'users:blackhole'], checkType: 'OR' })
143 .then(done)
144 .catch((err) => {
145 expect(err).to.be.an.error('Permission denied.')
146 done()
147 })
148 })
149
150 it('should pass if the user has at least one permission', function (done) {
151 const rbac = new Rbac({ getPermission: getPermission })
152 rbac
153 .authorize(1, { permissions: ['users:read', 'users:andromeda'], checkType: 'OR' })
154 .then(() => done())
155 .catch(done)
156 })
157 })
158 // "authorize "OR" method END
159
160 // "authorize "AND" method START
161 describe('- Rbac.authorize AND', () => {
162 it('should fail if the number of permissions is less than 2', function (done) {
163 const rbac = new Rbac({ getPermission: getPermission })
164 rbac
165 .authorize(1, { permissions: ['users:create'], checkType: 'AND' })
166 .then(done)
167 .catch((err) => {
168 expect(err).to.be.an.error()
169 expect(err.message).to.include('Invalid permissions:checkType combination.')
170 done()
171 })
172 })
173
174 it('should fail if the user has none of the permissions', function (done) {
175 const rbac = new Rbac({ getPermission: getPermission })
176 rbac
177 .authorize(0, { permissions: ['users:milkyway', '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('should fail if the user has just one of the permissions', function (done) {
186 const rbac = new Rbac({ getPermission: getPermission })
187 rbac
188 .authorize(0, { permissions: ['users:create', 'users:blackhole'], checkType: 'AND' })
189 .then(done)
190 .catch((err) => {
191 expect(err).to.be.an.error('Permission denied.')
192 done()
193 })
194 })
195
196 it('should pass if the user has all permissions', function (done) {
197 const rbac = new Rbac({ getPermission: getPermission })
198 rbac
199 .authorize(0, { permissions: ['users:create', 'users:remove'], checkType: 'AND' })
200 .then(() => done())
201 .catch(done)
202 })
203 })
204 // "authorize "AND" method END
205
206 // "Rbac.express.authorizeRemote" method START
207 describe('- Rbac.express.authorizeRemote', () => {
208 it("should fail if user isn't allowed the existing permission", function (done) {
209 const rbac = new Rbac({
210 remoteAuth: {
211 url: 'http://www.example.com/authorize',
212 headers: {
213 authorization: 'Bearer abcd'
214 }
215 }
216 })
217 rbac
218 .authorizeRemote('users:create')
219 .then(() => Code.fail('Rbac.authorize should fail'))
220 .catch((err) => {
221 expect(err.statusCode).to.equal(401)
222 done()
223 })
224 })
225
226 it('should pass if user is allowed the existing permission', function (done) {
227 const rbac = new Rbac({
228 remoteAuth: {
229 url: 'http://www.example.com/authorize',
230 headers: {
231 authorization: 'Bearer abcd'
232 }
233 }
234 })
235 rbac
236 .authorizeRemote('users:read')
237 .then(() => done())
238 .catch(done)
239 })
240
241 it("should fail if user isn't allowed the existing permission remotely", function (done) {
242 const rbac = new Rbac({
243 remoteAuth: {
244 url: 'http://www.example.com/authorize'
245 }
246 })
247 const middleware = rbac
248 .express
249 .authorizeRemote('users:create')
250
251 const req = {
252 headers: {
253 authorization: 'Bearer abcd'
254 }
255 }
256
257 middleware(req, null, (err) => {
258 expect(err).to.be.an.error()
259 expect(err.isBoom).to.exist().and.be.true()
260 expect(err.output.statusCode).to.exist().and.equal(401)
261 done()
262 })
263 })
264 })
265 // "Rbac.express.authorizeRemote" method END
266
267 // "Rbac.express.authorizeRemoteOr" method START
268 describe('- Rbac.express.authorizeRemoteOr', () => {
269 it("should fail if user isn't allowed the existing permission", function (done) {
270 const rbac = new Rbac({
271 remoteAuth: {
272 url: 'http://www.example.com/authorize',
273 headers: {
274 authorization: 'Bearer abcd'
275 }
276 }
277 })
278 rbac
279 .authorizeRemoteOr(['users:milkyway', 'users:blackhole'])
280 .then(() => Code.fail('Rbac.authorize should fail'))
281 .catch((err) => {
282 expect(err.statusCode).to.equal(401)
283 done()
284 })
285 })
286
287 it('should pass if user is allowed at least one permission', function (done) {
288 const rbac = new Rbac({
289 remoteAuth: {
290 url: 'http://www.example.com/authorize',
291 headers: {
292 authorization: 'Bearer abcd'
293 }
294 }
295 })
296 rbac
297 .authorizeRemoteOr(['users:read', 'users:void'])
298 .then(() => done())
299 .catch(done)
300 })
301
302 it("should fail if user isn't allowed the existing permission remotely", function (done) {
303 const rbac = new Rbac({
304 remoteAuth: {
305 url: 'http://www.example.com/authorize'
306 }
307 })
308 const middleware = rbac
309 .express
310 .authorizeRemoteOr(['users:void', 'users:blank'])
311
312 const req = {
313 headers: {
314 authorization: 'Bearer abcd'
315 }
316 }
317
318 middleware(req, null, (err) => {
319 expect(err).to.be.an.error()
320 expect(err.isBoom).to.exist().and.be.true()
321 expect(err.output.statusCode).to.exist().and.equal(401)
322 done()
323 })
324 })
325 })
326 // "Rbac.express.authorizeRemoteOr" method END
327
328 // "Rbac.express.authorizeRemoteAnd" method START
329 describe('- Rbac.express.authorizeRemoteAnd', () => {
330 it("should fail if user isn't allowed the existing permission", function (done) {
331 const rbac = new Rbac({
332 remoteAuth: {
333 url: 'http://www.example.com/authorize',
334 headers: {
335 authorization: 'Bearer abcd'
336 }
337 }
338 })
339 rbac
340 .authorizeRemoteAnd(['users:milkyway', 'users:blackhole'])
341 .then(() => Code.fail('Rbac.authorize should fail'))
342 .catch((err) => {
343 expect(err.statusCode).to.equal(401)
344 done()
345 })
346 })
347
348 it("should fail if user is doens't have all permissions", function (done) {
349 const rbac = new Rbac({
350 remoteAuth: {
351 url: 'http://www.example.com/authorize',
352 headers: {
353 authorization: 'Bearer abcd'
354 }
355 }
356 })
357 rbac
358 .authorizeRemoteAnd(['users:read', 'users:blackhole'])
359 .then(() => Code.fail('Rbac.authorize should fail'))
360 .catch((err) => {
361 expect(err.statusCode).to.equal(401)
362 done()
363 })
364 })
365
366 it("should fail if user isn't allowed any of the permissions", function (done) {
367 const rbac = new Rbac({
368 remoteAuth: {
369 url: 'http://www.example.com/authorize'
370 }
371 })
372 const middleware = rbac
373 .express
374 .authorizeRemoteOr(['users:void', 'users:blank'])
375
376 const req = {
377 headers: {
378 authorization: 'Bearer abcd'
379 }
380 }
381
382 middleware(req, null, (err) => {
383 expect(err).to.be.an.error()
384 expect(err.isBoom).to.exist().and.be.true()
385 expect(err.output.statusCode).to.exist().and.equal(401)
386 done()
387 })
388 })
389
390 it('should pass if user is allowed all permissions', function (done) {
391 const rbac = new Rbac({
392 remoteAuth: {
393 url: 'http://www.example.com/authorize',
394 headers: {
395 authorization: 'Bearer abcd'
396 }
397 }
398 })
399 rbac
400 .authorizeRemoteOr(['users:read:and', 'users:create:and'])
401 .then(() => done())
402 .catch(done)
403 })
404 })
405 // "Rbac.express.authorizeRemoteAnd" method END
406
407 // "Rbac.express.authorize" method START
408 describe('- Rbac.express.authorize', () => {
409 it("should fail if user isn't allowed the existing permission", function (done) {
410 const rbac = new Rbac({ getPermission: getPermission })
411 const middleware = rbac
412 .express
413 .authorize('users:create')
414
415 const req = {
416 user: {
417 id: 1
418 }
419 }
420
421 middleware(req, null, (err) => {
422 expect(err).to.be.an.error()
423 expect(err.isBoom).to.exist().and.be.true()
424 expect(err.output.statusCode).to.exist().and.equal(401)
425 done()
426 })
427 })
428
429 it('should pass if user is allowed the existing permission', function (done) {
430 const rbac = new Rbac({ getPermission: getPermission })
431 const middleware = rbac
432 .express
433 .authorize('users:read')
434
435 const req = {
436 user: {
437 id: 1
438 }
439 }
440
441 middleware(req, null, (err) => {
442 expect(err).to.be.undefined()
443 done()
444 })
445 })
446
447 it('should allow for userId being set', function (done) {
448 const rbac = new Rbac({
449 getPermission: getPermission,
450 getReqId: (req) => req.some.prop
451 })
452 const middleware = rbac
453 .express
454 .authorize('users:read')
455
456 const req = {
457 some: {
458 prop: 1
459 }
460 }
461
462 middleware(req, null, (err) => {
463 expect(err).to.be.undefined()
464 done()
465 })
466 })
467 })
468// "Rbac.express.authorize" method END
469})