From e2144051dfc676e4cf196e665468f84a76f4d863 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Thu, 24 May 2018 22:15:36 -0700 Subject: [PATCH] Fixed returning sensitive data in documents.info --- app/stores/UiStore.js | 2 +- server/api/documents.js | 8 +++++--- server/api/documents.test.js | 26 ++++++++++++++++++++++++-- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/app/stores/UiStore.js b/app/stores/UiStore.js index dda930c1e..109ee725e 100644 --- a/app/stores/UiStore.js +++ b/app/stores/UiStore.js @@ -30,7 +30,7 @@ class UiStore { this.activeDocumentId = document.id; if (document.publishedAt) { - this.activeCollectionId = document.collection.id; + this.activeCollectionId = document.collectionId; } }; diff --git a/server/api/documents.js b/server/api/documents.js index 30d7e7fc5..099751d77 100644 --- a/server/api/documents.js +++ b/server/api/documents.js @@ -10,7 +10,7 @@ import events from '../events'; import policy from '../policies'; const Op = Sequelize.Op; -const { authorize } = policy; +const { authorize, cannot } = policy; const router = new Router(); router.post('documents.list', auth(), pagination(), async ctx => { @@ -161,7 +161,7 @@ router.post('documents.info', auth({ required: false }), async ctx => { const { id, shareId } = ctx.body; ctx.assertPresent(id || shareId, 'id or shareId is required'); - const isPublic = !!shareId; + const user = ctx.state.user; let document; if (shareId) { @@ -177,9 +177,11 @@ router.post('documents.info', auth({ required: false }), async ctx => { document = share.document; } else { document = await Document.findById(id); - authorize(ctx.state.user, 'read', document); + authorize(user, 'read', document); } + const isPublic = cannot(user, 'read', document); + ctx.body = { data: await presentDocument(ctx, document, { isPublic }), }; diff --git a/server/api/documents.test.js b/server/api/documents.test.js index ba5ef342c..e38f1a2c3 100644 --- a/server/api/documents.test.js +++ b/server/api/documents.test.js @@ -36,8 +36,27 @@ describe('#documents.info', async () => { expect(body.data.id).toEqual(document.id); }); - it('should return documents from shareId', async () => { - const { user, document } = await seed(); + it('should return redacted documents from shareId without token', async () => { + const { document } = await seed(); + const share = await buildShare({ + documentId: document.id, + teamId: document.teamId, + }); + + const res = await server.post('/api/documents.info', { + body: { shareId: share.id }, + }); + const body = await res.json(); + + expect(res.status).toEqual(200); + expect(body.data.id).toEqual(document.id); + expect(body.data.collection).toEqual(undefined); + expect(body.data.createdBy).toEqual(undefined); + expect(body.data.updatedBy).toEqual(undefined); + }); + + it('should return documents from shareId with token', async () => { + const { user, document, collection } = await seed(); const share = await buildShare({ documentId: document.id, teamId: document.teamId, @@ -50,6 +69,9 @@ describe('#documents.info', async () => { expect(res.status).toEqual(200); expect(body.data.id).toEqual(document.id); + expect(body.data.collection.id).toEqual(collection.id); + expect(body.data.createdBy.id).toEqual(user.id); + expect(body.data.updatedBy.id).toEqual(user.id); }); });