Browse Source

Merge branch 'master' of https://github.com/sharelatex/web-sharelatex

Henry Oswald 11 years ago
parent
commit
bf38fb7459
44 changed files with 30 additions and 1700 deletions
  1. 0 81
      services/web/app/coffee/Features/Dropbox/DropboxHandler.coffee
  2. 0 12
      services/web/app/coffee/Features/Dropbox/DropboxProjectController.coffee
  3. 0 18
      services/web/app/coffee/Features/Dropbox/DropboxRouter.coffee
  4. 0 26
      services/web/app/coffee/Features/Dropbox/DropboxUserController.coffee
  5. 0 21
      services/web/app/coffee/Features/Dropbox/DropboxWebhookController.coffee
  6. 0 48
      services/web/app/coffee/Features/Dropbox/DropboxWebhookHandler.coffee
  7. 0 3
      services/web/app/coffee/Features/Editor/EditorController.coffee
  8. 3 3
      services/web/app/coffee/Features/Subscription/SubscriptionHandler.coffee
  9. 0 93
      services/web/app/coffee/Features/Templates/TemplatesController.coffee
  10. 0 25
      services/web/app/coffee/Features/Templates/TemplatesMiddlewear.coffee
  11. 0 36
      services/web/app/coffee/Features/Templates/TemplatesPublisher.coffee
  12. 0 30
      services/web/app/coffee/Features/Templates/TemplatesRouter.coffee
  13. 0 102
      services/web/app/coffee/Features/Templates/TemplatesWebController.coffee
  14. 7 10
      services/web/app/coffee/Features/User/UserPagesController.coffee
  15. 2 0
      services/web/app/coffee/infrastructure/Events.coffee
  16. 1 0
      services/web/app/coffee/infrastructure/ExpressLocals.coffee
  17. 3 0
      services/web/app/coffee/infrastructure/Modules.coffee
  18. 0 15
      services/web/app/coffee/router.coffee
  19. 0 1
      services/web/app/views/project/editor.jade
  20. 0 41
      services/web/app/views/project/editor/dropbox.jade
  21. 5 14
      services/web/app/views/project/editor/left-menu.jade
  22. 0 80
      services/web/app/views/templates/index.jade
  23. 0 31
      services/web/app/views/templates/tag.jade
  24. 0 69
      services/web/app/views/templates/template.jade
  25. 0 21
      services/web/app/views/user/settings.jade
  26. 1 1
      services/web/package.json
  27. 0 2
      services/web/public/coffee/ide.coffee
  28. 0 43
      services/web/public/coffee/ide/dropbox/controllers/DropboxController.coffee
  29. 0 4
      services/web/public/coffee/ide/dropbox/index.coffee
  30. 2 2
      services/web/public/coffee/ide/pdfng/directives/pdfRenderer.coffee
  31. 1 1
      services/web/public/coffee/ide/pdfng/directives/pdfViewer.coffee
  32. 0 84
      services/web/public/coffee/ide/templates/controllers/TemplatesController.coffee
  33. 0 4
      services/web/public/coffee/ide/templates/index.coffee
  34. 2 1
      services/web/public/stylesheets/app/editor/binary-file.less
  35. 0 83
      services/web/test/UnitTests/coffee/Dropbox/DropboxHandlerTests.coffee
  36. 0 41
      services/web/test/UnitTests/coffee/Dropbox/DropboxProjectControllerTests.coffee
  37. 0 70
      services/web/test/UnitTests/coffee/Dropbox/DropboxUserControllerTests.coffee
  38. 0 51
      services/web/test/UnitTests/coffee/Dropbox/DropboxWebhookControllerTests.coffee
  39. 0 99
      services/web/test/UnitTests/coffee/Dropbox/DropboxWebhookHandlerTests.coffee
  40. 0 7
      services/web/test/UnitTests/coffee/Editor/EditorControllerTests.coffee
  41. 3 4
      services/web/test/UnitTests/coffee/Subscription/SubscriptionHandlerTests.coffee
  42. 0 209
      services/web/test/UnitTests/coffee/Templates/TemplatesControllerTests.coffee
  43. 0 64
      services/web/test/UnitTests/coffee/Templates/TemplatesPublisherTests.coffee
  44. 0 150
      services/web/test/UnitTests/coffee/Templates/TemplatesWebControllerTests.coffee

+ 0 - 81
services/web/app/coffee/Features/Dropbox/DropboxHandler.coffee

@@ -1,81 +0,0 @@
-request = require('request')
-settings = require('settings-sharelatex')
-logger = require('logger-sharelatex')
-Project = require('../../models/Project').Project
-projectEntityHandler = require '../Project/ProjectEntityHandler'
-_ = require('underscore')
-async = require('async')
-
-module.exports =
-
-	getUserRegistrationStatus: (user_id, callback)->
-		logger.log user_id:user_id, "getting dropbox registration status from tpds"
-		opts =
-			url : "#{settings.apis.thirdPartyDataStore.url}/user/#{user_id}/dropbox/status"
-			timeout: 5000
-		request.get opts, (err, response, body)->
-			safelyGetResponse err, response, body, (err, body)->
-				if err?
-					logger.err err:err, response:response, "getUserRegistrationStatus problem"
-					return callback err
-				logger.log status:body, "getting dropbox registration status for user #{user_id}"
-				callback err, body
-
-	getDropboxRegisterUrl: (user_id, callback)->
-		opts =
-			url: "#{settings.apis.thirdPartyDataStore.url}/user/#{user_id}/dropbox/register"
-			timeout: 5000
-		request.get opts, (err, response, body)->
-			safelyGetResponse err, response, body, (err, body)->
-				if err?
-					logger.err err:err, response:response, "getUserRegistrationStatus problem"
-					return callback err
-				url = "#{body.authorize_url}&oauth_callback=#{settings.siteUrl}/dropbox/completeRegistration"
-				logger.log user_id:user_id, url:url, "starting dropbox register"
-				callback err, url
-
-	completeRegistration: (user_id, callback)->
-		opts =
-			url: "#{settings.apis.thirdPartyDataStore.url}/user/#{user_id}/dropbox/getaccesstoken"
-			timeout: 5000
-		request.get opts, (err, response, body)=>
-			safelyGetResponse err, response, body, (err, body)=>
-				if err?
-					logger.err err:err, response:response, "getUserRegistrationStatus problem"
-					return callback err
-				success = body.success
-				logger.log user_id:user_id, success:body.success, "completing dropbox register"
-				if success
-					@flushUsersProjectToDropbox user_id
-				callback err, body.success
-
-
-	unlinkAccount: (user_id, callback)->
-		opts =
-			url: "#{settings.apis.thirdPartyDataStore.url}/user/#{user_id}/dropbox"
-			timeout: 5000
-		request.del opts, (err, response, body)=>
-			callback(err)
-
-	flushUsersProjectToDropbox: (user_id, callback)->
-		Project.findAllUsersProjects user_id, '_id', (err, projects = [], collabertions = [], readOnlyProjects = [])->
-			projectList = []
-			projectList = projectList.concat(projects)
-			projectList = projectList.concat(collabertions)
-			projectList = projectList.concat(readOnlyProjects)
-			projectIds = _.pluck(projectList, "_id")
-			logger.log projectIds:projectIds, user_id:user_id, "flushing all a users projects to tpds"
-			jobs = projectIds.map (project_id)->
-				return (cb)->
-					projectEntityHandler.flushProjectToThirdPartyDataStore project_id, cb
-			async.series jobs, callback
-
-safelyGetResponse = (err, res, body, callback)->
-	statusCode =  if res? then res.statusCode else 500
-	if err? or statusCode != 200
-		e = new Error("something went wrong getting response from dropbox, #{err}, #{statusCode}")
-		logger.err err:err
-		callback(e, [])
-	else
-		body = JSON.parse body
-		callback(null, body)

+ 0 - 12
services/web/app/coffee/Features/Dropbox/DropboxProjectController.coffee

@@ -1,12 +0,0 @@
-DropboxHandler = require "./DropboxHandler"
-ProjectGetter = require "../Project/ProjectGetter"
-
-module.exports = DropboxProjectController =
-	getStatus: (req, res, next) ->
-		project_id = req.params.Project_id
-		ProjectGetter.getProject project_id, {owner_ref: 1}, (error, project) ->
-			return next(error) if error?
-			DropboxHandler.getUserRegistrationStatus project.owner_ref, (error, status) ->
-				return next(error) if error?
-				res.json status
-	

+ 0 - 18
services/web/app/coffee/Features/Dropbox/DropboxRouter.coffee

@@ -1,18 +0,0 @@
-DropboxUserController = require './DropboxUserController'
-DropboxWebhookController = require './DropboxWebhookController'
-DropboxProjectController = require "./DropboxProjectController"
-SecurityManager = require "../../managers/SecurityManager"
-
-module.exports =
-	apply: (app) ->
-		app.get  '/dropbox/beginAuth', DropboxUserController.redirectUserToDropboxAuth
-		app.get  '/dropbox/completeRegistration', DropboxUserController.completeDropboxRegistration
-		app.get  '/dropbox/unlink', DropboxUserController.unlinkDropbox
-		
-		app.get  '/dropbox/webhook', DropboxWebhookController.verify
-		app.post '/dropbox/webhook', DropboxWebhookController.webhook
-		app.ignoreCsrf('post', '/dropbox/webhook')
-
-		app.get '/project/:Project_id/dropbox/status', SecurityManager.requestIsOwner, DropboxProjectController.getStatus
-
-

+ 0 - 26
services/web/app/coffee/Features/Dropbox/DropboxUserController.coffee

@@ -1,26 +0,0 @@
-dropboxHandler = require('./DropboxHandler')
-logger = require('logger-sharelatex')
-
-
-module.exports =
-
-	redirectUserToDropboxAuth: (req, res, next)->
-		user_id = req.session.user._id
-		dropboxHandler.getDropboxRegisterUrl user_id, (err, url)->
-			return next(err) if err?
-			logger.log url:url, "redirecting user for dropbox auth"
-			res.redirect url
-
-	completeDropboxRegistration: (req, res, next)->
-		user_id = req.session.user._id
-		dropboxHandler.completeRegistration user_id, (err, success)->
-			return next(err) if err?
-			res.redirect('/user/settings#dropboxSettings')
-
-	unlinkDropbox: (req, res, next)->
-		user_id = req.session.user._id
-		dropboxHandler.unlinkAccount user_id, (err, success)->
-			return next(err) if err?
-			res.redirect('/user/settings#dropboxSettings')
-
-

