mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
add per-user compilation in server
when no user is defined, fallback to per-project compilation
This commit is contained in:
parent
061d4934f1
commit
9d7f129b61
4 changed files with 86 additions and 40 deletions
|
@ -11,11 +11,11 @@ ClsiCookieManager = require("./ClsiCookieManager")
|
|||
|
||||
module.exports = ClsiManager =
|
||||
|
||||
sendRequest: (project_id, options = {}, callback = (error, success) ->) ->
|
||||
sendRequest: (project_id, user_id, options = {}, callback = (error, success) ->) ->
|
||||
ClsiManager._buildRequest project_id, options, (error, req) ->
|
||||
return callback(error) if error?
|
||||
logger.log project_id: project_id, "sending compile to CLSI"
|
||||
ClsiManager._postToClsi project_id, req, options.compileGroup, (error, response) ->
|
||||
ClsiManager._postToClsi project_id, user_id, req, options.compileGroup, (error, response) ->
|
||||
if error?
|
||||
logger.err err:error, project_id:project_id, "error sending request to clsi"
|
||||
return callback(error)
|
||||
|
@ -27,14 +27,13 @@ module.exports = ClsiManager =
|
|||
outputFiles = ClsiManager._parseOutputFiles(project_id, response?.compile?.outputFiles)
|
||||
callback(null, response?.compile?.status, outputFiles, clsiServerId)
|
||||
|
||||
deleteAuxFiles: (project_id, options, callback = (error) ->) ->
|
||||
compilerUrl = @_getCompilerUrl(options?.compileGroup)
|
||||
deleteAuxFiles: (project_id, user_id, options, callback = (error) ->) ->
|
||||
compilerUrl = @_getCompilerUrl(options?.compileGroup, project_id, user_id)
|
||||
opts =
|
||||
url:"#{compilerUrl}/project/#{project_id}"
|
||||
url:compilerUrl
|
||||
method:"DELETE"
|
||||
ClsiManager._makeRequest project_id, opts, callback
|
||||
|
||||
|
||||
_makeRequest: (project_id, opts, callback)->
|
||||
ClsiCookieManager.getCookieJar project_id, (err, jar)->
|
||||
if err?
|
||||
|
@ -51,14 +50,17 @@ module.exports = ClsiManager =
|
|||
|
||||
return callback err, response, body
|
||||
|
||||
_getCompilerUrl: (compileGroup, project_id, user_id, action) ->
|
||||
host = Settings.apis.clsi.url
|
||||
path = "/project/#{project_id}"
|
||||
path += "/user/#{user_id}" if user_id?
|
||||
path += "/#{action}" if action?
|
||||
return "#{host}#{path}"
|
||||
|
||||
_getCompilerUrl: (compileGroup) ->
|
||||
return Settings.apis.clsi.url
|
||||
|
||||
_postToClsi: (project_id, req, compileGroup, callback = (error, response) ->) ->
|
||||
compilerUrl = Settings.apis.clsi.url
|
||||
_postToClsi: (project_id, user_id, req, compileGroup, callback = (error, response) ->) ->
|
||||
compileUrl = @_getCompilerUrl(compileGroup, project_id, user_id, "compile")
|
||||
opts =
|
||||
url: "#{compilerUrl}/project/#{project_id}/compile"
|
||||
url: compileUrl
|
||||
json: req
|
||||
method: "POST"
|
||||
ClsiManager._makeRequest project_id, opts, (error, response, body) ->
|
||||
|
@ -133,15 +135,15 @@ module.exports = ClsiManager =
|
|||
resources: resources
|
||||
}
|
||||
|
||||
wordCount: (project_id, file, options, callback = (error, response) ->) ->
|
||||
wordCount: (project_id, user_id, file, options, callback = (error, response) ->) ->
|
||||
ClsiManager._buildRequest project_id, options, (error, req) ->
|
||||
compilerUrl = ClsiManager._getCompilerUrl(options?.compileGroup)
|
||||
filename = file || req?.compile?.rootResourcePath
|
||||
wordcount_url = "#{compilerUrl}/project/#{project_id}/wordcount?file=#{encodeURIComponent(filename)}"
|
||||
if req.compile.options.imageName?
|
||||
wordcount_url += "&image=#{encodeURIComponent(req.compile.options.imageName)}"
|
||||
wordcount_url = ClsiManager._getCompilerUrl(options?.compileGroup, project_id, user_id, "wordcount")
|
||||
opts =
|
||||
url: wordcount_url
|
||||
qs:
|
||||
file: filename
|
||||
image: req.compile.options.imageName
|
||||
method: "GET"
|
||||
ClsiManager._makeRequest project_id, opts, (error, response, body) ->
|
||||
return callback(error) if error?
|
||||
|
|
|
@ -29,7 +29,9 @@ module.exports = CompileController =
|
|||
options.compiler = req.body.compiler
|
||||
if req.body?.draft
|
||||
options.draft = req.body.draft
|
||||
logger.log {options, project_id}, "got compile request"
|
||||
if req.query?.isolated is "true"
|
||||
options.isolated = true
|
||||
logger.log {options:options, project_id:project_id, user_id:user_id}, "got compile request"
|
||||
CompileManager.compile project_id, user_id, options, (error, status, outputFiles, clsiServerId, limits) ->
|
||||
return next(error) if error?
|
||||
res.contentType("application/json")
|
||||
|
@ -40,6 +42,13 @@ module.exports = CompileController =
|
|||
clsiServerId:clsiServerId
|
||||
}
|
||||
|
||||
_compileAsUser: (req, callback) ->
|
||||
isolated = req.query?.isolated is "true"
|
||||
if isolated
|
||||
AuthenticationController.getLoggedInUserId req, callback
|
||||
else
|
||||
callback()
|
||||
|
||||
downloadPdf: (req, res, next = (error) ->)->
|
||||
Metrics.inc "pdf-downloads"
|
||||
project_id = req.params.Project_id
|
||||
|
@ -76,28 +85,40 @@ module.exports = CompileController =
|
|||
|
||||
deleteAuxFiles: (req, res, next) ->
|
||||
project_id = req.params.Project_id
|
||||
CompileManager.deleteAuxFiles project_id, (error) ->
|
||||
CompileController._compileAsUser req, (error, user_id) ->
|
||||
return next(error) if error?
|
||||
CompileManager.deleteAuxFiles project_id, user_id, (error) ->
|
||||
return next(error) if error?
|
||||
res.sendStatus(200)
|
||||
|
||||
compileAndDownloadPdf: (req, res, next)->
|
||||
project_id = req.params.project_id
|
||||
CompileManager.compile project_id, null, {}, (err)->
|
||||
CompileController._compileAsUser req, (error, user_id) ->
|
||||
return next(error) if error?
|
||||
CompileManager.compile project_id, user_id, {}, (err)->
|
||||
if err?
|
||||
logger.err err:err, project_id:project_id, "something went wrong compile and downloading pdf"
|
||||
res.sendStatus 500
|
||||
url = "/project/#{project_id}/output/output.pdf"
|
||||
CompileController.proxyToClsi project_id, url, req, res, next
|
||||
CompileController.proxyToClsi project_id, user_id, url, req, res, next
|
||||
|
||||
getFileFromClsi: (req, res, next = (error) ->) ->
|
||||
project_id = req.params.Project_id
|
||||
build = req.params.build
|
||||
if build?
|
||||
user = req.params.user
|
||||
if user? and build?
|
||||
url = "/project/#{project_id}/user/#{user}/build/#{build}/output/#{req.params.file}"
|
||||
else if build?
|
||||
url = "/project/#{project_id}/build/#{build}/output/#{req.params.file}"
|
||||
else
|
||||
url = "/project/#{project_id}/output/#{req.params.file}"
|
||||
CompileController.proxyToClsi(project_id, url, req, res, next)
|
||||
|
||||
_getUrl: (project_id, user_id, action) ->
|
||||
path = "/project/#{project_id}"
|
||||
path += "/user/#{user_id}" if user_id?
|
||||
return "#{path}/#{action}"
|
||||
|
||||
proxySyncPdf: (req, res, next = (error) ->) ->
|
||||
project_id = req.params.Project_id
|
||||
{page, h, v} = req.query
|
||||
|
@ -107,7 +128,11 @@ module.exports = CompileController =
|
|||
return next(new Error("invalid h parameter"))
|
||||
if not v?.match(/^\d+\.\d+$/)
|
||||
return next(new Error("invalid v parameter"))
|
||||
destination = {url: "/project/#{project_id}/sync/pdf", qs: {page, h, v}}
|
||||
url = CompileController._getUrl(project_id, user_id, "sync/pdf")
|
||||
destination = {url: url, qs: {page, h, v}}
|
||||
# whether this request is going to a per-user container
|
||||
CompileController._compileAsUser req, (error, user_id) ->
|
||||
return next(error) if error?
|
||||
CompileController.proxyToClsi(project_id, destination, req, res, next)
|
||||
|
||||
proxySyncCode: (req, res, next = (error) ->) ->
|
||||
|
@ -119,7 +144,10 @@ module.exports = CompileController =
|
|||
return next(new Error("invalid line parameter"))
|
||||
if not column?.match(/^\d+$/)
|
||||
return next(new Error("invalid column parameter"))
|
||||
destination = {url:"/project/#{project_id}/sync/code", qs: {file, line, column}}
|
||||
url = CompileController._getUrl(project_id, user_id, "sync/code")
|
||||
destination = {url:url, qs: {file, line, column}}
|
||||
CompileController._compileAsUser req, (error, user_id) ->
|
||||
return next(error) if error?
|
||||
CompileController.proxyToClsi(project_id, destination, req, res, next)
|
||||
|
||||
proxyToClsi: (project_id, url, req, res, next = (error) ->) ->
|
||||
|
@ -168,7 +196,9 @@ module.exports = CompileController =
|
|||
wordCount: (req, res, next) ->
|
||||
project_id = req.params.Project_id
|
||||
file = req.query.file || false
|
||||
CompileManager.wordCount project_id, file, (error, body) ->
|
||||
CompileController._compileAsUser req, (error, user_id) ->
|
||||
return next(error) if error?
|
||||
CompileManager.wordCount project_id, user_id, file, (error, body) ->
|
||||
return next(error) if error?
|
||||
res.contentType("application/json")
|
||||
res.send body
|
||||
|
|
|
@ -37,15 +37,16 @@ module.exports = CompileManager =
|
|||
return callback(error) if error?
|
||||
for key, value of limits
|
||||
options[key] = value
|
||||
ClsiManager.sendRequest project_id, options, (error, status, outputFiles, clsiServerId) ->
|
||||
user_id = undefined if not options.isolated
|
||||
ClsiManager.sendRequest project_id, user_id, options, (error, status, outputFiles, clsiServerId) ->
|
||||
return callback(error) if error?
|
||||
logger.log files: outputFiles, "output files"
|
||||
callback(null, status, outputFiles, clsiServerId, limits)
|
||||
|
||||
deleteAuxFiles: (project_id, callback = (error) ->) ->
|
||||
deleteAuxFiles: (project_id, user_id, callback = (error) ->) ->
|
||||
CompileManager.getProjectCompileLimits project_id, (error, limits) ->
|
||||
return callback(error) if error?
|
||||
ClsiManager.deleteAuxFiles project_id, limits, callback
|
||||
ClsiManager.deleteAuxFiles project_id, user_id, limits, callback
|
||||
|
||||
getProjectCompileLimits: (project_id, callback = (error, limits) ->) ->
|
||||
Project.findById project_id, {owner_ref: 1}, (error, project) ->
|
||||
|
@ -92,7 +93,7 @@ module.exports = CompileManager =
|
|||
else
|
||||
ProjectRootDocManager.setRootDocAutomatically project_id, callback
|
||||
|
||||
wordCount: (project_id, file, callback = (error) ->) ->
|
||||
wordCount: (project_id, user_id, file, callback = (error) ->) ->
|
||||
CompileManager.getProjectCompileLimits project_id, (error, limits) ->
|
||||
return callback(error) if error?
|
||||
ClsiManager.wordCount project_id, file, limits, callback
|
||||
ClsiManager.wordCount project_id, user_id, file, limits, callback
|
||||
|
|
|
@ -124,6 +124,19 @@ module.exports = class Router
|
|||
next()
|
||||
), AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.getFileFromClsi
|
||||
|
||||
# direct url access to output files for a specific user and build (query string not required)
|
||||
webRouter.get /^\/project\/([^\/]*)\/user\/([0-9a-f]+)\/build\/([0-9a-f-]+)\/output\/(.*)$/,
|
||||
((req, res, next) ->
|
||||
params =
|
||||
"Project_id": req.params[0]
|
||||
"user": req.params[1]
|
||||
"build": req.params[2]
|
||||
"file": req.params[3]
|
||||
req.params = params
|
||||
next()
|
||||
), AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.getFileFromClsi
|
||||
|
||||
|
||||
webRouter.delete "/project/:Project_id/output", AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.deleteAuxFiles
|
||||
webRouter.get "/project/:Project_id/sync/code", AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.proxySyncCode
|
||||
webRouter.get "/project/:Project_id/sync/pdf", AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.proxySyncPdf
|
||||
|
|
Loading…
Reference in a new issue