Просмотр исходного кода

Merge pull request #1332 from sharelatex/ew-block-while-project-importing

block loading project while importing

GitOrigin-RevId: b96589e5cae9faf269abefd4ea732992a350e68c
Ersun Warncke 7 лет назад
Родитель
Сommit
985f0a97bc

+ 15 - 2
services/web/app/coffee/Features/Project/ProjectController.coffee

@@ -277,8 +277,16 @@ module.exports = ProjectController =
 			project: (cb)->
 				ProjectGetter.getProject(
 					project_id,
-					{ name: 1, lastUpdated: 1, track_changes: 1, owner_ref: 1, brandVariationId: 1, overleaf: 1 },
-					cb
+					{ name: 1, lastUpdated: 1, track_changes: 1, owner_ref: 1, brandVariationId: 1, overleaf: 1, tokens: 1 },
+					(err, project) ->
+						return cb(err) if err?
+						return cb(null, project) unless project.overleaf?.id? and project.tokens?.readAndWrite? and Settings.projectImportingCheckMaxCreateDelta?
+						createDelta = (new Date().getTime() - new Date(project._id.getTimestamp()).getTime()) / 1000
+						return cb(null, project) unless createDelta < Settings.projectImportingCheckMaxCreateDelta
+						TokenAccessHandler.getV1DocInfo project.tokens.readAndWrite, null, (err, doc_info) ->
+							return next err if err?
+							project.exporting = doc_info.exporting
+							cb(null, project)
 				)
 			user: (cb)->
 				if !user_id?
@@ -327,6 +335,11 @@ module.exports = ProjectController =
 				if !privilegeLevel? or privilegeLevel == PrivilegeLevels.NONE
 					return res.sendStatus 401
 
+				if project.exporting
+					res.render 'project/importing',
+						bodyClasses: ["editor"]
+					return
+
 				if subscription? and subscription.freeTrial? and subscription.freeTrial.expiresAt?
 					allowedFreeTrial = !!subscription.freeTrial.allowed || true
 

+ 10 - 4
services/web/app/coffee/Features/TokenAccess/TokenAccessHandler.coffee

@@ -126,12 +126,18 @@ module.exports = TokenAccessHandler =
 		return callback(null, {
 			exists: true
 			exported: false
+			exporting: false
 		}) unless Settings.apis?.v1?
 
-		UserGetter.getUser v2UserId, { overleaf: 1 }, (err, user) ->
-			return callback(err) if err?
-			v1UserId = user.overleaf?.id
-			V1Api.request { url: "/api/v1/sharelatex/users/#{v1UserId}/docs/#{token}/info" }, (err, response, body) ->
+		if v2UserId?
+			UserGetter.getUser v2UserId, { overleaf: 1 }, (err, user) ->
+				return callback(err) if err?
+				v1UserId = user.overleaf?.id
+				V1Api.request { url: "/api/v1/sharelatex/users/#{v1UserId}/docs/#{token}/info" }, (err, response, body) ->
+					return callback err if err?
+					callback null, body
+		else
+			V1Api.request { url: "/api/v1/sharelatex/docs/#{token}/info" }, (err, response, body) ->
 				return callback err if err?
 				callback null, body
 

+ 3 - 3
services/web/app/coffee/router.coffee

@@ -172,7 +172,7 @@ module.exports = class Router
 		webRouter.get  '/Project/:Project_id', RateLimiterMiddlewear.rateLimit({
 			endpointName: "open-project"
 			params: ["Project_id"]
-			maxRequests: 10
+			maxRequests: 15
 			timeInterval: 60
 		}), AuthorizationMiddlewear.ensureUserCanReadProject, ProjectController.loadEditor
 		webRouter.get  '/Project/:Project_id/file/:File_id', AuthorizationMiddlewear.ensureUserCanReadProject, FileStoreController.getFile
@@ -439,7 +439,7 @@ module.exports = class Router
 		webRouter.get '/read/:read_only_token([a-z]+)',
 			RateLimiterMiddlewear.rateLimit({
 				endpointName: 'read-only-token',
-				maxRequests: 10,
+				maxRequests: 15,
 				timeInterval: 60
 			}),
 			TokenAccessController.readOnlyToken
@@ -447,7 +447,7 @@ module.exports = class Router
 		webRouter.get '/:read_and_write_token([0-9]+[a-z]+)',
 			RateLimiterMiddlewear.rateLimit({
 				endpointName: 'read-and-write-token',
-				maxRequests: 10,
+				maxRequests: 15,
 				timeInterval: 60
 			}),
 			TokenAccessController.readAndWriteToken

+ 20 - 0
services/web/app/views/project/importing.pug

@@ -0,0 +1,20 @@
+extends ../layout
+
+block vars
+	- var suppressNavbar = true
+	- var suppressFooter = true
+	- var suppressSystemMessages = true
+	- metadata.robotsNoindexNofollow = true
+
+block content
+	.editor(ng-controller="ImportingController").full-size
+		.loading-screen
+			.loading-screen-brand-container
+				.loading-screen-brand(
+					style="height: 20%;"
+					ng-style="{ 'height': state.load_progress + '%' }"
+				)
+			h3.loading-screen-label #{translate("importing")}
+				span.loading-screen-ellip .
+				span.loading-screen-ellip .
+				span.loading-screen-ellip .

+ 1 - 0
services/web/public/src/main.js

