From 7f86ddc72c55ce61945066ef7bc5e537fa15f91c Mon Sep 17 00:00:00 2001 From: hugh-obrien Date: Thu, 31 May 2018 11:12:31 +0100 Subject: [PATCH 1/2] extract v1 templates code to web --- .../Templates/TemplatesController.coffee | 80 +++++++++++++++++++ .../Templates/TemplatesMiddlewear.coffee | 9 +++ .../Features/Templates/TemplatesRouter.coffee | 10 +++ services/web/app/coffee/router.coffee | 3 +- .../project/editor/new_from_template.pug | 26 ++++++ 5 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 services/web/app/coffee/Features/Templates/TemplatesController.coffee create mode 100644 services/web/app/coffee/Features/Templates/TemplatesMiddlewear.coffee create mode 100644 services/web/app/coffee/Features/Templates/TemplatesRouter.coffee create mode 100644 services/web/app/views/project/editor/new_from_template.pug diff --git a/services/web/app/coffee/Features/Templates/TemplatesController.coffee b/services/web/app/coffee/Features/Templates/TemplatesController.coffee new file mode 100644 index 0000000000..0d687a7f06 --- /dev/null +++ b/services/web/app/coffee/Features/Templates/TemplatesController.coffee @@ -0,0 +1,80 @@ +path = require('path') +Project = require('../../../js/models/Project').Project +ProjectUploadManager = require('../../../js/Features/Uploads/ProjectUploadManager') +ProjectOptionsHandler = require("../../../js/Features/Project/ProjectOptionsHandler") +AuthenticationController = require('../../../js/Features/Authentication/AuthenticationController') +settings = require('settings-sharelatex') +fs = require('fs') +request = require('request') +uuid = require('uuid') +logger = require('logger-sharelatex') +async = require("async") + + +module.exports = TemplatesController = + + getV1Template: (req, res)-> + templateVersionId = req.params.Template_version_id + templateId = req.query.id + if !/^[0-9]+$/.test(templateVersionId) || !/^[0-9]+$/.test(templateId) + logger.err templateVersionId:templateVersionId, templateId: templateId, "invalid template id or version" + return res.sendStatus 400 + data = {} + data.templateVersionId = templateVersionId + data.templateId = templateId + data.name = req.query.templateName + data.compiler = req.query.latexEngine + res.render path.resolve(__dirname, "../../../views/project/editor/new_from_template"), data + + createProjectFromV1Template: (req, res)-> + currentUserId = AuthenticationController.getLoggedInUserId(req) + zipUrl = "#{settings.apis.v1.url}/api/v1/sharelatex/templates/#{req.body.templateVersionId}" + zipReq = request(zipUrl, { + 'auth': { + 'user': settings.apis.v1.user, + 'pass': settings.apis.v1.pass + } + }) + + TemplatesController.createFromZip( + zipReq, + { + templateName: req.body.templateName, + currentUserId: currentUserId, + compiler: req.body.compiler + docId: req.body.docId + templateId: req.body.templateId + templateVersionId: req.body.templateVersionId + }, + req, + res + ) + + createFromZip: (zipReq, options, req, res)-> + dumpPath = "#{settings.path.dumpFolder}/#{uuid.v4()}" + writeStream = fs.createWriteStream(dumpPath) + + zipReq.on "error", (error) -> + logger.error err: error, "error getting zip from template API" + zipReq.pipe(writeStream) + writeStream.on 'close', -> + ProjectUploadManager.createProjectFromZipArchive options.currentUserId, options.templateName, dumpPath, (err, project)-> + if err? + logger.err err:err, zipReq:zipReq, "problem building project from zip" + return res.sendStatus 500 + setCompiler project._id, options.compiler, -> + fs.unlink dumpPath, -> + delete req.session.templateData + conditions = {_id:project._id} + update = { + fromV1TemplateId:options.templateId, + fromV1TemplateVersionId:options.templateVersionId + } + Project.update conditions, update, {}, (err)-> + res.redirect "/project/#{project._id}" + +setCompiler = (project_id, compiler, callback)-> + if compiler? + ProjectOptionsHandler.setCompiler project_id, compiler, callback + else + callback() diff --git a/services/web/app/coffee/Features/Templates/TemplatesMiddlewear.coffee b/services/web/app/coffee/Features/Templates/TemplatesMiddlewear.coffee new file mode 100644 index 0000000000..8baa0ca605 --- /dev/null +++ b/services/web/app/coffee/Features/Templates/TemplatesMiddlewear.coffee @@ -0,0 +1,9 @@ +settings = require("settings-sharelatex") +logger = require("logger-sharelatex") + + +module.exports = + saveTemplateDataInSession: (req, res, next)-> + if req.query.templateName + req.session.templateData = req.query + next() diff --git a/services/web/app/coffee/Features/Templates/TemplatesRouter.coffee b/services/web/app/coffee/Features/Templates/TemplatesRouter.coffee new file mode 100644 index 0000000000..3061789591 --- /dev/null +++ b/services/web/app/coffee/Features/Templates/TemplatesRouter.coffee @@ -0,0 +1,10 @@ +AuthenticationController = require('../Authentication/AuthenticationController') +TemplatesController = require("./TemplatesController") +TemplatesMiddlewear = require('./TemplatesMiddlewear') + +module.exports = + apply: (app)-> + + app.get '/project/new/template/:Template_version_id', TemplatesMiddlewear.saveTemplateDataInSession, AuthenticationController.requireLogin(), TemplatesController.getV1Template + + app.post '/project/new/template', AuthenticationController.requireLogin(), TemplatesController.createProjectFromV1Template diff --git a/services/web/app/coffee/router.coffee b/services/web/app/coffee/router.coffee index e6b2692f7c..2e766ac178 100644 --- a/services/web/app/coffee/router.coffee +++ b/services/web/app/coffee/router.coffee @@ -48,6 +48,7 @@ MetaController = require('./Features/Metadata/MetaController') TokenAccessController = require('./Features/TokenAccess/TokenAccessController') Features = require('./infrastructure/Features') LinkedFilesRouter = require './Features/LinkedFiles/LinkedFilesRouter' +TemplatesRouter = require './Features/Templates/TemplatesRouter' logger = require("logger-sharelatex") _ = require("underscore") @@ -80,10 +81,10 @@ module.exports = class Router ContactRouter.apply(webRouter, privateApiRouter) AnalyticsRouter.apply(webRouter, privateApiRouter, publicApiRouter) LinkedFilesRouter.apply(webRouter, privateApiRouter, publicApiRouter) + TemplatesRouter.apply(webRouter) Modules.applyRouter(webRouter, privateApiRouter, publicApiRouter) - if Settings.enableSubscriptions webRouter.get '/user/bonus', AuthenticationController.requireLogin(), ReferalController.bonus diff --git a/services/web/app/views/project/editor/new_from_template.pug b/services/web/app/views/project/editor/new_from_template.pug new file mode 100644 index 0000000000..6dc27a4241 --- /dev/null +++ b/services/web/app/views/project/editor/new_from_template.pug @@ -0,0 +1,26 @@ +extends ../../layout + +block content + script. + $(document).ready(function(){ + $('#create_form').submit(); + }); + + .editor.full-size + .loading-screen() + .loading-screen-brand-container + .loading-screen-brand( + style="height: 20%;" + ) + + h3.loading-screen-label() #{translate("Opening template")} + span.loading-screen-ellip . + span.loading-screen-ellip . + span.loading-screen-ellip . + + form(id='create_form' method='POST' action='/project/new/template/') + input(type="hidden", name="_csrf", value=csrfToken) + input(type="hidden" name="templateId" value=templateId) + input(type="hidden" name="templateVersionId" value=templateVersionId) + input(type="hidden" name="templateName" value=name) + input(type="hidden" name="compiler" value=compiler) From d47e84536716ead511bef4cbe62f4f888625fb36 Mon Sep 17 00:00:00 2001 From: hugh-obrien Date: Thu, 31 May 2018 12:15:42 +0100 Subject: [PATCH 2/2] add v1 template tests --- .../Templates/TemplatesController.coffee | 2 +- .../Features/Templates/TemplatesMiddlewear | 8 ++ .../Templates/TemplatesControllerTests.coffee | 76 +++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 services/web/app/coffee/Features/Templates/TemplatesMiddlewear create mode 100644 services/web/test/unit/coffee/Templates/TemplatesControllerTests.coffee diff --git a/services/web/app/coffee/Features/Templates/TemplatesController.coffee b/services/web/app/coffee/Features/Templates/TemplatesController.coffee index 0d687a7f06..fce6c9502c 100644 --- a/services/web/app/coffee/Features/Templates/TemplatesController.coffee +++ b/services/web/app/coffee/Features/Templates/TemplatesController.coffee @@ -1,7 +1,7 @@ path = require('path') Project = require('../../../js/models/Project').Project ProjectUploadManager = require('../../../js/Features/Uploads/ProjectUploadManager') -ProjectOptionsHandler = require("../../../js/Features/Project/ProjectOptionsHandler") +ProjectOptionsHandler = require('../../../js/Features/Project/ProjectOptionsHandler') AuthenticationController = require('../../../js/Features/Authentication/AuthenticationController') settings = require('settings-sharelatex') fs = require('fs') diff --git a/services/web/app/coffee/Features/Templates/TemplatesMiddlewear b/services/web/app/coffee/Features/Templates/TemplatesMiddlewear new file mode 100644 index 0000000000..300721c889 --- /dev/null +++ b/services/web/app/coffee/Features/Templates/TemplatesMiddlewear @@ -0,0 +1,8 @@ +settings = require("settings-sharelatex") +logger = require("logger-sharelatex") + +module.exports = + saveTemplateDataInSession: (req, res, next)-> + if req.query.templateName + req.session.templateData = req.query + next() diff --git a/services/web/test/unit/coffee/Templates/TemplatesControllerTests.coffee b/services/web/test/unit/coffee/Templates/TemplatesControllerTests.coffee new file mode 100644 index 0000000000..5cf52eca39 --- /dev/null +++ b/services/web/test/unit/coffee/Templates/TemplatesControllerTests.coffee @@ -0,0 +1,76 @@ +should = require('chai').should() +SandboxedModule = require('sandboxed-module') +assert = require('assert') +path = require('path') +sinon = require('sinon') +modulePath = '../../../../app/js/Features/Templates/TemplatesController' + + +describe 'TemplatesController', -> + + project_id = "213432" + + beforeEach -> + @request = sinon.stub() + @request.returns { + pipe:-> + on:-> + } + @fs = { + unlink : sinon.stub() + createWriteStream : sinon.stub().returns(on:(_, cb)->cb()) + } + @ProjectUploadManager = {createProjectFromZipArchive : sinon.stub().callsArgWith(3, null, {_id:project_id})} + @dumpFolder = "dump/path" + @ProjectOptionsHandler = {setCompiler:sinon.stub().callsArgWith(2)} + @uuid = "1234" + @ProjectDetailsHandler = + getProjectDescription:sinon.stub() + @Project = + update: sinon.stub().callsArgWith(3, null) + @controller = SandboxedModule.require modulePath, requires: + '../../../js/Features/Uploads/ProjectUploadManager':@ProjectUploadManager + '../../../js/Features/Project/ProjectOptionsHandler':@ProjectOptionsHandler + '../../../js/Features/Authentication/AuthenticationController': @AuthenticationController = {getLoggedInUserId: sinon.stub()} + './TemplatesPublisher':@TemplatesPublisher + "logger-sharelatex": + log:-> + err:-> + "settings-sharelatex": + path: + dumpFolder:@dumpFolder + siteUrl: @siteUrl = "http://localhost:3000" + apis: + v1: + url: @v1Url="http://overleaf.com" + user: "sharelatex" + pass: "password" + overleaf: + host: @v1Url + "uuid":v4:=>@uuid + "request": @request + "fs":@fs + "../../../../app/js/models/Project": {Project: @Project} + @zipUrl = "%2Ftemplates%2F52fb86a81ae1e566597a25f6%2Fv%2F4%2Fzip&templateName=Moderncv%20Banking&compiler=pdflatex" + @templateName = "project name here" + @user_id = "1234" + @req = + session: + user: _id:@user_id + templateData: + zipUrl: @zipUrl + templateName: @templateName + @redirect = {} + @AuthenticationController.getLoggedInUserId.returns(@user_id) + + describe 'v1Templates', -> + + it "should fetch zip from v1 based on template id", (done)-> + @templateVersionId = 15 + @req.body = {templateVersionId: @templateVersionId} + + redirect = => + @request.calledWith("#{@v1Url}/api/v1/sharelatex/templates/#{@templateVersionId}").should.equal true + done() + res = redirect:redirect + @controller.createProjectFromV1Template @req, res