• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict'
2
3const figgyPudding = require('figgy-pudding')
4const getStream = require('get-stream')
5const {test} = require('tap')
6const tnock = require('./util/tnock.js')
7
8const access = require('../index.js')
9
10const REG = 'http://localhost:1337'
11const OPTS = figgyPudding({})({
12  registry: REG
13})
14
15test('access public', t => {
16  tnock(t, REG).post(
17    '/-/package/%40foo%2Fbar/access', {access: 'public'}
18  ).reply(200)
19  return access.public('@foo/bar', OPTS).then(ret => {
20    t.deepEqual(ret, true, 'request succeeded')
21  })
22})
23
24test('access restricted', t => {
25  tnock(t, REG).post(
26    '/-/package/%40foo%2Fbar/access', {access: 'restricted'}
27  ).reply(200)
28  return access.restricted('@foo/bar', OPTS).then(ret => {
29    t.deepEqual(ret, true, 'request succeeded')
30  })
31})
32
33test('access 2fa-required', t => {
34  tnock(t, REG).post('/-/package/%40foo%2Fbar/access', {
35    publish_requires_tfa: true
36  }).reply(200, {ok: true})
37  return access.tfaRequired('@foo/bar', OPTS).then(ret => {
38    t.deepEqual(ret, true, 'request succeeded')
39  })
40})
41
42test('access 2fa-not-required', t => {
43  tnock(t, REG).post('/-/package/%40foo%2Fbar/access', {
44    publish_requires_tfa: false
45  }).reply(200, {ok: true})
46  return access.tfaNotRequired('@foo/bar', OPTS).then(ret => {
47    t.deepEqual(ret, true, 'request succeeded')
48  })
49})
50
51test('access grant basic read-write', t => {
52  tnock(t, REG).put('/-/team/myorg/myteam/package', {
53    package: '@foo/bar',
54    permissions: 'read-write'
55  }).reply(201)
56  return access.grant(
57    '@foo/bar', 'myorg:myteam', 'read-write', OPTS
58  ).then(ret => {
59    t.deepEqual(ret, true, 'request succeeded')
60  })
61})
62
63test('access grant basic read-only', t => {
64  tnock(t, REG).put('/-/team/myorg/myteam/package', {
65    package: '@foo/bar',
66    permissions: 'read-only'
67  }).reply(201)
68  return access.grant(
69    '@foo/bar', 'myorg:myteam', 'read-only', OPTS
70  ).then(ret => {
71    t.deepEqual(ret, true, 'request succeeded')
72  })
73})
74
75test('access grant bad perm', t => {
76  return access.grant(
77    '@foo/bar', 'myorg:myteam', 'unknown', OPTS
78  ).then(ret => {
79    throw new Error('should not have succeeded')
80  }, err => {
81    t.match(
82      err.message,
83      /must be.*read-write.*read-only/,
84      'only read-write and read-only are accepted'
85    )
86  })
87})
88
89test('access grant no entity', t => {
90  return access.grant(
91    '@foo/bar', undefined, 'read-write', OPTS
92  ).then(ret => {
93    throw new Error('should not have succeeded')
94  }, err => {
95    t.match(
96      err.message,
97      /Expected string/,
98      'passing undefined entity gives useful error'
99    )
100  })
101})
102
103test('access grant basic unscoped', t => {
104  tnock(t, REG).put('/-/team/myorg/myteam/package', {
105    package: 'bar',
106    permissions: 'read-write'
107  }).reply(201)
108  return access.grant(
109    'bar', 'myorg:myteam', 'read-write', OPTS
110  ).then(ret => {
111    t.deepEqual(ret, true, 'request succeeded')
112  })
113})
114
115test('access revoke basic', t => {
116  tnock(t, REG).delete('/-/team/myorg/myteam/package', {
117    package: '@foo/bar'
118  }).reply(200)
119  return access.revoke('@foo/bar', 'myorg:myteam', OPTS).then(ret => {
120    t.deepEqual(ret, true, 'request succeeded')
121  })
122})
123
124test('access revoke basic unscoped', t => {
125  tnock(t, REG).delete('/-/team/myorg/myteam/package', {
126    package: 'bar'
127  }).reply(200, {accessChanged: true})
128  return access.revoke('bar', 'myorg:myteam', OPTS).then(ret => {
129    t.deepEqual(ret, true, 'request succeeded')
130  })
131})
132
133test('ls-packages on team', t => {
134  const serverPackages = {
135    '@foo/bar': 'write',
136    '@foo/util': 'read',
137    '@foo/other': 'shrödinger'
138  }
139  const clientPackages = {
140    '@foo/bar': 'read-write',
141    '@foo/util': 'read-only',
142    '@foo/other': 'shrödinger'
143  }
144  tnock(t, REG).get(
145    '/-/team/myorg/myteam/package?format=cli'
146  ).reply(200, serverPackages)
147  return access.lsPackages('myorg:myteam', OPTS).then(data => {
148    t.deepEqual(data, clientPackages, 'got client package info')
149  })
150})
151
152test('ls-packages on org', t => {
153  const serverPackages = {
154    '@foo/bar': 'write',
155    '@foo/util': 'read',
156    '@foo/other': 'shrödinger'
157  }
158  const clientPackages = {
159    '@foo/bar': 'read-write',
160    '@foo/util': 'read-only',
161    '@foo/other': 'shrödinger'
162  }
163  tnock(t, REG).get(
164    '/-/org/myorg/package?format=cli'
165  ).reply(200, serverPackages)
166  return access.lsPackages('myorg', OPTS).then(data => {
167    t.deepEqual(data, clientPackages, 'got client package info')
168  })
169})
170
171test('ls-packages on user', t => {
172  const serverPackages = {
173    '@foo/bar': 'write',
174    '@foo/util': 'read',
175    '@foo/other': 'shrödinger'
176  }
177  const clientPackages = {
178    '@foo/bar': 'read-write',
179    '@foo/util': 'read-only',
180    '@foo/other': 'shrödinger'
181  }
182  const srv = tnock(t, REG)
183  srv.get('/-/org/myuser/package?format=cli').reply(404, {error: 'not found'})
184  srv.get('/-/user/myuser/package?format=cli').reply(200, serverPackages)
185  return access.lsPackages('myuser', OPTS).then(data => {
186    t.deepEqual(data, clientPackages, 'got client package info')
187  })
188})
189
190test('ls-packages error on team', t => {
191  tnock(t, REG).get('/-/team/myorg/myteam/package?format=cli').reply(404)
192  return access.lsPackages('myorg:myteam', OPTS).then(
193    () => { throw new Error('should not have succeeded') },
194    err => t.equal(err.code, 'E404', 'spit out 404 directly if team provided')
195  )
196})
197
198test('ls-packages error on user', t => {
199  const srv = tnock(t, REG)
200  srv.get('/-/org/myuser/package?format=cli').reply(404, {error: 'not found'})
201  srv.get('/-/user/myuser/package?format=cli').reply(404, {error: 'not found'})
202  return access.lsPackages('myuser', OPTS).then(
203    () => { throw new Error('should not have succeeded') },
204    err => t.equal(err.code, 'E404', 'spit out 404 if both reqs fail')
205  )
206})
207
208test('ls-packages bad response', t => {
209  tnock(t, REG).get(
210    '/-/team/myorg/myteam/package?format=cli'
211  ).reply(200, JSON.stringify(null))
212  return access.lsPackages('myorg:myteam', OPTS).then(data => {
213    t.deepEqual(data, null, 'succeeds with null')
214  })
215})
216
217test('ls-packages stream', t => {
218  const serverPackages = {
219    '@foo/bar': 'write',
220    '@foo/util': 'read',
221    '@foo/other': 'shrödinger'
222  }
223  const clientPackages = [
224    ['@foo/bar', 'read-write'],
225    ['@foo/util', 'read-only'],
226    ['@foo/other', 'shrödinger']
227  ]
228  tnock(t, REG).get(
229    '/-/team/myorg/myteam/package?format=cli'
230  ).reply(200, serverPackages)
231  return getStream.array(
232    access.lsPackages.stream('myorg:myteam', OPTS)
233  ).then(data => {
234    t.deepEqual(data, clientPackages, 'got streamed client package info')
235  })
236})
237
238test('ls-collaborators', t => {
239  const serverCollaborators = {
240    'myorg:myteam': 'write',
241    'myorg:anotherteam': 'read',
242    'myorg:thirdteam': 'special-case'
243  }
244  const clientCollaborators = {
245    'myorg:myteam': 'read-write',
246    'myorg:anotherteam': 'read-only',
247    'myorg:thirdteam': 'special-case'
248  }
249  tnock(t, REG).get(
250    '/-/package/%40foo%2Fbar/collaborators?format=cli'
251  ).reply(200, serverCollaborators)
252  return access.lsCollaborators('@foo/bar', OPTS).then(data => {
253    t.deepEqual(data, clientCollaborators, 'got collaborators')
254  })
255})
256
257test('ls-collaborators stream', t => {
258  const serverCollaborators = {
259    'myorg:myteam': 'write',
260    'myorg:anotherteam': 'read',
261    'myorg:thirdteam': 'special-case'
262  }
263  const clientCollaborators = [
264    ['myorg:myteam', 'read-write'],
265    ['myorg:anotherteam', 'read-only'],
266    ['myorg:thirdteam', 'special-case']
267  ]
268  tnock(t, REG).get(
269    '/-/package/%40foo%2Fbar/collaborators?format=cli'
270  ).reply(200, serverCollaborators)
271  return getStream.array(
272    access.lsCollaborators.stream('@foo/bar', OPTS)
273  ).then(data => {
274    t.deepEqual(data, clientCollaborators, 'got collaborators')
275  })
276})
277
278test('ls-collaborators w/scope', t => {
279  const serverCollaborators = {
280    'myorg:myteam': 'write',
281    'myorg:anotherteam': 'read',
282    'myorg:thirdteam': 'special-case'
283  }
284  const clientCollaborators = {
285    'myorg:myteam': 'read-write',
286    'myorg:anotherteam': 'read-only',
287    'myorg:thirdteam': 'special-case'
288  }
289  tnock(t, REG).get(
290    '/-/package/%40foo%2Fbar/collaborators?format=cli&user=zkat'
291  ).reply(200, serverCollaborators)
292  return access.lsCollaborators('@foo/bar', 'zkat', OPTS).then(data => {
293    t.deepEqual(data, clientCollaborators, 'got collaborators')
294  })
295})
296
297test('ls-collaborators w/o scope', t => {
298  const serverCollaborators = {
299    'myorg:myteam': 'write',
300    'myorg:anotherteam': 'read',
301    'myorg:thirdteam': 'special-case'
302  }
303  const clientCollaborators = {
304    'myorg:myteam': 'read-write',
305    'myorg:anotherteam': 'read-only',
306    'myorg:thirdteam': 'special-case'
307  }
308  tnock(t, REG).get(
309    '/-/package/bar/collaborators?format=cli&user=zkat'
310  ).reply(200, serverCollaborators)
311  return access.lsCollaborators('bar', 'zkat', OPTS).then(data => {
312    t.deepEqual(data, clientCollaborators, 'got collaborators')
313  })
314})
315
316test('ls-collaborators bad response', t => {
317  tnock(t, REG).get(
318    '/-/package/%40foo%2Fbar/collaborators?format=cli'
319  ).reply(200, JSON.stringify(null))
320  return access.lsCollaborators('@foo/bar', null, OPTS).then(data => {
321    t.deepEqual(data, null, 'succeeds with null')
322  })
323})
324
325test('error on non-registry specs', t => {
326  const resolve = () => { throw new Error('should not succeed') }
327  const reject = err => t.match(
328    err.message, /spec.*must be a registry spec/, 'registry spec required'
329  )
330  return Promise.all([
331    access.public('foo/bar').then(resolve, reject),
332    access.restricted('foo/bar').then(resolve, reject),
333    access.grant('foo/bar', 'myorg', 'myteam', 'read-only').then(resolve, reject),
334    access.revoke('foo/bar', 'myorg', 'myteam').then(resolve, reject),
335    access.lsCollaborators('foo/bar').then(resolve, reject),
336    access.tfaRequired('foo/bar').then(resolve, reject),
337    access.tfaNotRequired('foo/bar').then(resolve, reject)
338  ])
339})
340
341test('edit', t => {
342  t.equal(typeof access.edit, 'function', 'access.edit exists')
343  t.throws(() => {
344    access.edit()
345  }, /Not implemented/, 'directly throws NIY message')
346  t.done()
347})
348