+ 0 - 21
services/web/app/coffee/Features/Dropbox/DropboxWebhookController.coffee

@@ -1,21 +0,0 @@
-logger = require("logger-sharelatex")
-DropboxWebhookHandler = require("./DropboxWebhookHandler")
-
-module.exports = DropboxWebhookController =
-	verify: (req, res, next = (error) ->) ->
-		res.send(req.query.challenge)
-		req.session.destroy()
-		
-	webhook: (req, res, next = (error) ->) ->
-		dropbox_uids = req.body?.delta?.users
-		logger.log dropbox_uids: dropbox_uids, "received webhook request from Dropbox"
-		if !dropbox_uids?
-			return res.send(400) # Bad Request
-			
-		# Do this in the background so as not to keep Dropbox waiting
-		DropboxWebhookHandler.pollDropboxUids dropbox_uids, (error) ->
-			if error?
-				logger.error err: error, dropbox_uids: dropbox_uids, "error in webhook"
-		
-		res.send(200)
-		req.session.destroy()

+ 0 - 48
services/web/app/coffee/Features/Dropbox/DropboxWebhookHandler.coffee

@@ -1,48 +0,0 @@
-logger = require("logger-sharelatex")
-settings = require("settings-sharelatex")
-async = require "async"
-User = require("../../models/User").User
-TpdsUpdateSender = require "../ThirdPartyDataStore/TpdsUpdateSender"
-
-redis = require("redis-sharelatex")
-rclient = redis.createClient(settings.redis.web)
-
-module.exports = DropboxWebhookHandler =
-	pollDropboxUids: (dropbox_uids, callback = (error) ->) ->
-		jobs = []
-		for uid in dropbox_uids
-			do (uid) ->
-				jobs.push (callback) ->
-					DropboxWebhookHandler.pollDropboxUid uid, callback
-		async.series jobs, callback
-		
-	pollDropboxUid: (dropbox_uid, callback = (error) ->) ->
-		DropboxWebhookHandler._delayAndBatchPoll dropbox_uid, (error, shouldPoll) ->
-			return callback(error) if error?
-			return callback() if !shouldPoll
-			User.find {
-				"dropbox.access_token.uid": dropbox_uid.toString()
-				"features.dropbox": true
-			}, (error, users = []) ->
-				return callback(error) if error?
-				user = users[0]
-				if !user?
-					logger.log dropbox_uid: dropbox_uid, "no sharelatex user found"
-					return callback()
-				TpdsUpdateSender.pollDropboxForUser user._id, callback
-		
-	POLL_DELAY_IN_MS: 5000 # 5 seconds
-	_delayAndBatchPoll: (dropbox_uid, callback = (error, shouldPoll) ->) ->
-		rclient.set(
-			"dropbox-poll-lock:#{dropbox_uid}", "LOCK",
-			"PX", DropboxWebhookHandler.POLL_DELAY_IN_MS,
-			"NX",
-		(error, gotLock) ->
-			return callback(error) if error?
-			if gotLock
-				setTimeout () ->
-					callback(null, true)
-				, DropboxWebhookHandler.POLL_DELAY_IN_MS
-			else
-				callback(null, false)
-		)

+ 0 - 3
services/web/app/coffee/Features/Editor/EditorController.coffee

@@ -151,9 +151,6 @@ module.exports = EditorController =
 				return {_id:doc._id, path:path.substring(1)}
 			callback(null, docList)
 
-	forceResyncOfDropbox: (project_id, callback)->
-		ProjectEntityHandler.flushProjectToThirdPartyDataStore project_id, callback
-
 	notifyUsersProjectHasBeenDeletedOrRenamed: (project_id, callback)->
 		EditorRealTimeController.emitToRoom(project_id, 'projectRenamedOrDeletedByExternalSource')
 		callback()

+ 3 - 3
services/web/app/coffee/Features/Subscription/SubscriptionHandler.coffee

@@ -6,7 +6,7 @@ logger = require('logger-sharelatex')
 SubscriptionUpdater = require("./SubscriptionUpdater")
 LimitationsManager = require('./LimitationsManager')
 EmailHandler = require("../Email/EmailHandler")
-DropboxHandler = require("../Dropbox/DropboxHandler")
+Events = require "../../infrastructure/Events"
 
 module.exports =
 
@@ -52,8 +52,8 @@ module.exports =
 					ONE_HOUR_IN_MS = 1000 * 60 * 60
 					setTimeout (-> EmailHandler.sendEmail "canceledSubscription", emailOpts
 					), ONE_HOUR_IN_MS
-					DropboxHandler.unlinkAccount user._id, ->
-						callback()
+					Events.emit "cancelSubscription", user._id
+					callback()
 			else
 				callback()
 

+ 0 - 93
services/web/app/coffee/Features/Templates/TemplatesController.coffee

@@ -1,93 +0,0 @@
-path = require('path')
-ProjectUploadManager = require('../Uploads/ProjectUploadManager')
-ProjectOptionsHandler = require("../Project/ProjectOptionsHandler")
-ProjectDetailsHandler = require('../Project/ProjectDetailsHandler')
-ProjectGetter = require('../Project/ProjectGetter')
-EditorController = require('../Editor/EditorController')
-TemplatesPublisher = require("./TemplatesPublisher")
-settings = require('settings-sharelatex')
-fs = require('fs')
-request = require('request')
-uuid = require('node-uuid')
-logger = require('logger-sharelatex')
-async = require("async")
-
-
-module.exports =
-		
-	createProjectFromZipTemplate: (req, res)->
-		logger.log body:req.session.templateData, "creating project from zip"
-		if !req.session.templateData?
-			return res.redirect "/project"
-			
-		dumpPath = "#{settings.path.dumpFolder}/#{uuid.v4()}"
-		writeStream = fs.createWriteStream(dumpPath)
-		zipUrl = req.session.templateData.zipUrl
-		if zipUrl.slice(0,12).indexOf("templates") == -1
-			zipUrl = "#{settings.apis.web.url}#{zipUrl}"
-		else
-			zipUrl = "#{settings.apis.templates.url}#{zipUrl}"
-		zipReq = request(zipUrl)
-		zipReq.on "error", (error) ->
-			logger.error err: error, "error getting zip from template API"
-		zipReq.pipe(writeStream)
-		writeStream.on 'close', ->
-			ProjectUploadManager.createProjectFromZipArchive req.session.user._id, req.session.templateData.templateName, dumpPath, (err, project)->
-				if err?
-					logger.err err:err, zipUrl:zipUrl, "problem building project from zip"
-					return res.send 500
-				setCompiler project._id, req.session.templateData.compiler, ->
-					fs.unlink dumpPath, ->
-					delete req.session.templateData
-					res.redirect "/project/#{project._id}"
-
-	publishProject: (req, res, next) ->
-		project_id = req.params.Project_id
-		ProjectGetter.getProject project_id, {owner_ref: 1}, (error, project) ->
-			return callback(error) if error?
-			user_id = project.owner_ref.toString()
-			logger.log user_id:user_id, project_id:project_id, "receiving request to publish project as template"
-			TemplatesPublisher.publish user_id, project_id, (error) ->
-				return next(error) if error?
-				res.send 204
-
-	unpublishProject: (req, res, next) ->
-		project_id = req.params.Project_id
-		ProjectGetter.getProject project_id, {owner_ref: 1}, (error, project) ->
-			return callback(error) if error?
-			user_id = project.owner_ref.toString()
-			logger.log user_id:user_id, project_id:project_id, "receiving request to unpublish project"
-			TemplatesPublisher.unpublish user_id, project_id, (error) ->
-				return next(error) if error?
-				res.send 204
-				
-	updateProjectDescription: (req, res, next) ->
-		project_id = req.params.Project_id
-		{description} = req.body
-		EditorController.updateProjectDescription project_id, description, (error) ->
-			return next(error) if error?
-			res.send 204
-
-	getTemplateDetails: (req, res, next)->
-		project_id = req.params.Project_id
-		ProjectGetter.getProject project_id, {owner_ref: 1}, (error, project) ->
-			return next(error) if error?
-			user_id = project.owner_ref.toString()
-			async.parallel {
-				details: (cb)->
-					TemplatesPublisher.getTemplateDetails user_id, project_id, cb
-				description: (cb)->
-					ProjectDetailsHandler.getProjectDescription project_id, cb
-			}, (err, results)->
-				if err?
-					logger.err err:err, user_id:user_id, project_id:project_id, "something went wrong getting template details"
-					return next(err)
-				details = results.details
-				details.description = results.description
-				res.json details
-
-setCompiler = (project_id, compiler, callback)->
-	if compiler?
-		ProjectOptionsHandler.setCompiler project_id, compiler, callback
-	else
-		callback()

+ 0 - 25
services/web/app/coffee/Features/Templates/TemplatesMiddlewear.coffee

@@ -1,25 +0,0 @@
-settings = require("settings-sharelatex")
-logger = require("logger-sharelatex")
-
-
-module.exports =
-	saveTemplateDataInSession: (req, res, next)->
-		if req.query.templateName
-			req.session.templateData = req.query
-		next()
-
-	id_or_tag_parse: (req, res, next)->
-		tag_or_template_id = req.params.tag_or_template_id
-		if _isObjectId(tag_or_template_id)
-			req.params.template_id = tag_or_template_id
-		else
-			req.params.tag_name = tag_or_template_id
-		next()
-
-	_isObjectId: _isObjectId = (tag_or_id)->
-		checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$")
-		checkForHexRegExp.test(tag_or_id)
-
-	insert_templates_user_id: (req, res, next)->
-		req.params.user_id = settings.templates.user_id
-		next()

+ 0 - 36
services/web/app/coffee/Features/Templates/TemplatesPublisher.coffee

