1 |
|
2 | const { expect } = require('chai');
|
3 |
|
4 | const Grown = require('../../..')();
|
5 |
|
6 | Grown.use(require('../../test'));
|
7 | Grown.use(require('..'));
|
8 |
|
9 |
|
10 |
|
11 | describe('Grown.Access', () => {
|
12 | let server;
|
13 |
|
14 | beforeEach(() => {
|
15 | server = new Grown();
|
16 | server.mount(conn => conn.req.end());
|
17 | server.plug(Grown.Test);
|
18 | });
|
19 |
|
20 | it('should validate given input', () => {
|
21 | expect(() => server.plug(Grown.Access.rules())).to.throw('No role-groups were defined');
|
22 | expect(() => server.plug(Grown.Access.rules({ roles: 'Foo.Bar' }))).to.throw('Ruleset cannot be empty');
|
23 | });
|
24 |
|
25 | it('should allow requests without access', () => {
|
26 | return server.request('/im_not_exists', (err, conn) => {
|
27 | expect(conn.res.statusCode).to.eql(200);
|
28 | });
|
29 | });
|
30 |
|
31 | it('should warn about invalid routes', () => {
|
32 | expect(() => server.plug(Grown.Access.rules({
|
33 | roles: 'Guest',
|
34 | resources: {
|
35 | Sample: /^test/,
|
36 | Broken: '/x-path(',
|
37 | },
|
38 | }))).to.throw("Cannot compile '/x-path(' as route handler");
|
39 | });
|
40 |
|
41 | describe('Resources', () => {
|
42 | let role;
|
43 |
|
44 | beforeEach(() => {
|
45 | server.plug(Grown.Access({
|
46 | access_filter: () => role,
|
47 | access_rules: {
|
48 | roles: [
|
49 | 'Guest.User.Editor.Admin',
|
50 | ],
|
51 | resources: {
|
52 | Fixed: '/**',
|
53 | Public: '/ok',
|
54 | System: '/admin',
|
55 | Dynamic: '/testing',
|
56 | Example: '/protected',
|
57 | 'Example.create': 'POST /protected',
|
58 | },
|
59 | permissions: {
|
60 | Example: {
|
61 | Admin: 'allow',
|
62 | },
|
63 | System: {
|
64 | Admin: 'allow',
|
65 | Editor: 'inherit',
|
66 | },
|
67 | Public: {
|
68 | Guest: 'allow',
|
69 | User: 'deny',
|
70 | },
|
71 | Fixed: {
|
72 | User: 'inherit',
|
73 | },
|
74 | Dynamic: {
|
75 | Guest: conn => conn.req.headers['x-password'] === '42',
|
76 | },
|
77 | },
|
78 | },
|
79 | }));
|
80 | });
|
81 |
|
82 | it('should validate all requested resources', () => {
|
83 | return server.request('/im_not_exists', (err, conn) => {
|
84 | expect(conn.res.statusCode).to.eql(403);
|
85 | expect(conn.res.statusMessage).to.eql('Forbidden');
|
86 | expect(conn.res.getHeader('X-Failure')).to.eql('Access denied for role: Unknown');
|
87 | });
|
88 | });
|
89 |
|
90 | it('should allow some protected resources', () => {
|
91 | role = 'Admin';
|
92 | return server.request('/protected', (err, conn) => {
|
93 | expect(conn.res.statusCode).to.eql(200);
|
94 | expect(conn.res.statusMessage).to.eql('OK');
|
95 | });
|
96 | });
|
97 |
|
98 | it('should deny some protected resources', () => {
|
99 | role = 'User';
|
100 | return server.request('/protected', (err, conn) => {
|
101 | expect(conn.res.statusCode).to.eql(403);
|
102 | expect(conn.res.statusMessage).to.eql('Forbidden');
|
103 | expect(conn.res.getHeader('X-Failure')).to.eql('Access denied for role: User');
|
104 | });
|
105 | });
|
106 |
|
107 | it('should allow inheritance of access', () => {
|
108 | role = 'Editor';
|
109 | return server.request('/admin', (err, conn) => {
|
110 | expect(conn.res.statusCode).to.eql(200);
|
111 | expect(conn.res.statusMessage).to.eql('OK');
|
112 | });
|
113 | });
|
114 |
|
115 | it('should allow denial of some resources', () => {
|
116 | role = 'User';
|
117 | return server.request('/ok', (err, conn) => {
|
118 | expect(conn.res.statusCode).to.eql(403);
|
119 | expect(conn.res.statusMessage).to.eql('Forbidden');
|
120 | expect(conn.res.getHeader('X-Failure')).to.eql('Access denied for role: User');
|
121 | });
|
122 | });
|
123 |
|
124 | it('should allow access by inheritance', () => {
|
125 | role = 'Admin';
|
126 | return server.request('/ok', (err, conn) => {
|
127 | expect(conn.res.statusCode).to.eql(200);
|
128 | expect(conn.res.statusMessage).to.eql('OK');
|
129 | });
|
130 | });
|
131 |
|
132 | it('should inherit from previous access', () => {
|
133 | role = 'User';
|
134 | return server.request('/x', (err, conn) => {
|
135 | expect(conn.res.statusCode).to.eql(200);
|
136 | expect(conn.res.statusMessage).to.eql('OK');
|
137 | });
|
138 | });
|
139 |
|
140 | it('should allow dynamic permissions', () => {
|
141 | role = 'Guest';
|
142 | return server.request('/testing', {
|
143 | headers: {
|
144 | 'x-password': 42,
|
145 | },
|
146 | }, (err, conn) => {
|
147 | expect(conn.res.statusCode).to.eql(200);
|
148 | expect(conn.res.statusMessage).to.eql('OK');
|
149 | });
|
150 | });
|
151 |
|
152 | it('should allow static check() calls', () => {
|
153 | return server.request('/', (err, conn) => Promise.resolve()
|
154 | .then(() => conn.check('Guest', ['Example', 'create'])
|
155 | .catch(e => expect(e.message).to.eql('Access denied for role: Guest')))
|
156 | .then(() => conn.check('Guest', 'Example', 'create')
|
157 | .catch(e => expect(e.message).to.eql('Access denied for role: Guest')))
|
158 | .then(() => conn.check('Other', 'Example')
|
159 | .catch(e => expect(e.message).to.eql('Access denied for role: Other')))
|
160 | .then(() => expect(err).to.be.null));
|
161 | });
|
162 | });
|
163 | });
|