From 237810509adff8dd4b67bd164b031fca87a5d731 Mon Sep 17 00:00:00 2001 From: Alasdair Smith Date: Mon, 24 Sep 2018 17:06:11 +0100 Subject: [PATCH] If no project found for read token, redirect to v1 --- .../TokenAccess/TokenAccessController.coffee | 6 ++- .../TokenAccess/TokenAccessHandler.coffee | 14 +++++-- .../TokenAccessControllerTests.coffee | 18 +++++---- .../TokenAccessHandlerTests.coffee | 39 ++++++++++++++++++- 4 files changed, 63 insertions(+), 14 deletions(-) diff --git a/services/web/app/coffee/Features/TokenAccess/TokenAccessController.coffee b/services/web/app/coffee/Features/TokenAccess/TokenAccessController.coffee index 08aa4663f1..ada8c6cc10 100644 --- a/services/web/app/coffee/Features/TokenAccess/TokenAccessController.coffee +++ b/services/web/app/coffee/Features/TokenAccess/TokenAccessController.coffee @@ -77,11 +77,15 @@ module.exports = TokenAccessController = userId = AuthenticationController.getLoggedInUserId(req) token = req.params['read_only_token'] logger.log {userId, token}, "[TokenAccess] requesting read-only token access" - TokenAccessHandler.findProjectWithReadOnlyToken token, (err, project) -> + TokenAccessHandler.findProjectWithReadOnlyToken token, (err, project, projectExists) -> if err? logger.err {err, token, userId}, "[TokenAccess] error getting project by readOnly token" return next(err) + if !projectExists and settings.overleaf + logger.log {token, userId}, + "[TokenAccess] no project found for this token" + return res.redirect(302, settings.overleaf.host + '/read/' + token) if !project? logger.log {token, userId}, "[TokenAccess] no project found for readOnly token" diff --git a/services/web/app/coffee/Features/TokenAccess/TokenAccessHandler.coffee b/services/web/app/coffee/Features/TokenAccess/TokenAccessHandler.coffee index ed7f51f0d7..0f785abbc8 100644 --- a/services/web/app/coffee/Features/TokenAccess/TokenAccessHandler.coffee +++ b/services/web/app/coffee/Features/TokenAccess/TokenAccessHandler.coffee @@ -10,11 +10,17 @@ module.exports = TokenAccessHandler = ANONYMOUS_READ_AND_WRITE_ENABLED: Settings.allowAnonymousReadAndWriteSharing == true - findProjectWithReadOnlyToken: (token, callback=(err, project)->) -> + findProjectWithReadOnlyToken: (token, callback=(err, project, projectExists)->) -> Project.findOne { - 'tokens.readOnly': token, - 'publicAccesLevel': PublicAccessLevels.TOKEN_BASED - }, {_id: 1, publicAccesLevel: 1, owner_ref: 1}, callback + 'tokens.readOnly': token + }, {_id: 1, publicAccesLevel: 1, owner_ref: 1}, (err, project) -> + if err? + return callback(err) + if !project? + return callback(null, null, false) + if project.publicAccesLevel != PublicAccessLevels.TOKEN_BASED + return callback(null, null, true) + return callback(null, project, true) findProjectWithReadAndWriteToken: (token, callback=(err, project)->) -> Project.findOne { diff --git a/services/web/test/unit/coffee/TokenAccess/TokenAccessControllerTests.coffee b/services/web/test/unit/coffee/TokenAccess/TokenAccessControllerTests.coffee index 0bdb6d59e6..cb9e6afa39 100644 --- a/services/web/test/unit/coffee/TokenAccess/TokenAccessControllerTests.coffee +++ b/services/web/test/unit/coffee/TokenAccess/TokenAccessControllerTests.coffee @@ -405,7 +405,7 @@ describe "TokenAccessController", -> @next = sinon.stub() @req.params['read_only_token'] = @readOnlyToken @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub() - .callsArgWith(1, null, @project) + .callsArgWith(1, null, @project, true) @TokenAccessHandler.addReadOnlyUserToProject = sinon.stub() .callsArgWith(2, null) @ProjectController.loadEditor = sinon.stub() @@ -441,7 +441,7 @@ describe "TokenAccessController", -> @req.params['read_only_token'] = @readOnlyToken @project.owner_ref = @userId @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub() - .callsArgWith(1, null, @project) + .callsArgWith(1, null, @project, true) @TokenAccessHandler.addReadOnlyUserToProject = sinon.stub() .callsArgWith(2, null) @ProjectController.loadEditor = sinon.stub() @@ -513,7 +513,7 @@ describe "TokenAccessController", -> @next = sinon.stub() @req.params['read_and_write_token'] = '123abc' @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub() - .callsArgWith(1, null, null) + .callsArgWith(1, null, null, true) @TokenAccessHandler.findProjectWithHigherAccess = sinon.stub() .callsArgWith(2, null, @project, false) @@ -626,7 +626,7 @@ describe "TokenAccessController", -> @next = sinon.stub() @req.params['read_only_token'] = @readOnlyToken @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub() - .callsArgWith(1, null, @project) + .callsArgWith(1, null, @project, true) @TokenAccessHandler.addReadOnlyUserToProject = sinon.stub() .callsArgWith(2, new Error('woops')) @ProjectController.loadEditor = sinon.stub() @@ -670,7 +670,7 @@ describe "TokenAccessController", -> @next = sinon.stub() @req.params['read_only_token'] = @readOnlyToken @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub() - .callsArgWith(1, null, @project) + .callsArgWith(1, null, @project, true) @TokenAccessHandler.addReadOnlyUserToProject = sinon.stub() .callsArgWith(2, null) @ProjectController.loadEditor = sinon.stub() @@ -748,6 +748,7 @@ describe "TokenAccessController", -> beforeEach -> @req = new MockRequest() @res = new MockResponse() + @res.redirect = sinon.stub() @next = sinon.stub() @req.params['read_only_token'] = @readOnlyToken @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub() @@ -780,7 +781,10 @@ describe "TokenAccessController", -> done() it 'should call next with a not-found error', (done) -> - expect(@next.callCount).to.equal 1 - expect(@next.lastCall.args[0]).to.be.instanceof Error + expect(@res.redirect.callCount).to.equal 1 + expect(@res.redirect.calledWith( + 302, + "http://overleaf.test:5000/read/#{@readOnlyToken}" + )).to.equal true done() diff --git a/services/web/test/unit/coffee/TokenAccess/TokenAccessHandlerTests.coffee b/services/web/test/unit/coffee/TokenAccess/TokenAccessHandlerTests.coffee index 722a8496a2..8a2e66bb64 100644 --- a/services/web/test/unit/coffee/TokenAccess/TokenAccessHandlerTests.coffee +++ b/services/web/test/unit/coffee/TokenAccess/TokenAccessHandlerTests.coffee @@ -31,8 +31,7 @@ describe "TokenAccessHandler", -> @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project) => expect(@Project.findOne.callCount).to.equal 1 expect(@Project.findOne.calledWith({ - 'tokens.readOnly': @token, - 'publicAccesLevel': 'tokenBased' + 'tokens.readOnly': @token })).to.equal true done() @@ -43,6 +42,11 @@ describe "TokenAccessHandler", -> expect(project).to.deep.equal @project done() + it 'should return projectExists flag as true', (done) -> + @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project, projectExists) -> + expect(projectExists).to.equal true + done() + describe 'when Project.findOne produces an error', -> beforeEach -> @Project.findOne = sinon.stub().callsArgWith(2, new Error('woops')) @@ -54,6 +58,37 @@ describe "TokenAccessHandler", -> expect(err).to.be.instanceof Error done() + describe 'when project is not tokenBased', -> + beforeEach -> + @project.publicAccesLevel = 'private' + @Project.findOne = sinon.stub().callsArgWith(2, null, @project, true) + + it 'should not return a project', (done) -> + @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project) -> + expect(err).to.not.exist + expect(project).to.not.exist + done() + + it 'should return projectExists flag as true', (done) -> + @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project, projectExists) -> + expect(projectExists).to.equal true + done() + + describe 'when project does not exist', -> + beforeEach -> + @Project.findOne = sinon.stub().callsArgWith(2, null, null) + + it 'should not return a project', (done) -> + @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project) -> + expect(err).to.not.exist + expect(project).to.not.exist + done() + + it 'should return projectExists flag as false', (done) -> + @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project, projectExists) -> + expect(projectExists).to.equal false + done() + describe 'findProjectWithReadAndWriteToken', -> beforeEach -> @Project.findOne = sinon.stub().callsArgWith(2, null, @project)