@@ -37,6 +37,7 @@ define([
   'main/keys',
   'main/cms/blog',
   'main/cms/index',
+  'main/importing',
   'analytics/AbTestingManager',
   'directives/asyncForm',
   'directives/stopPropagation',

+ 21 - 0
services/web/public/src/main/importing.js

@@ -0,0 +1,21 @@
+define(['base'], function(App) {
+  App.controller('ImportingController', function(
+    $interval,
+    $scope,
+    $timeout,
+    $window
+  ) {
+    $interval(function() {
+      $scope.state.load_progress += 5
+      if ($scope.state.load_progress > 100) {
+        $scope.state.load_progress = 20
+      }
+    }, 500)
+    $timeout(function() {
+      $window.location.reload()
+    }, 5000)
+    $scope.state = {
+      load_progress: 20
+    }
+  })
+})

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

@@ -1,5 +1,6 @@
 expect = require("chai").expect
 async = require("async")
+MockV1Api = require "./helpers/MockV1Api"
 User = require "./helpers/User"
 request = require "./helpers/request"
 settings = require "settings-sharelatex"
@@ -441,3 +442,48 @@ describe 'TokenAccess', ->
 					'/sign_in_to_v1?return_to=/read/abcd'
 				)
 			, done)
+
+	describe 'importing v1 project', ->
+		before (done) ->
+			settings.projectImportingCheckMaxCreateDelta = 3600
+			settings.overleaf =
+				host: 'http://localhost:5000'
+			@owner.createProject "token-rw-test#{Math.random()}", (err, project_id) =>
+				return done(err) if err?
+				@project_id = project_id
+				@owner.makeTokenBased @project_id, (err) =>
+					return done(err) if err?
+					db.projects.update {_id: ObjectId(project_id)}, $set: overleaf: id: 1234, (err) =>
+						return done(err) if err?
+						@owner.getProject @project_id, (err, project) =>
+							return done(err) if err?
+							@tokens = project.tokens
+							MockV1Api.setDocInfo @tokens.readAndWrite, exporting: true
+							MockV1Api.setDocInfo @tokens.readOnly, exporting: true
+							done()
+
+		after ->
+			delete settings.projectImportingCheckMaxCreateDelta
+			delete settings.overleaf
+
+		it 'should show importing page for read and write token', (done) ->
+			try_read_and_write_token_access(@owner, @tokens.readAndWrite, (response, body) =>
+				expect(response.statusCode).to.equal 200
+				expect(body).to.include('ImportingController')
+			, done)
+
+		it 'should show importing page for read only token', (done) ->
+			try_read_only_token_access(@owner, @tokens.readOnly, (response, body) =>
+				expect(response.statusCode).to.equal 200
+				expect(body).to.include('ImportingController')
+			, done)
+
+		describe 'when importing check not configured', ->
+			before ->
+				delete settings.projectImportingCheckMaxCreateDelta
+
+			it 'should load editor', (done) ->
+				try_read_and_write_token_access(@owner, @tokens.readAndWrite, (response, body) =>
+					expect(response.statusCode).to.equal 200
+					expect(body).to.include('IdeController')
+				, done)

+ 14 - 6
services/web/test/acceptance/coffee/helpers/MockV1Api.coffee

@@ -42,6 +42,10 @@ module.exports = MockV1Api =
 
 	setAffiliations: (affiliations) -> @affiliations = affiliations
 
+	doc_info: {}
+
+	setDocInfo: (token, info) -> @doc_info[token] = info
+
 	run: () ->
 		app.get "/api/v1/sharelatex/users/:v1_user_id/plan_code", (req, res, next) =>
 			user = @users[req.params.v1_user_id]
@@ -136,16 +140,20 @@ module.exports = MockV1Api =
 			else
 				res.status(404).json {}
 
-		app.listen 5000, (error) ->
-			throw error if error?
-		.on "error", (error) ->
-			console.error "error starting MockV1Api:", error.message
-			process.exit(1)
-
 		app.get '/api/v1/sharelatex/docs/:token/is_published', (req, res, next) =>
 			res.json { allow: true }
 
 		app.get '/api/v1/sharelatex/users/:user_id/docs/:token/info', (req, res, next) =>
 			res.json { exported: false }
 
+		app.get '/api/v1/sharelatex/docs/:token/info', (req, res, next) =>
+			return res.json @doc_info[req.params.token] if @doc_info[req.params.token]?
+			res.json { exporting: false }
+
+		app.listen 5000, (error) ->
+			throw error if error?
+		.on "error", (error) ->
+			console.error "error starting MockV1Api:", error.message
+			process.exit(1)
+
 MockV1Api.run()

+ 13 - 0
services/web/test/unit/coffee/TokenAccess/TokenAccessHandlerTests.coffee

@@ -541,6 +541,7 @@ describe "TokenAccessHandler", ->
 				expect(@callback.calledWith null, {
 					exists: true
 					exported: false
+					exporting: false
 				}).to.equal true
 
 		describe 'when v1 api is set', ->
@@ -579,6 +580,18 @@ describe "TokenAccessHandler", ->
 					expect(@V1Api.request.calledWith { url: "/api/v1/sharelatex/users/#{@v1UserId}/docs/#{@token}/info" }).to.equal true
 					expect(@callback.calledWith null, 'mock-data').to.equal true
 
+			describe 'when user id arg is null', ->
+				beforeEach ->
+					@v2UserId = null
+					@UserGetter.getUser = sinon.stub()
+					@V1Api.request = sinon.stub().callsArgWith(1, null, null, 'mock-data')
+					@TokenAccessHandler.getV1DocInfo @token, @v2UserId, @callback
+
+				it 'should get info without user', ->
+					expect(@UserGetter.getUser.called).to.equal false
+					expect(@V1Api.request.calledWith { url: "/api/v1/sharelatex/docs/#{@token}/info" }).to.equal true
+					expect(@callback.calledWith null, 'mock-data').to.equal true
+
 			describe 'on V1Api.request error', ->
 				beforeEach ->
 					@UserGetter.getUser = sinon.stub().yields(null, {