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.
@@ -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 = (oldDoc.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, req.body)
184
- await util.notify('changed', req, req.params.collection, req.body)
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
@@ -114,6 +114,7 @@ module.exports.api = function (settings) {
114
114
  return util.getPgPool(router.settings.postgresql_uri)
115
115
  },
116
116
  doLogin: auth.doLogin,
117
+ createHash: auth.createHash,
117
118
  ...util,
118
119
  }
119
120
  router.eventListeners = {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expressa",
3
- "version": "2.0.3",
3
+ "version": "2.0.5",
4
4
  "description": "API framework using JSON schemas",
5
5
  "main": "index.js",
6
6
  "repository": "https://github.com/thomas4019/expressa",
package/test/testutils.js CHANGED
@@ -85,3 +85,4 @@ exports.clone = util.clone
85
85
  exports.sleep = function sleep(ms) {
86
86
  return new Promise(resolve => setTimeout(resolve, ms))
87
87
  }
88
+ exports.generateDocumentId = util.generateDocumentId
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