diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000000000000000000000000000000000..c6f98d843d7958f5ffcede4a2da0fe6dbaef3159 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,17 @@ +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "daily" + + pull-request-branch-name: + # Separate sections of the branch name with a hyphen + # Docker images use the branch name and do not support slashes in tags + # https://github.com/overleaf/google-ops/issues/822 + # https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#pull-request-branch-nameseparator + separator: "-" + + # Block informal upgrades -- security upgrades use a separate queue. + # https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#open-pull-requests-limit + open-pull-requests-limit: 0 diff --git a/.gitignore b/.gitignore index 008b9d7cae36857bf12165c96dcc0b1283f83ead..edcda84f243f2fc192bad3fb33272e0d6889040f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,6 @@ clsi filestore track-changes docstore -tags chat spelling real-time @@ -23,4 +22,4 @@ tmp db.sqlite .DS_Store -.vagrant \ No newline at end of file +.vagrant diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5d9f82d9fc280e176244c5a040181e5f6a093220..814c1c677550b9954f4a72b808ed4d0a0edaf943 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ Contributing to ShareLaTeX Thank you for reading this! If you'd like to report a bug or join in the development of ShareLaTeX, then here are some notes on how to do that. -*Note that ShareLaTeX is actually made up of many seperate repositories (a list is available +*Note that ShareLaTeX is actually made up of many separate repositories (a list is available [here](https://github.com/sharelatex/sharelatex/blob/master/README.md#other-repositories)).* Reporting bugs and opening issues diff --git a/Dockerfile b/Dockerfile index a8798a9e6c6d98847c12fde3b18440028c2be36c..2f394fed64f420bedb8906e32d08805de5c4fc0d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -58,7 +58,7 @@ RUN cd /var/www/sharelatex \ RUN cd /var/www/sharelatex \ && bash ./bin/compile-services -# Links CLSI sycntex to its default location +# Links CLSI synctex to its default location # ------------------------------------------ RUN ln -s /var/www/sharelatex/clsi/bin/synctex /opt/synctex @@ -77,6 +77,7 @@ ADD ${baseDir}/nginx/sharelatex.conf /etc/nginx/sites-enabled/sharelatex.conf # Configure log rotation # ---------------------- ADD ${baseDir}/logrotate/sharelatex /etc/logrotate.d/sharelatex +RUN chmod 644 /etc/logrotate.d/sharelatex # Copy Phusion Image startup scripts to its location @@ -93,6 +94,8 @@ ENV WEB_API_USER "sharelatex" ENV SHARELATEX_APP_NAME "Overleaf Community Edition" +ENV OPTIMISE_PDF "true" + EXPOSE 80 diff --git a/Dockerfile-base b/Dockerfile-base index f3334cda57fed27ef7efd64e7b526b84b7fce25d..15ac43da33f10f25961346680150c071e2b32683 100644 --- a/Dockerfile-base +++ b/Dockerfile-base @@ -7,6 +7,11 @@ FROM phusion/baseimage:0.11 ENV baseDir . +# Makes sure LuaTex cache is writable +# ----------------------------------- +ENV TEXMFVAR=/var/lib/sharelatex/tmp/texmf-var + + # Install dependencies # -------------------- RUN apt-get update \ diff --git a/Gruntfile.coffee b/Gruntfile.coffee index 7fb8881930bf2bd2ff8ab8fedb8bee3f0d113cda..3af76ef7637f3b393c2970c22a9600a7b239e84a 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -193,7 +193,7 @@ module.exports = (grunt) -> grunt.log.errorlns """ !!!!!!!!!!!!!! MONGO ERROR !!!!!!!!!!!!!! - ShareLaTeX can not talk to the mongdb instance + ShareLaTeX can not talk to the mongodb instance Check the mongodb instance is running and accessible on env var SHARELATEX_MONGO_URL diff --git a/README.md b/README.md index 8b1463d23c8b2185b9650143bd392a624c99195c..03c1f4d47ff2cf1a7c16a2a50d8d7de9b40dcf6e 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,9 @@ If you are upgrading from a previous version of Overleaf, please see the [Releas ## Other repositories -This repository does not contain any code. It acts a wrapper and toolkit for managing the many different Overleaf services. These each run as their own Node.js process and have their own Github repository. These are all downloaded and set up when you run `grunt install` +This repository does not contain any code. It acts a wrapper and toolkit for managing the many different Overleaf services. These each run as their own Node.js process and have their own GitHub repository. These are all downloaded and set up when you run `grunt install` -| Service | Description | +| Service | Description | | ------- | ----------- | | **[web](https://github.com/overleaf/web)** | The front facing web server that serves all the HTML pages, CSS and JavaScript to the client. Also contains a lot of logic around creating and editing projects, and account management. | | **[document-updater](https://github.com/overleaf/document-updater)** | Processes updates that come in from the editor when users modify documents. Ensures that the updates are applied in the right order, and that only one operation is modifying the document at a time. Also caches the documents in redis for very fast but persistent modifications. | @@ -51,7 +51,6 @@ This repository does not contain any code. It acts a wrapper and toolkit for man | **[filestore](https://github.com/overleaf/filestore)** | An API for performing CRUD (Create, Read, Update and Delete) operations on binary files (like images) stored in Overleaf. | | **[track-changes](https://github.com/overleaf/track-changes)** | An API for compressing and storing the updates applied to a document, and then rendering a diff of the changes between any two time points. | | **[chat](https://github.com/overleaf/chat)** | The backend API for storing and fetching chat messages. | -| **[tags](https://github.com/overleaf/tags)** | The backend API for managing project tags (folders). | | **[spelling](https://github.com/overleaf/spelling)** | An API for running server-side spelling checking on Overleaf documents. | ## Overleaf Docker Image diff --git a/bin/compile-services b/bin/compile-services index 76c432143abcd4e9cb201afa1e93b1eeaa6a434b..4045a49a4c1e4e98a388db7506a84a9146151ac6 100755 --- a/bin/compile-services +++ b/bin/compile-services @@ -12,9 +12,6 @@ grep 'name:' config/services.js | \ web) npm run webpack:production ;; - real-time) - npm run compile:all - ;; *) echo "$service doesn't require a compilation" ;; diff --git a/docker-compose.yml b/docker-compose.yml index 059221e0c6c55d419c322c40d0aa933bd1fd3d0b..0d7c80f70adfa7cb63f80003a01ae73d50de2071 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,6 @@ services: condition: service_healthy redis: condition: service_started - privileged: true ports: - 80:80 links: @@ -20,7 +19,7 @@ services: volumes: - ~/sharelatex_data:/var/lib/sharelatex ######################################################################## - #### Server Pro: Un-comment the following line to mount the docker #### + #### Server Pro: Uncomment the following line to mount the docker #### #### socket, required for Sibling Containers to work #### ######################################################################## # - /var/run/docker.sock:/var/run/docker.sock @@ -39,7 +38,7 @@ services: # Enables Thumbnail generation using ImageMagick ENABLE_CONVERSIONS: 'true' - + # Disables email confirmation requirement EMAIL_CONFIRMATION_DISABLED: 'true' @@ -70,7 +69,7 @@ services: # SHARELATEX_EMAIL_SMTP_PASS: # SHARELATEX_EMAIL_SMTP_TLS_REJECT_UNAUTH: true # SHARELATEX_EMAIL_SMTP_IGNORE_TLS: false - # SHARELATEX_CUSTOM_EMAIL_FOOTER: "<div>This system is run by department x </div>" + # SHARELATEX_CUSTOM_EMAIL_FOOTER: "This system is run by department x" ################ ## Server Pro ## @@ -103,7 +102,7 @@ services: mongo: restart: always - image: mongo + image: mongo:4.0 container_name: mongo expose: - 27017 @@ -117,7 +116,7 @@ services: redis: restart: always - image: redis + image: redis:5 container_name: redis expose: - 6379 diff --git a/hotfix/2.3.1/Dockerfile b/hotfix/2.3.1/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..36f136aacc6d9860a4b3acd3f557ed197110e43d --- /dev/null +++ b/hotfix/2.3.1/Dockerfile @@ -0,0 +1,7 @@ +FROM sharelatex/sharelatex:2.3.0 + + +# Patch: Fixes NPE when invoking synctex (https://github.com/overleaf/overleaf/issues/756) +ADD check-clsi-setting-exists.patch /var/www/sharelatex/clsi/app/js/check-clsi-setting-exists.patch +RUN cd /var/www/sharelatex/clsi/app/js && \ + patch < check-clsi-setting-exists.patch diff --git a/hotfix/2.3.1/check-clsi-setting-exists.patch b/hotfix/2.3.1/check-clsi-setting-exists.patch new file mode 100644 index 0000000000000000000000000000000000000000..6f6535bc69ac017441a949dfe3c5b896a447b953 --- /dev/null +++ b/hotfix/2.3.1/check-clsi-setting-exists.patch @@ -0,0 +1,11 @@ +--- a/app/js/CompileManager.js ++++ b/app/js/CompileManager.js +@@ -536,7 +536,7 @@ module.exports = CompileManager = { + compileName, + command, + directory, +- Settings.clsi != null ? Settings.clsi.docker.image : undefined, ++ Settings.clsi && Settings.clsi.docker ? Settings.clsi.docker.image : undefined, + timeout, + {}, + function(error, output) { diff --git a/hotfix/2.4.1/Dockerfile b/hotfix/2.4.1/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..d7655511c1ccc2a70d0e09ec09df08cb48f0a1d7 --- /dev/null +++ b/hotfix/2.4.1/Dockerfile @@ -0,0 +1,6 @@ +FROM sharelatex/sharelatex:2.4.0 + + +# Patch: Fixes missing dependencies on web startup (https://github.com/overleaf/overleaf/issues/767) +RUN cd /var/www/sharelatex/web && \ + npm install i18next@^19.6.3 i18next-fs-backend@^1.0.7 i18next-http-middleware@^3.0.2 diff --git a/hotfix/2.4.2/Dockerfile b/hotfix/2.4.2/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..640eea78c3c9c7d4d9ea1a53eb2858e7f7ef7853 --- /dev/null +++ b/hotfix/2.4.2/Dockerfile @@ -0,0 +1,10 @@ +FROM sharelatex/sharelatex:2.4.1 + + +# Patch: Fixes anonymous read/write sharing +COPY anonymous-metadata.patch ${baseDir} +RUN cd ${baseDir} && patch -p0 < anonymous-metadata.patch + +# Patch: Fixes left footer with html text +COPY left-footer-skip-translation.patch ${baseDir} +RUN cd ${baseDir} && patch -p0 < left-footer-skip-translation.patch diff --git a/hotfix/2.4.2/anonymous-metadata.patch b/hotfix/2.4.2/anonymous-metadata.patch new file mode 100644 index 0000000000000000000000000000000000000000..ea041abf9cc660da289605d0d17d0aa9bc361de3 --- /dev/null +++ b/hotfix/2.4.2/anonymous-metadata.patch @@ -0,0 +1,43 @@ +--- /var/www/sharelatex/web/app/src/router.js 2020-09-14 20:21:39.741433000 +0000 ++++ /var/www/sharelatex/web/app/src/router.js 2020-09-14 20:13:08.000000000 +0000 +@@ -607,16 +607,17 @@ + ProjectDownloadsController.downloadMultipleProjects + ) + ++ console.log(`allowAnonymousReadAndWriteSharing: ${Settings.allowAnonymousReadAndWriteSharing}`) + webRouter.get( + '/project/:project_id/metadata', + AuthorizationMiddleware.ensureUserCanReadProject, +- AuthenticationController.requireLogin(), ++ Settings.allowAnonymousReadAndWriteSharing ? (req, res, next) => { next() } : AuthenticationController.requireLogin(), + MetaController.getMetadata +- ) ++ ) + webRouter.post( + '/project/:project_id/doc/:doc_id/metadata', + AuthorizationMiddleware.ensureUserCanReadProject, +- AuthenticationController.requireLogin(), ++ Settings.allowAnonymousReadAndWriteSharing ? (req, res, next) => { next() } : AuthenticationController.requireLogin(), + MetaController.broadcastMetadataForDoc + ) + privateApiRouter.post( +--- /var/www/sharelatex/web/app/src/Features/Contacts/ContactRouter.js 2020-09-14 20:21:52.243779000 +0000 ++++ /var/www/sharelatex/web/app/src/Features/Contacts/ContactRouter.js 2020-09-14 20:13:08.000000000 +0000 +@@ -5,6 +5,8 @@ + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ ++const Settings = require('settings-sharelatex') ++ + const AuthenticationController = require('../Authentication/AuthenticationController') + const ContactController = require('./ContactController') + +@@ -12,7 +14,7 @@ + apply(webRouter, apiRouter) { + return webRouter.get( + '/user/contacts', +- AuthenticationController.requireLogin(), ++ Settings.allowAnonymousReadAndWriteSharing ? (req, res, next) => { next() } : AuthenticationController.requireLogin(), + ContactController.getContacts + ) + } diff --git a/hotfix/2.4.2/left-footer-skip-translation.patch b/hotfix/2.4.2/left-footer-skip-translation.patch new file mode 100644 index 0000000000000000000000000000000000000000..ee6e33a4175b121f208853ce6155cd6eb5ada4ab --- /dev/null +++ b/hotfix/2.4.2/left-footer-skip-translation.patch @@ -0,0 +1,12 @@ + +--- /var/www/sharelatex/web/app/views/layout/footer.pug ++++ /var/www/sharelatex/web/app/app/views/layout/footer.pug +@@ -32,7 +32,7 @@ footer.site-footer + if item.url + a(href=item.url, class=item.class) !{translate(item.text)} + else +- | !{translate(item.text)} ++ | !{item.text} + + ul.col-md-3.text-right + diff --git a/hotfix/2.5.1/Dockerfile b/hotfix/2.5.1/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..d22f9123d18470f11bfe51a8bcd866509872d8a4 --- /dev/null +++ b/hotfix/2.5.1/Dockerfile @@ -0,0 +1,13 @@ +FROM sharelatex/sharelatex:2.5.0 + +# Patch #826: Fixes log path for contacts service to be picked up by logrotate +COPY contacts-run.patch /etc/service/contacts-sharelatex +RUN cd /etc/service/contacts-sharelatex && patch < contacts-run.patch + +# Patch #826: delete old logs for the contacts service +COPY delete-old-logs.patch /etc/my_init.d +RUN cd /etc/my_init.d && patch < delete-old-logs.patch \ +&& chmod +x /etc/my_init.d/10_delete_old_logs.sh + +# Patch #827: fix logrotate file permissions +RUN chmod 644 /etc/logrotate.d/sharelatex diff --git a/hotfix/2.5.1/contacts-run.patch b/hotfix/2.5.1/contacts-run.patch new file mode 100644 index 0000000000000000000000000000000000000000..81ef36ecb050fd19b758272524889839f91e1b88 --- /dev/null +++ b/hotfix/2.5.1/contacts-run.patch @@ -0,0 +1,8 @@ +--- a/run ++++ b/run +@@ -7,4 +7,4 @@ if [ "$DEBUG_NODE" == "true" ]; then + NODE_PARAMS="--inspect=0.0.0.0:30360" + fi + +-exec /sbin/setuser www-data /usr/bin/node $NODE_PARAMS /var/www/sharelatex/contacts/app.js >> /var/log/sharelatex/contacts 2>&1 ++exec /sbin/setuser www-data /usr/bin/node $NODE_PARAMS /var/www/sharelatex/contacts/app.js >> /var/log/sharelatex/contacts.log 2>&1 diff --git a/hotfix/2.5.1/delete-old-logs.patch b/hotfix/2.5.1/delete-old-logs.patch new file mode 100644 index 0000000000000000000000000000000000000000..bc2be14adfa99c9021a65f1e283f814b8afebc54 --- /dev/null +++ b/hotfix/2.5.1/delete-old-logs.patch @@ -0,0 +1,10 @@ +--- /dev/null ++++ b/10_delete_old_logs.sh +@@ -0,0 +1,7 @@ ++#!/bin/sh ++set -e ++ ++# Up to version 2.5.0 the logs of the contacts service were written into a ++# file that was not picked up by logrotate. ++# The service is stable and we can safely discard any logs. ++rm -vf /var/log/sharelatex/contacts diff --git a/hotfix/2.5.2/12_update_token_email.js b/hotfix/2.5.2/12_update_token_email.js new file mode 100644 index 0000000000000000000000000000000000000000..e4d6e32254b448a95468211a0bd611c3da1ecd95 --- /dev/null +++ b/hotfix/2.5.2/12_update_token_email.js @@ -0,0 +1,28 @@ +const Settings = require('settings-sharelatex') +const mongojs = require('mongojs') +const db = mongojs(Settings.mongo.url, ['tokens']) +const async = require('async') + +exports.migrate = (client, done) => { + console.log(`>> Updating 'data.email' to lower case in tokens`) + + db.tokens.find({}, { 'data.email': 1 }, (err, tokens) => { + if (err) { + return done(err) + } + + async.eachSeries( + tokens, + (token, callback) => { + db.tokens.update( + { _id: token._id }, + { $set: { 'data.email': token.data.email.toLowerCase() } }, + callback + ) + }, + done + ) + }) +} + +exports.rollback = (client, done) => done() diff --git a/hotfix/2.5.2/Dockerfile b/hotfix/2.5.2/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..ddf596deeab9f73bb002d96e6062b6b4fe497463 --- /dev/null +++ b/hotfix/2.5.2/Dockerfile @@ -0,0 +1,8 @@ +FROM sharelatex/sharelatex:2.5.1 + +# Patch: fixes registration token creation +COPY create-token-lowercase-email.patch ${baseDir} +RUN cd ${baseDir} && patch -p0 < create-token-lowercase-email.patch + +# Migration for tokens with invalid email addresses +ADD 12_update_token_email.js /var/www/sharelatex/migrations/12_update_token_email.js diff --git a/hotfix/2.5.2/create-token-lowercase-email.patch b/hotfix/2.5.2/create-token-lowercase-email.patch new file mode 100644 index 0000000000000000000000000000000000000000..23dfaa3a432bdb05dbfe6b53548e5a56cc2bece1 --- /dev/null +++ b/hotfix/2.5.2/create-token-lowercase-email.patch @@ -0,0 +1,11 @@ +--- /var/www/sharelatex/web/app/src/Features/User/UserRegistrationHandler.js ++++ /var/www/sharelatex/web/app/src/Features/User/UserRegistrationHandler.js +@@ -122,7 +122,7 @@ const UserRegistrationHandler = { + const ONE_WEEK = 7 * 24 * 60 * 60 // seconds + OneTimeTokenHandler.getNewToken( + 'password', +- { user_id: user._id.toString(), email }, ++ { user_id: user._id.toString(), email: user.email }, + { expiresIn: ONE_WEEK }, + (err, token) => { + if (err != null) { diff --git a/init_scripts/10_delete_old_logs.sh b/init_scripts/10_delete_old_logs.sh new file mode 100755 index 0000000000000000000000000000000000000000..1b606dbf92e10b1b066f8872119f2276c7e0b953 --- /dev/null +++ b/init_scripts/10_delete_old_logs.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -e + +# Up to version 2.5.0 the logs of the contacts service were written into a +# file that was not picked up by logrotate. +# The service is stable and we can safely discard any logs. +rm -vf /var/log/sharelatex/contacts diff --git a/migrations/1_move_doc_lines_to_doc_collection.coffee b/migrations/1_move_doc_lines_to_doc_collection.coffee index e4433de7bd16a65bd854ac626c96ffe8dedcb9a9..ce8c208657acbfb3fdf8fc72c66af4754ad2ea8a 100644 --- a/migrations/1_move_doc_lines_to_doc_collection.coffee +++ b/migrations/1_move_doc_lines_to_doc_collection.coffee @@ -19,7 +19,7 @@ printProgress = -> exec "wc #{finished_projects_path}", (error, results) -> setTimeout printProgress, 1000 * 30 -checkIfFileHasBeenProccessed = (project_id, callback)-> +checkIfFileHasBeenProcessed = (project_id, callback)-> exec "grep #{project_id} #{finished_projects_path}", (error, results) -> hasBeenProcessed = _.include(results, project_id) callback(error, hasBeenProcessed) @@ -125,9 +125,9 @@ saveDocsIntoMongo = (project_id, docs, callback)-> processNext = (project_id, callback)-> - checkIfFileHasBeenProccessed project_id, (err, hasBeenProcessed)-> + checkIfFileHasBeenProcessed project_id, (err, hasBeenProcessed)-> if hasBeenProcessed - console.log "#{project_id} already procssed, skipping" + console.log "#{project_id} already processed, skipping" return callback() console.log "#{project_id} processing" getAllDocs project_id, (err, docs)-> diff --git a/migrations/2_doc_lines_delete_from_project.coffee b/migrations/2_doc_lines_delete_from_project.coffee index 2d5222f63d0befb770a2a9eca2673ca167792e75..0be28446d8c6aa20d046a8074cf74ee4495ab21e 100644 --- a/migrations/2_doc_lines_delete_from_project.coffee +++ b/migrations/2_doc_lines_delete_from_project.coffee @@ -16,7 +16,7 @@ printProgress = -> exec "wc #{finished_projects_path}", (error, results) -> setTimeout printProgress, 1000 * 30 -checkIfFileHasBeenProccessed = (project_id, callback)-> +checkIfFileHasBeenProcessed = (project_id, callback)-> exec "grep #{project_id} #{finished_projects_path}", (error, results) -> hasBeenProcessed = _.include(results, project_id) callback(error, hasBeenProcessed) @@ -125,7 +125,7 @@ getWhichDocsCanBeDeleted = (docs, callback = (err, docsToBeDeleted, unmigratedDo async.series jobs, (err)-> callback err, docsToBeDeleted, unmigratedDocs -whipeDocLines = (project_id, mongoPath, callback)-> +wipeDocLines = (project_id, mongoPath, callback)-> update = $unset: {} update.$unset["#{mongoPath}.lines"] = "" @@ -137,15 +137,15 @@ removeDocLinesFromProject = (docs, project, callback)-> jobs = _.map docs, (doc)-> (cb)-> findDocInProject project, doc._id, (err, doc, mongoPath)-> - whipeDocLines project._id, mongoPath, cb + wipeDocLines project._id, mongoPath, cb async.parallelLimit jobs, 5, callback processNext = (project_id, callback)-> if !project_id? or project_id.length == 0 return callback() - checkIfFileHasBeenProccessed project_id, (err, hasBeenProcessed)-> + checkIfFileHasBeenProcessed project_id, (err, hasBeenProcessed)-> if hasBeenProcessed - console.log "#{project_id} already procssed, skipping" + console.log "#{project_id} already processed, skipping" return callback() console.log "#{project_id} processing" getAllDocs project_id, (err, docs, project)-> diff --git a/migrations/3_pack_docHistory_collection.coffee b/migrations/3_pack_docHistory_collection.coffee index c652dd7816b7b969be8c422ce34e9a59e6fe23fa..affe1fcfd1744ae25ddef9095ac57ff4b5ec05a7 100644 --- a/migrations/3_pack_docHistory_collection.coffee +++ b/migrations/3_pack_docHistory_collection.coffee @@ -65,7 +65,7 @@ markDocAsUnmigrated = (doc_id, callback)-> markDocAsProcessed doc_id, (err)-> fs.appendFile unmigrated_docs_path, "#{doc_id}\n", callback -checkIfDocHasBeenProccessed = (doc_id, callback)-> +checkIfDocHasBeenProcessed = (doc_id, callback)-> callback(null, finished_docs[doc_id]) processNext = (doc_id, callback)-> @@ -73,7 +73,7 @@ processNext = (doc_id, callback)-> return callback() if needToExit return callback(new Error("graceful shutdown")) - checkIfDocHasBeenProccessed doc_id, (err, hasBeenProcessed)-> + checkIfDocHasBeenProcessed doc_id, (err, hasBeenProcessed)-> if hasBeenProcessed console.log "#{doc_id} already processed, skipping" return callback() diff --git a/migrations/about_migrations.md b/migrations/about_migrations.md index 97f91442b1f431ee79be3ebf41976a93bb7dbf46..8a9d7596ba5f519be15ec2168f0b6a9095429d55 100644 --- a/migrations/about_migrations.md +++ b/migrations/about_migrations.md @@ -1,4 +1,4 @@ -If migration is stopped mid way it will start at the beginging next time +If migration is stopped mid way it will start at the beginning next time To see the run migrations do db.getCollection('_migrations').find() you can't do db._migrations.find() diff --git a/nginx/sharelatex.conf b/nginx/sharelatex.conf index 3a10a999f0a1b35f55e2c3521bed8403c27e971d..8123e65bcd5b949d9b3923963801684032943d3d 100644 --- a/nginx/sharelatex.conf +++ b/nginx/sharelatex.conf @@ -11,8 +11,8 @@ server { proxy_set_header Connection "upgrade"; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_read_timeout 3m; - proxy_send_timeout 3m; + proxy_read_timeout 10m; + proxy_send_timeout 10m; } location /socket.io { @@ -23,8 +23,8 @@ server { proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_read_timeout 3m; - proxy_send_timeout 3m; + proxy_read_timeout 10m; + proxy_send_timeout 10m; } location /stylesheets { diff --git a/runit/contacts-sharelatex/run b/runit/contacts-sharelatex/run index e220d9ac1d001dbaf04e9fd869b7760e07e8edc8..4c01aa098583cd5ac3a8e5f3c0ce81d6bf954cd0 100755 --- a/runit/contacts-sharelatex/run +++ b/runit/contacts-sharelatex/run @@ -7,4 +7,4 @@ if [ "$DEBUG_NODE" == "true" ]; then NODE_PARAMS="--inspect=0.0.0.0:30360" fi -exec /sbin/setuser www-data /usr/bin/node $NODE_PARAMS /var/www/sharelatex/contacts/app.js >> /var/log/sharelatex/contacts 2>&1 +exec /sbin/setuser www-data /usr/bin/node $NODE_PARAMS /var/www/sharelatex/contacts/app.js >> /var/log/sharelatex/contacts.log 2>&1 diff --git a/runit/tags-sharelatex/run b/runit/tags-sharelatex/run deleted file mode 100755 index 62fe058ad9cace0ddf200e027e2b202767376f3c..0000000000000000000000000000000000000000 --- a/runit/tags-sharelatex/run +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -export SHARELATEX_CONFIG=/etc/sharelatex/settings.coffee - -NODE_PARAMS="" -if [ "$DEBUG_NODE" == "true" ]; then - echo "running debug - tags" - NODE_PARAMS="--inspect=0.0.0.0:30120" -fi - -exec /sbin/setuser www-data /usr/bin/node $NODE_PARAMS /var/www/sharelatex/tags/app.js >> /var/log/sharelatex/tags.log 2>&1 diff --git a/services.js b/services.js index 236eb165e23eae3aaf8562c006f892992752a78c..2e502b21d220e9b9a8a3547256e7d789db31f1c5 100644 --- a/services.js +++ b/services.js @@ -32,10 +32,6 @@ module.exports = name: "chat", repo: "https://github.com/sharelatex/chat-sharelatex.git", version: "master" -}, { - name: "tags", - repo: "https://github.com/sharelatex/tags-sharelatex.git", - version: "master" }, { name: "spelling", repo: "https://github.com/sharelatex/spelling-sharelatex.git", diff --git a/settings.coffee b/settings.coffee index 61f1be0958ab46c3dd8be9f545bb84a9990389db..eccabd843c36e1660f7af7d587be08385a975167 100644 --- a/settings.coffee +++ b/settings.coffee @@ -13,15 +13,22 @@ parse = (option)-> opt = JSON.parse(option) return opt catch err - console.error "problem parsing #{option}, invalid JSON" - return undefined + throw new Error("problem parsing #{option}, invalid JSON") +parseIntOrFail = (value)-> + parsedValue = parseInt(value, 10) + if isNaN(parsedValue) + throw new Error("'#{value}' is an invalid integer") + return parsedValue DATA_DIR = '/var/lib/sharelatex/data' TMP_DIR = '/var/lib/sharelatex/tmp' settings = + clsi: + optimiseInDocker: process.env['OPTIMISE_PDF'] == 'true' + brandPrefix: "" allowAnonymousReadAndWriteSharing: @@ -30,7 +37,7 @@ settings = # Databases # --------- - # ShareLaTeX's main persistant data store is MongoDB (http://www.mongodb.org/) + # ShareLaTeX's main persistent data store is MongoDB (http://www.mongodb.org/) # Documentation about the URL connection string format can be found at: # # http://docs.mongodb.org/manual/reference/connection-string/ @@ -68,7 +75,7 @@ settings = # track-changes:lock historyLock: ({doc_id}) -> "HistoryLock:#{doc_id}" historyIndexLock: ({project_id}) -> "HistoryIndexLock:#{project_id}" - # track-chanegs:history + # track-changes:history uncompressedHistoryOps: ({doc_id}) -> "UncompressedHistoryOps:#{doc_id}" docsWithHistoryOps: ({project_id}) -> "DocsWithHistoryOps:#{project_id}" # realtime @@ -86,8 +93,8 @@ settings = project_history: redisConfig # The compile server (the clsi) uses a SQL database to cache files and - # meta-data. sqllite is the default, and the load is low enough that this will - # be fine in production (we use sqllite at sharelatex.com). + # meta-data. sqlite is the default, and the load is low enough that this will + # be fine in production (we use sqlite at sharelatex.com). # # If you want to configure a different database, see the Sequelize documentation # for available options: @@ -210,13 +217,13 @@ settings = collaborators: -1 dropbox: true versioning: true - compileTimeout: 180 + compileTimeout: parseIntOrFail(process.env["COMPILE_TIMEOUT"] or 180) compileGroup: "standard" trackChanges: true templates: true references: true -## OPTIONAL CONFIGERABLE SETTINGS +## OPTIONAL CONFIGURABLE SETTINGS if process.env["SHARELATEX_LEFT_FOOTER"]? try @@ -280,9 +287,12 @@ if process.env["SHARELATEX_EMAIL_FROM_ADDRESS"]? ignoreTLS: parse(process.env["SHARELATEX_EMAIL_SMTP_IGNORE_TLS"]) textEncoding: process.env["SHARELATEX_EMAIL_TEXT_ENCODING"] - templates: + template: customFooter: process.env["SHARELATEX_CUSTOM_EMAIL_FOOTER"] + if process.env["SHARELATEX_EMAIL_AWS_SES_REGION"]? + settings.email.parameters.region = process.env["SHARELATEX_EMAIL_AWS_SES_REGION"] + if process.env["SHARELATEX_EMAIL_SMTP_USER"]? or process.env["SHARELATEX_EMAIL_SMTP_PASS"]? settings.email.parameters.auth = user: process.env["SHARELATEX_EMAIL_SMTP_USER"] @@ -376,7 +386,7 @@ if process.env["SHARELATEX_LDAP_URL"] timeout: ( if _ldap_timeout = process.env["SHARELATEX_LDAP_TIMEOUT"] try - parseInt(_ldap_timeout) + parseIntOrFail(_ldap_timeout) catch e console.error "Cannot parse SHARELATEX_LDAP_TIMEOUT" else @@ -385,7 +395,7 @@ if process.env["SHARELATEX_LDAP_URL"] connectTimeout: ( if _ldap_connect_timeout = process.env["SHARELATEX_LDAP_CONNECT_TIMEOUT"] try - parseInt(_ldap_connect_timeout) + parseIntOrFail(_ldap_connect_timeout) catch e console.error "Cannot parse SHARELATEX_LDAP_CONNECT_TIMEOUT" else @@ -443,16 +453,16 @@ if process.env["SHARELATEX_SAML_ENTRYPOINT"] acceptedClockSkewMs: ( if _saml_skew = process.env["SHARELATEX_SAML_ACCEPTED_CLOCK_SKEW_MS"] try - parseInt(_saml_skew) + parseIntOrFail(_saml_skew) catch e console.error "Cannot parse SHARELATEX_SAML_ACCEPTED_CLOCK_SKEW_MS" else undefined ) requestIdExpirationPeriodMs: ( - if _saml_exiration = process.env["SHARELATEX_SAML_REQUEST_ID_EXPIRATION_PERIOD_MS"] + if _saml_expiration = process.env["SHARELATEX_SAML_REQUEST_ID_EXPIRATION_PERIOD_MS"] try - parseInt(_saml_expiration) + parseIntOrFail(_saml_expiration) catch e console.error "Cannot parse SHARELATEX_SAML_REQUEST_ID_EXPIRATION_PERIOD_MS" else diff --git a/tasks/CreateAndDestoryUsers.coffee b/tasks/CreateAndDestoryUsers.coffee deleted file mode 100644 index 14ed4ca3608f18aeee409efc732f6891e3b05072..0000000000000000000000000000000000000000 --- a/tasks/CreateAndDestoryUsers.coffee +++ /dev/null @@ -1,56 +0,0 @@ - -module.exports = (grunt) -> - - grunt.registerTask 'user:create-admin', "Create a user with the given email address and make them an admin. Update in place if the user already exists. Usage: grunt user:create-admin --email joe@example.com", () -> - done = @async() - email = grunt.option("email") - if !email? - console.error "Usage: grunt user:create-admin --email=joe@example.com" - process.exit(1) - - settings = require "settings-sharelatex" - UserRegistrationHandler = require "../web/app/src/Features/User/UserRegistrationHandler" - OneTimeTokenHandler = require "../web/app/src/Features/Security/OneTimeTokenHandler" - UserRegistrationHandler.registerNewUser { - email: email - password: require("crypto").randomBytes(32).toString("hex") - }, (error, user) -> - if error? and error?.message != "EmailAlreadyRegistered" - throw error - user.isAdmin = true - user.save (error) -> - throw error if error? - ONE_WEEK = 7 * 24 * 60 * 60 # seconds - OneTimeTokenHandler.getNewToken "password", { expiresIn: ONE_WEEK, email:user.email, user_id: user._id.toString() }, (err, token)-> - return next(err) if err? - - console.log "" - console.log """ - Successfully created #{email} as an admin user. - - Please visit the following URL to set a password for #{email} and log in: - - #{settings.siteUrl}/user/password/set?passwordResetToken=#{token} - - """ - done() - - grunt.registerTask 'user:delete', "deletes a user and all their data, Usage: grunt user:delete --email joe@example.com", () -> - done = @async() - email = grunt.option("email") - if !email? - console.error "Usage: grunt user:delete --email=joe@example.com" - process.exit(1) - settings = require "settings-sharelatex" - UserGetter = require "../web/app/src/Features/User/UserGetter" - UserDeleter = require "../web/app/src/Features/User/UserDeleter" - UserGetter.getUser email:email, (error, user) -> - if error? - throw error - if !user? - console.log("user #{email} not in database, potentially already deleted") - return done() - UserDeleter.deleteUser user._id, (err)-> - if err? - throw err - done() diff --git a/tasks/CreateAndDestroyUsers.coffee b/tasks/CreateAndDestroyUsers.coffee new file mode 100644 index 0000000000000000000000000000000000000000..79da259c67ddef5aac35c7e65152f409377a8398 --- /dev/null +++ b/tasks/CreateAndDestroyUsers.coffee @@ -0,0 +1,60 @@ + +module.exports = (grunt) -> + + grunt.registerTask 'user:create-admin', "Create a user with the given email address and make them an admin. Update in place if the user already exists. Usage: grunt user:create-admin --email joe@example.com", () -> + done = @async() + email = grunt.option("email") + if !email? + console.error "Usage: grunt user:create-admin --email=joe@example.com" + process.exit(1) + + settings = require "settings-sharelatex" + mongodb = require "../web/app/src/infrastructure/mongodb" + UserRegistrationHandler = require "../web/app/src/Features/User/UserRegistrationHandler" + OneTimeTokenHandler = require "../web/app/src/Features/Security/OneTimeTokenHandler" + mongodb.waitForDb().then () -> + UserRegistrationHandler.registerNewUser { + email: email + password: require("crypto").randomBytes(32).toString("hex") + }, (error, user) -> + if error? and error?.message != "EmailAlreadyRegistered" + throw error + user.isAdmin = true + user.save (error) -> + throw error if error? + ONE_WEEK = 7 * 24 * 60 * 60 # seconds + OneTimeTokenHandler.getNewToken "password", { expiresIn: ONE_WEEK, email:user.email, user_id: user._id.toString() }, (err, token)-> + return next(err) if err? + + console.log "" + console.log """ + Successfully created #{email} as an admin user. + + Please visit the following URL to set a password for #{email} and log in: + + #{settings.siteUrl}/user/password/set?passwordResetToken=#{token} + + """ + done() + + grunt.registerTask 'user:delete', "deletes a user and all their data, Usage: grunt user:delete --email joe@example.com", () -> + done = @async() + email = grunt.option("email") + if !email? + console.error "Usage: grunt user:delete --email=joe@example.com" + process.exit(1) + settings = require "settings-sharelatex" + mongodb = require "../web/app/src/infrastructure/mongodb" + UserGetter = require "../web/app/src/Features/User/UserGetter" + UserDeleter = require "../web/app/src/Features/User/UserDeleter" + mongodb.waitForDb().then () -> + UserGetter.getUser email:email, (error, user) -> + if error? + throw error + if !user? + console.log("user #{email} not in database, potentially already deleted") + return done() + UserDeleter.deleteUser user._id, (err)-> + if err? + throw err + done()