1 | var tape = require('tape')
|
2 | var pull = require('pull-stream')
|
3 | var pushable = require('pull-pushable')
|
4 | var mux = require('../')
|
5 | var cont = require('cont')
|
6 | var Permissions = require('../permissions')
|
7 |
|
8 | var api = {
|
9 | login : 'async',
|
10 | logout : 'async',
|
11 | get : 'async',
|
12 | put : 'async',
|
13 | del : 'async',
|
14 | read : 'source',
|
15 | nested: {
|
16 | get : 'async',
|
17 | put : 'async',
|
18 | del : 'async',
|
19 | read : 'source'
|
20 | }
|
21 | }
|
22 |
|
23 | function id (e) {
|
24 | return e
|
25 | }
|
26 |
|
27 | var store = {
|
28 | foo: 1,
|
29 | bar: 2,
|
30 | baz: 3
|
31 | }
|
32 |
|
33 | function createServerAPI (store) {
|
34 | var rpc
|
35 | var name = 'nobody'
|
36 |
|
37 |
|
38 |
|
39 | var perms = Permissions({allow: ['login']})
|
40 |
|
41 | var session = {
|
42 |
|
43 |
|
44 |
|
45 | login: function (opts, cb) {
|
46 |
|
47 | if(opts.name === 'user' && opts.pass === "password")
|
48 | perms({deny: ['put', 'del'], allow: null})
|
49 |
|
50 |
|
51 | else if(opts.name === 'admin' && opts.pass === "admin")
|
52 | perms({deny: null, allow: null})
|
53 |
|
54 |
|
55 | else if(opts.name === 'nested' && opts.pass === 'foofoo')
|
56 | perms({
|
57 |
|
58 | allow: ['nested'],
|
59 | deny: [['nested', 'put'], ['nested', 'del']]
|
60 | })
|
61 |
|
62 |
|
63 | else
|
64 | return cb(new Error('not authorized'))
|
65 |
|
66 | name = opts.name
|
67 |
|
68 | cb(null, {okay: true, name: name})
|
69 | },
|
70 | logout: function (cb) {
|
71 | name = 'nobody'
|
72 | perms({allow: ['login'], deny: null})
|
73 | cb(null, {okay: true, user: name})
|
74 | },
|
75 | whoami: function (cb) {
|
76 | cb(null, {okay: true, user: name})
|
77 | },
|
78 | get: function (key, cb) {
|
79 | return cb(null, store[key])
|
80 | },
|
81 | put: function (key, value, cb) {
|
82 | store[key] = value
|
83 | cb()
|
84 | },
|
85 | del: function (key, cb) {
|
86 | delete store[key]
|
87 | cb()
|
88 | },
|
89 | read: function () {
|
90 | return pull.values(
|
91 | Object.keys(store).map(function (k) {
|
92 | return {key: k, value: store[k]}
|
93 | })
|
94 | )
|
95 | }
|
96 | }
|
97 |
|
98 | session.nested = session
|
99 |
|
100 | return rpc = mux(null, api, id)(session, perms)
|
101 | }
|
102 |
|
103 | function createClientAPI() {
|
104 | return mux(api, null, id)()
|
105 | }
|
106 |
|
107 | tape('secure rpc', function (t) {
|
108 |
|
109 | var server = createServerAPI(store)
|
110 | var client = createClientAPI()
|
111 |
|
112 | var ss = server.createStream()
|
113 | var cs = client.createStream()
|
114 |
|
115 | pull(cs, ss, cs)
|
116 |
|
117 | cont.para([
|
118 | function (cb) {
|
119 | client.get('foo', function (err) {
|
120 | t.ok(err); cb()
|
121 | })
|
122 | },
|
123 | function (cb) {
|
124 | client.put('foo', function (err) {
|
125 | t.ok(err); cb()
|
126 | })
|
127 | },
|
128 | function (cb) {
|
129 | client.del('foo', function (err) {
|
130 | t.ok(err); cb()
|
131 | })
|
132 | },
|
133 | function (cb) {
|
134 | pull(client.read(), pull.collect(function (err) {
|
135 | t.ok(err); cb()
|
136 | }))
|
137 | }
|
138 | ])(function (err) {
|
139 | client.login({name: 'user', pass: 'password'}, function (err, res) {
|
140 | if(err) throw err
|
141 | t.ok(res.okay)
|
142 | console.log(res)
|
143 | t.equal(res.name, 'user')
|
144 |
|
145 | cont.para([
|
146 | function (cb) {
|
147 | client.get('foo', function (err, value) {
|
148 | if(err) throw err
|
149 | t.equal(value, 1)
|
150 | cb()
|
151 | })
|
152 | },
|
153 | function (cb) {
|
154 | client.put('foo', -1, function (err) {
|
155 | t.ok(err); cb()
|
156 | })
|
157 | },
|
158 | function (cb) {
|
159 | client.del('foo', function (err) {
|
160 | t.ok(err); cb()
|
161 | })
|
162 | },
|
163 | function (cb) {
|
164 | pull(client.read(), pull.collect(function (err, ary) {
|
165 | if(err) throw err
|
166 | t.deepEqual(ary, [
|
167 | {key: 'foo', value: 1},
|
168 | {key: 'bar', value: 2},
|
169 | {key: 'baz', value: 3},
|
170 | ]); cb()
|
171 | }))
|
172 | }
|
173 | ])(function (err) {
|
174 | t.end()
|
175 | })
|
176 | })
|
177 | })
|
178 |
|
179 | })
|
180 |
|
181 | tape('multiple sessions at once', function (t) {
|
182 |
|
183 | var server1 = createServerAPI(store)
|
184 | var server2 = createServerAPI(store)
|
185 | var admin = createClientAPI()
|
186 | var user = createClientAPI()
|
187 |
|
188 | var s1s = server1.createStream()
|
189 | var s2s = server2.createStream()
|
190 | var us = user.createStream()
|
191 | var as = admin.createStream()
|
192 |
|
193 | pull(us, s1s, us)
|
194 | pull(as, s2s, as)
|
195 |
|
196 | cont.para([
|
197 | function (cb) {
|
198 | user.login({name: 'user', pass: 'password'}, cb)
|
199 | },
|
200 | function (cb) {
|
201 | admin.login({name: 'admin', pass: 'admin'}, cb)
|
202 | }
|
203 | ])(function (err) {
|
204 | if(err) throw err
|
205 |
|
206 | user.get('foo', function (err, value) {
|
207 | if(err) throw err
|
208 | t.equal(value, 1)
|
209 | admin.put('foo', 2, function (err) {
|
210 | if(err) throw err
|
211 | user.get('foo', function (err, value) {
|
212 | if(err) throw err
|
213 | t.equal(value, 2)
|
214 | t.end()
|
215 | })
|
216 | })
|
217 | })
|
218 |
|
219 | })
|
220 |
|
221 | })
|
222 |
|
223 | tape('nested sessions', function (t) {
|
224 | var server = createServerAPI(store)
|
225 | var client = createClientAPI()
|
226 |
|
227 | var ss = server.createStream()
|
228 | var cs = client.createStream()
|
229 |
|
230 | pull(cs, ss, cs)
|
231 |
|
232 | cont.para([
|
233 | function (cb) {
|
234 | client.nested.get('foo', function (err) {
|
235 | t.ok(err); cb()
|
236 | })
|
237 | },
|
238 | function (cb) {
|
239 | client.nested.put('foo', function (err) {
|
240 | t.ok(err); cb()
|
241 | })
|
242 | },
|
243 | function (cb) {
|
244 | client.nested.del('foo', function (err) {
|
245 | t.ok(err); cb()
|
246 | })
|
247 | },
|
248 | function (cb) {
|
249 | pull(client.nested.read(), pull.collect(function (err) {
|
250 | t.ok(err); cb()
|
251 | }))
|
252 | }
|
253 | ])(function (err) {
|
254 | client.login({name: 'nested', pass: 'foofoo'}, function (err, res) {
|
255 | cont.para([
|
256 | function (cb) {
|
257 | client.nested.get('foo', function (err, value) {
|
258 | if(err) throw err
|
259 | t.equal(value, 2, 'foo should be 2')
|
260 | cb()
|
261 | })
|
262 | },
|
263 | function (cb) {
|
264 | client.nested.put('foo', -1, function (err) {
|
265 | t.ok(err); cb()
|
266 | })
|
267 | },
|
268 | function (cb) {
|
269 | client.nested.del('foo', function (err) {
|
270 | t.ok(err); cb()
|
271 | })
|
272 | },
|
273 | function (cb) {
|
274 | pull(client.nested.read(), pull.collect(function (err, ary) {
|
275 | if(err) throw err
|
276 | t.deepEqual(ary, [
|
277 | {key: 'foo', value: 2},
|
278 | {key: 'bar', value: 2},
|
279 | {key: 'baz', value: 3},
|
280 | ]); cb()
|
281 | }))
|
282 | }
|
283 | ])(function (err) {
|
284 |
|
285 | t.end()
|
286 | })
|
287 | })
|
288 | })
|
289 |
|
290 | })
|