diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 196efbcff6..3e8ddce75c 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -6,9 +6,12 @@ projectCreationHandler = require("./ProjectCreationHandler") metrics = require('../../infrastructure/Metrics') sanitize = require('sanitizer') Project = require('../../models/Project').Project +User = require('../../models/User').User TagsHandler = require("../Tags/TagsHandler") SubscriptionLocator = require("../Subscription/SubscriptionLocator") _ = require("underscore") +Settings = require("settings-sharelatex") +SecurityManager = require("../../managers/SecurityManager") module.exports = @@ -72,6 +75,88 @@ module.exports = timer.done() + + loadEditor: (req, res)-> + timer = new metrics.Timer("load-editor") + if !Settings.editorIsOpen + res.render("general/closed", {title:"updating site"}) + else + if req.session.user? + user_id = req.session.user._id + else + user_id = 'openUser' + project_id = req.params.Project_id + Project.findPopulatedById project_id, (err, project)-> + User.findById user_id, (err, user)-> + if user_id == 'openUser' + anonymous = true + user = + id : user_id + ace: + mode:'none' + theme:'textmate' + fontSize: '12' + autoComplete: true + spellCheckLanguage: "" + pdfViewer: "" + subscription: + freeTrial: + allowed: true + featureSwitches: + dropbox: false + trackChanges: false + else + anonymous = false + SubscriptionLocator.getUsersSubscription user?._id, (err, subscription)-> + SecurityManager.userCanAccessProject user, project, (canAccess, privilegeLevel)-> + allowedFreeTrial = true + if subscription? and subscription.freeTrial? and subscription.freeTrial.expiresAt? + allowedFreeTrial = !!subscription.freeTrial.allowed + if canAccess + timer.done() + res.render 'project/editor', + title: project.name + priority_title: true + bodyClasses: ["editor"] + project : project + #owner : project.owner_ref + userObject : JSON.stringify({ + id : user.id + email : user.email + first_name : user.first_name + last_name : user.last_name + referal_id : user.referal_id + subscription : + freeTrial: {allowed: allowedFreeTrial} + }) + userSettingsObject: JSON.stringify({ + mode : user.ace.mode + theme : user.ace.theme + project_id : project._id + fontSize : user.ace.fontSize + autoComplete: user.ace.autoComplete + spellCheckLanguage: user.ace.spellCheckLanguage + pdfViewer : user.ace.pdfViewer + docPositions: {} + oldHistory: !!user.featureSwitches?.oldHistory + }) + sharelatexObject : JSON.stringify({ + siteUrl: Settings.siteUrl, + jsPath: res.locals.jsPath + }) + privilegeLevel: privilegeLevel + loadPdfjs: (user.ace.pdfViewer == "pdfjs") + chatUrl: Settings.apis.chat.url + anonymous: anonymous + languages: Settings.languages + else + res.send 401 + + + + + + _buildListViewModel = (projects, collabertions, readOnlyProjects, tags, tagsGroupedByProject, subscription)-> # TODO: Remove this one month after the ability to start free trials was removed if subscription? and subscription.freeTrial? and subscription.freeTrial.expiresAt? diff --git a/services/web/app/coffee/controllers/ProjectController.coffee b/services/web/app/coffee/controllers/ProjectController.coffee index 02316995c2..482294941e 100755 --- a/services/web/app/coffee/controllers/ProjectController.coffee +++ b/services/web/app/coffee/controllers/ProjectController.coffee @@ -20,130 +20,6 @@ FileStoreHandler = require("../Features/FileStore/FileStoreHandler") module.exports = class ProjectController constructor: ()-> - list: (req, res, next)-> - timer = new metrics.Timer("project-list") - user_id = req.session.user._id - startTime = new Date() - User.findById user_id, (error, user) -> - logger.log user_id: user_id, duration: (new Date() - startTime), "project list timer - User.findById" - startTime = new Date() - # TODO: Remove this one month after the ability to start free trials was removed - SubscriptionLocator.getUsersSubscription user._id, (err, subscription)-> - logger.log user_id: user_id, duration: (new Date() - startTime), "project list timer - Subscription.getUsersSubscription" - startTime = new Date() - return next(error) if error? - # TODO: Remove this one month after the ability to start free trials was removed - if subscription? and subscription.freeTrial? and subscription.freeTrial.expiresAt? - freeTrial = - expired: !!subscription.freeTrial.downgraded - expiresAt: SubscriptionFormatters.formatDate(subscription.freeTrial.expiresAt) - TagsHandler.getAllTags user_id, (err, tags, tagsGroupedByProject)-> - logger.log user_id: user_id, duration: (new Date() - startTime), "project list timer - TagsHandler.getAllTags" - startTime = new Date() - Project.findAllUsersProjects user_id, 'name lastUpdated publicAccesLevel', (projects, collabertions, readOnlyProjects)-> - logger.log user_id: user_id, duration: (new Date() - startTime), "project list timer - Project.findAllUsersProjects" - startTime = new Date() - for project in projects - project.accessLevel = "owner" - for project in collabertions - project.accessLevel = "readWrite" - for project in readOnlyProjects - project.accessLevel = "readOnly" - projects = projects.concat(collabertions).concat(readOnlyProjects) - projects = projects.map (project)-> - project.tags = tagsGroupedByProject[project._id] || [] - return project - tags = _.sortBy tags, (tag)-> - -tag.project_ids.length - logger.log projects:projects, collabertions:collabertions, readOnlyProjects:readOnlyProjects, user_id:user_id, "rendering project list" - sortedProjects = _.sortBy projects, (project)-> - return - project.lastUpdated - res.render 'project/list', - title:'Your Projects' - priority_title: true - projects: sortedProjects - freeTrial: freeTrial - tags:tags - projectTabActive: true - logger.log user_id: user_id, duration: (new Date() - startTime), "project list timer - Finished" - timer.done() - - - - loadEditor: (req, res)-> - timer = new metrics.Timer("load-editor") - if !Settings.editorIsOpen - res.render("general/closed", {title:"updating site"}) - else - if req.session.user? - user_id = req.session.user._id - else - user_id = 'openUser' - project_id = req.params.Project_id - Project.findPopulatedById project_id, (err, project)-> - User.findById user_id, (err, user)-> - if user_id == 'openUser' - anonymous = true - user = - id : user_id - ace: - mode:'none' - theme:'textmate' - fontSize: '12' - autoComplete: true - spellCheckLanguage: "" - pdfViewer: "" - subscription: - freeTrial: - allowed: true - featureSwitches: - dropbox: false - trackChanges: false - else - anonymous = false - SubscriptionLocator.getUsersSubscription user?._id, (err, subscription)-> - SecurityManager.userCanAccessProject user, project, (canAccess, privilegeLevel)-> - allowedFreeTrial = true - if subscription? and subscription.freeTrial? and subscription.freeTrial.expiresAt? - allowedFreeTrial = !!subscription.freeTrial.allowed - if canAccess - timer.done() - res.render 'project/editor', - title: project.name - priority_title: true - bodyClasses: ["editor"] - project : project - owner : project.owner_ref - userObject : JSON.stringify({ - id : user.id - email : user.email - first_name : user.first_name - last_name : user.last_name - referal_id : user.referal_id - subscription : - freeTrial: {allowed: allowedFreeTrial} - }) - userSettingsObject: JSON.stringify({ - mode : user.ace.mode - theme : user.ace.theme - project_id : project._id - fontSize : user.ace.fontSize - autoComplete: user.ace.autoComplete - spellCheckLanguage: user.ace.spellCheckLanguage - pdfViewer : user.ace.pdfViewer - docPositions: {} - oldHistory: !!user.featureSwitches?.oldHistory - }) - sharelatexObject : JSON.stringify({ - siteUrl: Settings.siteUrl, - jsPath: res.locals.jsPath - }) - privilegeLevel: privilegeLevel - userCanSeeDropbox: user.featureSwitches.dropbox and project.owner_ref._id+"" == user._id+"" - loadPdfjs: (user.ace.pdfViewer == "pdfjs") - chatUrl: Settings.apis.chat.url - anonymous: anonymous - languages: Settings.languages, startBufferingRequest: (req, res, next) -> req.bufferedChunks = [] diff --git a/services/web/app/coffee/router.coffee b/services/web/app/coffee/router.coffee index bfe7185dae..eb56539f48 100644 --- a/services/web/app/coffee/router.coffee +++ b/services/web/app/coffee/router.coffee @@ -96,7 +96,7 @@ module.exports = class Router app.post '/project/new', AuthenticationController.requireLogin(), ProjectController.newProject app.get '/project/new/template', TemplatesMiddlewear.saveTemplateDataInSession, AuthenticationController.requireLogin(), TemplatesController.createProjectFromZipTemplate - app.get '/Project/:Project_id', SecurityManager.requestCanAccessProject, Project.loadEditor + app.get '/Project/:Project_id', SecurityManager.requestCanAccessProject, ProjectController.loadEditor app.get '/Project/:Project_id/file/:File_id', SecurityManager.requestCanAccessProject, FileStoreController.getFile app.get '/Project/:Project_id/output/output.pdf', SecurityManager.requestCanAccessProject, CompileController.downloadPdf diff --git a/services/web/app/views/project/partials/manage.jade b/services/web/app/views/project/partials/manage.jade index 8b317930a2..000f34daf4 100644 --- a/services/web/app/views/project/partials/manage.jade +++ b/services/web/app/views/project/partials/manage.jade @@ -9,10 +9,9 @@ a(href='#exportSettings', data-toggle="tab") Export & Copy li a(href='#deleteProjectTab', data-toggle="tab") Delete Project - - if(userCanSeeDropbox) - li#manageDropboxSettiingsTabLink - a(href='#dropboxProjectSettings', data-toggle='tab') Dropbox - span.label.label-warning beta + li#manageDropboxSettiingsTabLink + a(href='#dropboxProjectSettings', data-toggle='tab') Dropbox + span.label.label-warning beta .tab-content.form-horizontal .tab-pane#generalProjectSettings.form.form-horizontal.active diff --git a/services/web/app/views/user/settings.jade b/services/web/app/views/user/settings.jade index c7349bbc13..a982adb6cd 100644 --- a/services/web/app/views/user/settings.jade +++ b/services/web/app/views/user/settings.jade @@ -20,10 +20,9 @@ block content a(href='#passwordReset', data-toggle="tab") Password li a(href='#newsletter', data-toggle="tab") Newsletter - - if(userCanSeeDropbox) - li - a(href='#dropboxSettings', data-toggle="tab") Dropbox - span.label.label-warning beta + li + a(href='#dropboxSettings', data-toggle="tab") Dropbox + span.label.label-warning beta li a(href='#deleteAccount', data-toggle="tab") Delete Account diff --git a/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee b/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee index b0d86553bf..f7a04c6a59 100644 --- a/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee @@ -12,7 +12,11 @@ describe "ProjectController", -> @project_id = "123213jlkj9kdlsaj" - @settings = {} + @settings = + apis: + chat: + url:"chat.com" + siteUrl: "mysite.com" @ProjectDeleter = deleteProject: sinon.stub().callsArgWith(1) @ProjectDuplicator = @@ -26,6 +30,11 @@ describe "ProjectController", -> getAllTags: sinon.stub() @ProjectModel = findAllUsersProjects: sinon.stub() + findPopulatedById: sinon.stub() + @UserModel = + findById: sinon.stub() + @SecurityManager = + userCanAccessProject:sinon.stub() @ProjectController = SandboxedModule.require modulePath, requires: "settings-sharelatex":@settings "logger-sharelatex": log:-> @@ -35,6 +44,8 @@ describe "ProjectController", -> "../Subscription/SubscriptionLocator": @SubscriptionLocator "../Tags/TagsHandler":@TagsHandler '../../models/Project': Project:@ProjectModel + "../../models/User":User:@UserModel + "../../managers/SecurityManager":@SecurityManager @user = _id:"!£123213kjljkl" @@ -47,7 +58,9 @@ describe "ProjectController", -> user: @user body: projectName: @projectName - @res = {} + @res = + locals: + jsPath:"js path here" describe "deleteProject", -> @@ -69,8 +82,6 @@ describe "ProjectController", -> done() @ProjectController.cloneProject @req, @res - - describe "newProject", -> it "should call the projectCreationHandler with createExampleProject", (done)-> @@ -90,9 +101,6 @@ describe "ProjectController", -> done() @ProjectController.newProject @req, @res - - - describe "projectListPage", -> beforeEach -> @@ -105,8 +113,6 @@ describe "ProjectController", -> @ProjectModel.findAllUsersProjects.callsArgWith(2, null, @projects, @collabertions, @readOnly) it "should render the project/list page", (done)-> - - @req.body.template = "example" @res.render = (pageName, opts)=> pageName.should.equal "project/list" done() @@ -118,11 +124,75 @@ describe "ProjectController", -> done() @ProjectController.projectListPage @req, @res - it "should send the projects", (done)-> @res.render = (pageName, opts)=> opts.projects.length.should.equal (@projects.length + @collabertions.length + @readOnly.length) done() - @ProjectController.projectListPage @req, @res + @ProjectController.projectListPage @req, @res + describe "loadEditor", -> + beforeEach -> + @settings.editorIsOpen = true + @project = + name:"my proj" + _id:"213123kjlkj" + @user = + _id:"123kj21k3lj" + ace: + fontSize:"massive" + theme:"sexy" + email: "bob@bob.com" + @ProjectModel.findPopulatedById.callsArgWith 1, null, @project + @UserModel.findById.callsArgWith(1, null, @user) + @SubscriptionLocator.getUsersSubscription.callsArgWith(1, null, {}) + @SecurityManager.userCanAccessProject.callsArgWith 2, true, "owner" + + it "should render the project/editor page", (done)-> + @res.render = (pageName, opts)=> + pageName.should.equal "project/editor" + done() + @ProjectController.loadEditor @req, @res + + it "should add the project onto the opts", (done)-> + @res.render = (pageName, opts)=> + opts.project.should.equal @project + done() + @ProjectController.loadEditor @req, @res + + it "should add userObject", (done)-> + @res.render = (pageName, opts)=> + userObject = JSON.parse(opts.userObject) + userObject.email.should.equal @user.email + done() + @ProjectController.loadEditor @req, @res + + it "should add on userSettingsObject", (done)-> + @res.render = (pageName, opts)=> + userSettingsObject = JSON.parse(opts.userSettingsObject) + userSettingsObject.project_id.should.equal @project._id + userSettingsObject.fontSize.should.equal @user.ace.fontSize + userSettingsObject.theme.should.equal @user.ace.theme + done() + @ProjectController.loadEditor @req, @res + + it "should add sharelatexObject", (done)-> + @res.render = (pageName, opts)=> + sharelatexObject = JSON.parse(opts.sharelatexObject) + sharelatexObject.siteUrl.should.equal @settings.siteUrl + done() + @ProjectController.loadEditor @req, @res + + it "should render the closed page if the editor is closed", (done)-> + @settings.editorIsOpen = false + @res.render = (pageName, opts)=> + pageName.should.equal "general/closed" + done() + @ProjectController.loadEditor @req, @res + + it "should not render the page if the project can not be accessed", (done)-> + @SecurityManager.userCanAccessProject = sinon.stub().callsArgWith 2, false + @res.send = (resCode, opts)=> + resCode.should.equal 401 + done() + @ProjectController.loadEditor @req, @res