فهرست منبع

Merge pull request #905 from sharelatex/as-project-intelligent-redirect

Intelligently redirect to v1 if no v2 project found
Alasdair Smith 8 سال پیش
والد
کامیت
e1e7091f30

+ 7 - 1
services/web/app/coffee/Features/TokenAccess/TokenAccessController.coffee

@@ -3,6 +3,7 @@ AuthenticationController = require '../Authentication/AuthenticationController'
 TokenAccessHandler = require './TokenAccessHandler'
 TokenAccessHandler = require './TokenAccessHandler'
 Errors = require '../Errors/Errors'
 Errors = require '../Errors/Errors'
 logger = require 'logger-sharelatex'
 logger = require 'logger-sharelatex'
+settings = require 'settings-sharelatex'
 
 
 module.exports = TokenAccessController =
 module.exports = TokenAccessController =
 
 
@@ -11,11 +12,16 @@ module.exports = TokenAccessController =
 		return ProjectController.loadEditor(req, res, next)
 		return ProjectController.loadEditor(req, res, next)
 
 
 	_tryHigherAccess: (token, userId, req, res, next) ->
 	_tryHigherAccess: (token, userId, req, res, next) ->
-		TokenAccessHandler.findProjectWithHigherAccess token, userId, (err, project) ->
+		TokenAccessHandler.findProjectWithHigherAccess token, userId, (err, project, projectExists) ->
 			if err?
 			if err?
 				logger.err {err, token, userId},
 				logger.err {err, token, userId},
 					"[TokenAccess] error finding project with higher access"
 					"[TokenAccess] error finding project with higher access"
 				return next(err)
 				return next(err)
+			if !projectExists and settings.overleaf
+				logger.log {token, userId},
+					"[TokenAccess] no project found for this token"
+				# Project does not exist, but may be unimported - try it on v1
+				return res.redirect(settings.overleaf.host + req.url)
 			if !project?
 			if !project?
 				logger.log {token, userId},
 				logger.log {token, userId},
 					"[TokenAccess] no project with higher access found for this user and token"
 					"[TokenAccess] no project with higher access found for this user and token"

+ 7 - 3
services/web/app/coffee/Features/TokenAccess/TokenAccessHandler.coffee

@@ -22,7 +22,7 @@ module.exports = TokenAccessHandler =
 			'publicAccesLevel': PublicAccessLevels.TOKEN_BASED
 			'publicAccesLevel': PublicAccessLevels.TOKEN_BASED
 		}, {_id: 1, publicAccesLevel: 1, owner_ref: 1}, callback
 		}, {_id: 1, publicAccesLevel: 1, owner_ref: 1}, callback
 
 