@@ -1,36 +0,0 @@
-request = require("request")
-settings = require("settings-sharelatex")
-logger = require("logger-sharelatex")
-
-module.exports = 
-
-	publish : (user_id, project_id, callback)->
-		url = buildUrl(user_id, project_id)
-		request.post url, (err)->
-			if err?
-				logger.err err:err, "something went wrong publishing project as template"
-			callback err
-
-	unpublish: (user_id, project_id, callback)->
-		url = buildUrl(user_id, project_id)
-		request.del url, (err)->
-			callback()
-
-
-	getTemplateDetails: (user_id, project_id, callback)->
-		url = buildUrl(user_id, project_id)+"/details"
-		request.get url, (err, res, body)->
-			if err?
-				logger.err err:err, user_id:user_id, project_id:project_id, body:body, "error getting template details"
-				return callback err
-			try
-				json = JSON.parse body
-			catch err
-				logger.err err:err, user_id:user_id, project_id:project_id, body:body, "error parsing project json details"
-				return callback err
-			logger.log json:json, user_id:user_id, project_id:project_id, "got template details"
-			callback(err, json)
-
-
-buildUrl = (user_id, project_id)->
-	url = "#{settings.apis.templates.url}/templates/user/#{user_id}/project/#{project_id}"

+ 0 - 30
services/web/app/coffee/Features/Templates/TemplatesRouter.coffee

@@ -1,30 +0,0 @@
-SecurityManager = require("../../managers/SecurityManager")
-AuthenticationController = require("../Authentication/AuthenticationController")
-TemplatesWebController = require("./TemplatesWebController")
-TemplatesController = require("./TemplatesController")
-TemplatesMiddlewear = require('./TemplatesMiddlewear')
-middleWear = require("./TemplatesMiddlewear")
-
-module.exports = 
-	apply: (app)->
-
-		app.get "/templates", middleWear.insert_templates_user_id, TemplatesWebController.renderTemplatesIndexPage
-		app.get "/templates/user/:user_id", TemplatesWebController.renderTemplatesIndexPage
-
-		app.get "/templates/:tag_or_template_id", middleWear.id_or_tag_parse, middleWear.insert_templates_user_id, TemplatesWebController.tagOrCanonicalPage
-		app.get "/templates/user/:user_id/:tag_or_template_id", middleWear.id_or_tag_parse, TemplatesWebController.tagOrCanonicalPage
-
-		app.get "/templates/:tag_name/:template_name", middleWear.insert_templates_user_id, TemplatesWebController.renerTemplateInTag
-		app.get "/templates/user/:user_id/:tag_name/:template_name", TemplatesWebController.renerTemplateInTag
-
-		app.get "/templates/:template_id/v/:version/:file_type", TemplatesWebController.proxyToTemplatesApi
-
-		app.post "/project/:Project_id/template/publish", SecurityManager.requestIsOwner, TemplatesController.publishProject
-		app.post "/project/:Project_id/template/unpublish", SecurityManager.requestIsOwner, TemplatesController.unpublishProject
-		app.post "/project/:Project_id/template/description", SecurityManager.requestCanModifyProject, TemplatesController.updateProjectDescription
-
-		# Make sure the /project/new/template route comes before the /project/:project_id/template route
-		# This is a get request so that it can be linked to.
-		app.get '/project/new/template', TemplatesMiddlewear.saveTemplateDataInSession, AuthenticationController.requireLogin(), TemplatesController.createProjectFromZipTemplate
-		
-		app.get  "/project/:Project_id/template", SecurityManager.requestCanAccessProject, TemplatesController.getTemplateDetails

+ 0 - 102
services/web/app/coffee/Features/Templates/TemplatesWebController.coffee

@@ -1,102 +0,0 @@
-request = require("request")
-settings = require("settings-sharelatex")
-logger = require("logger-sharelatex")
-ErrorController = require("../Errors/ErrorController")
-
-module.exports = TemplatesWebController =
-
-	renderTemplatesIndexPage: (req, res)->
-		logger.log "rendering index page of templates"
-		TemplatesWebController._getDataFromTemplatesApi "/user/#{req.params.user_id}", (err, data)->
-			if err? or !data?
-				logger.err err:err, "something went wrong in renderTemplatesIndexPage"
-				return res.send 500
-			data.title = "latex_templates"
-			res.render "templates/index", data
-
-	renerTemplateInTag: (req, res)->
-		{user_id, tag_name, template_name} = req.params
-		logger.log user_id:user_id, tag_name:tag_name, template_name:template_name, "rendering latex template page"
-		TemplatesWebController._getDataFromTemplatesApi "/user/#{user_id}/tag/#{tag_name}/template/#{template_name}", (err, data)->
-			if err? and err == 404
-				return ErrorController.notFound req, res
-			if err? or !data?
-				logger.err err:err, user_id:user_id, tag_name:tag_name, template_name:template_name, "something went wrong in renerTemplateInTag"
-				return res.send 500
-			data.title = data?.template?.name
-			res.render "templates/template", data
-
-	tagOrCanonicalPage: (req, res)->
-		if req.params.template_id?
-			TemplatesWebController._renderCanonicalPage(req, res)
-		else if req.params.tag_name?.toLowerCase() == "all"
-			TemplatesWebController._renderAllTemplatesPage(req, res)
-		else if req.params.tag_name?
-			TemplatesWebController._renderTagPage(req, res)
-		else
-			logger.log params:req.params, "problem rendering tagOrCanonicalPage"
-			res.send 500
-
-	proxyToTemplatesApi: (req, res)->
-		url = req.url
-		
-		name = req.query.name or "Template"
-		if req.query.inline?
-			disposition = "inline"
-		else
-			disposition = "attachment"
-		res.header({"content-disposition": "#{disposition}; filename=\"#{name.replace("\"", "-")}.#{req.params.file_type}\""})
-		
-		logger.log url:url, template_name: name, disposition: disposition, "proxying request to templates api"
-		
-		getReq = request.get("#{settings.apis.templates.url}#{url}")
-		getReq.pipe(res)
-		getReq.on "error", (error) ->
-			logger.error err: error, "templates proxy API error"
-			res.send 500
-
-	_renderCanonicalPage: (req, res)->
-		{user_id, template_id} = req.params
-		logger.log user_id:user_id, template_id:template_id, "rendering template page"
-		TemplatesWebController._getDataFromTemplatesApi "/user/#{user_id}/template/#{template_id}", (err, data)->
-			if err? and err == 404
-				return ErrorController.notFound req, res
-			if err?
-				logger.err err:err, user_id:user_id, template_id:template_id, "something went wrong in _renderCanonicalPage"
-				return res.send 500
-			data.title = data?.template?.name
-			data.tag = null
-			res.render "templates/template", data
-
-	_renderAllTemplatesPage: (req, res)->
-		{user_id} = req.params
-		logger.log user_id:user_id, "rendering all templates page"
-		TemplatesWebController._getDataFromTemplatesApi "/user/#{user_id}/all", (err, data)->
-			if err? and err == 404
-				return ErrorController.notFound req, res
-			if err?
-				logger.err err:err, user_id:user_id, "something went wrong in _renderCanonicalPage"
-				return res.send 500
-			data.title = "all_templates"
-			res.render "templates/tag", data
-
-	_renderTagPage:  (req, res)->
-		{user_id, tag_name} = req.params
-		logger.log user_id:user_id, tag_name:tag_name, "rendinging tag page for templates"
-		TemplatesWebController._getDataFromTemplatesApi "/user/#{user_id}/tag/#{tag_name}", (err, data)->
-			if err? and err == 404
-				return ErrorController.notFound req, res
-			if err?
-				logger.err err:err, user_id:user_id, tag_name:tag_name, "something went wrong in _renderCanonicalPage"
-				return res.send 500
-			data.title = data?.tag?.name
-			res.render "templates/tag", data
-
-	_getDataFromTemplatesApi: (path, callback)->
-		opts = 
-			url: "#{settings.apis.templates.url}#{path}"
-			json:true
-		request.get opts, (err, response, data)->
-			if response.statusCode == 404
-				return callback 404
-			callback err, data

+ 7 - 10
services/web/app/coffee/Features/User/UserPagesController.coffee

@@ -1,5 +1,4 @@
 UserLocator = require("./UserLocator")
-dropboxHandler = require('../Dropbox/DropboxHandler')
 logger = require("logger-sharelatex")
 Settings = require("settings-sharelatex")
 fs = require('fs')
@@ -27,14 +26,12 @@ module.exports =
 			title: 'login',
 			redir: req.query.redir
 
-	settingsPage : (req, res)->
+	settingsPage : (req, res, next)->
 		logger.log user: req.session.user, "loading settings page"
 		UserLocator.findById req.session.user._id, (err, user)->
-			dropboxHandler.getUserRegistrationStatus user._id, (err, status)->
-				userIsRegisteredWithDropbox = !err? and status.registered
-				res.render 'user/settings',
-					title:'account_settings'
-					userIsRegisteredWithDropbox: userIsRegisteredWithDropbox
-					user: user,
-					languages: Settings.languages,
-					accountSettingsTabActive: true
+			return next(err) if err?
+			res.render 'user/settings',
+				title:'account_settings'
+				user: user,
+				languages: Settings.languages,
+				accountSettingsTabActive: true

+ 2 - 0
services/web/app/coffee/infrastructure/Events.coffee

@@ -0,0 +1,2 @@
+events = require "events"
+module.exports = new events.EventEmitter()

+ 1 - 0
services/web/app/coffee/infrastructure/ExpressLocals.coffee

@@ -157,5 +157,6 @@ module.exports = (app)->
 		if Settings.reloadModuleViewsOnEachRequest
 			Modules.loadViewIncludes()
 		res.locals.moduleIncludes = Modules.moduleIncludes
+		res.locals.moduleIncludesAvailable = Modules.moduleIncludesAvailable
 		next()
 

+ 3 - 0
services/web/app/coffee/infrastructure/Modules.coffee

@@ -32,5 +32,8 @@ module.exports = Modules =
 			compiler = jade.compile(partial, doctype: "html")
 			html += compiler(locals)
 		return html
+
+	moduleIncludesAvailable: (view) ->
+		return (Modules.viewIncludes[view] or []).length > 0
 		
 Modules.loadModules()

+ 0 - 15
services/web/app/coffee/router.coffee

@@ -14,7 +14,6 @@ UploadsRouter = require './Features/Uploads/UploadsRouter'
 metrics = require('./infrastructure/Metrics')
 ReferalController = require('./Features/Referal/ReferalController')
 ReferalMiddleware = require('./Features/Referal/ReferalMiddleware')
-TemplatesRouter = require('./Features/Templates/TemplatesRouter')
 AuthenticationController = require('./Features/Authentication/AuthenticationController')
 TagsController = require("./Features/Tags/TagsController")
 CollaboratorsRouter = require('./Features/Collaborators/CollaboratorsRouter')
