expressa 2.0.4 → 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/controllers/collections.js +23 -10
- package/package.json +1 -1
- package/test/testutils.js +1 -0
- package/test/users.js +114 -0
|
@@ -14,13 +14,11 @@ async function validateDocumentOwner(req, doc) {
|
|
|
14
14
|
if (!doc.meta.owner_collection) {
|
|
15
15
|
throw new util.ApiError(417, 'no owner_collection for owner found')
|
|
16
16
|
}
|
|
17
|
-
if (doc._id
|
|
17
|
+
if (!(doc._id === doc.meta.owner && req.params.collection === doc.meta.owner_collection)) {
|
|
18
18
|
const count = await req.db[doc.meta.owner_collection].count({ _id: doc.meta.owner }, undefined, 1)
|
|
19
19
|
if (!count) {
|
|
20
20
|
throw new util.ApiError(417, 'invalid owner')
|
|
21
21
|
}
|
|
22
|
-
} else if (req.params.collection !== doc.meta.owner_collection) {
|
|
23
|
-
throw new util.ApiError(417, 'invalid owner collection')
|
|
24
22
|
}
|
|
25
23
|
}
|
|
26
24
|
|
|
@@ -167,22 +165,37 @@ exports.getById = async function (req) {
|
|
|
167
165
|
exports.replaceById = async function (req) {
|
|
168
166
|
assertValidCollection(req)
|
|
169
167
|
req.customResponseData = req.customResponseData || {}
|
|
168
|
+
const data = req.body
|
|
170
169
|
let oldDoc = {}
|
|
171
170
|
try {
|
|
172
171
|
oldDoc = await req.db[req.params.collection].get(req.params.id)
|
|
173
172
|
} catch (error) {
|
|
174
173
|
// happens when new documents are created via a PUT
|
|
175
|
-
|
|
176
|
-
|
|
174
|
+
oldDoc = { meta: { owner: req.user._id, owner_collection: 'users' } }
|
|
175
|
+
data._id = req.params.id.trim()
|
|
176
|
+
await setDocumentOwner(req, data)
|
|
177
|
+
}
|
|
178
|
+
if (data._id) {
|
|
179
|
+
data._id = data._id.trim()
|
|
180
|
+
} else {
|
|
181
|
+
data._id = req.params.id.trim()
|
|
177
182
|
}
|
|
178
|
-
const data = req.body
|
|
179
|
-
data._id = req.params.id
|
|
180
183
|
data.meta = data.meta || {}
|
|
181
184
|
data.meta.created = (oldDoc.meta || {}).created
|
|
182
|
-
data.meta.owner
|
|
185
|
+
if (data.meta.owner !== oldDoc.meta.owner || data.meta.owner_collection !== oldDoc.meta.owner_ollection) {
|
|
186
|
+
if (req.hasPermission(`${req.params.collection}: modify owner`)) {
|
|
187
|
+
if (oldDoc.meta.owner) {
|
|
188
|
+
await validateDocumentOwner(req, data)
|
|
189
|
+
}
|
|
190
|
+
} else {
|
|
191
|
+
debug('attempting to change document owner.')
|
|
192
|
+
data.meta.owner = oldDoc.meta.owner
|
|
193
|
+
data.meta.owner_collection = oldDoc.meta.owner_collection
|
|
194
|
+
}
|
|
195
|
+
}
|
|
183
196
|
await util.notify('put', req, req.params.collection, data)
|
|
184
|
-
await req.db[req.params.collection].update(req.params.id,
|
|
185
|
-
await util.notify('changed', req, req.params.collection,
|
|
197
|
+
await req.db[req.params.collection].update(req.params.id, data)
|
|
198
|
+
await util.notify('changed', req, req.params.collection, data)
|
|
186
199
|
return {
|
|
187
200
|
status: 'OK',
|
|
188
201
|
id: data._id,
|
package/package.json
CHANGED
package/test/testutils.js
CHANGED
package/test/users.js
CHANGED
|
@@ -232,6 +232,50 @@ describe('user functionality', function () {
|
|
|
232
232
|
expect(res2.body.meta.owner).to.equal(user._id)
|
|
233
233
|
})
|
|
234
234
|
|
|
235
|
+
it('cannot change owner with a PUT by default', async function () {
|
|
236
|
+
const token = await testutils.getUserWithPermissions(api, ['users: view', 'users: edit', 'users: view hashed passwords'])
|
|
237
|
+
|
|
238
|
+
const res = await request(app)
|
|
239
|
+
.get(`/users/me`)
|
|
240
|
+
.set('x-access-token', token)
|
|
241
|
+
const newUser = JSON.parse(JSON.stringify(res.body))
|
|
242
|
+
|
|
243
|
+
res.body.meta.owner = user._id
|
|
244
|
+
await request(app)
|
|
245
|
+
.put(`/users/${newUser._id}`)
|
|
246
|
+
.set('x-access-token', token)
|
|
247
|
+
.send(res.body)
|
|
248
|
+
.expect(200)
|
|
249
|
+
|
|
250
|
+
const res2 = await request(app)
|
|
251
|
+
.get(`/users/${newUser._id}`)
|
|
252
|
+
.set('x-access-token', token)
|
|
253
|
+
expect(res2.body.meta.owner).to.not.equal(user._id)
|
|
254
|
+
expect(res2.body.meta.owner).to.equal(newUser._id)
|
|
255
|
+
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
it('can change owner with a PUT with correct permission', async function () {
|
|
259
|
+
const token = await testutils.getUserWithPermissions(api, ['users: view', 'users: edit', 'users: view hashed passwords', 'users: modify owner'])
|
|
260
|
+
|
|
261
|
+
const res = await request(app)
|
|
262
|
+
.get(`/users/me`)
|
|
263
|
+
.set('x-access-token', token)
|
|
264
|
+
const newUser = JSON.parse(JSON.stringify(res.body))
|
|
265
|
+
|
|
266
|
+
res.body.meta.owner = user._id
|
|
267
|
+
await request(app)
|
|
268
|
+
.put(`/users/${newUser._id}`)
|
|
269
|
+
.set('x-access-token', token)
|
|
270
|
+
.send(res.body) // try change owner to another user
|
|
271
|
+
.expect(200)
|
|
272
|
+
|
|
273
|
+
const res2 = await request(app)
|
|
274
|
+
.get(`/users/${newUser._id}`)
|
|
275
|
+
.set('x-access-token', token)
|
|
276
|
+
expect(res2.body.meta.owner).to.equal(user._id)
|
|
277
|
+
})
|
|
278
|
+
|
|
235
279
|
it('changing to bogus owner fails', async function () {
|
|
236
280
|
const token = await testutils.getUserWithPermissions(api, ['users: view', 'users: edit', 'users: modify owner'])
|
|
237
281
|
|
|
@@ -308,4 +352,74 @@ describe('user functionality', function () {
|
|
|
308
352
|
expect(res3.body.meta.owner).to.not.equal(newUser._id)
|
|
309
353
|
expect(res3.body.meta.owner).to.equal(user._id)
|
|
310
354
|
})
|
|
355
|
+
|
|
356
|
+
it('cannot set owner with a PUT on creation by default', async function () {
|
|
357
|
+
const token = await testutils.getUserWithPermissions(api, ['users: view', 'users: edit', 'testdoc: edit', 'testdoc: view own'])
|
|
358
|
+
|
|
359
|
+
const res = await request(app)
|
|
360
|
+
.get(`/users/me`)
|
|
361
|
+
.set('x-access-token', token)
|
|
362
|
+
const newUser = res.body
|
|
363
|
+
|
|
364
|
+
const doc = {
|
|
365
|
+
title: 'Test Title',
|
|
366
|
+
meta: {
|
|
367
|
+
owner: user._id,
|
|
368
|
+
owner_collection: 'users',
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const docId = testutils.generateDocumentId()
|
|
373
|
+
|
|
374
|
+
const res2 = await request(app)
|
|
375
|
+
.put(`/testdoc/${docId}`)
|
|
376
|
+
.set('x-access-token', token)
|
|
377
|
+
.send(doc)
|
|
378
|
+
.expect(200) // will succeed but owner will not change
|
|
379
|
+
|
|
380
|
+
expect(res2.body.id).to.equal(docId)
|
|
381
|
+
doc._id = docId
|
|
382
|
+
|
|
383
|
+
const res3 = await request(app)
|
|
384
|
+
.get(`/testdoc/${doc._id}`)
|
|
385
|
+
.set('x-access-token', token)
|
|
386
|
+
.expect(200)
|
|
387
|
+
expect(res3.body.meta.owner).to.not.equal(user._id)
|
|
388
|
+
expect(res3.body.meta.owner).to.equal(newUser._id)
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
it('can set owner with a PUT on creation with correct permission', async function () {
|
|
392
|
+
const token = await testutils.getUserWithPermissions(api, ['users: view', 'users: edit', 'testdoc: edit', 'testdoc: view', 'testdoc: modify owner'])
|
|
393
|
+
|
|
394
|
+
const res = await request(app)
|
|
395
|
+
.get(`/users/me`)
|
|
396
|
+
.set('x-access-token', token)
|
|
397
|
+
const newUser = res.body
|
|
398
|
+
|
|
399
|
+
const doc = {
|
|
400
|
+
title: 'Test Title',
|
|
401
|
+
meta: {
|
|
402
|
+
owner: user._id,
|
|
403
|
+
owner_collection: 'users',
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const docId = testutils.generateDocumentId()
|
|
408
|
+
|
|
409
|
+
const res2 = await request(app)
|
|
410
|
+
.put(`/testdoc/${docId}`)
|
|
411
|
+
.set('x-access-token', token)
|
|
412
|
+
.send(doc)
|
|
413
|
+
.expect(200) // will succeed but owner will not change
|
|
414
|
+
|
|
415
|
+
expect(res2.body.id).to.equal(docId)
|
|
416
|
+
doc._id = docId
|
|
417
|
+
|
|
418
|
+
const res3 = await request(app)
|
|
419
|
+
.get(`/testdoc/${doc._id}`)
|
|
420
|
+
.set('x-access-token', token)
|
|
421
|
+
.expect(200)
|
|
422
|
+
expect(res3.body.meta.owner).to.not.equal(newUser._id)
|
|
423
|
+
expect(res3.body.meta.owner).to.equal(user._id)
|
|
424
|
+
})
|
|
311
425
|
})
|