expressa 2.0.3 → 2.0.5
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 +27 -6
- package/index.js +1 -0
- package/package.json +1 -1
- package/test/testutils.js +1 -0
- package/test/users.js +114 -0
- package/util.js +3 -1
|
@@ -167,21 +167,37 @@ exports.getById = async function (req) {
|
|
|
167
167
|
exports.replaceById = async function (req) {
|
|
168
168
|
assertValidCollection(req)
|
|
169
169
|
req.customResponseData = req.customResponseData || {}
|
|
170
|
+
const data = req.body
|
|
170
171
|
let oldDoc = {}
|
|
171
172
|
try {
|
|
172
173
|
oldDoc = await req.db[req.params.collection].get(req.params.id)
|
|
173
174
|
} catch (error) {
|
|
174
175
|
// happens when new documents are created via a PUT
|
|
175
|
-
oldDoc = { meta: { owner: req.user._id } }
|
|
176
|
+
oldDoc = { meta: { owner: req.user._id, owner_collection: 'users' } }
|
|
177
|
+
data._id = req.params.id.trim()
|
|
178
|
+
await setDocumentOwner(req, data)
|
|
179
|
+
}
|
|
180
|
+
if (data._id) {
|
|
181
|
+
data._id = data._id.trim()
|
|
182
|
+
} else {
|
|
183
|
+
data._id = req.params.id.trim()
|
|
176
184
|
}
|
|
177
|
-
const data = req.body
|
|
178
|
-
data._id = req.params.id
|
|
179
185
|
data.meta = data.meta || {}
|
|
180
186
|
data.meta.created = (oldDoc.meta || {}).created
|
|
181
|
-
data.meta.owner
|
|
187
|
+
if (data.meta.owner !== oldDoc.meta.owner || data.meta.owner_collection !== oldDoc.meta.owner_ollection) {
|
|
188
|
+
if (req.hasPermission(`${req.params.collection}: modify owner`)) {
|
|
189
|
+
if (oldDoc.meta.owner) {
|
|
190
|
+
await validateDocumentOwner(req, data)
|
|
191
|
+
}
|
|
192
|
+
} else {
|
|
193
|
+
debug('attempting to change document owner.')
|
|
194
|
+
data.meta.owner = oldDoc.meta.owner
|
|
195
|
+
data.meta.owner_collection = oldDoc.meta.owner_collection
|
|
196
|
+
}
|
|
197
|
+
}
|
|
182
198
|
await util.notify('put', req, req.params.collection, data)
|
|
183
|
-
await req.db[req.params.collection].update(req.params.id,
|
|
184
|
-
await util.notify('changed', req, req.params.collection,
|
|
199
|
+
await req.db[req.params.collection].update(req.params.id, data)
|
|
200
|
+
await util.notify('changed', req, req.params.collection, data)
|
|
185
201
|
return {
|
|
186
202
|
status: 'OK',
|
|
187
203
|
id: data._id,
|
|
@@ -211,6 +227,11 @@ exports.updateById = async function (req) {
|
|
|
211
227
|
doc.meta.owner_collection = ownerCollection
|
|
212
228
|
}
|
|
213
229
|
}
|
|
230
|
+
if (doc._id) {
|
|
231
|
+
doc._id = doc._id.trim()
|
|
232
|
+
} else {
|
|
233
|
+
throw new util.ApiError(400, '_id property is required')
|
|
234
|
+
}
|
|
214
235
|
req.body = doc
|
|
215
236
|
await util.notify('put', req, req.params.collection, doc)
|
|
216
237
|
await req.db[req.params.collection].update(req.params.id, req.body)
|
package/index.js
CHANGED
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
|
})
|
package/util.js
CHANGED
|
@@ -338,7 +338,9 @@ exports.generateDocumentId = function generateDocumentId() {
|
|
|
338
338
|
|
|
339
339
|
exports.addIdIfMissing = function addIdIfMissing (document) {
|
|
340
340
|
if (!document._id) {
|
|
341
|
-
document._id = exports.generateDocumentId()
|
|
341
|
+
document._id = exports.generateDocumentId().trim()
|
|
342
|
+
} else {
|
|
343
|
+
document._id = document._id.trim()
|
|
342
344
|
}
|
|
343
345
|
}
|
|
344
346
|
|