diff --git a/services/web/app/coffee/Features/TokenAccess/TokenAccessController.coffee b/services/web/app/coffee/Features/TokenAccess/TokenAccessController.coffee index 08aa4663f1..49a3892855 100644 --- a/services/web/app/coffee/Features/TokenAccess/TokenAccessController.coffee +++ b/services/web/app/coffee/Features/TokenAccess/TokenAccessController.coffee @@ -4,6 +4,7 @@ TokenAccessHandler = require './TokenAccessHandler' Errors = require '../Errors/Errors' logger = require 'logger-sharelatex' settings = require 'settings-sharelatex' +V1Api = require "../V1/V1Api" module.exports = TokenAccessController = @@ -91,23 +92,26 @@ module.exports = TokenAccessController = return next(new Errors.NotFoundError()) TokenAccessController._tryHigherAccess(token, userId, req, res, next) else - if !userId? - logger.log {userId, projectId: project._id}, - "[TokenAccess] adding anonymous user to project with readOnly token" - TokenAccessHandler.grantSessionTokenAccess(req, project._id, token) - req._anonymousAccessToken = token - return TokenAccessController._loadEditor(project._id, req, res, next) - else - if project.owner_ref.toString() == userId + V1Api.request { url: "/api/v1/sharelatex/docs/#{token}/read" }, (err, respose, body) -> + return next err if err? + return res.redirect body.published_path if body.allow == false + if !userId? logger.log {userId, projectId: project._id}, - "[TokenAccess] user is already project owner" - return TokenAccessController._loadEditor(project._id, req, res, next) - logger.log {userId, projectId: project._id}, - "[TokenAccess] adding user to project with readOnly token" - TokenAccessHandler.addReadOnlyUserToProject userId, project._id, (err) -> - if err? - logger.err {err, token, userId, projectId: project._id}, - "[TokenAccess] error adding user to project with readAndWrite token" - return next(err) + "[TokenAccess] adding anonymous user to project with readOnly token" + TokenAccessHandler.grantSessionTokenAccess(req, project._id, token) + req._anonymousAccessToken = token return TokenAccessController._loadEditor(project._id, req, res, next) + else + if project.owner_ref.toString() == userId + logger.log {userId, projectId: project._id}, + "[TokenAccess] user is already project owner" + return TokenAccessController._loadEditor(project._id, req, res, next) + logger.log {userId, projectId: project._id}, + "[TokenAccess] adding user to project with readOnly token" + TokenAccessHandler.addReadOnlyUserToProject userId, project._id, (err) -> + if err? + logger.err {err, token, userId, projectId: project._id}, + "[TokenAccess] error adding user to project with readAndWrite token" + return next(err) + return TokenAccessController._loadEditor(project._id, req, res, next) diff --git a/services/web/app/coffee/Features/V1/V1Api.coffee b/services/web/app/coffee/Features/V1/V1Api.coffee new file mode 100644 index 0000000000..6e781ef147 --- /dev/null +++ b/services/web/app/coffee/Features/V1/V1Api.coffee @@ -0,0 +1,26 @@ +request = require 'request' +settings = require 'settings-sharelatex' + +# TODO: check what happens when these settings aren't defined +DEFAULT_V1_PARAMS = { + baseUrl: settings?.apis?.v1?.url + auth: + user: settings?.apis?.v1?.user + pass: settings?.apis?.v1?.pass + json: true, + timeout: 30 * 1000 +} + +request = request.defaults(DEFAULT_V1_PARAMS) + +module.exports = V1Api = + request: (options, callback) -> + return request(options) if !callback? + request options, (error, response, body) -> + return callback(error, response, body) if error? + if 200 <= response.statusCode < 300 or response.statusCode in (options.expectedStatusCodes or []) + callback null, response, body + else + error = new Error("overleaf v1 returned non-success code: #{response.statusCode}") + error.statusCode = response.statusCode + callback error diff --git a/services/web/test/acceptance/coffee/helpers/MockV1Api.coffee b/services/web/test/acceptance/coffee/helpers/MockV1Api.coffee index eeafa6a44b..5ecd11a991 100644 --- a/services/web/test/acceptance/coffee/helpers/MockV1Api.coffee +++ b/services/web/test/acceptance/coffee/helpers/MockV1Api.coffee @@ -81,5 +81,8 @@ module.exports = MockV1Api = .on "error", (error) -> console.error "error starting MockV1Api:", error.message process.exit(1) + + app.get '/api/v1/sharelatex/docs/:token/read', (req, res, next) => + res.json { allow: true } MockV1Api.run() diff --git a/services/web/test/unit/coffee/TokenAccess/TokenAccessControllerTests.coffee b/services/web/test/unit/coffee/TokenAccess/TokenAccessControllerTests.coffee index 0bdb6d59e6..0d65948225 100644 --- a/services/web/test/unit/coffee/TokenAccess/TokenAccessControllerTests.coffee +++ b/services/web/test/unit/coffee/TokenAccess/TokenAccessControllerTests.coffee @@ -34,6 +34,9 @@ describe "TokenAccessController", -> overleaf: host: 'http://overleaf.test:5000' } + '../V1/V1Api': @V1Api = { + request: sinon.stub().callsArgWith(1, null, {}, { allow: true }) + } @AuthenticationController.getLoggedInUserId = sinon.stub().returns(@userId.toString()) @@ -394,6 +397,20 @@ describe "TokenAccessController", -> describe 'readOnlyToken', -> beforeEach -> + describe 'when access not allowed by v1 api', -> + beforeEach -> + @req = new MockRequest() + @res = new MockResponse() + @res.redirect = sinon.stub() + @next = sinon.stub() + @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub() + .callsArgWith(1, null, @project) + @V1Api.request = sinon.stub().callsArgWith(1, null, {}, { allow: false, published_path: 'doc-url'} ) + @TokenAccessController.readOnlyToken @req, @res, @next + + it 'should redirect to doc-url', -> + expect(@res.redirect.calledWith('doc-url')).to.equal true + describe 'with a user', -> beforeEach -> @AuthenticationController.getLoggedInUserId = sinon.stub().returns(@userId.toString())