From 00a489a000b283d1ab1d0164c5095bfc393c3ed7 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Wed, 17 Oct 2018 14:14:17 +0100 Subject: [PATCH] Fetch brand variation details for branded projects; inject details into the editor page front-end. Test brand variation details. Rename BrandVariationsController to BrandVariationsHandler. Use the V1 API helper. Do not swallow errors when fetching brand details for project load. Fix indentation. --- .../BrandVariationsHandler.coffee | 16 +++++++ .../Features/Project/ProjectController.coffee | 13 +++++- services/web/app/views/project/editor.pug | 3 +- .../BrandVariationsHandlerTests.coffee | 46 +++++++++++++++++++ .../Project/ProjectControllerTests.coffee | 35 ++++++++++++++ 5 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 services/web/app/coffee/Features/BrandVariations/BrandVariationsHandler.coffee create mode 100644 services/web/test/unit/coffee/BrandVariations/BrandVariationsHandlerTests.coffee diff --git a/services/web/app/coffee/Features/BrandVariations/BrandVariationsHandler.coffee b/services/web/app/coffee/Features/BrandVariations/BrandVariationsHandler.coffee new file mode 100644 index 0000000000..b3ba29d308 --- /dev/null +++ b/services/web/app/coffee/Features/BrandVariations/BrandVariationsHandler.coffee @@ -0,0 +1,16 @@ +settings = require "settings-sharelatex" +logger = require "logger-sharelatex" +V1Api = require "../V1/V1Api" + +module.exports = BrandVariationsHandler = + getBrandVariationById: (brandVariationId, callback = (error, brandVariationDetails) ->)-> + if !brandVariationId? or brandVariationId == "" + return callback(new Error("Branding variation id not provided")) + logger.log brandVariationId: brandVariationId, "fetching brand variation details from v1" + V1Api.request { + uri: "/api/v2/brand_variations/#{brandVariationId}" + }, (error, response, brandVariationDetails) -> + if error? + logger.err { brandVariationId, error}, "error getting brand variation details" + return callback(error) + callback(null, brandVariationDetails) diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 59c0647c19..00c066b831 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -31,6 +31,7 @@ NotificationsBuilder = require("../Notifications/NotificationsBuilder") crypto = require 'crypto' { V1ConnectionError } = require '../Errors/Errors' Features = require('../../infrastructure/Features') +BrandVariationsHandler = require("../BrandVariations/BrandVariationsHandler") module.exports = ProjectController = @@ -265,11 +266,11 @@ module.exports = ProjectController = project_id = req.params.Project_id logger.log project_id:project_id, anonymous:anonymous, user_id:user_id, "loading editor" - async.parallel { + async.auto { project: (cb)-> ProjectGetter.getProject( project_id, - { name: 1, lastUpdated: 1, track_changes: 1, owner_ref: 1, 'overleaf.history.display': 1 }, + { name: 1, lastUpdated: 1, track_changes: 1, owner_ref: 1, brandVariationId: 1, 'overleaf.history.display': 1 }, cb ) user: (cb)-> @@ -294,6 +295,12 @@ module.exports = ProjectController = if !user_id? return cb() CollaboratorsHandler.userIsTokenMember user_id, project_id, cb + brandVariation: [ "project", (cb, results) -> + if !results.project?.brandVariationId? + return cb() + BrandVariationsHandler.getBrandVariationById results.project.brandVariationId, (error, brandVariationDetails) -> + cb(error, brandVariationDetails) + ] }, (err, results)-> if err? logger.err err:err, "error getting details for project page" @@ -301,6 +308,7 @@ module.exports = ProjectController = project = results.project user = results.user subscription = results.subscription + brandVariation = results.brandVariation daysSinceLastUpdated = (new Date() - project.lastUpdated) / 86400000 logger.log project_id:project_id, daysSinceLastUpdated:daysSinceLastUpdated, "got db results for loading editor" @@ -359,6 +367,7 @@ module.exports = ProjectController = useV2History: !!project.overleaf?.history?.display richTextEnabled: Features.hasFeature('rich-text') showTestControls: req.query?.tc == 'true' || user.isAdmin + brandVariation: brandVariation allowedImageNames: Settings.allowedImageNames || [] timer.done() diff --git a/services/web/app/views/project/editor.pug b/services/web/app/views/project/editor.pug index 980f578210..7f936efd01 100644 --- a/services/web/app/views/project/editor.pug +++ b/services/web/app/views/project/editor.pug @@ -115,7 +115,7 @@ block requirejs //- We need to do .replace(/\//g, '\\/') do that '' -> '<\/script>' //- and doesn't prematurely end the script tag. script#data(type="application/json"). - !{JSON.stringify({userSettings: userSettings, user: user, trackChangesState: trackChangesState, useV2History: useV2History, enabledLinkedFileTypes: settings.enabledLinkedFileTypes}).replace(/\//g, '\\/')} + !{JSON.stringify({userSettings: userSettings, user: user, trackChangesState: trackChangesState, useV2History: useV2History, enabledLinkedFileTypes: settings.enabledLinkedFileTypes, brandVariation: brandVariation}).replace(/\//g, '\\/')} script(type="text/javascript"). window.data = JSON.parse($("#data").text()); @@ -127,6 +127,7 @@ block requirejs window.enabledLinkedFiles = data.enabledLinkedFiles; window.csrfToken = "!{csrfToken}"; window.anonymous = #{anonymous}; + window.brandVariation = data.brandVariation; window.anonymousAccessToken = "#{anonymousAccessToken}"; window.isTokenMember = #{!!isTokenMember}; window.maxDocLength = #{maxDocLength}; diff --git a/services/web/test/unit/coffee/BrandVariations/BrandVariationsHandlerTests.coffee b/services/web/test/unit/coffee/BrandVariations/BrandVariationsHandlerTests.coffee new file mode 100644 index 0000000000..a4c476c57f --- /dev/null +++ b/services/web/test/unit/coffee/BrandVariations/BrandVariationsHandlerTests.coffee @@ -0,0 +1,46 @@ +expect = require("chai").expect +SandboxedModule = require("sandboxed-module") +assert = require("assert") +path = require("path") +sinon = require("sinon") +expect = require("chai").expect +modulePath = path.join __dirname, "../../../../app/js/Features/BrandVariations/BrandVariationsHandler" + +describe "BrandVariationsHandler", -> + + beforeEach -> + @logger = + err: -> + log: -> + @V1Api = + request: sinon.stub() + @BrandVariationsHandler = SandboxedModule.require modulePath, requires: + "settings-sharelatex": @settings + "logger-sharelatex": @logger + "../V1/V1Api": @V1Api + @mockedBrandVariationDetails = + id: "12" + active: true + brand_name: "The journal" + home_url: "http://www.thejournal.com/" + publish_menu_link_html: "Submit your paper to the The Journal" + + describe "getBrandVariationById", -> + it "should call the callback with an error when the branding variation id is not provided", (done) -> + @BrandVariationsHandler.getBrandVariationById null, (err, brandVariationDetails) => + expect(err).to.be.instanceof Error + done() + + it "should call the callback with an error when the request errors", (done) -> + @V1Api.request.callsArgWith 1, new Error() + @BrandVariationsHandler.getBrandVariationById "12", (err, brandVariationDetails) => + expect(err).to.be.instanceof Error + done() + + it "should call the callback with branding details when request succeeds", (done) -> + @V1Api.request.callsArgWith 1, null, { statusCode: 200 }, @mockedBrandVariationDetails + @BrandVariationsHandler.getBrandVariationById "12", (err, brandVariationDetails) => + expect(err).to.not.exist + expect(brandVariationDetails).to.deep.equal @mockedBrandVariationDetails + done() + diff --git a/services/web/test/unit/coffee/Project/ProjectControllerTests.coffee b/services/web/test/unit/coffee/Project/ProjectControllerTests.coffee index f7edc94ad1..67a37cff6c 100644 --- a/services/web/test/unit/coffee/Project/ProjectControllerTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectControllerTests.coffee @@ -22,6 +22,12 @@ describe "ProjectController", -> chat: url:"chat.com" siteUrl: "mysite.com" + @brandVariationDetails = + id: "12" + active: true + brand_name: "The journal" + home_url: "http://www.thejournal.com/" + publish_menu_link_html: "Submit your paper to the The Journal" @token = 'some-token' @ProjectDeleter = archiveProject: sinon.stub().callsArg(1) @@ -78,6 +84,9 @@ describe "ProjectController", -> fire: sinon.stub() @Features = hasFeature: sinon.stub() + @BrandVariationsHandler = + getBrandVariationById: sinon.stub().callsArgWith 1, null, @brandVariationDetails + @ProjectController = SandboxedModule.require modulePath, requires: "settings-sharelatex":@settings "logger-sharelatex": @@ -111,6 +120,7 @@ describe "ProjectController", -> "../../infrastructure/Features": @Features "../Notifications/NotificationsBuilder":@NotificationBuilder "../User/UserGetter": @UserGetter + "../BrandVariations/BrandVariationsHandler": @BrandVariationsHandler @projectName = "£12321jkj9ujkljds" @req = @@ -510,6 +520,11 @@ describe "ProjectController", -> name:"my proj" _id:"213123kjlkj" owner_ref: '59fc84d5fbea77482d436e1b' + @brandedProject = + name:"my branded proj" + _id:"3252332" + owner_ref: '59fc84d5fbea77482d436e1b' + brandVariationId:"12" @user = _id: "588f3ddae8ebc1bac07c9fa4" ace: @@ -570,6 +585,26 @@ describe "ProjectController", -> done() @ProjectController.loadEditor @req, @res + it "should call the brand variations handler for branded projects", (done)-> + @ProjectGetter.getProject.callsArgWith 2, null, @brandedProject + @res.render = (pageName, opts)=> + @BrandVariationsHandler.getBrandVariationById.calledWith().should.equal true + done() + @ProjectController.loadEditor @req, @res + + it "should not call the brand variations handler for unbranded projects", (done)-> + @res.render = (pageName, opts)=> + @BrandVariationsHandler.getBrandVariationById.called.should.equal false + done() + @ProjectController.loadEditor @req, @res + + it "should expose the brand variation details as locals for branded projects", (done)-> + @ProjectGetter.getProject.callsArgWith 2, null, @brandedProject + @res.render = (pageName, opts)=> + opts.brandVariation.should.deep.equal @brandVariationDetails + done() + @ProjectController.loadEditor @req, @res + describe 'userProjectsJson', -> beforeEach (done) -> projects = [