-	findProjectWithHigherAccess: (token, userId, callback=(err, project)->) ->
+	findProjectWithHigherAccess: (token, userId, callback=(err, project, projectExists)->) ->
 		Project.findOne {
 		Project.findOne {
 			$or: [
 			$or: [
 				{'tokens.readAndWrite': token},
 				{'tokens.readAndWrite': token},
@@ -32,12 +32,16 @@ module.exports = TokenAccessHandler =
 			if err?
 			if err?
 				return callback(err)
 				return callback(err)
 			if !project?
 			if !project?
-				return callback(null, null)
+				return callback(null, null, false) # Project doesn't exist, so we handle differently
 			projectId = project._id
 			projectId = project._id
 			CollaboratorsHandler.isUserInvitedMemberOfProject userId, projectId, (err, isMember) ->
 			CollaboratorsHandler.isUserInvitedMemberOfProject userId, projectId, (err, isMember) ->
 				if err?
 				if err?
 					return callback(err)
 					return callback(err)
-				callback(null, if isMember == true then project else null)
+				callback(
+					null,
+					if isMember == true then project else null,
+					true # Project does exist, but user doesn't have access
+				)
 
 
 	addReadOnlyUserToProject: (userId, projectId, callback=(err)->) ->
 	addReadOnlyUserToProject: (userId, projectId, callback=(err)->) ->
 		userId = ObjectId(userId.toString())
 		userId = ObjectId(userId.toString())

+ 10 - 0
services/web/test/acceptance/coffee/TokenAccessTests.coffee

@@ -415,3 +415,13 @@ describe 'TokenAccess', ->
 			try_content_access(@other2, @project_id, (response, body) =>
 			try_content_access(@other2, @project_id, (response, body) =>
 				expect(body.privilegeLevel).to.equal false
 				expect(body.privilegeLevel).to.equal false
 			, done)
 			, done)
+
+	describe 'unimported v1 project', ->
+		it 'should redirect to v1', (done) ->
+			unimportedV1Token = '123abc'
+			try_read_and_write_token_access(@owner, unimportedV1Token, (response, body) =>
+				expect(response.statusCode).to.equal 302
+				expect(response.headers.location).to.equal(
+					'http://overleaf.test:5000/123abc'
+				)
+			, done)

+ 3 - 0
services/web/test/acceptance/config/settings.test.coffee

@@ -105,3 +105,6 @@ module.exports =
 			path: (params) -> "/universities/list/#{params.id}"
 			path: (params) -> "/universities/list/#{params.id}"
 		'/institutions/domains': { baseUrl: v1Api.url, path: '/university/domains' }
 		'/institutions/domains': { baseUrl: v1Api.url, path: '/university/domains' }
 		'/proxy/missing/baseUrl': path: '/foo/bar'
 		'/proxy/missing/baseUrl': path: '/foo/bar'
+
+	overleaf:
+		host: "http://overleaf.test:5000"

+ 50 - 4
services/web/test/unit/coffee/TokenAccess/TokenAccessControllerTests.coffee

@@ -30,6 +30,10 @@ describe "TokenAccessController", ->
 			'../Authentication/AuthenticationController': @AuthenticationController = {}
 			'../Authentication/AuthenticationController': @AuthenticationController = {}
 			'./TokenAccessHandler': @TokenAccessHandler = {}
 			'./TokenAccessHandler': @TokenAccessHandler = {}
 			'logger-sharelatex': {log: sinon.stub(), err: sinon.stub()}
 			'logger-sharelatex': {log: sinon.stub(), err: sinon.stub()}
+			'settings-sharelatex': {
+				overleaf:
+					host: 'http://overleaf.test:5000'
+			}
 
 
 		@AuthenticationController.getLoggedInUserId = sinon.stub().returns(@userId.toString())
 		@AuthenticationController.getLoggedInUserId = sinon.stub().returns(@userId.toString())
 
 
@@ -231,6 +235,27 @@ describe "TokenAccessController", ->
 					@AuthenticationController.getLoggedInUserId =
 					@AuthenticationController.getLoggedInUserId =
 						sinon.stub().returns(@userId.toString())
 						sinon.stub().returns(@userId.toString())
 
 
+				describe 'when project does not exist', ->
+					beforeEach ->
+						@req = new MockRequest()
+						@req.url = '/123abc'
+						@res = new MockResponse()
+						@res.redirect = sinon.stub()
+						@next = sinon.stub()
+						@req.params['read_and_write_token'] = '123abc'
+						@TokenAccessHandler.findProjectWithReadAndWriteToken = sinon.stub()
+							.callsArgWith(1, null, null)
+						@TokenAccessHandler.findProjectWithHigherAccess =
+							sinon.stub()
+							.callsArgWith(2, null, @project, false)
+						@TokenAccessController.readAndWriteToken @req, @res, @next
+
+					it 'should redirect to v1', (done) ->
+						expect(@res.redirect.callCount).to.equal 1
+						expect(@res.redirect.firstCall.args[0])
+							.to.equal 'http://overleaf.test:5000/123abc'
+						done()
+
 				describe 'when token access is off, but user has higher access anyway', ->
 				describe 'when token access is off, but user has higher access anyway', ->
 					beforeEach ->
 					beforeEach ->
 						@req = new MockRequest()
 						@req = new MockRequest()
@@ -242,7 +267,7 @@ describe "TokenAccessController", ->
 							.callsArgWith(1, null, null)
 							.callsArgWith(1, null, null)
 						@TokenAccessHandler.findProjectWithHigherAccess =
 						@TokenAccessHandler.findProjectWithHigherAccess =
 							sinon.stub()
 							sinon.stub()
-							.callsArgWith(2, null, @project)
+							.callsArgWith(2, null, @project, true)
 						@TokenAccessHandler.addReadAndWriteUserToProject = sinon.stub()
 						@TokenAccessHandler.addReadAndWriteUserToProject = sinon.stub()
 							.callsArgWith(2, null)
 							.callsArgWith(2, null)
 						@ProjectController.loadEditor = sinon.stub()
 						@ProjectController.loadEditor = sinon.stub()
@@ -291,7 +316,7 @@ describe "TokenAccessController", ->
 							.callsArgWith(1, null, null)
 							.callsArgWith(1, null, null)
 						@TokenAccessHandler.findProjectWithHigherAccess =
 						@TokenAccessHandler.findProjectWithHigherAccess =
 							sinon.stub()
 							sinon.stub()
-							.callsArgWith(2, null, null)
+							.callsArgWith(2, null, null, true)
 						@TokenAccessHandler.addReadAndWriteUserToProject = sinon.stub()
 						@TokenAccessHandler.addReadAndWriteUserToProject = sinon.stub()
 							.callsArgWith(2, null)
 							.callsArgWith(2, null)
 						@ProjectController.loadEditor = sinon.stub()
 						@ProjectController.loadEditor = sinon.stub()
@@ -479,6 +504,27 @@ describe "TokenAccessController", ->
 		describe 'when findProject does not find a project', ->
 		describe 'when findProject does not find a project', ->
 			beforeEach ->
 			beforeEach ->
 
 
+			describe 'when project does not exist', ->
+				beforeEach ->
+					@req = new MockRequest()
+					@req.url = '/123abc'
+					@res = new MockResponse()
+					@res.redirect = sinon.stub()
+					@next = sinon.stub()
+					@req.params['read_and_write_token'] = '123abc'
+					@TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
+						.callsArgWith(1, null, null)
+					@TokenAccessHandler.findProjectWithHigherAccess =
+						sinon.stub()
+						.callsArgWith(2, null, @project, false)
+					@TokenAccessController.readOnlyToken @req, @res, @next
+
+				it 'should return a ProjectNotTokenAccessError', (done) ->
+					expect(@res.redirect.callCount).to.equal 1
+					expect(@res.redirect.firstCall.args[0])
+						.to.equal 'http://overleaf.test:5000/123abc'
+					done()
+
 			describe 'when token access is off, but user has higher access anyway', ->
 			describe 'when token access is off, but user has higher access anyway', ->
 				beforeEach ->
 				beforeEach ->
 					@req = new MockRequest()
 					@req = new MockRequest()
@@ -490,7 +536,7 @@ describe "TokenAccessController", ->
 						.callsArgWith(1, null, null)
 						.callsArgWith(1, null, null)
 					@TokenAccessHandler.findProjectWithHigherAccess =
 					@TokenAccessHandler.findProjectWithHigherAccess =
 						sinon.stub()
 						sinon.stub()
-						.callsArgWith(2, null, @project)
+						.callsArgWith(2, null, @project, true)
 					@TokenAccessHandler.addReadAndWriteUserToProject = sinon.stub()
 					@TokenAccessHandler.addReadAndWriteUserToProject = sinon.stub()
 						.callsArgWith(2, null)
 						.callsArgWith(2, null)
 					@ProjectController.loadEditor = sinon.stub()
 					@ProjectController.loadEditor = sinon.stub()
@@ -538,7 +584,7 @@ describe "TokenAccessController", ->
 						.callsArgWith(1, null, null)
 						.callsArgWith(1, null, null)
 					@TokenAccessHandler.findProjectWithHigherAccess =
 					@TokenAccessHandler.findProjectWithHigherAccess =
 						sinon.stub()
 						sinon.stub()
-						.callsArgWith(2, null, null)
+						.callsArgWith(2, null, null, true)
 					@TokenAccessHandler.addReadOnlyUserToProject = sinon.stub()
 					@TokenAccessHandler.addReadOnlyUserToProject = sinon.stub()
 						.callsArgWith(2, null)
 						.callsArgWith(2, null)
 					@ProjectController.loadEditor = sinon.stub()
 					@ProjectController.loadEditor = sinon.stub()