diff --git a/services/web/app/coffee/Features/Authentication/AuthenticationManager.coffee b/services/web/app/coffee/Features/Authentication/AuthenticationManager.coffee index b661455028..49bd994b2c 100644 --- a/services/web/app/coffee/Features/Authentication/AuthenticationManager.coffee +++ b/services/web/app/coffee/Features/Authentication/AuthenticationManager.coffee @@ -29,8 +29,12 @@ module.exports = AuthenticationManager = callback null, null setUserPassword: (user_id, password, callback = (error) ->) -> - if Settings.passwordStrengthOptions?.length?.max? and Settings.passwordStrengthOptions?.length?.max < password.length + if (Settings.passwordStrengthOptions?.length?.max? and + Settings.passwordStrengthOptions?.length?.max < password.length) return callback("password is too long") + if (Settings.passwordStrengthOptions?.length?.min? and + Settings.passwordStrengthOptions?.length?.min > password.length) + return callback("password is too short") bcrypt.genSalt BCRYPT_ROUNDS, (error, salt) -> return callback(error) if error? diff --git a/services/web/app/coffee/Features/Subscription/SubscriptionUpdater.coffee b/services/web/app/coffee/Features/Subscription/SubscriptionUpdater.coffee index 7b857c6460..12faf0e234 100644 --- a/services/web/app/coffee/Features/Subscription/SubscriptionUpdater.coffee +++ b/services/web/app/coffee/Features/Subscription/SubscriptionUpdater.coffee @@ -62,6 +62,15 @@ module.exports = SubscriptionUpdater = invited_emails: email }, callback + deleteSubscription: (subscription_id, callback = (error) ->) -> + SubscriptionLocator.getSubscription subscription_id, (err, subscription) -> + return callback(err) if err? + affected_user_ids = [subscription.admin_id].concat(subscription.member_ids or []) + logger.log {subscription_id, affected_user_ids}, "deleting subscription and downgrading users" + Subscription.remove {_id: ObjectId(subscription_id)}, (err) -> + return callback(err) if err? + async.mapSeries affected_user_ids, SubscriptionUpdater._setUsersMinimumFeatures, callback + _createNewSubscription: (adminUser_id, callback)-> logger.log adminUser_id:adminUser_id, "creating new subscription" subscription = new Subscription(admin_id:adminUser_id) diff --git a/services/web/app/coffee/Features/User/UserController.coffee b/services/web/app/coffee/Features/User/UserController.coffee index 65000985e1..9954294577 100644 --- a/services/web/app/coffee/Features/User/UserController.coffee +++ b/services/web/app/coffee/Features/User/UserController.coffee @@ -74,6 +74,8 @@ module.exports = UserController = user.ace.fontSize = req.body.fontSize if req.body.autoComplete? user.ace.autoComplete = req.body.autoComplete + if req.body.autoPairDelimiters? + user.ace.autoPairDelimiters = req.body.autoPairDelimiters if req.body.spellCheckLanguage? user.ace.spellCheckLanguage = req.body.spellCheckLanguage if req.body.pdfViewer? diff --git a/services/web/app/coffee/infrastructure/ExpressLocals.coffee b/services/web/app/coffee/infrastructure/ExpressLocals.coffee index 4c6b3a7722..498127cdbd 100644 --- a/services/web/app/coffee/infrastructure/ExpressLocals.coffee +++ b/services/web/app/coffee/infrastructure/ExpressLocals.coffee @@ -11,6 +11,7 @@ async = require("async") Modules = require "./Modules" Url = require "url" PackageVersions = require "./PackageVersions" +htmlEncoder = new require("node-html-encoder").Encoder("numerical") fingerprints = {} Path = require 'path' @@ -151,9 +152,10 @@ module.exports = (app, webRouter, privateApiRouter, publicApiRouter)-> next() webRouter.use (req, res, next)-> - res.locals.translate = (key, vars = {}) -> + res.locals.translate = (key, vars = {}, htmlEncode = false) -> vars.appName = Settings.appName - req.i18n.translate(key, vars) + str = req.i18n.translate(key, vars) + if htmlEncode then htmlEncoder.htmlEncode(str) else str # Don't include the query string parameters, otherwise Google # treats ?nocdn=true as the canonical version res.locals.currentUrl = Url.parse(req.originalUrl).pathname diff --git a/services/web/app/views/contact-us-modal.pug b/services/web/app/views/contact-us-modal.pug index d3e5aa0e87..aad68a53d3 100644 --- a/services/web/app/views/contact-us-modal.pug +++ b/services/web/app/views/contact-us-modal.pug @@ -7,36 +7,61 @@ script(type='text/ng-template', id='supportModalTemplate') ) × h3 #{translate("contact_us")} .modal-body.contact-us-modal - span(ng-show="sent == false") - label - | #{translate("subject")} - .form-group - input.field.text.medium.span8.form-control( - ng-model="form.subject", - ng-model-options="{ updateOn: 'default blur', debounce: {'default': 350, 'blur': 0} }" - maxlength='255', - tabindex='1', - onkeyup='') - .contact-suggestions(ng-show="suggestions.length") - p.contact-suggestion-label !{translate("kb_suggestions_enquiry", { kbLink: "__kb__", kb: translate("knowledge_base") })} - ul.contact-suggestion-list - li(ng-repeat="suggestion in suggestions") - a.contact-suggestion-list-item(ng-href="{{ suggestion.url }}", ng-click="clickSuggestionLink(suggestion.url);" target="_blank") - span(ng-bind-html="suggestion.name") - i.fa.fa-angle-right - label.desc(ng-show="'"+getUserEmail()+"'.length < 1") - | #{translate("email")} - .form-group(ng-show="'"+getUserEmail()+"'.length < 1") - input.field.text.medium.span8.form-control(ng-model="form.email", ng-init="form.email = '"+getUserEmail()+"'", type='email', spellcheck='false', value='', maxlength='255', tabindex='2') - label#title12.desc - | #{translate("project_url")} (#{translate("optional")}) - .form-group - input.field.text.medium.span8.form-control(ng-model="form.project_url", tabindex='3', onkeyup='') - label.desc - | #{translate("contact_message_label")} - .form-group - textarea.field.text.medium.span8.form-control(ng-model="form.message",type='text', value='', tabindex='4', onkeyup='') - .form-group.text-center - input.btn-success.btn.btn-lg(type='submit', ng-disabled="sending", ng-click="contactUs()" value=translate("contact_us")) + form(name="contactForm") + span(ng-show="sent == false") + .alert.alert-danger(ng-show="error") Something went wrong sending your request :( + label + | #{translate("subject")} + .form-group + input.field.text.medium.span8.form-control( + name="subject", + required + ng-model="form.subject", + ng-model-options="{ updateOn: 'default blur', debounce: {'default': 350, 'blur': 0} }" + maxlength='255', + tabindex='1', + onkeyup='') + .contact-suggestions(ng-show="suggestions.length") + p.contact-suggestion-label !{translate("kb_suggestions_enquiry", { kbLink: "__kb__", kb: translate("knowledge_base") })} + ul.contact-suggestion-list + li(ng-repeat="suggestion in suggestions") + a.contact-suggestion-list-item(ng-href="{{ suggestion.url }}", ng-click="clickSuggestionLink(suggestion.url);" target="_blank") + span(ng-bind-html="suggestion.name") + i.fa.fa-angle-right + label.desc(ng-show="'"+getUserEmail()+"'.length < 1") + | #{translate("email")} + .form-group(ng-show="'"+getUserEmail()+"'.length < 1") + input.field.text.medium.span8.form-control( + name="email", + required + ng-model="form.email", + ng-init="form.email = '"+getUserEmail()+"'", + type='email', spellcheck='false', + value='', + maxlength='255', + tabindex='2') + label#title12.desc + | #{translate("project_url")} (#{translate("optional")}) + .form-group + input.field.text.medium.span8.form-control(ng-model="form.project_url", tabindex='3', onkeyup='') + label.desc + | #{translate("contact_message_label")} + .form-group + textarea.field.text.medium.span8.form-control( + name="body", + required + ng-model="form.message", + type='text', + value='', + tabindex='4', + onkeyup='' + ) + .form-group.text-center + input.btn-success.btn.btn-lg( + type='submit', + ng-disabled="contactForm.$invalid || sending", + ng-click="contactUs()" + value=translate("contact_us") + ) span(ng-show="sent") p #{translate("request_sent_thank_you")} diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index 8b58c98bcd..6007f2e0be 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -82,7 +82,7 @@ div.full-size( i.fa.fa-long-arrow-right br a.btn.btn-default.btn-xs( - tooltip-html="'"+translate('go_to_pdf_location_in_code')+"'" + tooltip-html="'"+translate('go_to_pdf_location_in_code', {}, true)+"'" tooltip-placement="right" tooltip-append-to-body="true" ng-click="syncToCode()" diff --git a/services/web/config/settings.defaults.coffee b/services/web/config/settings.defaults.coffee index 8fb00aff31..046903de7b 100644 --- a/services/web/config/settings.defaults.coffee +++ b/services/web/config/settings.defaults.coffee @@ -226,8 +226,8 @@ module.exports = settings = # passwordStrengthOptions: # pattern: "aA$3" # length: - # min: 1 - # max: 10 + # min: 6 + # max: 128 # Email support # ------------- diff --git a/services/web/npm-shrinkwrap.json b/services/web/npm-shrinkwrap.json index f22ecf0219..6f6d9e475e 100644 --- a/services/web/npm-shrinkwrap.json +++ b/services/web/npm-shrinkwrap.json @@ -54,6 +54,12 @@ "from": "ansi-regex@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" }, + "ansi-styles": { + "version": "2.2.1", + "from": "ansi-styles@>=2.2.1 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "dev": true + }, "aproba": { "version": "1.1.1", "from": "aproba@>=1.0.3 <2.0.0", @@ -145,6 +151,12 @@ "from": "asynckit@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" }, + "autoprefixer": { + "version": "6.7.7", + "from": "autoprefixer@>=6.6.1 <7.0.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", + "dev": true + }, "aws-sdk": { "version": "2.41.0", "from": "aws-sdk@>=2.2.36 <3.0.0", @@ -287,25 +299,17 @@ "from": "brace-expansion@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz" }, + "browserslist": { + "version": "1.7.7", + "from": "browserslist@>=1.7.6 <2.0.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "dev": true + }, "bson": { "version": "1.0.4", "from": "bson@>=1.0.4 <1.1.0", "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.4.tgz" }, - "bson-ext": { - "version": "0.1.13", - "from": "bson-ext@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/bson-ext/-/bson-ext-0.1.13.tgz", - "optional": true, - "dependencies": { - "nan": { - "version": "2.0.9", - "from": "nan@>=2.0.9 <2.1.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.0.9.tgz", - "optional": true - } - } - }, "buffer": { "version": "4.9.1", "from": "buffer@4.9.1", @@ -372,6 +376,12 @@ "from": "camelcase@>=1.0.2 <2.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz" }, + "caniuse-db": { + "version": "1.0.30000708", + "from": "caniuse-db@>=1.0.30000634 <2.0.0", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000708.tgz", + "dev": true + }, "caseless": { "version": "0.12.0", "from": "caseless@>=0.12.0 <0.13.0", @@ -392,6 +402,20 @@ "from": "chai-spies@latest", "resolved": "https://registry.npmjs.org/chai-spies/-/chai-spies-0.7.1.tgz" }, + "chalk": { + "version": "1.1.3", + "from": "chalk@>=1.1.3 <2.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "dev": true, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "from": "supports-color@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "dev": true + } + } + }, "character-parser": { "version": "1.2.0", "from": "character-parser@1.2.0", @@ -545,6 +569,12 @@ "from": "cookie-signature@1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" }, + "cookies": { + "version": "0.7.0", + "from": "cookies@>=0.2.2", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.7.0.tgz", + "dev": true + }, "core-js": { "version": "1.2.7", "from": "core-js@>=1.2.0 <2.0.0", @@ -639,6 +669,13 @@ } } }, + "ctype": { + "version": "0.5.3", + "from": "ctype@0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "dev": true, + "optional": true + }, "dashdash": { "version": "1.14.1", "from": "dashdash@>=1.12.0 <2.0.0", @@ -730,6 +767,38 @@ "from": "doctypes@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz" }, + "dom-serializer": { + "version": "0.1.0", + "from": "dom-serializer@>=0.0.0 <1.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "dev": true, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "from": "domelementtype@>=1.1.1 <1.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.0", + "from": "domelementtype@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "dev": true + }, + "domhandler": { + "version": "2.4.1", + "from": "domhandler@>=2.3.0 <3.0.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", + "dev": true + }, + "domutils": { + "version": "1.6.2", + "from": "domutils@>=1.5.1 <2.0.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.6.2.tgz", + "dev": true + }, "dottie": { "version": "1.1.1", "from": "dottie@>=1.0.0 <2.0.0", @@ -761,6 +830,12 @@ "from": "ejs@>=0.8.3 <0.9.0", "resolved": "https://registry.npmjs.org/ejs/-/ejs-0.8.8.tgz" }, + "electron-to-chromium": { + "version": "1.3.16", + "from": "electron-to-chromium@>=1.2.7 <2.0.0", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.16.tgz", + "dev": true + }, "encoding": { "version": "0.1.12", "from": "encoding@>=0.1.0 <0.2.0", @@ -778,6 +853,18 @@ "from": "end-of-stream@>=0.1.3 <0.2.0", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz" }, + "entities": { + "version": "1.1.1", + "from": "entities@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "dev": true + }, + "es6-promise": { + "version": "4.1.1", + "from": "es6-promise@>=4.0.5 <5.0.0", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz", + "dev": true + }, "escape-html": { "version": "1.0.2", "from": "escape-html@1.0.2", @@ -887,6 +974,12 @@ "from": "failure@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/failure/-/failure-1.1.1.tgz" }, + "faye-websocket": { + "version": "0.10.0", + "from": "faye-websocket@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "dev": true + }, "file-utils": { "version": "0.1.5", "from": "file-utils@>=0.1.5 <0.2.0", @@ -960,6 +1053,12 @@ "from": "form-data@>=2.1.1 <2.2.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz" }, + "formatio": { + "version": "1.1.1", + "from": "formatio@1.1.1", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", + "dev": true + }, "forwarded": { "version": "0.1.0", "from": "forwarded@>=0.1.0 <0.2.0", @@ -1029,6 +1128,12 @@ "from": "gauge@>=2.7.1 <2.8.0", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.3.tgz" }, + "gaze": { + "version": "1.1.2", + "from": "gaze@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", + "dev": true + }, "generic-pool": { "version": "2.4.2", "from": "generic-pool@2.4.2", @@ -1063,6 +1168,26 @@ } } }, + "globule": { + "version": "1.2.0", + "from": "globule@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", + "dev": true, + "dependencies": { + "glob": { + "version": "7.1.2", + "from": "glob@>=7.1.1 <7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "from": "minimatch@>=3.0.2 <3.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "dev": true + } + } + }, "graceful-fs": { "version": "4.1.11", "from": "graceful-fs@>=4.1.2 <5.0.0", @@ -1130,6 +1255,26 @@ } } }, + "grunt-available-tasks": { + "version": "0.4.1", + "from": "grunt-available-tasks@0.4.1", + "resolved": "https://registry.npmjs.org/grunt-available-tasks/-/grunt-available-tasks-0.4.1.tgz", + "dev": true, + "dependencies": { + "lodash": { + "version": "2.4.2", + "from": "lodash@>=2.4.0 <2.5.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "from": "underscore.string@>=2.3.3 <2.4.0", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "dev": true + } + } + }, "grunt-bunyan": { "version": "0.5.0", "from": "grunt-bunyan@>=0.5.0 <0.6.0", @@ -1142,11 +1287,145 @@ } } }, + "grunt-contrib-clean": { + "version": "0.5.0", + "from": "grunt-contrib-clean@0.5.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-0.5.0.tgz", + "dev": true + }, + "grunt-contrib-coffee": { + "version": "0.10.0", + "from": "grunt-contrib-coffee@0.10.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-coffee/-/grunt-contrib-coffee-0.10.0.tgz", + "dev": true, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "from": "ansi-styles@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "dev": true + }, + "chalk": { + "version": "0.4.0", + "from": "chalk@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "dev": true + }, + "coffee-script": { + "version": "1.7.1", + "from": "coffee-script@>=1.7.0 <1.8.0", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.7.1.tgz", + "dev": true + }, + "lodash": { + "version": "2.4.2", + "from": "lodash@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "dev": true + }, + "mkdirp": { + "version": "0.3.5", + "from": "mkdirp@>=0.3.5 <0.4.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "dev": true + }, + "strip-ansi": { + "version": "0.1.1", + "from": "strip-ansi@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "dev": true + } + } + }, + "grunt-contrib-less": { + "version": "0.9.0", + "from": "grunt-contrib-less@0.9.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-less/-/grunt-contrib-less-0.9.0.tgz", + "dev": true, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "from": "ansi-styles@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "dev": true + }, + "chalk": { + "version": "0.4.0", + "from": "chalk@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "dev": true + }, + "strip-ansi": { + "version": "0.1.1", + "from": "strip-ansi@~0.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "dev": true + } + } + }, + "grunt-contrib-requirejs": { + "version": "0.4.1", + "from": "grunt-contrib-requirejs@0.4.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-requirejs/-/grunt-contrib-requirejs-0.4.1.tgz", + "dev": true + }, + "grunt-contrib-watch": { + "version": "1.0.0", + "from": "grunt-contrib-watch@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.0.0.tgz", + "dev": true, + "dependencies": { + "async": { + "version": "1.5.2", + "from": "async@>=1.5.0 <2.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "dev": true + }, + "lodash": { + "version": "3.10.1", + "from": "lodash@>=3.10.1 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "dev": true + } + } + }, + "grunt-env": { + "version": "0.4.4", + "from": "grunt-env@0.4.4", + "resolved": "https://registry.npmjs.org/grunt-env/-/grunt-env-0.4.4.tgz", + "dev": true, + "dependencies": { + "lodash": { + "version": "2.4.2", + "from": "lodash@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "dev": true + } + } + }, + "grunt-exec": { + "version": "0.4.7", + "from": "grunt-exec@>=0.4.7 <0.5.0", + "resolved": "https://registry.npmjs.org/grunt-exec/-/grunt-exec-0.4.7.tgz", + "dev": true + }, "grunt-execute": { "version": "0.2.2", "from": "grunt-execute@>=0.2.2 <0.3.0", "resolved": "https://registry.npmjs.org/grunt-execute/-/grunt-execute-0.2.2.tgz" }, + "grunt-file-append": { + "version": "0.0.6", + "from": "grunt-file-append@0.0.6", + "resolved": "https://registry.npmjs.org/grunt-file-append/-/grunt-file-append-0.0.6.tgz", + "dev": true + }, + "grunt-git-rev-parse": { + "version": "0.1.5", + "from": "grunt-git-rev-parse@>=0.1.4 <0.2.0", + "resolved": "https://registry.npmjs.org/grunt-git-rev-parse/-/grunt-git-rev-parse-0.1.5.tgz", + "dev": true + }, "grunt-legacy-log": { "version": "0.1.3", "from": "grunt-legacy-log@>=0.1.0 <0.2.0", @@ -1198,6 +1477,84 @@ } } }, + "grunt-lib-contrib": { + "version": "0.6.1", + "from": "grunt-lib-contrib@>=0.6.1 <0.7.0", + "resolved": "https://registry.npmjs.org/grunt-lib-contrib/-/grunt-lib-contrib-0.6.1.tgz", + "dev": true + }, + "grunt-mocha-test": { + "version": "0.9.0", + "from": "grunt-mocha-test@0.9.0", + "resolved": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.9.0.tgz", + "dev": true + }, + "grunt-newer": { + "version": "1.3.0", + "from": "grunt-newer@>=1.2.0 <2.0.0", + "resolved": "https://registry.npmjs.org/grunt-newer/-/grunt-newer-1.3.0.tgz", + "dev": true, + "dependencies": { + "async": { + "version": "1.5.2", + "from": "async@^1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "dev": true + }, + "glob": { + "version": "7.1.2", + "from": "glob@^7.0.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "from": "minimatch@^3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "dev": true + }, + "rimraf": { + "version": "2.6.1", + "from": "rimraf@>=2.5.2 <3.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "dev": true + } + } + }, + "grunt-parallel": { + "version": "0.5.1", + "from": "grunt-parallel@>=0.5.1 <0.6.0", + "resolved": "https://registry.npmjs.org/grunt-parallel/-/grunt-parallel-0.5.1.tgz", + "dev": true, + "dependencies": { + "q": { + "version": "0.8.12", + "from": "q@>=0.8.12 <0.9.0", + "resolved": "https://registry.npmjs.org/q/-/q-0.8.12.tgz", + "dev": true + } + } + }, + "grunt-postcss": { + "version": "0.8.0", + "from": "grunt-postcss@>=0.8.0 <0.9.0", + "resolved": "https://registry.npmjs.org/grunt-postcss/-/grunt-postcss-0.8.0.tgz", + "dev": true, + "dependencies": { + "diff": { + "version": "2.2.3", + "from": "diff@>=2.0.2 <3.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-2.2.3.tgz", + "dev": true + } + } + }, + "grunt-sed": { + "version": "0.1.1", + "from": "grunt-sed@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/grunt-sed/-/grunt-sed-0.1.1.tgz", + "dev": true + }, "hang": { "version": "1.0.0", "from": "hang@>=1.0.0 <1.1.0", @@ -1218,6 +1575,24 @@ "from": "has@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz" }, + "has-ansi": { + "version": "2.0.0", + "from": "has-ansi@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "dev": true + }, + "has-color": { + "version": "0.1.7", + "from": "has-color@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "dev": true + }, + "has-flag": { + "version": "1.0.0", + "from": "has-flag@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "dev": true + }, "has-unicode": { "version": "2.0.1", "from": "has-unicode@>=2.0.0 <3.0.0", @@ -1244,9 +1619,41 @@ "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz" }, "hooks-fixed": { - "version": "1.1.0", - "from": "hooks-fixed@1.1.0", - "resolved": "https://registry.npmjs.org/hooks-fixed/-/hooks-fixed-1.1.0.tgz" + "version": "2.0.0", + "from": "hooks-fixed@2.0.0", + "resolved": "https://registry.npmjs.org/hooks-fixed/-/hooks-fixed-2.0.0.tgz" + }, + "htmlparser2": { + "version": "3.9.2", + "from": "htmlparser2@>=3.9.0 <4.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "dev": true, + "dependencies": { + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "from": "readable-stream@>=2.0.2 <3.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "from": "safe-buffer@>=5.1.1 <5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "dev": true + }, + "string_decoder": { + "version": "1.0.3", + "from": "string_decoder@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "dev": true + } + } }, "http-errors": { "version": "1.6.1", @@ -1263,6 +1670,12 @@ "from": "http-signature@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz" }, + "i18next": { + "version": "1.7.10", + "from": "i18next@>=1.7.1 <1.8.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-1.7.10.tgz", + "dev": true + }, "iconv-lite": { "version": "0.2.11", "from": "iconv-lite@>=0.2.11 <0.3.0", @@ -1285,7 +1698,7 @@ }, "inherits": { "version": "2.0.3", - "from": "inherits@>=2.0.0 <3.0.0", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" }, "ini": { @@ -1398,6 +1811,12 @@ "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", "optional": true }, + "js-base64": { + "version": "2.1.9", + "from": "js-base64@>=2.1.9 <3.0.0", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.1.9.tgz", + "dev": true + }, "js-stringify": { "version": "1.0.2", "from": "js-stringify@>=1.0.1 <2.0.0", @@ -1429,6 +1848,12 @@ "from": "json-stringify-safe@>=5.0.1 <5.1.0", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" }, + "json5": { + "version": "0.2.0", + "from": "json5@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.2.0.tgz", + "dev": true + }, "jsonfile": { "version": "1.1.1", "from": "jsonfile@>=1.1.0 <1.2.0", @@ -1469,23 +1894,15 @@ } }, "kareem": { - "version": "1.0.1", - "from": "kareem@1.0.1", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-1.0.1.tgz" + "version": "1.5.0", + "from": "kareem@1.5.0", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-1.5.0.tgz" }, - "kerberos": { - "version": "0.0.23", - "from": "kerberos@>=0.0.0 <0.1.0", - "resolved": "https://registry.npmjs.org/kerberos/-/kerberos-0.0.23.tgz", - "optional": true, - "dependencies": { - "nan": { - "version": "2.5.1", - "from": "nan@>=2.5.1 <2.6.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.5.1.tgz", - "optional": true - } - } + "keygrip": { + "version": "1.0.1", + "from": "keygrip@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.1.tgz", + "dev": true }, "kind-of": { "version": "3.1.0", @@ -1628,6 +2045,42 @@ } } }, + "less": { + "version": "1.6.3", + "from": "less@>=1.6.0 <1.7.0", + "resolved": "https://registry.npmjs.org/less/-/less-1.6.3.tgz", + "dev": true, + "dependencies": { + "clean-css": { + "version": "2.0.8", + "from": "clean-css@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-2.0.8.tgz", + "dev": true, + "optional": true + }, + "commander": { + "version": "2.0.0", + "from": "commander@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.0.0.tgz", + "dev": true, + "optional": true + }, + "mime": { + "version": "1.2.11", + "from": "mime@>=1.2.0 <1.3.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "dev": true, + "optional": true + }, + "mkdirp": { + "version": "0.3.5", + "from": "mkdirp@~0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "dev": true, + "optional": true + } + } + }, "libbase64": { "version": "0.1.0", "from": "libbase64@0.1.0", @@ -1650,6 +2103,12 @@ "from": "libqp@1.1.0", "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz" }, + "livereload-js": { + "version": "2.2.2", + "from": "livereload-js@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.2.2.tgz", + "dev": true + }, "loads": { "version": "0.0.4", "from": "loads@>=0.0.0 <0.1.0", @@ -1862,11 +2321,23 @@ } } }, + "lolex": { + "version": "1.3.2", + "from": "lolex@1.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "dev": true + }, "longest": { "version": "1.0.1", "from": "longest@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz" }, + "lpad": { + "version": "0.1.0", + "from": "lpad@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/lpad/-/lpad-0.1.0.tgz", + "dev": true + }, "lru-cache": { "version": "2.7.3", "from": "lru-cache@>=2.0.0 <3.0.0", @@ -2090,46 +2561,54 @@ } }, "mongoose": { - "version": "4.1.0", - "from": "mongoose@4.1.0", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-4.1.0.tgz", + "version": "4.11.4", + "from": "mongoose@4.11.4", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-4.11.4.tgz", "dependencies": { "async": { - "version": "0.9.0", - "from": "async@0.9.0", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" + "version": "2.1.4", + "from": "async@2.1.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.1.4.tgz" }, - "bson": { - "version": "0.3.2", - "from": "bson@>=0.3.0 <0.4.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-0.3.2.tgz" + "es6-promise": { + "version": "3.2.1", + "from": "es6-promise@3.2.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz" + }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" }, "mongodb": { - "version": "2.0.34", - "from": "mongodb@2.0.34", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.0.34.tgz" + "version": "2.2.27", + "from": "mongodb@2.2.27", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.27.tgz" }, "mongodb-core": { - "version": "1.2.0", - "from": "mongodb-core@1.2.0", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.2.0.tgz", - "dependencies": { - "bson": { - "version": "0.4.23", - "from": "bson@>=0.4.0 <0.5.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.23.tgz" - } - } + "version": "2.1.11", + "from": "mongodb-core@2.1.11", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.11.tgz" }, "ms": { - "version": "0.1.0", - "from": "ms@0.1.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.1.0.tgz" + "version": "2.0.0", + "from": "ms@2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" }, "readable-stream": { - "version": "1.0.31", - "from": "readable-stream@1.0.31", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz" + "version": "2.2.7", + "from": "readable-stream@2.2.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz" + }, + "safe-buffer": { + "version": "5.1.1", + "from": "safe-buffer@>=5.1.0 <5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + }, + "string_decoder": { + "version": "1.0.3", + "from": "string_decoder@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz" } } }, @@ -2139,34 +2618,39 @@ "resolved": "https://registry.npmjs.org/monocle/-/monocle-1.1.51.tgz" }, "mpath": { - "version": "0.1.1", - "from": "mpath@0.1.1", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.1.1.tgz" + "version": "0.3.0", + "from": "mpath@0.3.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.3.0.tgz" }, "mpromise": { - "version": "0.5.4", - "from": "mpromise@0.5.4", - "resolved": "https://registry.npmjs.org/mpromise/-/mpromise-0.5.4.tgz" + "version": "0.5.5", + "from": "mpromise@0.5.5", + "resolved": "https://registry.npmjs.org/mpromise/-/mpromise-0.5.5.tgz" }, "mquery": { - "version": "1.6.1", - "from": "mquery@1.6.1", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-1.6.1.tgz", + "version": "2.3.1", + "from": "mquery@2.3.1", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-2.3.1.tgz", "dependencies": { "bluebird": { - "version": "2.9.26", - "from": "bluebird@2.9.26", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.9.26.tgz" + "version": "2.10.2", + "from": "bluebird@2.10.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.10.2.tgz" }, "debug": { - "version": "2.2.0", - "from": "debug@2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + "version": "2.6.8", + "from": "debug@2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" }, "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + "version": "2.0.0", + "from": "ms@2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + }, + "sliced": { + "version": "0.0.5", + "from": "sliced@0.0.5", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz" } } }, @@ -2208,9 +2692,9 @@ } }, "muri": { - "version": "1.0.0", - "from": "muri@1.0.0", - "resolved": "https://registry.npmjs.org/muri/-/muri-1.0.0.tgz" + "version": "1.2.2", + "from": "muri@1.2.2", + "resolved": "https://registry.npmjs.org/muri/-/muri-1.2.2.tgz" }, "mv": { "version": "0.0.5", @@ -2244,6 +2728,11 @@ "from": "node-forge@0.2.24", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.2.24.tgz" }, + "node-html-encoder": { + "version": "0.0.2", + "from": "node-html-encoder@0.0.2", + "resolved": "https://registry.npmjs.org/node-html-encoder/-/node-html-encoder-0.0.2.tgz" + }, "node-pre-gyp": { "version": "0.6.30", "from": "node-pre-gyp@0.6.30", @@ -2311,16 +2800,48 @@ "from": "nodemailer-wellknown@0.1.7", "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.7.tgz" }, + "nomnom": { + "version": "1.6.2", + "from": "nomnom@>=1.6.0 <1.7.0", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz", + "dev": true, + "dependencies": { + "colors": { + "version": "0.5.1", + "from": "colors@0.5.x", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", + "dev": true + }, + "underscore": { + "version": "1.4.4", + "from": "underscore@>=1.4.4 <1.5.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "dev": true + } + } + }, "nopt": { "version": "3.0.6", "from": "nopt@>=3.0.1 <3.1.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz" }, + "normalize-range": { + "version": "0.1.2", + "from": "normalize-range@>=0.1.2 <0.2.0", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "dev": true + }, "npmlog": { "version": "4.0.2", "from": "npmlog@>=4.0.0 <5.0.0", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.0.2.tgz" }, + "num2fraction": { + "version": "1.2.2", + "from": "num2fraction@>=1.2.2 <2.0.0", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "dev": true + }, "number-is-nan": { "version": "1.0.1", "from": "number-is-nan@>=1.0.0 <2.0.0", @@ -2356,6 +2877,154 @@ "from": "one-time@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz" }, + "onesky": { + "version": "0.1.6", + "from": "onesky@>=0.1.5 <0.2.0", + "resolved": "https://registry.npmjs.org/onesky/-/onesky-0.1.6.tgz", + "dev": true, + "dependencies": { + "asn1": { + "version": "0.1.11", + "from": "asn1@0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.1.5", + "from": "assert-plus@>=0.1.5 <0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "dev": true, + "optional": true + }, + "async": { + "version": "0.9.2", + "from": "async@>=0.9.0 <0.10.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.5.0", + "from": "aws-sign2@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "dev": true, + "optional": true + }, + "boom": { + "version": "0.4.2", + "from": "boom@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "dev": true + }, + "combined-stream": { + "version": "0.0.7", + "from": "combined-stream@>=0.0.4 <0.1.0", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "dev": true, + "optional": true + }, + "cryptiles": { + "version": "0.2.2", + "from": "cryptiles@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "0.0.5", + "from": "delayed-stream@0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "dev": true, + "optional": true + }, + "forever-agent": { + "version": "0.5.2", + "from": "forever-agent@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "dev": true + }, + "form-data": { + "version": "0.1.4", + "from": "form-data@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "dev": true, + "optional": true + }, + "hawk": { + "version": "1.1.1", + "from": "hawk@1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "dev": true, + "optional": true + }, + "hoek": { + "version": "0.9.1", + "from": "hoek@>=0.9.0 <0.10.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "dev": true + }, + "http-signature": { + "version": "0.10.1", + "from": "http-signature@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "dev": true, + "optional": true + }, + "mime": { + "version": "1.2.11", + "from": "mime@~1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "dev": true, + "optional": true + }, + "mime-types": { + "version": "1.0.2", + "from": "mime-types@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "dev": true + }, + "node-uuid": { + "version": "1.4.8", + "from": "node-uuid@>=1.4.0 <1.5.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "dev": true + }, + "oauth-sign": { + "version": "0.3.0", + "from": "oauth-sign@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz", + "dev": true, + "optional": true + }, + "qs": { + "version": "1.0.2", + "from": "qs@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.0.2.tgz", + "dev": true + }, + "request": { + "version": "2.40.0", + "from": "request@>=2.40.0 <2.41.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.40.0.tgz", + "dev": true + }, + "sntp": { + "version": "0.2.4", + "from": "sntp@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "dev": true, + "optional": true + }, + "tunnel-agent": { + "version": "0.4.3", + "from": "tunnel-agent@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "dev": true, + "optional": true + } + } + }, "optimist": { "version": "0.6.1", "from": "optimist@0.6.1", @@ -2479,6 +3148,26 @@ } } }, + "postcss": { + "version": "5.2.17", + "from": "postcss@>=5.2.16 <6.0.0", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz", + "dev": true, + "dependencies": { + "source-map": { + "version": "0.5.6", + "from": "source-map@>=0.5.6 <0.6.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "dev": true + } + } + }, + "postcss-value-parser": { + "version": "3.3.0", + "from": "postcss-value-parser@>=3.2.3 <4.0.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", + "dev": true + }, "precond": { "version": "0.2.3", "from": "precond@>=0.2.0 <0.3.0", @@ -2935,11 +3624,31 @@ "from": "regexp-clone@0.0.1", "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz" }, + "regexp-quote": { + "version": "0.0.0", + "from": "regexp-quote@0.0.0", + "resolved": "https://registry.npmjs.org/regexp-quote/-/regexp-quote-0.0.0.tgz", + "dev": true + }, "repeat-string": { "version": "1.6.1", "from": "repeat-string@>=1.5.2 <2.0.0", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" }, + "replace": { + "version": "0.2.10", + "from": "replace@>=0.2.4 <0.3.0", + "resolved": "https://registry.npmjs.org/replace/-/replace-0.2.10.tgz", + "dev": true, + "dependencies": { + "colors": { + "version": "0.5.1", + "from": "colors@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", + "dev": true + } + } + }, "request": { "version": "2.81.0", "from": "request@>=2.69.0 <3.0.0", @@ -2967,6 +3676,12 @@ "from": "require-like@0.1.2", "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz" }, + "requirejs": { + "version": "2.1.22", + "from": "requirejs@>=2.1.0 <2.2.0", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.1.22.tgz", + "dev": true + }, "requires-port": { "version": "1.0.0", "from": "requires-port@>=1.0.0 <2.0.0", @@ -3035,6 +3750,26 @@ "from": "samsam@1.1.2", "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz" }, + "sandboxed-module": { + "version": "0.2.0", + "from": "sandboxed-module@0.2.0", + "resolved": "https://registry.npmjs.org/sandboxed-module/-/sandboxed-module-0.2.0.tgz", + "dev": true, + "dependencies": { + "stack-trace": { + "version": "0.0.6", + "from": "stack-trace@0.0.6", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.6.tgz", + "dev": true + } + } + }, + "sanitize-html": { + "version": "1.14.1", + "from": "sanitize-html@>=1.14.1 <2.0.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.14.1.tgz", + "dev": true + }, "sanitizer": { "version": "0.1.1", "from": "sanitizer@0.1.1", @@ -3195,15 +3930,21 @@ "from": "signal-exit@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz" }, + "sinon": { + "version": "1.17.7", + "from": "sinon@>=1.17.0 <2.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "dev": true + }, "sixpack-client": { "version": "1.0.0", "from": "sixpack-client@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/sixpack-client/-/sixpack-client-1.0.0.tgz" }, "sliced": { - "version": "0.0.5", - "from": "sliced@0.0.5", - "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz" + "version": "1.0.1", + "from": "sliced@1.0.1", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz" }, "smtp-connection": { "version": "2.0.1", @@ -3287,6 +4028,12 @@ "from": "strip-json-comments@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" }, + "supports-color": { + "version": "3.2.3", + "from": "supports-color@>=3.2.3 <4.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "dev": true + }, "tar": { "version": "2.2.1", "from": "tar@>=2.2.0 <2.3.0", @@ -3369,6 +4116,78 @@ "from": "timekeeper@", "resolved": "https://registry.npmjs.org/timekeeper/-/timekeeper-1.0.0.tgz" }, + "tiny-lr": { + "version": "0.2.1", + "from": "tiny-lr@>=0.2.1 <0.3.0", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", + "dev": true, + "dependencies": { + "body-parser": { + "version": "1.14.2", + "from": "body-parser@>=1.14.0 <1.15.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", + "dev": true, + "dependencies": { + "qs": { + "version": "5.2.0", + "from": "qs@5.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", + "dev": true + } + } + }, + "bytes": { + "version": "2.2.0", + "from": "bytes@2.2.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", + "dev": true + }, + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "dev": true + }, + "http-errors": { + "version": "1.3.1", + "from": "http-errors@>=1.3.1 <1.4.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "dev": true + }, + "iconv-lite": { + "version": "0.4.13", + "from": "iconv-lite@0.4.13", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "dev": true + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "dev": true + }, + "qs": { + "version": "5.1.0", + "from": "qs@>=5.1.0 <5.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", + "dev": true + }, + "raw-body": { + "version": "2.1.7", + "from": "raw-body@>=2.1.5 <2.2.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "dev": true, + "dependencies": { + "bytes": { + "version": "2.4.0", + "from": "bytes@2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "dev": true + } + } + } + } + }, "to-mongodb-core": { "version": "2.0.0", "from": "to-mongodb-core@>=2.0.0 <3.0.0", @@ -3406,6 +4225,20 @@ } } }, + "translations-sharelatex": { + "version": "0.1.4", + "from": "git+https://github.com/sharelatex/translations-sharelatex.git#master", + "resolved": "git+https://github.com/sharelatex/translations-sharelatex.git#c2bcc5c8b39034d3dfa2f4509fcc8e1e0be6ed75", + "dev": true, + "dependencies": { + "async": { + "version": "2.5.0", + "from": "async@>=2.1.4 <3.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", + "dev": true + } + } + }, "tsscmp": { "version": "1.0.5", "from": "tsscmp@1.0.5", @@ -3634,6 +4467,18 @@ "from": "void-elements@>=2.0.1 <3.0.0", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz" }, + "websocket-driver": { + "version": "0.6.5", + "from": "websocket-driver@>=0.5.1", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", + "dev": true + }, + "websocket-extensions": { + "version": "0.1.1", + "from": "websocket-extensions@>=0.1.1", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz", + "dev": true + }, "which": { "version": "1.0.9", "from": "which@>=1.0.5 <1.1.0", @@ -3759,6 +4604,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" } } + }, + "zlib-browserify": { + "version": "0.0.1", + "from": "zlib-browserify@0.0.1", + "resolved": "https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz", + "dev": true } } } diff --git a/services/web/package.json b/services/web/package.json index 9c7c7b58de..14c7f00070 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -30,8 +30,8 @@ "ioredis": "^2.4.0", "jade": "~1.3.1", "ldapjs": "^0.7.1", - "logger-sharelatex": "git+https://github.com/sharelatex/logger-sharelatex.git#master", "lodash": "^4.13.1", + "logger-sharelatex": "git+https://github.com/sharelatex/logger-sharelatex.git#master", "lynx": "0.1.1", "marked": "^0.3.5", "method-override": "^2.3.3", @@ -39,8 +39,9 @@ "mimelib": "0.2.14", "mocha": "1.17.1", "mongojs": "2.4.0", - "mongoose": "4.1.0", + "mongoose": "4.11.4", "multer": "^0.1.8", + "node-html-encoder": "0.0.2", "nodemailer": "2.1.0", "nodemailer-sendgrid-transport": "^0.2.0", "nodemailer-ses-transport": "^1.3.0", @@ -48,23 +49,23 @@ "passport": "^0.3.2", "passport-ldapauth": "^0.6.0", "passport-local": "^1.0.0", + "passport-saml": "^0.15.0", + "pug": "^2.0.0-beta6", "redis": "0.10.1", "redis-sharelatex": "git+https://github.com/sharelatex/redis-sharelatex.git#v1.0.2", "request": "^2.69.0", "requests": "^0.1.7", "rimraf": "2.2.6", + "rolling-rate-limiter": "git+https://github.com/ShaneKilkelly/rolling-rate-limiter.git#master", "sanitizer": "0.1.1", "sequelize": "^3.2.0", "settings-sharelatex": "git+https://github.com/sharelatex/settings-sharelatex.git#v1.0.0", "sixpack-client": "^1.0.0", "temp": "^0.8.3", "underscore": "1.6.0", - "v8-profiler": "^5.2.3", - "xml2js": "0.2.0", - "passport-saml": "^0.15.0", - "pug": "^2.0.0-beta6", "uuid": "^3.0.1", - "rolling-rate-limiter": "git+https://github.com/ShaneKilkelly/rolling-rate-limiter.git#master" + "v8-profiler": "^5.2.3", + "xml2js": "0.2.0" }, "devDependencies": { "autoprefixer": "^6.6.1", diff --git a/services/web/public/coffee/directives/asyncForm.coffee b/services/web/public/coffee/directives/asyncForm.coffee index 2fc336c934..0e6ae19ec2 100644 --- a/services/web/public/coffee/directives/asyncForm.coffee +++ b/services/web/public/coffee/directives/asyncForm.coffee @@ -103,8 +103,8 @@ define [ defaultPasswordOpts = pattern: "" length: - min: 1 - max: 50 + min: 6 + max: 128 allowEmpty: false allowAnyChars: false isMasked: true @@ -127,8 +127,6 @@ define [ [asyncFormCtrl, ngModelCtrl] = ctrl ngModelCtrl.$parsers.unshift (modelValue) -> - - isValid = passField.validatePass() email = asyncFormCtrl.getEmail() || window.usersEmail if !isValid @@ -141,5 +139,8 @@ define [ if opts.length.max? and modelValue.length == opts.length.max isValid = false scope.complexPasswordErrorMessage = "Maximum password length #{opts.length.max} reached" + if opts.length.min? and modelValue.length < opts.length.min + isValid = false + scope.complexPasswordErrorMessage = "Password too short, minimum #{opts.length.min}" ngModelCtrl.$setValidity('complexPassword', isValid) return modelValue diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor.coffee index af633ea369..9b272841be 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor.coffee @@ -11,6 +11,8 @@ define [ "ide/editor/directives/aceEditor/track-changes/TrackChangesManager" "ide/editor/directives/aceEditor/labels/LabelsManager" "ide/labels/services/labels" + "ide/graphics/services/graphics" + "ide/preamble/services/preamble" ], (App, Ace, SearchBox, ModeList, UndoManager, AutoCompleteManager, SpellCheckManager, HighlightsManager, CursorPositionManager, TrackChangesManager, LabelsManager) -> EditSession = ace.require('ace/edit_session').EditSession ModeList = ace.require('ace/ext/modelist') @@ -33,9 +35,8 @@ define [ url = ace.config._moduleUrl(args...) + "?fingerprint=#{window.aceFingerprint}" return url - App.directive "aceEditor", ($timeout, $compile, $rootScope, event_tracking, localStorage, $cacheFactory, labels) -> + App.directive "aceEditor", ($timeout, $compile, $rootScope, event_tracking, localStorage, $cacheFactory, labels, graphics, preamble) -> monkeyPatchSearch($rootScope, $compile) - return { scope: { @@ -102,7 +103,7 @@ define [ cursorPositionManager = new CursorPositionManager(scope, editor, element, localStorage) trackChangesManager = new TrackChangesManager(scope, editor, element) labelsManager = new LabelsManager(scope, editor, element, labels) - autoCompleteManager = new AutoCompleteManager(scope, editor, element, labelsManager) + autoCompleteManager = new AutoCompleteManager(scope, editor, element, labelsManager, graphics, preamble) # Prevert Ctrl|Cmd-S from triggering save dialog diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee index c320266a5a..751e534a32 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee @@ -17,7 +17,7 @@ define [ commandFragment?.match(/\\(\w+)\{/)?[1] class AutoCompleteManager - constructor: (@$scope, @editor, @element, @labelsManager) -> + constructor: (@$scope, @editor, @element, @labelsManager, @graphics, @preamble) -> @suggestionManager = new SuggestionManager() @monkeyPatchAutocomplete() @@ -44,6 +44,37 @@ define [ SnippetCompleter = new SnippetManager() + Graphics = @graphics + Preamble = @preamble + GraphicsCompleter = + getCompletions: (editor, session, pos, prefix, callback) -> + upToCursorRange = new Range(pos.row, 0, pos.row, pos.column) + lineUpToCursor = editor.getSession().getTextRange(upToCursorRange) + commandFragment = getLastCommandFragment(lineUpToCursor) + if commandFragment + match = commandFragment.match(/^~?\\(includegraphics(?:\[.*])?){([^}]*, *)?(\w*)/) + if match + beyondCursorRange = new Range(pos.row, pos.column, pos.row, 99999) + lineBeyondCursor = editor.getSession().getTextRange(beyondCursorRange) + needsClosingBrace = !lineBeyondCursor.match(/^[^{]*}/) + commandName = match[1] + currentArg = match[3] + graphicsPaths = Preamble.getGraphicsPaths() + result = [] + for graphic in Graphics.getGraphicsFiles() + path = graphic.path + for graphicsPath in graphicsPaths + if path.indexOf(graphicsPath) == 0 + path = path.slice(graphicsPath.length) + break + result.push { + caption: "\\#{commandName}{#{path}#{if needsClosingBrace then '}' else ''}", + value: "\\#{commandName}{#{path}#{if needsClosingBrace then '}' else ''}", + meta: "graphic", + score: 50 + } + callback null, result + labelsManager = @labelsManager LabelsCompleter = getCompletions: (editor, session, pos, prefix, callback) -> @@ -112,7 +143,13 @@ define [ else callback null, result - @editor.completers = [@suggestionManager, SnippetCompleter, ReferencesCompleter, LabelsCompleter] + @editor.completers = [ + @suggestionManager, + SnippetCompleter, + ReferencesCompleter, + LabelsCompleter, + GraphicsCompleter + ] disable: () -> @editor.setOptions({ @@ -245,7 +282,22 @@ define [ editor.completer.autoSelect = true editor.completer.showPopup(editor) editor.completer.cancelContextMenu() - $(editor.completer.popup?.container).css({'font-size': @$scope.fontSize + 'px'}) + container = $(editor.completer.popup?.container) + container.css({'font-size': @$scope.fontSize + 'px'}) + # Dynamically set width of autocomplete popup + if filtered = editor?.completer?.completions?.filtered + longestCaption = _.max(filtered.map( (c) -> c.caption.length )) + longestMeta = _.max(filtered.map( (c) -> c.meta.length )) + charWidth = editor.renderer.characterWidth + # between 280 and 700 px + width = Math.max( + Math.min( + Math.round(longestCaption*charWidth + longestMeta*charWidth + 5*charWidth), + 700 + ), + 280 + ) + container.css({width: "#{width}px"}) if editor.completer?.completions?.filtered?.length == 0 editor.completer.detach() bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space" diff --git a/services/web/public/coffee/ide/graphics/services/graphics.coffee b/services/web/public/coffee/ide/graphics/services/graphics.coffee new file mode 100644 index 0000000000..355614b7f4 --- /dev/null +++ b/services/web/public/coffee/ide/graphics/services/graphics.coffee @@ -0,0 +1,17 @@ +define [ + "base" +], (App) -> + + App.factory 'graphics', (ide) -> + + Graphics = + getGraphicsFiles: () -> + graphicsFiles = [] + ide.fileTreeManager.forEachEntity (entity, folder, path) -> + if entity.type == 'file' && entity?.name?.match?(/.*\.(png|jpg|jpeg|pdf|eps)/) + cloned = _.clone(entity) + cloned.path = path + graphicsFiles.push cloned + return graphicsFiles + + return Graphics diff --git a/services/web/public/coffee/ide/preamble/services/preamble.coffee b/services/web/public/coffee/ide/preamble/services/preamble.coffee new file mode 100644 index 0000000000..f95cfd9bbe --- /dev/null +++ b/services/web/public/coffee/ide/preamble/services/preamble.coffee @@ -0,0 +1,22 @@ +define [ + "base" +], (App) -> + + App.factory 'preamble', (ide) -> + + Preamble = + getPreambleText: () -> + text = ide.editorManager.getCurrentDocValue().slice(0, 5000) + preamble = text.match(/([^]*)^\\begin\{document\}/m)?[1] || "" + return preamble + + getGraphicsPaths: () -> + preamble = Preamble.getPreambleText() + graphicsPathsArgs = preamble.match(/\\graphicspath\{(.*)\}/)?[1] || "" + paths = [] + re = /\{([^}]*)\}/g + while match = re.exec(graphicsPathsArgs) + paths.push(match[1]) + return paths + + return Preamble diff --git a/services/web/public/coffee/main/contact-us.coffee b/services/web/public/coffee/main/contact-us.coffee index 2f3a2c61e0..7bb86a6b93 100644 --- a/services/web/public/coffee/main/contact-us.coffee +++ b/services/web/public/coffee/main/contact-us.coffee @@ -30,7 +30,7 @@ define [ $scope.suggestions = suggestions $scope.contactUs = -> - if !$scope.form.email? + if !$scope.form.email? or $scope.form.email == "" console.log "email not set" return $scope.sending = true @@ -46,8 +46,16 @@ define [ about: "