@@ -33,8 +32,6 @@ StaticPagesRouter = require("./Features/StaticPages/StaticPagesRouter")
 ChatController = require("./Features/Chat/ChatController")
 BlogController = require("./Features/Blog/BlogController")
 WikiController = require("./Features/Wiki/WikiController")
-DropboxRouter = require "./Features/Dropbox/DropboxRouter"
-dropboxHandler = require "./Features/Dropbox/DropboxHandler"
 Modules = require "./infrastructure/Modules"
 RateLimiterMiddlewear = require('./Features/Security/RateLimiterMiddlewear')
 
@@ -65,8 +62,6 @@ module.exports = class Router
 		UploadsRouter.apply(app)
 		PasswordResetRouter.apply(app)
 		StaticPagesRouter.apply(app)
-		TemplatesRouter.apply(app)
-		DropboxRouter.apply(app)
 		
 		Modules.applyRouter(app)
 
@@ -190,16 +185,6 @@ module.exports = class Router
 			), 10000
 			req.session.destroy()
 
-		app.get '/test', (req, res) ->
-			res.render "tests",
-				privilegeLevel: "owner"
-				project:
-					name: "test"
-				date: Date.now()
-				layout: false
-				userCanSeeDropbox: true
-				languages: []
-
 		app.get "/ip", (req, res, next) ->
 			res.send({
 				ip: req.ip

+ 0 - 1
services/web/app/views/project/editor.jade

@@ -56,7 +56,6 @@ block content
 						include ./editor/binary-file
 						include ./editor/track-changes
 						include ./editor/publish-template
-						include ./editor/dropbox
 
 			.ui-layout-east
 				include ./editor/chat

+ 0 - 41
services/web/app/views/project/editor/dropbox.jade

@@ -1,41 +0,0 @@
-script(type="text/ng-template", id="dropboxModalTemplate")
-	.modal-header
-		button.close(
-			type="button"
-			data-dismiss="modal"
-			ng-click="cancel()"
-		) ×
-		h3 #{translate("dropbox_sync")}
-	.modal-body.modal-body-share
-
-		div(ng-show="dbState.gotLinkStatus")
-			div(ng-hide="dbState.userIsLinkedToDropbox || !dbState.hasDropboxFeature")
-
-				span(ng-hide="dbState.startedLinkProcess") #{translate("account_not_linked_to_dropbox")}
-					|    
-					a(ng-click="linkToDropbox()").btn.btn-info #{translate("update_dropbox_settings")}
-
-				p.small.text-center(ng-show="dbState.startedLinkProcess")
-					| #{translate("refresh_page_after_starting_free_trial")}
-
-
-			div(ng-show="dbState.hasDropboxFeature && dbState.userIsLinkedToDropbox")
-				p.small
-					| #{translate("this_project_will_appear_in_your_dropbox_folder_at")}
-					strong Dropbox/sharelatex/{{ project.name }}
-			div.text-center(ng-hide="dbState.hasDropboxFeature")
-				p #{translate("need_to_upgrade_for_dropbox")}
-				p(ng-controller="FreeTrialModalController")
-					a.btn(ng-click="startFreeTrial('dropbox')", ng-class="buttonClass") #{translate("start_free_trial")}
-				p.small(ng-show="startedFreeTrial")
-					| #{translate("refresh_page_after_starting_free_trial")}
-
-		div(ng-hide="dbState.gotLinkStatus")
-			i.fa.fa-refresh.fa-spin 
-			span.small   #{translate("checking_dropbox_status")}
-
-	.modal-footer()
-		button.btn.btn-default(
-			ng-click="cancel()",
-		)
-			span #{translate("dismiss")}

+ 5 - 14
services/web/app/views/project/editor/left-menu.jade

@@ -41,21 +41,12 @@ aside#left-menu.full-size(
 				)
 					i.fa.fa-fw.fa-copy
 					|    #{translate("copy_project")}
-			li(ng-controller="TemplatesController", ng-show="permissions.admin")
-				a(ng-click="openPublishTemplateModal()")
-					i.fa.fa-external-link.fa-fw 
-					|    #{translate("publish_as_template")}
+			!{moduleIncludes("editorLeftMenu:actions", locals)}
 
-	div(ng-show="!anonymous")
-		h4() #{translate("sync")}
-		span(ng-controller="DropboxController")
-			ul.list-unstyled.nav()
-				li
-					a(ng-click="openDropboxModal()")
-						i.fa.fa-dropbox.fa-fw
-						|    Dropbox
-					
-	!{moduleIncludes("editorLeftMenu", locals)}
+	if (moduleIncludesAvailable("editorLeftMenu:sync"))
+		div(ng-show="!anonymous")
+			h4() #{translate("sync")}
+			!{moduleIncludes("editorLeftMenu:sync", locals)}
 
 	h4(ng-show="!anonymous") #{translate("settings")}
 	form.settings(ng-controller="SettingsController", ng-show="!anonymous")

+ 0 - 80
services/web/app/views/templates/index.jade

@@ -1,80 +0,0 @@
-extends ../layout
-
-block vars
-	- var meta = "Over 400 LaTeX templates for journal articles, theses, CV and resumes, posters, presentations, and much more"
-
-block content
-	.content.content-alt
-		.container
-			.row.template-page-header(ng-controller="SearchController")
-				
-				.col-md-2
-					h2
-						a(href="/templates") #{translate("templates")}
-				.col-md-8
-					form.project-search.form-horizontal(role="form")
-						.form-group.has-feedback.has-feedback-left.col-md-12
-							input.form-control.col-md-12(type='text', ng-model='searchQueryText', ng-keyup='search()', placeholder="Search template library....")
-							i.fa.fa-search.form-control-feedback-left
-							i.fa.fa-times.form-control-feedback(
-								ng-click="clearSearchText()",
-								style="cursor: pointer;",
-								ng-show="searchQueryText.length > 0"
-							)
-				.col-md-2(ng-controller="MissingTemplateController")
-					a.btn.btn-primary(ng-click="showMissingTemplateModal()") #{translate("missing_template_question")}
-				.col-md-8(ng-cloak)
-					ul.list-unstyled
-						li(ng-repeat='hit in hits')
-							.thumbnail.searchResult
-								.row
-									a(ng-href='{{hit.url}}')
-										.col-md-3
-											img(ng-src='{{hit.image_url}}')
-										.col-md-7
-											h1(ng-bind-html='hit.name')
-											p(ng-bind-html='hit.description')
-
-
-
-
-
-			.row
-				-each tag in tags
-					-if(tag.totalNumberOfTemplates > 0)
-						.template-section-header.col-md-12
-							h2 
-								a(href=tag.tagPagePath) #{tag.name}
-						.row
-							-each template in tag.exampleTemplates
-								.col-md-3.template-thumbnail
-									a(href=template.templatePagePath ? template.templatePagePath : template.canonicalUrl).thumbnail
-										img(src=template.thumbnailUrl)
-										div.caption
-											h3.txt-middle #{template.name}
-
-						-if(tag.totalNumberOfTemplates > 4)
-							.row
-								.col-md-12.text-center
-									a(href=tag.tagPagePath) View all #{tag.totalNumberOfTemplates} #{tag.name} templates »
-
-
-
-	script(type="text/ng-template", id="missingTemplateModal")
-		.modal-header
-			button.close(
-				type="button"
-				data-dismiss="modal"
-				ng-click="cancel()"
-			) ×
-			h3 #{translate("missing_template_question")}
-		.modal-body #{translate("tell_us_about_the_template")}
-		.modal-footer
-			button.btn.btn-default(
-				ng-click="cancel()",
-			)
-				span #{translate("dismiss")}
-			a.btn.btn-primary(href='mailto:team@sharelatex.com?Subject=template') #{translate("email_us")}
-
-
-

+ 0 - 31
services/web/app/views/templates/tag.jade

@@ -1,31 +0,0 @@
-extends ../layout
-
-mixin template(template)
-	.template-thumbnail
-		a(href=template.templatePagePath ? template.templatePagePath : template.canonicalUrl).thumbnail
-			img(src=template.thumbnailUrl)
-			div.caption
-				h3 #{template.name}
-					
-block content
-	.content.content-alt
-		.container
-			.row
-				.page-header
-					h2
-						a(href="/templates") #{translate("templates")}
-						|  ›
-						a(href=tag.tagPagePath)  #{tag.name}
-				- for (var row = 0; row <= Math.floor(templates.length / 4); row++)
-					.row
-						- for (var column = 0; column < 4; column++)
-							- if (templates[row*4 + column])
-								.col-md-3
-									+template(templates[row*4 + column])
-					//- -each template in templates
-					//- 	a(href=template.templatePagePath || template.canonicalUrl) 
-					//- 		.col-md-3.template-thumbnail
-					//- 			a(href=template.templatePagePath ? template.templatePagePath : template.canonicalUrl).thumbnail
-					//- 				img(src=template.thumbnailUrl)
-					//- 				div.caption
-					//- 					h3 #{template.name}

+ 0 - 69
services/web/app/views/templates/template.jade

@@ -1,69 +0,0 @@
-extends ../layout
-
-block vars
-	- var meta = template.description
-	- title = title + " - LaTeX Template"
-
-block content
-	.content.content-alt
-		.container
-			.row
-				.page-header
-					h2
-						a(href="/templates") #{translate("templates")}
-						|  ›
-						- if(tag)
-							a(href=tag.tagPagePath)  #{tag.name}
-							|  ›
-						|  #{template.name}
-				.row
-					.col-md-6
-						.entry
-							.row
-								.col-md-12.template-large-pdf-preview
-									a(href="#{template.pdfUrl}?inline=true&name=#{template.name}")
-										img(src="#{template.previewUrl}")
-
-					.col-md-6
-						.template-details-section
-							h3 #{translate("about")}
-							div !{template.description}
-							div(ng-controller="openInSlController", ng-cloak).download-buttons
-								a.btn.btn-primary.btn-large(href=template.open_in_sharelatex_url, ng-click='open()', ng-disabled="isDisabled", rel='nofollow') {{openInSlText}}
-								| &nbsp;
-
-								a.btn.btn-default(
-									href="#{template.zipUrl}?name=#{template.name}",
-									rel='nofollow', 
-									ng-click='downloadZip()',
-									tooltip-placement="bottom",
-									tooltip="#{translate('download_zip_file')}"
-								)
-									i.fa.fa-cloud-download
-						.template-details-section.social_buttons
-							.addthis_toolbox.addthis_default_style.addthis_32x32_style
-								a.addthis_button_facebook
-								a.addthis_button_twitter
-								a.addthis_button_google_plusone_share
-								a.addthis_button_compact
-							script(type='text/javascript', src='//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-517c16586439faa7')
-
-						h3 #{translate("comment")}
-						#disqus_thread
-						script(type='text/javascript').
-							/* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
-							var disqus_shortname = 'sharelatextemplates'; // required: replace example with your forum shortname
-							/* * * DON'T EDIT BELOW THIS LINE * * */
-							(function() {
-							var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
-							dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
-							(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
-							})();
-						noscript
-							| Please enable JavaScript to view the
-							a(href='http://disqus.com/?ref_noscript') comments powered by Disqus.
-						a.dsq-brlink(href='http://disqus.com')
-							| comments powered by
-							span.logo-disqus Disqus
-
-

+ 0 - 21
services/web/app/views/user/settings.jade

@@ -96,27 +96,6 @@ block content
 													ng-disabled="changePasswordForm.$invalid"
 												) #{translate("change")}
 
-							hr
-
-							h3 #{translate("dropbox_integration")} 
-								span.small
-									a(href='/help/kb/dropbox-2') (#{translate("learn_more")})
-							- if(!user.features.dropbox)
-								p.small #{translate("dropbox_sync_description")}
-								.alert.alert-info
-									p #{translate("dropbox_is_premium")}
-									p
-										a.btn.btn-info(href='/user/subscription/plans') #{translate("upgrade")}
-							- else if(userIsRegisteredWithDropbox)
-								.alert.alert-success
-									| #{translate("account_is_linked")}.
-									| 
-									a(href='/dropbox/unlink') #{translate("unlink_dropbox")}
-							- else
-								p.small #{translate("dropbox_sync_description")}
-								p
-									a.btn.btn-info(href='/dropbox/beginAuth') #{translate("link_to_dropbox")}
-										
 							| !{moduleIncludes("userSettings", locals)}
 
 							hr

+ 1 - 1
services/web/package.json

@@ -1,6 +1,6 @@
 {
   "name": "web-sharelatex",
-  "version": "0.1.0",
+  "version": "0.1.2",
   "description": "The HTTP front end for ShareLaTeX",
   "repository": {
     "type": "git",

+ 0 - 2
services/web/public/coffee/ide.coffee

@@ -12,8 +12,6 @@ define [
 	"ide/share/index"
 	"ide/chat/index"
 	"ide/clone/index"
-	"ide/templates/index"
-	"ide/dropbox/index"
 	"ide/hotkeys/index"
 	"ide/directives/layout"
 	"ide/services/ide"

+ 0 - 43
services/web/public/coffee/ide/dropbox/controllers/DropboxController.coffee

@@ -1,43 +0,0 @@
-define [
-	"base"
-	"ide/permissions/PermissionsManager"
-], (App, PermissionsManager) ->
-	
-	POLLING_INTERVAL = 15
-	ONE_MIN_MILI = 1000 * 60
-
-	cachedState =
-		gotLinkStatus: false
-		startedLinkProcess: false
-		userIsLinkedToDropbox: false
-		hasDropboxFeature: false
-
-
-	App.controller "DropboxController", ($scope, $modal, ide) ->
-		$scope.openDropboxModal = () ->
-
-			$modal.open {
-				templateUrl: "dropboxModalTemplate"
-				controller: "DropboxModalController"
-				scope:$scope
-			}
-
-	App.controller "DropboxModalController", ($scope, $modalInstance, ide, $timeout, $http) ->
-		user_id = ide.$scope.user.id
-
-		$scope.dbState = cachedState
-		$scope.dbState.hasDropboxFeature = $scope.project.features.dropbox
-
-		$http.get("/project/#{ide.project_id}/dropbox/status")
-			.success (status) ->
-				$scope.dbState.gotLinkStatus = true
-				if status.registered
-					$scope.dbState.userIsLinkedToDropbox = true
-					cachedState = $scope.dbState
-		
-		$scope.linkToDropbox = ->
-			window.open("/user/settings#dropboxSettings")
-			$scope.startedLinkProcess = true
-
-		$scope.cancel = () ->
-			$modalInstance.dismiss()

+ 0 - 4
services/web/public/coffee/ide/dropbox/index.coffee

@@ -1,4 +0,0 @@
-define [
-	"ide/dropbox/controllers/DropboxController"
-], () ->
-			

+ 2 - 2
services/web/public/coffee/ide/pdfng/directives/pdfRenderer.coffee

@@ -145,7 +145,7 @@ define [
 
 				timedOut = false
 				timer = $timeout () =>
-					Raven?.captureMessage?('pdfng page load timed out after ' + @PAGE_LOAD_TIMEOUT + 'ms')
+					Raven?.captureMessage?('pdfng page load timed out after ' + @PAGE_LOAD_TIMEOUT + 'ms (1% sample)') if Math.random() < 0.01
 					# console.log 'page load timed out', pagenum
 					timedOut = true
 					clearTimeout(spinTimer)
@@ -246,7 +246,7 @@ define [
 				timedOut = false
 
 				timer = $timeout () =>
-					Raven?.captureMessage?('pdfng page render timed out after ' + @PAGE_RENDER_TIMEOUT + 'ms')
+					Raven?.captureMessage?('pdfng page render timed out after ' + @PAGE_RENDER_TIMEOUT + 'ms (1% sample)') if Math.random() < 0.01
 					# console.log 'page render timed out', pagenum
 					timedOut = true
 					result.cancel()

+ 1 - 1
services/web/public/coffee/ide/pdfng/directives/pdfViewer.coffee

@@ -38,7 +38,7 @@ define [
 				loadedCallback: () ->
 					$scope.$emit 'loaded'
 				errorCallback: (error) ->
-					Raven?.captureMessage?('pdfng error ' + error)
+					Raven?.captureMessage?('pdfng error ' + error + ' (1% sample)') if Math.random() < 0.01
 					$scope.$emit 'pdf:error', error
 				pageSizeChangeCallback: (pageNum, deltaH) ->
 					$scope.$broadcast 'pdf:page:size-change', pageNum, deltaH

+ 0 - 84
services/web/public/coffee/ide/templates/controllers/TemplatesController.coffee

@@ -1,84 +0,0 @@
-define [
-	"base"
-	"ide/permissions/PermissionsManager"
-], (App, PermissionsManager) ->
-
-	App.controller "TemplatesController", ($scope, $modal, ide) ->
-		$scope.openPublishTemplateModal = () ->
-			resetState = ->
-				$scope.problemTalkingToTemplateApi = false
-
-			resetState()
-
-			modal = $modal.open {
-				templateUrl: "publishProjectAsTemplateModalTemplate"
-				controller: "PublishProjectAsTemplateModalController"
-				scope:$scope
-			}
-			modal.result.then(resetState, resetState)
-
-	App.controller "PublishProjectAsTemplateModalController", ($scope, $modalInstance, ide, $http) ->
-		user_id = ide.$scope.user.id
-		$scope.templateDetails = {exists:false}
-
-		$scope.state =
-			publishInflight: false
-			unpublishInflight: false
-
-		problemTalkingToTemplateApi = ->
-			$scope.problemTalkingToTemplateApi = true
-
-		refreshPublishedStatus = ->
-			$http.get("/project/#{ide.project_id}/template")
-				.success (data) ->
-					$scope.templateDetails = data
-					$scope.templateDetails.publishedDate = moment(data.publishedDate).format("Do MMM YYYY, h:mm a")
-					$scope.templateDetails.description = data.description
-				.error () ->
-					problemTalkingToTemplateApi()
-
-		refreshPublishedStatus()
-		$scope.$watch $scope.problemTalkingToTemplateApi, (value) ->
-			if value?
-				refreshPublishedStatus()
-
-		updateProjectDescription = ->
-			$http.post("/project/#{ide.project_id}/template/description", {
-				description: $scope.templateDetails.description
-				_csrf: window.csrfToken
-			})
-			
-		# Save the description on modal close
-		$modalInstance.result.finally () -> updateProjectDescription()
-
-		$scope.publishTemplate = ->
-			$scope.state.publishInflight = true
-			updateProjectDescription()
-				.error () ->
-					problemTalkingToTemplateApi()
-				.success () ->
-					$http
-						.post("/project/#{ide.project_id}/template/publish", {
-							_csrf: window.csrfToken
-						})
-						.error () ->
-							problemTalkingToTemplateApi()
-						.success () ->
-							refreshPublishedStatus()
-							$scope.state.publishInflight = false
-					
-
-		$scope.unpublishTemplate = ->
-			$scope.state.unpublishInflight = true
-			$http
-				.post("/project/#{ide.project_id}/template/unpublish", {
-					_csrf: window.csrfToken
-				})
-				.success () ->
-					refreshPublishedStatus()
-					$scope.state.unpublishInflight = false
-				.error () ->
-					problemTalkingToTemplateApi()
-
-		$scope.cancel = () ->
-			$modalInstance.dismiss()

+ 0 - 4
services/web/public/coffee/ide/templates/index.coffee

@@ -1,4 +0,0 @@
-define [
-	"ide/templates/controllers/TemplatesController"
-], () ->
-			

+ 2 - 1
services/web/public/stylesheets/app/editor/binary-file.less

@@ -2,6 +2,7 @@
 	padding: @line-height-computed / 2;
 	background-color: @gray-lightest;
 	text-align: center;
+	overflow: auto;
 	img {
 		max-width: 100%;
 		max-height: 90%;
@@ -17,4 +18,4 @@
 		color: @gray;
 	}
 
-}
+}

+ 0 - 83
services/web/test/UnitTests/coffee/Dropbox/DropboxHandlerTests.coffee

@@ -1,83 +0,0 @@
-SandboxedModule = require('sandboxed-module')
-assert = require('assert')
-require('chai').should()
-sinon = require('sinon')
-modulePath = require('path').join __dirname, '../../../../app/js/Features/Dropbox/DropboxHandler.js'
-
-thirdPartyDataStoreApiUrl = "http://third-party-json-store.herokuapp.com"
-siteUrl = "www.sharelatex.com"
-
-describe 'third party data store', ->
-	user_id = "123nd3ijdks"
-
-	beforeEach ->
-		@stubGet = sinon.stub()
-		@stubDel = sinon.stub()
-		@projectEntityHandler = flushProjectToThirdPartyDataStore:sinon.stub().callsArgWith(1)
-		@projectModel = findAllUsersProjects : sinon.stub()
-		@handler = SandboxedModule.require modulePath, requires:
-			"settings-sharelatex": {siteUrl:siteUrl, apis: {thirdPartyDataStore: {url: thirdPartyDataStoreApiUrl}}}
-			"../../models/Project":{Project:@projectModel}
-			'../Project/ProjectEntityHandler':@projectEntityHandler
-			"request":
-				get:@stubGet
-				del: @stubDel
-			'logger-sharelatex':
-				log:->
-				err:->
-
-
-	it 'should be able to get userStatus', (done)->
-		body = JSON.stringify({registered:true})
-		opts =
-			url: "#{thirdPartyDataStoreApiUrl}/user/#{user_id}/dropbox/status"
-			timeout: 5000
-		@stubGet.withArgs(opts).callsArgWith(1, null, {statusCode:200}, body)
-		@handler.getUserRegistrationStatus user_id, (err, status)->
-			status.registered.should.equal true
-			done()
-
-	it 'should be able to get auth url with callback url on it', (done)->
-		url = "http://www.dropbox.com"
-		body = JSON.stringify({authorize_url:url})
-		opts =
-			url: "#{thirdPartyDataStoreApiUrl}/user/#{user_id}/dropbox/register"
-			timeout: 5000
-		@stubGet.withArgs(opts).callsArgWith(1, null, {statusCode:200}, body)
-		@handler.getDropboxRegisterUrl user_id, (err, returnedUrl)->
-			returnedUrl.should.equal "#{url}&oauth_callback=#{siteUrl}/dropbox/completeRegistration"
-			done()
-
-	it 'should be able to complete registration and get getAccessToken from dropbox', (done)->
-		body = JSON.stringify({success:true})
-		opts =
-			url: "#{thirdPartyDataStoreApiUrl}/user/#{user_id}/dropbox/getaccesstoken"
-			timeout: 5000
-		@stubGet.withArgs(opts).callsArgWith(1, null, {statusCode:200}, body)
-		@handler.flushUsersProjectToDropbox = sinon.stub()
-		@handler.completeRegistration user_id, (err, successful)=>
-			@handler.flushUsersProjectToDropbox.called.should.equal true
-			successful.should.equal true
-			done()
-
-	it 'should tell the tpds to unlink the account', (done)->
-		opts =
-			url: "#{thirdPartyDataStoreApiUrl}/user/#{user_id}/dropbox"
-			timeout: 5000
-		@stubDel.callsArgWith(1, null, {statusCode:200})
-		@handler.unlinkAccount user_id, (err)=>
-			@stubDel.calledWith(opts).should.equal true
-			done()
-
-	it 'should tell the project entity handler to flush project to tpds', (done)->
-		user_id = "123u9oijllkj"
-		projectList = [{_id:"123lk"}, {_id:"12ji3ojio"}, {_id:"2jiojdoi"}]
-		collabProjectList = [{_id:"213ds"}]
-		@projectModel.findAllUsersProjects.callsArgWith(2, null, projectList, collabProjectList)
-		@handler.flushUsersProjectToDropbox user_id, =>
-			@projectEntityHandler.flushProjectToThirdPartyDataStore.calledWith(projectList[0]._id).should.equal true
-			@projectEntityHandler.flushProjectToThirdPartyDataStore.calledWith(projectList[1]._id).should.equal true
-			@projectEntityHandler.flushProjectToThirdPartyDataStore.calledWith(projectList[2]._id).should.equal true
-			@projectEntityHandler.flushProjectToThirdPartyDataStore.calledWith(collabProjectList[0]._id).should.equal true
-			done()
-

+ 0 - 41
services/web/test/UnitTests/coffee/Dropbox/DropboxProjectControllerTests.coffee

@@ -1,41 +0,0 @@
-SandboxedModule = require('sandboxed-module')
-assert = require('assert')
-require('chai').should()
-sinon = require('sinon')
-modulePath = require('path').join __dirname, '../../../../app/js/Features/Dropbox/DropboxProjectController.js'
-
-describe 'DropboxProjectController', ->
-	beforeEach ->
-		@DropboxProjectController = SandboxedModule.require modulePath, requires:
-			'./DropboxHandler': @DropboxHandler = {}
-			'../Project/ProjectGetter': @ProjectGetter = {}
-			'logger-sharelatex':
-				log:->
-				err:->
-
-		@project_id = "project-id-123"
-		@user_id = "user-id-123"
-		@req = {}
-		@res =
-			json: sinon.stub()
-
-	describe "getStatus", ->
-		beforeEach ->
-			@req.params =
-				Project_id: @project_id
-			@ProjectGetter.getProject = sinon.stub().callsArgWith(2, null, { owner_ref: @user_id })
-			@DropboxHandler.getUserRegistrationStatus = sinon.stub().callsArgWith(1, null, @status = {"mock": "status"})
-			@DropboxProjectController.getStatus @req, @res
-
-		it "should look up the project owner", ->
-			@ProjectGetter.getProject
-				.calledWith(@project_id, {owner_ref: 1})
-				.should.equal true
-				
-		it "should get the owner's Dropbox status", ->
-			@DropboxHandler.getUserRegistrationStatus
-				.calledWith(@user_id)
-				.should.equal true
-				
-		it "should send the status to the client", ->
-			@res.json.calledWith(@status).should.equal true

+ 0 - 70
services/web/test/UnitTests/coffee/Dropbox/DropboxUserControllerTests.coffee

@@ -1,70 +0,0 @@
-SandboxedModule = require('sandboxed-module')
-assert = require('assert')
-require('chai').should()
-sinon = require('sinon')
-modulePath = require('path').join __dirname, '../../../../app/js/Features/Dropbox/DropboxUserController.js'
-
-
-describe 'DropboxUserController', ->
-
-	beforeEach ->
-		@DropboxHandler =
-			getDropboxRegisterUrl: sinon.stub()
-			completeRegistration: sinon.stub()
-			unlinkAccount: sinon.stub()
-
-		@controller = SandboxedModule.require modulePath, requires:
-			'./DropboxHandler': @DropboxHandler
-			'logger-sharelatex':
-				log:->
-				err:->
-
-		@user_id = "23j21lk3j1312j321jkljkl"
-		@req = 
-			session:
-				user:
-					_id: @user_id
-		@res = {}
-
-	describe "redirectUserToDropboxAuth", ->
-		beforeEach ->
-			@dropboxUrl = "www.dropbox.com"
-			@DropboxHandler.getDropboxRegisterUrl.callsArgWith(1, null, @dropboxUrl)
-
-		it "should call getDropboxRegisterUrl with the user id", (done)->
-
-			@res.redirect = (redirectUrl)=>
-				redirectUrl.should.equal @dropboxUrl
-				@DropboxHandler.getDropboxRegisterUrl.calledWith(@user_id).should.equal true
-				done()
-
-			@controller.redirectUserToDropboxAuth @req, @res
-
-	describe "completeDropboxRegistration", ->
-		beforeEach ->
-			@DropboxHandler.completeRegistration.callsArgWith(1)
-
-		it "should call getDropboxRegisterUrl with the user id", (done)->
-
-			@res.redirect = (redirectUrl)=>
-				redirectUrl.should.equal "/user/settings#dropboxSettings"
-				@DropboxHandler.completeRegistration.calledWith(@user_id).should.equal true
-				done()
-
-			@controller.completeDropboxRegistration @req, @res
-
-
-	describe "unlinkDropbox", ->
-
-		beforeEach ->
-			@DropboxHandler.unlinkAccount.callsArgWith(1)
-
-		it "should call getDropboxRegisterUrl with the user id", (done)->
-
-			@res.redirect = (redirectUrl)=>
-				redirectUrl.should.equal "/user/settings#dropboxSettings"
-				@DropboxHandler.unlinkAccount.calledWith(@user_id).should.equal true
-				done()
-
-			@controller.unlinkDropbox @req, @res
-

+ 0 - 51
services/web/test/UnitTests/coffee/Dropbox/DropboxWebhookControllerTests.coffee

@@ -1,51 +0,0 @@
-SandboxedModule = require('sandboxed-module')
-assert = require('assert')
-require('chai').should()
-sinon = require('sinon')
-modulePath = require('path').join __dirname, '../../../../app/js/Features/Dropbox/DropboxWebhookController.js'
-
-describe 'DropboxWebhookController', ->
-	beforeEach ->
-		@req =
-			session:
-				destroy: ->
-
-		@DropboxWebhookController = SandboxedModule.require modulePath, requires:
-			"./DropboxWebhookHandler": @DropboxWebhookHandler = {}
-			'logger-sharelatex':
-				log:->
-				err:->
-
-	describe "verify", ->
-		beforeEach ->
-			@res =
-				send: sinon.stub()
-			@req.query =
-				challenge: @challenge = "foo"
-			@DropboxWebhookController.verify(@req, @res)
-			
-		it "should echo the challenge parameter back", ->
-			@res.send.calledWith(@challenge).should.equal true
-			
-	describe "webhook", ->
-		beforeEach ->
-			@req.body =
-				delta:
-					users: @dropbox_uids = [
-						"123456",
-						"789123"
-					]
-			@res.send = sinon.stub()
-			@DropboxWebhookHandler.pollDropboxUids = sinon.stub().callsArg(1)
-			@DropboxWebhookController.webhook(@req, @res)
-			
-		it "should poll the Dropbox uids", ->
-			@DropboxWebhookHandler.pollDropboxUids
-				.calledWith(@dropbox_uids)
-				.should.equal true
-				
-		it "should return success", ->
-			@res.send
-				.calledWith(200)
-				.should.equal true
-

+ 0 - 99
services/web/test/UnitTests/coffee/Dropbox/DropboxWebhookHandlerTests.coffee

@@ -1,99 +0,0 @@
-SandboxedModule = require('sandboxed-module')
-assert = require('assert')
-require('chai').should()
-expect = require("chai").expect
-sinon = require('sinon')
-modulePath = require('path').join __dirname, '../../../../app/js/Features/Dropbox/DropboxWebhookHandler.js'
-
-describe 'DropboxWebhookHandler', ->
-	beforeEach ->
-		@DropboxWebhookHandler = SandboxedModule.require modulePath, requires:
-			"../../models/User": User: @User = {}
-			"../ThirdPartyDataStore/TpdsUpdateSender": @TpdsUpdateSender = {}
-			"redis-sharelatex":
-				createClient: () => @rclient =
-					auth: sinon.stub()
-			'settings-sharelatex': redis: web: {}
-			'logger-sharelatex':
-				log:->
-				err:->
-		@callback = sinon.stub()
-
-	describe "pollDropboxUids", ->
-		beforeEach (done) ->
-			@dropbox_uids = [
-				"123456",
-				"789123"
-			]
-			@DropboxWebhookHandler.pollDropboxUid = sinon.stub().callsArg(1)
-			@DropboxWebhookHandler.pollDropboxUids @dropbox_uids, done
-			
-		it "should call pollDropboxUid for each uid", ->
-			for uid in @dropbox_uids
-				@DropboxWebhookHandler.pollDropboxUid
-					.calledWith(uid)
-					.should.equal true
-					
-	describe "pollDropboxUid", ->
-		beforeEach ->
-			@dropbox_uid = "dropbox-123456"
-			@user_id = "sharelatex-user-id"
-			@User.find = sinon.stub().callsArgWith(1, null, [ _id: @user_id ])
-			@TpdsUpdateSender.pollDropboxForUser = sinon.stub().callsArg(1)
-			
-		describe "when there is already a poll in progress", () ->
-			beforeEach ->
-				@DropboxWebhookHandler._delayAndBatchPoll = sinon.stub().callsArgWith(1, null, false)
-				@DropboxWebhookHandler.pollDropboxUid @dropbox_uid, @callback
-				
-			it "should not go ahead with the poll", ->
-				@TpdsUpdateSender.pollDropboxForUser.called.should.equal false
-				
-		describe "when we are the one to do the delayed poll", () ->
-			beforeEach ->
-				@DropboxWebhookHandler._delayAndBatchPoll = sinon.stub().callsArgWith(1, null, true)
-				@DropboxWebhookHandler.pollDropboxUid @dropbox_uid, @callback
-				
-			it "should look up the user", ->
-				@User.find
-					.calledWith({ "dropbox.access_token.uid": @dropbox_uid, "features.dropbox": true })
-					.should.equal true
-					
-			it "should poll the user's Dropbox", ->
-				@TpdsUpdateSender.pollDropboxForUser
-					.calledWith(@user_id)
-					.should.equal true
-					
-			it "should call the callback", ->
-				@callback.called.should.equal true
-				
-	describe "_delayAndBatchPoll", () ->
-		beforeEach ->
-			@dropbox_uid = "dropbox-uid-123"
-			@DropboxWebhookHandler.POLL_DELAY_IN_MS = 100
-			
-		describe "when no one else is polling yet", ->
-			beforeEach (done) ->
-				@rclient.set = sinon.stub().callsArgWith(5, null, "OK")
-				@start = Date.now()
-				@DropboxWebhookHandler._delayAndBatchPoll @dropbox_uid, (error, @shouldPoll) =>
-					@end = Date.now()
-					done()
-					
-			it "should set the lock", ->
-				@rclient.set
-					.calledWith("dropbox-poll-lock:#{@dropbox_uid}", "LOCK", "PX", @DropboxWebhookHandler.POLL_DELAY_IN_MS, "NX")
-					.should.equal true
-			
-			it "should return the callback after the delay with shouldPoll=true", ->
-				@shouldPoll.should.equal true
-				expect(@end - @start).to.be.at.least(@DropboxWebhookHandler.POLL_DELAY_IN_MS)
-			
-		describe "when someone else is already polling", ->
-			beforeEach ->
-				@rclient.set = sinon.stub().callsArgWith(5, null, null)
-				@DropboxWebhookHandler._delayAndBatchPoll @dropbox_uid, @callback
-			
-			it "should return the callback immediately with shouldPoll=false", ->
-				@callback.calledWith(null, false).should.equal true
-				

+ 0 - 7
services/web/test/UnitTests/coffee/Editor/EditorControllerTests.coffee

@@ -512,13 +512,6 @@ describe "EditorController", ->
 				returnedDocs[1].path.should.equal "doc2.tex"	
 				done()
 
-	describe "forceResyncOfDropbox", ->
-		it 'should tell the project entity handler to flush to tpds', (done)->
-			@ProjectEntityHandler.flushProjectToThirdPartyDataStore = sinon.stub().callsArgWith(1)
-			@EditorController.forceResyncOfDropbox @project_id, (err)=>
-				@ProjectEntityHandler.flushProjectToThirdPartyDataStore.calledWith(@project_id).should.equal true
-				done()
-
 	describe "notifyUsersProjectHasBeenDeletedOrRenamed", ->
 		it 'should emmit a message to all users in a project', (done)->
 			@EditorRealTimeController.emitToRoom = sinon.stub()

+ 3 - 4
services/web/test/UnitTests/coffee/Subscription/SubscriptionHandlerTests.coffee

@@ -66,6 +66,7 @@ describe "Subscription Handler sanboxed", ->
 			'./LimitationsManager':@LimitationsManager
 			"../Email/EmailHandler":@EmailHandler
 			"../Dropbox/DropboxHandler":@DropboxHandler
+			"../../infrastructure/Events": @Events = {emit: sinon.stub()}
 
 		@SubscriptionHandler.syncSubscriptionToUser = sinon.stub().callsArgWith(2)
 
@@ -160,10 +161,8 @@ describe "Subscription Handler sanboxed", ->
 				@RecurlyWrapper.cancelSubscription.called.should.equal true
 				@RecurlyWrapper.cancelSubscription.calledWith(@subscription.recurlySubscription_id).should.equal true
 
-
-			it "should unlink dropbox", ->
-				@DropboxHandler.unlinkAccount.called.should.equal true
-				@DropboxHandler.unlinkAccount.calledWith(@user._id).should.equal true
+			it "should trigger the cancel subscription event", ->
+				@Events.emit.calledWith("cancelSubscription", @user._id).should.equal true
 
 	describe "reactiveRecurlySubscription", ->
 		describe "with a user without a subscription", ->

+ 0 - 209
services/web/test/UnitTests/coffee/Templates/TemplatesControllerTests.coffee

@@ -1,209 +0,0 @@
-should = require('chai').should()
-SandboxedModule = require('sandboxed-module')
-assert = require('assert')
-path = require('path')
-sinon = require('sinon')
-modulePath = path.join __dirname, '../../../../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"
-		@TemplatesPublisher = 
-			publish: sinon.stub()
-			unpublish:sinon.stub()
-			getTemplateDetails: sinon.stub()
-		@ProjectDetailsHandler =
-			getProjectDescription:sinon.stub()
-		@controller = SandboxedModule.require modulePath, requires:
-			'../Uploads/ProjectUploadManager':@ProjectUploadManager
-			'../Project/ProjectOptionsHandler':@ProjectOptionsHandler
-			'../Project/ProjectDetailsHandler':@ProjectDetailsHandler
-			'../Project/ProjectGetter':@ProjectGetter = {}
-			'../Editor/EditorController': @EditorController = {}
-			'./TemplatesPublisher':@TemplatesPublisher
-			"logger-sharelatex": 
-				log:->
-				err:->
-			"settings-sharelatex": 
-				path:
-					dumpFolder:@dumpFolder
-				siteUrl: "http://localhost:3000"
-				apis:
-					templates:
-						url: @templateApiUrl="http://templates.sharelatex.env"
-					web:
-						url: @webApiUrl="http://web-api.sharelatex.env"
-			"node-uuid":v4:=>@uuid
-			"request": @request
-			"fs":@fs
-		@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 = {}
-
-	describe 'reciving a request to create project from templates.sharelatex.com', ->
-
-		it 'should take the zip url and write it to disk', (done)->
-			redirect = =>
-				@ProjectUploadManager.createProjectFromZipArchive.calledWith(@user_id, @templateName, "#{@dumpFolder}/#{@uuid}").should.equal true
-				@request.calledWith("#{@templateApiUrl}#{@zipUrl}").should.equal true
-				@fs.unlink.calledWith("#{@dumpFolder}/#{@uuid}").should.equal true
-				done()
-			res = redirect:redirect
-			@controller.createProjectFromZipTemplate @req, res
-
-
-		it "should go to the web api if the url does not contain templates", (done)->
-			@req.session.templateData.zipUrl = @zipUrl = "/project/52fd24abf080d80a22000fbd/download/zip&templateName=Example_Project&compiler=xelatex"
-			redirect = =>
-				@request.calledWith("#{@webApiUrl}#{@zipUrl}").should.equal true
-				done()
-			res = redirect:redirect
-			@controller.createProjectFromZipTemplate @req, res
-
-		it "should go to the web api if the url has template futher down the string", (done)->
-			@req.session.templateData.zipUrl = @zipUrl = "/project/52fd24abf080d80a22000fbd/download/zip&templateName=templates&compiler=xelatex"
-			redirect = =>
-				@request.calledWith("#{@webApiUrl}#{@zipUrl}").should.equal true
-				done()
-			res = redirect:redirect
-			@controller.createProjectFromZipTemplate @req, res
-
-	describe 'publishProject', ->
-		beforeEach ->
-			@user_id = "user-id-123"
-			@project_id = "project-id-123"
-			@res =
-				send: sinon.stub()
-			@req.params =
-				Project_id: @project_id
-				
-			@ProjectGetter.getProject = sinon.stub().callsArgWith(2, null, {owner_ref: @user_id})
-			@TemplatesPublisher.publish = sinon.stub().callsArgWith(2)
-			@controller.publishProject @req, @res
-			
-		it "should look up the project owner", ->
-			@ProjectGetter.getProject
-				.calledWith(@project_id, { owner_ref: 1 })
-				.should.equal true
-				
-		it "should publish the template", ->
-			@TemplatesPublisher.publish
-				.calledWith(@user_id, @project_id)
-				.should.equal true
-				
-		it "should return a success status", ->
-			@res.send.calledWith(204).should.equal true
-
-	describe 'unpublishProject', ->
-		beforeEach ->
-			@user_id = "user-id-123"
-			@project_id = "project-id-123"
-			@res =
-				send: sinon.stub()
-			@req.params =
-				Project_id: @project_id
-				
-			@ProjectGetter.getProject = sinon.stub().callsArgWith(2, null, {owner_ref: @user_id})
-			@TemplatesPublisher.unpublish = sinon.stub().callsArgWith(2)
-			@controller.unpublishProject @req, @res
-			
-		it "should look up the project owner", ->
-			@ProjectGetter.getProject
-				.calledWith(@project_id, { owner_ref: 1 })
-				.should.equal true
-				
-		it "should publish the template", ->
-			@TemplatesPublisher.unpublish
-				.calledWith(@user_id, @project_id)
-				.should.equal true
-				
-		it "should return a success status", ->
-			@res.send.calledWith(204).should.equal true
-
-	describe 'settings the compiler from the query string', ->
-		it 'should use the said compiler', (done)->
-			@req.session.templateData.compiler = "xelatex"
-			redirect = =>
-				@ProjectOptionsHandler.setCompiler.calledWith(project_id, "xelatex").should.equal true
-				done()
-			res = redirect:redirect
-			@controller.createProjectFromZipTemplate @req, res
-
-		it 'should not call the options handler if there is not set compiler', (done)->
-			redirect = =>
-				@ProjectOptionsHandler.setCompiler.called.should.equal false
-				done()
-			res = redirect:redirect
-			@controller.createProjectFromZipTemplate @req, res
-
-	describe "updateProjectDescription", ->
-		beforeEach ->
-			@EditorController.updateProjectDescription = sinon.stub().callsArg(2)
-			@res =
-				send: sinon.stub()
-			@req.params =
-				Project_id: @project_id = "project-id-123"
-			@req.body =
-				description: @description = "test description"
-				
-			@controller.updateProjectDescription @req, @res
-			
-		it "should update the project description", ->
-			@EditorController.updateProjectDescription
-				.calledWith(@project_id, @description)
-				.should.equal true
-				
-		it "should return a success code", ->
-			@res.send.calledWith(204).should.equal true
-
-	describe 'getTemplateDetails', ->
-		beforeEach ->
-			@user_id = "user-id-123"
-			@project_id = "project-id-123"
-			@res =
-				json: sinon.stub()
-			@req.params =
-				Project_id: @project_id
-				
-			@ProjectGetter.getProject = sinon.stub().callsArgWith(2, null, {owner_ref: @user_id})
-			@TemplatesPublisher.getTemplateDetails.callsArgWith(2, null, @details = {exists: true})
-			@ProjectDetailsHandler.getProjectDescription.callsArgWith(1, null, @description = "test description")
-			
-			@controller.getTemplateDetails @req, @res
-
-		it "should get the template details for the user_id and project_id", ->
-			@TemplatesPublisher.getTemplateDetails
-				.calledWith(@user_id, @project_id)
-				.should.equal true
-				
-		it "should return the details and description", ->
-			@res.json
-				.calledWith({
-					exists: @details.exists
-					description: @description
-				})
-				.should.equal true
-

+ 0 - 64
services/web/test/UnitTests/coffee/Templates/TemplatesPublisherTests.coffee

@@ -1,64 +0,0 @@
-should = require('chai').should()
-SandboxedModule = require('sandboxed-module')
-assert = require('assert')
-path = require('path')
-sinon = require('sinon')
-modulePath = path.join __dirname, '../../../../app/js/Features/Templates/TemplatesPublisher'
-expect = require("chai").expect
-
-describe 'Templates publish', ->
-
-	beforeEach ->
-		@request = 
-			post: sinon.stub().callsArgWith(1)
-			del: sinon.stub().callsArgWith(1)
-			get: sinon.stub()
-		@settings = 
-			apis:
-				templates:
-					url: "http://templates.sharelatex.env"
-		@TemplatesPublisher = SandboxedModule.require modulePath, requires:
-			"request": @request
-			"settings-sharelatex":@settings
-			"logger-sharelatex": 
-				log:->
-				err:->
-					
-		@project_id = "12312132"
-		@user_id = "132jlkjdsaoij"
-
-	describe "publish", ->
-
-		it 'should post the project to the templates api', (done)->
-			@TemplatesPublisher.publish @user_id, @project_id, =>
-				uri = "#{@settings.apis.templates.url}/templates/user/#{@user_id}/project/#{@project_id}"
-				@request.post.calledWith(uri).should.equal true
-				done()
-
-
-	describe "unpublish", ->
-
-		it "should make a DELETE request to templates api", (done)->
-			@TemplatesPublisher.unpublish @user_id, @project_id, =>
-				uri = "#{@settings.apis.templates.url}/templates/user/#{@user_id}/project/#{@project_id}"
-				@request.del.calledWith(uri).should.equal true
-				done()
-
-
-	describe "getTemplateDetails", ->	
-		it "should make a get request to templates api", (done)->
-			body =
-				exists:true
-			@request.get.callsArgWith(1, null, null, JSON.stringify(body))
-			@TemplatesPublisher.getTemplateDetails @user_id, @project_id, (err, details)=>
-				uri = "#{@settings.apis.templates.url}/templates/user/#{@user_id}/project/#{@project_id}/details"
-				@request.get.calledWith(uri).should.equal true
-				assert.deepEqual details, body
-				done()
-
-
-		it "should catch an error thrown from trying to parse bad json", (done)->	
-			@request.get.callsArgWith(1, null, null, "<not json>")
-			@TemplatesPublisher.getTemplateDetails @user_id, @project_id, (err, details)=>
-				expect(err).to.exist	
-				done()

+ 0 - 150
services/web/test/UnitTests/coffee/Templates/TemplatesWebControllerTests.coffee

@@ -1,150 +0,0 @@
-should = require('chai').should()
-SandboxedModule = require('sandboxed-module')
-assert = require('assert')
-path = require('path')
-sinon = require('sinon')
-modulePath = path.join __dirname, "../../../../app/js/Features/Templates/TemplatesWebController"
-expect = require("chai").expect
-
-describe "TemplatesWebController", ->
-
-	beforeEach ->
-
-		@settings = 
-			apis:
-				templates_api:
-					url:"templates.sharelatex.env"
-		@TemplatesWebController = SandboxedModule.require modulePath, requires:
-			"settings-sharelatex":@settings
-			"logger-sharelatex": 
-				log:->
-				err:->
-		@stubbedApiData = 
-			template:{_id:"12312321", name:"bob"}
-			tag: {name:"tag name"}
-
-		@TemplatesWebController._getDataFromTemplatesApi = sinon.stub().callsArgWith(1, null, @stubbedApiData)
-
-		@user_id = "12332lk3jlkj"
-		@tag_name = "tag-name-here"
-		@template_name = "template-name-here"
-		@template_id = "template_id_here"
-		@req = 
-			params: 
-				user_id: @user_id
-		@res = {}
-
-	describe "renderTemplatesIndexPage", ->
-
-		it "should get the data from the templates api", (done)->
-			@res.render = (viewName, data)=>
-				@TemplatesWebController._getDataFromTemplatesApi.calledWith("/user/#{@user_id}").should.equal true
-				data.should.equal @stubbedApiData
-				done()
-			@TemplatesWebController.renderTemplatesIndexPage @req, @res
-
-
-	describe "renerTemplateInTag", ->
-
-		it "should get the data from the templates api", (done)->
-			@res.render = (viewName, data)=>
-				@TemplatesWebController._getDataFromTemplatesApi.calledWith("/user/#{@user_id}/tag/#{@tag_name}/template/#{@template_name}").should.equal true
-				data.should.equal @stubbedApiData
-				done()
-
-			@req.params =
-				user_id:@user_id
-				template_name:@template_name
-				tag_name:@tag_name
-
-			@TemplatesWebController.renerTemplateInTag @req, @res
-
-
-	describe "tagOrCanonicalPage", ->
-
-		beforeEach ->
-			@TemplatesWebController._renderCanonicalPage = sinon.stub()
-			@TemplatesWebController._renderAllTemplatesPage = sinon.stub()
-			@TemplatesWebController._renderTagPage = sinon.stub()
-
-		it "should call _renderCanonicalPage if there is a template id", ()->
-
-			@req.params =
-				template_id:@template_id
-
-			@TemplatesWebController.tagOrCanonicalPage @req, @res
-
-			@TemplatesWebController._renderCanonicalPage.called.should.equal true
-			@TemplatesWebController._renderAllTemplatesPage.called.should.equal false
-			@TemplatesWebController._renderTagPage.called.should.equal false
-
-		it "should call _renderAllTemplatesPage the tag name is all", ()->
-
-			@req.params =
-				tag_name:"all"
-
-			@TemplatesWebController.tagOrCanonicalPage @req, @res
-
-			@TemplatesWebController._renderCanonicalPage.called.should.equal false
-			@TemplatesWebController._renderAllTemplatesPage.called.should.equal true
-			@TemplatesWebController._renderTagPage.called.should.equal false
-
-
-		it "should call _renderTagPage the tag name is set", ()->
-
-			@req.params =
-				tag_name:"some-tag"
-
-			@TemplatesWebController.tagOrCanonicalPage @req, @res
-
-			@TemplatesWebController._renderCanonicalPage.called.should.equal false
-			@TemplatesWebController._renderAllTemplatesPage.called.should.equal false
-			@TemplatesWebController._renderTagPage.called.should.equal true
-
-	describe "_renderCanonicalPage", ->
-
-		it "should get the data from the templates api", (done)->
-			@res.render = (viewName, data)=>
-				@TemplatesWebController._getDataFromTemplatesApi.calledWith("/user/#{@user_id}/template/#{@template_id}").should.equal true
-				data.tag = null
-				data.should.equal @stubbedApiData
-				done()
-
-			@req.params =
-				user_id:@user_id
-				template_id:@template_id
-
-			@TemplatesWebController._renderCanonicalPage @req, @res
-
-
-	describe "_renderAllTemplatesPage", ->
-
-		it "should get the data from the templates api", (done)->
-			@res.render = (viewName, data)=>
-				@TemplatesWebController._getDataFromTemplatesApi.calledWith("/user/#{@user_id}/all").should.equal true
-				data.should.equal @stubbedApiData
-				done()
-
-			@req.params =
-				user_id:@user_id
-
-			@TemplatesWebController._renderAllTemplatesPage @req, @res
-
-
-	describe "_renderTagPage", ->
-
-		it "should get the data from the templates api", (done)->
-			@res.render = (viewName, data)=>
-				@TemplatesWebController._getDataFromTemplatesApi.calledWith("/user/#{@user_id}/tag/#{@tag_name}").should.equal true
-				data.should.equal @stubbedApiData
-				done()
-
-			@req.params =
-				user_id:@user_id
-				tag_name:@tag_name
-
-			@TemplatesWebController._renderTagPage @req, @res
-
-
-
-