From 98a0c540040e3ad98f392f6d2cf568fc4550bf8b Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Fri, 17 Jun 2016 12:11:39 +0100 Subject: [PATCH 01/34] use parameter for bcrypt rounds, rehash passwords on login if necessary --- .../AuthenticationManager.coffee | 16 +++++++-- services/web/config/settings.defaults.coffee | 1 + .../AuthenticationManagerTests.coffee | 33 ++++++++++++++++++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/services/web/app/coffee/Features/Authentication/AuthenticationManager.coffee b/services/web/app/coffee/Features/Authentication/AuthenticationManager.coffee index 201643e88e..bfcd55855d 100644 --- a/services/web/app/coffee/Features/Authentication/AuthenticationManager.coffee +++ b/services/web/app/coffee/Features/Authentication/AuthenticationManager.coffee @@ -1,8 +1,11 @@ +Settings = require "settings-sharelatex" User = require("../../models/User").User {db, ObjectId} = require("../../infrastructure/mongojs") crypto = require 'crypto' bcrypt = require 'bcrypt' +BCRYPT_ROUNDS = Settings?.security?.bcryptRounds or 12 + module.exports = AuthenticationManager = authenticate: (query, password, callback = (error, user) ->) -> # Using Mongoose for legacy reasons here. The returned User instance @@ -15,7 +18,9 @@ module.exports = AuthenticationManager = bcrypt.compare password, user.hashedPassword, (error, match) -> return callback(error) if error? if match - callback null, user + AuthenticationManager.checkRounds user, user.hashedPassword, password, (err) -> + return callback(err) if err? + callback null, user else callback null, null else @@ -24,7 +29,7 @@ module.exports = AuthenticationManager = callback null, null setUserPassword: (user_id, password, callback = (error) ->) -> - bcrypt.genSalt 7, (error, salt) -> + bcrypt.genSalt BCRYPT_ROUNDS, (error, salt) -> return callback(error) if error? bcrypt.hash password, salt, (error, hash) -> return callback(error) if error? @@ -35,3 +40,10 @@ module.exports = AuthenticationManager = $unset: password: true }, callback) + checkRounds: (user, hashedPassword, password, callback = (error) ->) -> + # check current number of rounds and rehash if necessary + currentRounds = bcrypt.getRounds hashedPassword + if currentRounds < BCRYPT_ROUNDS + AuthenticationManager.setUserPassword user._id, password, callback + else + callback() diff --git a/services/web/config/settings.defaults.coffee b/services/web/config/settings.defaults.coffee index beb933e4c9..1950141518 100644 --- a/services/web/config/settings.defaults.coffee +++ b/services/web/config/settings.defaults.coffee @@ -137,6 +137,7 @@ module.exports = # -------- security: sessionSecret: sessionSecret + bcryptRounds: 14 httpAuthUsers: httpAuthUsers diff --git a/services/web/test/UnitTests/coffee/Authentication/AuthenticationManagerTests.coffee b/services/web/test/UnitTests/coffee/Authentication/AuthenticationManagerTests.coffee index f4d5e72c26..2805527259 100644 --- a/services/web/test/UnitTests/coffee/Authentication/AuthenticationManagerTests.coffee +++ b/services/web/test/UnitTests/coffee/Authentication/AuthenticationManagerTests.coffee @@ -16,6 +16,7 @@ describe "AuthenticationManager", -> users: {} ObjectId: ObjectId "bcrypt": @bcrypt = {} + "settings-sharelatex": { security: { bcryptRounds: 12 } } @callback = sinon.stub() describe "authenticate", -> @@ -31,6 +32,7 @@ describe "AuthenticationManager", -> beforeEach (done) -> @user.hashedPassword = @hashedPassword = "asdfjadflasdf" @bcrypt.compare = sinon.stub().callsArgWith(2, null, true) + @bcrypt.getRounds = sinon.stub().returns 12 @AuthenticationManager.authenticate email: @email, @unencryptedPassword, (error, user) => @callback(error, user) done() @@ -54,6 +56,35 @@ describe "AuthenticationManager", -> it "should not return the user", -> @callback.calledWith(null, null).should.equal true + describe "when the hashed password matches but the number of rounds is too low", -> + beforeEach (done) -> + @user.hashedPassword = @hashedPassword = "asdfjadflasdf" + @bcrypt.compare = sinon.stub().callsArgWith(2, null, true) + @bcrypt.getRounds = sinon.stub().returns 7 + @AuthenticationManager.setUserPassword = sinon.stub().callsArgWith(2, null) + @AuthenticationManager.authenticate email: @email, @unencryptedPassword, (error, user) => + @callback(error, user) + done() + + it "should look up the correct user in the database", -> + @User.findOne.calledWith(email: @email).should.equal true + + it "should check that the passwords match", -> + @bcrypt.compare + .calledWith(@unencryptedPassword, @hashedPassword) + .should.equal true + + it "should check the number of rounds", -> + @bcrypt.getRounds.called.should.equal true + + it "should set the users password (with a higher number of rounds)", -> + @AuthenticationManager.setUserPassword + .calledWith("user-id", @unencryptedPassword) + .should.equal true + + it "should return the user", -> + @callback.calledWith(null, @user).should.equal true + describe "when the user does not exist in the database", -> beforeEach -> @User.findOne = sinon.stub().callsArgWith(1, null, null) @@ -87,7 +118,7 @@ describe "AuthenticationManager", -> it "should hash the password", -> @bcrypt.genSalt - .calledWith(7) + .calledWith(12) .should.equal true @bcrypt.hash .calledWith(@password, @salt) From 0906bef5f9ba01b5d6914e59d8749b4019f51889 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Fri, 17 Jun 2016 13:50:32 +0100 Subject: [PATCH 02/34] change default bcrypt rounds to 12, to match default in AuthenticationManager --- services/web/config/settings.defaults.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/config/settings.defaults.coffee b/services/web/config/settings.defaults.coffee index 1950141518..80e4c9588e 100644 --- a/services/web/config/settings.defaults.coffee +++ b/services/web/config/settings.defaults.coffee @@ -137,7 +137,7 @@ module.exports = # -------- security: sessionSecret: sessionSecret - bcryptRounds: 14 + bcryptRounds: 12 # number of rounds used to hash user passwords (raised to power 2) httpAuthUsers: httpAuthUsers From d6c966934d64bb4609dc7396cd28c6e7b4b17d80 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Tue, 21 Jun 2016 16:53:50 +0100 Subject: [PATCH 03/34] Set the key binding which is reported on Windows. --- .../public/coffee/ide/editor/directives/aceEditor.coffee | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor.coffee index 596f350812..800d6bd194 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor.coffee @@ -74,15 +74,17 @@ define [ editor.commands.removeCommand "foldall" # For European keyboards, the / is above 7 so needs Shift pressing. - # This comes through as Ctrl-Shift-/ which is mapped to toggleBlockComment. + # This comes through as Command-Shift-/ on OS X, which is mapped to + # toggleBlockComment. # This doesn't do anything for LaTeX, so remap this to togglecomment to # work for European keyboards as normal. + # On Windows, the key combo comes as Ctrl-Shift-7. editor.commands.removeCommand "toggleBlockComment" editor.commands.removeCommand "togglecomment" editor.commands.addCommand { name: "togglecomment", - bindKey: { win: "Ctrl-/|Ctrl-Shift-/", mac: "Command-/|Command-Shift-/" }, + bindKey: { win: "Ctrl-/|Ctrl-Shift-7", mac: "Command-/|Command-Shift-/" }, exec: (editor) -> editor.toggleCommentLines(), multiSelectAction: "forEachLine", scrollIntoView: "selectionPart" From 249381b6a84f6a10bd568274f66025c550e99ddd Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Fri, 24 Jun 2016 11:42:58 +0100 Subject: [PATCH 04/34] WIP: initial work on sending address to recurly for paypal subscriptions --- .../Subscription/RecurlyWrapper.coffee | 159 +++++++++++++++++- .../coffee/main/new-subscription.coffee | 7 + 2 files changed, 157 insertions(+), 9 deletions(-) diff --git a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee index 680905ca6c..edf4dc8841 100644 --- a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee +++ b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee @@ -4,11 +4,140 @@ request = require 'request' Settings = require "settings-sharelatex" xml2js = require "xml2js" logger = require("logger-sharelatex") +Async = require('async') module.exports = RecurlyWrapper = apiUrl : "https://api.recurly.com/v2" - createSubscription: (user, subscriptionDetails, recurly_token_id, callback)-> + _createPaypalSubscription: (user, subscriptionDetails, recurly_token_id, callback) -> + logger.log {user_id: user._id, recurly_token_id}, "starting process of creating paypal subscription" + Async.waterfall([ + (next) -> # create account + logger.log {user_id: user._id, recurly_token_id}, "creating user in recurly" + address = subscriptionDetails.address + if !address + return next(new Error('no address in subscriptionDetails at createAccount stage')) + requestBody = """ + + #{user._id} + #{user.email} + #{user.first_name} + #{user.last_name} +
+ #{address.address1} + #{address.address2} + #{address.city} + #{address.state} + #{address.zip} + #{address.country} +
+
+ """ + RecurlyWrapper.apiRequest({ + url : "accounts" + method : "POST" + body : requestBody + }, (error, response, responseBody) => + return next(error) if error? + RecurlyWrapper._parseAccountXml responseBody, (err, account) -> + if err + logger.error {err, user_id: user._id, recurly_token_id}, "error creating account" + return next(err) + result = {account} + return next(null, result) + ) + , (result, next) -> # create billing info + logger.log {user_id: user._id, recurly_token_id}, "creating billing info in recurly" + accountCode = result?.account?.account_code + if !accountCode + return next(new Error('no account code at createBillingInfo stage')) + requestBody = """ + + #{recurly_token_id} + + """ + RecurlyWrapper.apiRequest({ + url: "accounts/#{accountCode}/billing_info" + method: "POST" + body: requestBody + }, (error, response, responseBody) => + return next(error) if error? + RecurlyWrapper._parseBillingInfoXml responseBody, (err, billingInfo) -> + if err + logger.error {err, user_id: user._id, accountCode, recurly_token_id}, "error creating billing info" + return next(err) + result.billingInfo = billingInfo + return next(null, result) + ) + , (result, next) -> # set address + logger.log {user_id: user._id, recurly_token_id}, "setting billing address in recurly" + accountCode = result?.account?.account_code + if !accountCode + return next(new Error('no account code at setAddress stage')) + address = subscriptionDetails.address + if !address + return next(new Error('no address in subscriptionDetails at setAddress stage')) + requestBody = """ + + #{address.address1} + #{address.address2} + #{address.city} + #{address.state} + #{address.zip} + #{address.country} + + """ + RecurlyWrapper.apiRequest({ + url: "accounts/#{accountCode}/billing_info" + method: "PUT" + body: requestBody + }, (error, response, responseBody) => + return next(error) if error? + RecurlyWrapper._parseBillingInfoXml responseBody, (err, billingInfo) -> + if err + logger.error {err, user_id: user._id, recurly_token_id}, "error updating billing info" + return next(err) + result.billingInfo = billingInfo + return next(null, result) + ) + , (result, next) -> # create subscription + logger.log {user_id: user._id, recurly_token_id}, "creating subscription in recurly" + requestBody = """ + + #{subscriptionDetails.plan_code} + #{subscriptionDetails.currencyCode} + #{subscriptionDetails.coupon_code} + + #{user._id} + + + """ # TODO: check account details and billing + RecurlyWrapper.apiRequest({ + url : "subscriptions" + method : "POST" + body : requestBody + }, (error, response, responseBody) => + return next(error) if error? + RecurlyWrapper._parseSubscriptionXml responseBody, (err, subscription) -> + if err + logger.error {err, user_id: user._id, recurly_token_id}, "error creating subscription" + return next(err) + result.subscription = subscription + return next(null, result) + ) + ], (err, result) -> + if err + logger.error {err, user_id: user._id, recurly_token_id}, "error in paypal subscription creation process" + return callback(err) + if !result.subscription + err = new Error('no subscription object in result') + logger.error {err, user_id: user._id, recurly_token_id}, "error in paypal subscription creation process" + return callback(err) + logger.log {user_id: user._id, recurly_token_id}, "done creating paypal subscription for user" + callback(null, result.subscription) + ) + + _createCreditCardSubscription: (user, subscriptionDetails, recurly_token_id, callback) -> requestBody = """ #{subscriptionDetails.plan_code} @@ -32,7 +161,13 @@ module.exports = RecurlyWrapper = }, (error, response, responseBody) => return callback(error) if error? @_parseSubscriptionXml responseBody, callback - ) + ) + + createSubscription: (user, subscriptionDetails, recurly_token_id, callback)-> + isPaypal = subscriptionDetails.isPaypal + logger.log {user_id: user._id, isPaypal, recurly_token_id}, "setting up subscription in recurly" + fn = if isPaypal then RecurlyWrapper._createPaypalSubscription else RecurlyWrapper._createCreditCardSubscription + fn user, subscriptionDetails, recurly_token_id, callback apiRequest : (options, callback) -> options.url = @apiUrl + "/" + options.url @@ -60,7 +195,7 @@ module.exports = RecurlyWrapper = newAttributes[key] = value else newAttributes[newKey] = value - + return newAttributes crypto.randomBytes 32, (error, buffer) -> @@ -74,7 +209,7 @@ module.exports = RecurlyWrapper = signature = "#{signed}|#{unsignedQuery}" callback null, signature - + getSubscriptions: (accountId, callback)-> @apiRequest({ @@ -227,7 +362,7 @@ module.exports = RecurlyWrapper = }, (error, response, body) -> callback(error) ) - + redeemCoupon: (account_code, coupon_code, callback)-> requestBody = """ @@ -278,6 +413,15 @@ module.exports = RecurlyWrapper = return callback "I don't understand the response from Recurly" callback null, account + _parseBillingInfoXml: (xml, callback) -> + @_parseXml xml, (error, data) -> + return callback(error) if error? + if data? and data.account? + billingInfo = data.billing_info + else + return callback "I don't understand the response from Recurly" + callback null, billingInfo + _parseXml: (xml, callback) -> convertDataTypes = (data) -> if data? and data["$"]? @@ -299,7 +443,7 @@ module.exports = RecurlyWrapper = else array.push(convertDataTypes(value)) data = array - + if data instanceof Array data = (convertDataTypes(entry) for entry in data) else if typeof data == "object" @@ -315,6 +459,3 @@ module.exports = RecurlyWrapper = return callback(error) if error? result = convertDataTypes(data) callback null, result - - - diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index 404b512e7b..9547508337 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -115,6 +115,13 @@ define [ currencyCode:pricing.items.currency plan_code:pricing.items.plan.code coupon_code:pricing.items?.coupon?.code || "" + isPaypal: $scope.paymentMethod == 'paypal' + address: + address1: $scope.data.address1 + address2: $scope.data.address2 + country: $scope.data.country + state: $scope.data.state + zip: $scope.data.zip $http.post("/user/subscription/create", postData) .success (data, status, headers)-> sixpack.convert "in-editor-free-trial-plan", pricing.items.plan.code, (err)-> From 56bc840b88014a8868711e52e6378914bc478430 Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Fri, 24 Jun 2016 14:11:28 +0100 Subject: [PATCH 05/34] WIP: fix up error handling and account for possibility of account already existing. --- .../Subscription/RecurlyWrapper.coffee | 49 ++++++++++++++++--- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee index edf4dc8841..75d1f1667a 100644 --- a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee +++ b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee @@ -12,7 +12,32 @@ module.exports = RecurlyWrapper = _createPaypalSubscription: (user, subscriptionDetails, recurly_token_id, callback) -> logger.log {user_id: user._id, recurly_token_id}, "starting process of creating paypal subscription" Async.waterfall([ - (next) -> # create account + (next) -> # check if account exists + logger.log {user_id: user._id, recurly_token_id}, "checking if recurly account exists for user" + RecurlyWrapper.apiRequest({ + url: "accounts/#{user._id}" + method: "GET" + }, (error, response, responseBody) -> + if error + logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while checking account" + return next(error) + result = {userExists: true} + if response.statusCode == 404 + result.userExists = false + return next(null, result) + logger.log {user_id: user._id, recurly_token_id}, "user appears to exist in recurly" + RecurlyWrapper._parseAccountXml responseBody, (err, account) -> + if err + logger.error {err, user_id: user._id, recurly_token_id}, "error parsing account" + return next(err) + result.account = account + return next(null, result) + ) + + , (result, next) -> # create account + if !result.userExists + logger.log {user_id: user._id, recurly_token_id}, "user already exists in recurly" + return next(null, result) logger.log {user_id: user._id, recurly_token_id}, "creating user in recurly" address = subscriptionDetails.address if !address @@ -38,14 +63,17 @@ module.exports = RecurlyWrapper = method : "POST" body : requestBody }, (error, response, responseBody) => - return next(error) if error? + if error + logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while creating account" + return next(error) RecurlyWrapper._parseAccountXml responseBody, (err, account) -> if err logger.error {err, user_id: user._id, recurly_token_id}, "error creating account" return next(err) - result = {account} + result.account = account return next(null, result) ) + , (result, next) -> # create billing info logger.log {user_id: user._id, recurly_token_id}, "creating billing info in recurly" accountCode = result?.account?.account_code @@ -61,7 +89,9 @@ module.exports = RecurlyWrapper = method: "POST" body: requestBody }, (error, response, responseBody) => - return next(error) if error? + if error + logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while creating billing info" + return next(error) RecurlyWrapper._parseBillingInfoXml responseBody, (err, billingInfo) -> if err logger.error {err, user_id: user._id, accountCode, recurly_token_id}, "error creating billing info" @@ -69,6 +99,7 @@ module.exports = RecurlyWrapper = result.billingInfo = billingInfo return next(null, result) ) + , (result, next) -> # set address logger.log {user_id: user._id, recurly_token_id}, "setting billing address in recurly" accountCode = result?.account?.account_code @@ -92,7 +123,9 @@ module.exports = RecurlyWrapper = method: "PUT" body: requestBody }, (error, response, responseBody) => - return next(error) if error? + if error + logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while setting address" + return next(error) RecurlyWrapper._parseBillingInfoXml responseBody, (err, billingInfo) -> if err logger.error {err, user_id: user._id, recurly_token_id}, "error updating billing info" @@ -100,6 +133,7 @@ module.exports = RecurlyWrapper = result.billingInfo = billingInfo return next(null, result) ) + , (result, next) -> # create subscription logger.log {user_id: user._id, recurly_token_id}, "creating subscription in recurly" requestBody = """ @@ -117,7 +151,9 @@ module.exports = RecurlyWrapper = method : "POST" body : requestBody }, (error, response, responseBody) => - return next(error) if error? + if error + logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while creating subscription" + return next(error) RecurlyWrapper._parseSubscriptionXml responseBody, (err, subscription) -> if err logger.error {err, user_id: user._id, recurly_token_id}, "error creating subscription" @@ -125,6 +161,7 @@ module.exports = RecurlyWrapper = result.subscription = subscription return next(null, result) ) + ], (err, result) -> if err logger.error {err, user_id: user._id, recurly_token_id}, "error in paypal subscription creation process" From 026e9f46c8d75bb8571ac8fb6c1aff07c6c74d90 Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Fri, 24 Jun 2016 15:03:46 +0100 Subject: [PATCH 06/34] WIP: process appears to work, setting address correctly --- .../Features/Subscription/RecurlyWrapper.coffee | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee index 75d1f1667a..5f0c7877f4 100644 --- a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee +++ b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee @@ -35,7 +35,7 @@ module.exports = RecurlyWrapper = ) , (result, next) -> # create account - if !result.userExists + if result.userExists logger.log {user_id: user._id, recurly_token_id}, "user already exists in recurly" return next(null, result) logger.log {user_id: user._id, recurly_token_id}, "creating user in recurly" @@ -51,9 +51,9 @@ module.exports = RecurlyWrapper =
#{address.address1} #{address.address2} - #{address.city} - #{address.state} - #{address.zip} + #{address.city || ''} + #{address.state || ''} + #{address.zip || ''} #{address.country}
@@ -112,9 +112,9 @@ module.exports = RecurlyWrapper = #{address.address1} #{address.address2} - #{address.city} - #{address.state} - #{address.zip} + #{address.city || ''} + #{address.state || ''} + #{address.zip || ''} #{address.country} """ @@ -455,6 +455,8 @@ module.exports = RecurlyWrapper = return callback(error) if error? if data? and data.account? billingInfo = data.billing_info + else if data? and data.billing_info? + billingInfo = data.billing_info else return callback "I don't understand the response from Recurly" callback null, billingInfo From 883ae307a98428897884dd70d22261218243b64d Mon Sep 17 00:00:00 2001 From: MCribbin Date: Fri, 24 Jun 2016 15:37:39 +0100 Subject: [PATCH 07/34] Update HumanReadableLogsRules.coffee Changed extraInfoURL links from /Errors:... to /Errors/... Added math mode description to "Missing $ inserted." (humanReadableHint might be too long with this extra description) --- .../HumanReadableLogsRules.coffee | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/services/web/public/coffee/ide/human-readable-logs/HumanReadableLogsRules.coffee b/services/web/public/coffee/ide/human-readable-logs/HumanReadableLogsRules.coffee index b4cb138be8..62d36f4f0d 100644 --- a/services/web/public/coffee/ide/human-readable-logs/HumanReadableLogsRules.coffee +++ b/services/web/public/coffee/ide/human-readable-logs/HumanReadableLogsRules.coffee @@ -1,90 +1,90 @@ define -> [ regexToMatch: /Misplaced alignment tab character \&/ - extraInfoURL: "https://www.sharelatex.com/learn/Errors:Misplaced_alignment_tab_character_%26" + extraInfoURL: "https://www.sharelatex.com/learn/Errors/Misplaced_alignment_tab_character_%26" humanReadableHint: """ You have placed an alignment tab character '&' in the wrong place. If you want to align something, you must write it inside an align environment such as \\begin{align} \u2026 \\end{align}, \\begin{tabular} \u2026 \\end{tabular}, etc. If you want to write an ampersand '&' in text, you must write \\& instead. """ , regexToMatch: /Extra alignment tab has been changed to \\cr/ - extraInfoURL: "https://www.sharelatex.com/learn/Errors:Extra_alignment_tab_has_been_changed_to_%5Ccr" + extraInfoURL: "https://www.sharelatex.com/learn/Errors/Extra_alignment_tab_has_been_changed_to_%5Ccr" humanReadableHint: """ You have written too many alignment tabs in a table, causing one of them to be turned into a line break. Make sure you have specified the correct number of columns in your table. """ , regexToMatch: /Display math should end with \$\$/ - extraInfoURL: "https://www.sharelatex.com/learn/Errors:Display_math_should_end_with_$$." + extraInfoURL: "https://www.sharelatex.com/learn/Errors/Display_math_should_end_with_$$." humanReadableHint: """ You have forgotten a $ sign at the end of 'display math' mode. When writing in display math mode, you must always math write inside $$ \u2026 $$. Check that the number of $s match around each math expression. """ , regexToMatch: /Missing [{$] inserted./ - extraInfoURL: "https://www.sharelatex.com/learn/Errors:Missing_$_inserted" + extraInfoURL: "https://www.sharelatex.com/learn/Errors/Missing_$_inserted" humanReadableHint: """ - Check that your $'s match around math expressions. If they do, then you've probably used a symbol in normal text that needs to be in math mode. Symbols such as subscripts ( _ ), integrals ( \\int ), Greek letters ( \\alpha, \\beta, \\delta ), and modifiers (\\vec{x}, \\tilde{x} ) must be written in math mode. See the full list here. + Check that your $'s match around math expressions. If they do, then you've probably used a symbol in normal text that needs to be in math mode. Symbols such as subscripts ( _ ), integrals ( \\int ), Greek letters ( \\alpha, \\beta, \\delta ), and modifiers (\\vec{x}, \\tilde{x} ) must be written in math mode. See the full list here.If you intended to use mathematics mode, then use $ … $ for 'inline math mode', $$...$$ for 'display math mode' or alternatively \begin{math} … \end{math}. """ , regexToMatch: /(undefined )?[rR]eference(s)?.+(undefined)?/ - extraInfoURL: "https://www.sharelatex.com/learn/Errors:There_were_undefined_references." + extraInfoURL: "https://www.sharelatex.com/learn/Errors/There_were_undefined_references." humanReadableHint: """ You have referenced something which has not yet been labelled. If you have labelled it already, make sure that what is written inside \\ref{...} is the same as what is written inside \\label{...}. """ , regexToMatch: /Citation .+ on page .+ undefined on input line .+/ - extraInfoURL: "https://www.sharelatex.com/learn/Errors:Citation_XXX_on_page_XXX_undefined_on_input_line_XXX." + extraInfoURL: "https://www.sharelatex.com/learn/Errors/Citation_XXX_on_page_XXX_undefined_on_input_line_XXX." humanReadableHint: """ You have cited something which is not included in your bibliography. Make sure that the citation (\\cite{...}) has a corresponding key in your bibliography, and that both are spelled the same way. """ , regexToMatch: /(Label .+)? multiply[ -]defined( labels)?/ - extraInfoURL: "https://www.sharelatex.com/learn/Errors:There_were_multiply-defined_labels." + extraInfoURL: "https://www.sharelatex.com/learn/Errors/There_were_multiply-defined_labels." humanReadableHint: """ You have used the same label more than once. Check that each \\label{...} labels only one item. """ , regexToMatch: /`!?h' float specifier changed to `!?ht'/ - extraInfoURL: "https://www.sharelatex.com/learn/Errors:%60!h%27_float_specifier_changed_to_%60!ht%27." + extraInfoURL: "https://www.sharelatex.com/learn/Errors/%60!h%27_float_specifier_changed_to_%60!ht%27." humanReadableHint: """ The float specifier 'h' is too strict of a demand for LaTeX to place your float in a nice way here. Try relaxing it by using 'ht', or even 'htbp' if necessary. If you want to try keep the float here anyway, check out the float package. """ , regexToMatch: /No positions in optional float specifier/ - extraInfoURL: "https://www.sharelatex.com/learn/Errors:No_positions_in_optional_float_specifier." + extraInfoURL: "https://www.sharelatex.com/learn/Errors/No_positions_in_optional_float_specifier." humanReadableHint: """ You have forgotten to include a float specifier, which tells LaTeX where to position your figure. Find out more about float specifiers here. """ , regexToMatch: /Undefined control sequence/ - extraInfoURL: "https://www.sharelatex.com/learn/Errors:Undefined_control_sequence." + extraInfoURL: "https://www.sharelatex.com/learn/Errors/Undefined_control_sequence." humanReadableHint: """ The compiler is having trouble understanding a command you have used. Check that the command is spelled correctly. If the command is part of a package, make sure you have included the package in your preamble using \\usepackage{...}. """ , regexToMatch: /File .+ not found/ - extraInfoURL: "https://www.sharelatex.com/learn/Errors:File_XXX_not_found_on_input_line_XXX." + extraInfoURL: "https://www.sharelatex.com/learn/Errors/File_XXX_not_found_on_input_line_XXX." humanReadableHint: """ - The compiler cannot find the file you want to include. Make sure that you have uploaded the file and specified the file location correctly. + The compiler cannot find the file you want to include. Make sure that you have uploaded the file and specified the file location correctly. """ , regexToMatch: /LaTeX Error: Unknown graphics extension: \..+/ - extraInfoURL: "https://www.sharelatex.com/learn/Errors:LaTeX_Error:_Unknown_graphics_extension:_.gif." + extraInfoURL: "https://www.sharelatex.com/learn/Errors/LaTeX_Error:_Unknown_graphics_extension:_.gif." humanReadableHint: """ - The compiler does not recognise the file type of one of your images. Make sure you are using a supported image format for your choice of compiler, and check that there are no periods (.) in the name of your image. + The compiler does not recognise the file type of one of your images. Make sure you are using a supported image format for your choice of compiler, and check that there are no periods (.) in the name of your image. """ , regexToMatch: /LaTeX Error: Unknown float option `H'/ - extraInfoURL: "https://www.sharelatex.com/learn/Errors:LaTeX_Error:_Unknown_float_option_%60H%27." + extraInfoURL: "https://www.sharelatex.com/learn/Errors/LaTeX_Error:_Unknown_float_option_%60H%27." humanReadableHint: """ The compiler isn't recognizing the float option 'H'. Include \\usepackage{float} in your preamble to fix this. """ , regexToMatch: /LaTeX Error: Unknown float option `.+'/ - extraInfoURL: "https://www.sharelatex.com/learn/Errors:LaTeX_Error:_Unknown_float_option_%60H%27." + extraInfoURL: "https://www.sharelatex.com/learn/Errors/LaTeX_Error:_Unknown_float_option_%60H%27." humanReadableHint: """ You have used a float specifier which the compiler does not understand. You can learn more about the different float options available for placing figures here. """ , regexToMatch: /LaTeX Error: \\math.+ allowed only in math mode/ - extraInfoURL: "https://www.sharelatex.com/learn/Errors:LaTeX_Error:_%5Cmathrm_allowed_only_in_math_mode." + extraInfoURL: "https://www.sharelatex.com/learn/Errors/LaTeX_Error:_%5Cmathrm_allowed_only_in_math_mode." humanReadableHint: """ You have used a font command which is only available in math mode. To use this command, you must be in maths mode (E.g. $ \u2026 $ or \\begin{math} \u2026 \\end{math}). If you want to use it outside of math mode, use the text version instead: \\textrm, \\textit, etc. """ From 9a399ebd15967e03f77e6a5f57b37801f182195e Mon Sep 17 00:00:00 2001 From: MCribbin Date: Fri, 24 Jun 2016 15:50:23 +0100 Subject: [PATCH 08/34] Update HumanReadableLogsRules.coffee Space added after URL. '...' changed to '\u2026' --- .../ide/human-readable-logs/HumanReadableLogsRules.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/web/public/coffee/ide/human-readable-logs/HumanReadableLogsRules.coffee b/services/web/public/coffee/ide/human-readable-logs/HumanReadableLogsRules.coffee index 62d36f4f0d..e7735e89dc 100644 --- a/services/web/public/coffee/ide/human-readable-logs/HumanReadableLogsRules.coffee +++ b/services/web/public/coffee/ide/human-readable-logs/HumanReadableLogsRules.coffee @@ -20,7 +20,7 @@ define -> [ regexToMatch: /Missing [{$] inserted./ extraInfoURL: "https://www.sharelatex.com/learn/Errors/Missing_$_inserted" humanReadableHint: """ - Check that your $'s match around math expressions. If they do, then you've probably used a symbol in normal text that needs to be in math mode. Symbols such as subscripts ( _ ), integrals ( \\int ), Greek letters ( \\alpha, \\beta, \\delta ), and modifiers (\\vec{x}, \\tilde{x} ) must be written in math mode. See the full list here.If you intended to use mathematics mode, then use $ … $ for 'inline math mode', $$...$$ for 'display math mode' or alternatively \begin{math} … \end{math}. + Check that your $'s match around math expressions. If they do, then you've probably used a symbol in normal text that needs to be in math mode. Symbols such as subscripts ( _ ), integrals ( \\int ), Greek letters ( \\alpha, \\beta, \\delta ), and modifiers (\\vec{x}, \\tilde{x} ) must be written in math mode. See the full list here.If you intended to use mathematics mode, then use $ \u2026 $ for 'inline math mode', $$ \u2026 $$ for 'display math mode' or alternatively \begin{math} \u2026 \end{math}. """ , regexToMatch: /(undefined )?[rR]eference(s)?.+(undefined)?/ From dfc375adf88dfeef753fa433933ca73dcc79995f Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Fri, 24 Jun 2016 15:55:19 +0100 Subject: [PATCH 09/34] Add more feedback on :hover. --- .../web/app/views/project/editor/pdf.jade | 1 + .../public/stylesheets/app/editor/pdf.less | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/services/web/app/views/project/editor/pdf.jade b/services/web/app/views/project/editor/pdf.jade index 75ff03020d..1957cce98b 100644 --- a/services/web/app/views/project/editor/pdf.jade +++ b/services/web/app/views/project/editor/pdf.jade @@ -103,6 +103,7 @@ div.full-size.pdf(ng-controller="PdfController") ng-init="feedbackSent = false;" ) span.line-no + i.fa.fa-link(aria-hidden="true")  span(ng-show="entry.file") {{ entry.file }} span(ng-show="entry.line") , line {{ entry.line }} p.entry-message(ng-show="entry.message") {{ entry.message }} diff --git a/services/web/public/stylesheets/app/editor/pdf.less b/services/web/public/stylesheets/app/editor/pdf.less index db29870c1a..2d147c2f69 100644 --- a/services/web/public/stylesheets/app/editor/pdf.less +++ b/services/web/public/stylesheets/app/editor/pdf.less @@ -120,6 +120,10 @@ float: right; color: @gray; font-weight: 700; + + .fa { + display: none; + } } .entry-message { font-weight: 700; @@ -130,6 +134,26 @@ font-size: 0.8rem; //font-family: @font-family-monospace; } + + &:hover .line-no { + color: inherit; + .fa { + display: inline-block; + } + } + + &.alert-danger:hover { + background-color: darken(@alert-danger-bg, 5%); + } + + &.alert-warning:hover { + background-color: darken(@alert-warning-bg, 5%); + } + + &.alert-info:hover { + background-color: darken(@alert-info-bg, 5%); + } + } pre { font-size: 12px; From f427ce88d90b2181e9b739fecf3107df8b5571e9 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Fri, 24 Jun 2016 16:37:35 +0100 Subject: [PATCH 10/34] Better Jade syntax. --- services/web/app/views/project/editor/pdf.jade | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/web/app/views/project/editor/pdf.jade b/services/web/app/views/project/editor/pdf.jade index 1957cce98b..54f7c6c0af 100644 --- a/services/web/app/views/project/editor/pdf.jade +++ b/services/web/app/views/project/editor/pdf.jade @@ -103,7 +103,8 @@ div.full-size.pdf(ng-controller="PdfController") ng-init="feedbackSent = false;" ) span.line-no - i.fa.fa-link(aria-hidden="true")  + i.fa.fa-link(aria-hidden="true") + |   span(ng-show="entry.file") {{ entry.file }} span(ng-show="entry.line") , line {{ entry.line }} p.entry-message(ng-show="entry.message") {{ entry.message }} From 72c73809f61508efe1ff5cb3819bd30bb94ab20c Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Mon, 27 Jun 2016 09:44:40 +0100 Subject: [PATCH 11/34] Generate address xml from object. --- .../Subscription/RecurlyWrapper.coffee | 20 +++++++------- .../coffee/main/new-subscription.coffee | 11 ++++---- .../Subscription/RecurlyWrapperTests.coffee | 26 +++++++++++++++++++ 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee index 5f0c7877f4..e49cb12b39 100644 --- a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee +++ b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee @@ -9,6 +9,15 @@ Async = require('async') module.exports = RecurlyWrapper = apiUrl : "https://api.recurly.com/v2" + _addressToXml: (address) -> + allowedKeys = ['address1', 'address2', 'city', 'country', 'state', 'zip', 'postal_code'] + resultString = "\n" + for k, v of address + if v and (k in allowedKeys) + resultString += "<#{k}#{if k == 'address2' then ' nil="nil"' else ''}>#{v || ''}\n" + resultString += "\n" + return resultString + _createPaypalSubscription: (user, subscriptionDetails, recurly_token_id, callback) -> logger.log {user_id: user._id, recurly_token_id}, "starting process of creating paypal subscription" Async.waterfall([ @@ -108,16 +117,7 @@ module.exports = RecurlyWrapper = address = subscriptionDetails.address if !address return next(new Error('no address in subscriptionDetails at setAddress stage')) - requestBody = """ - - #{address.address1} - #{address.address2} - #{address.city || ''} - #{address.state || ''} - #{address.zip || ''} - #{address.country} - - """ + requestBody = RecurlyWrapper._addressToXml(address) RecurlyWrapper.apiRequest({ url: "accounts/#{accountCode}/billing_info" method: "PUT" diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index 9547508337..0dc2d68e52 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -117,11 +117,12 @@ define [ coupon_code:pricing.items?.coupon?.code || "" isPaypal: $scope.paymentMethod == 'paypal' address: - address1: $scope.data.address1 - address2: $scope.data.address2 - country: $scope.data.country - state: $scope.data.state - zip: $scope.data.zip + address1: $scope.data.address1 + address2: $scope.data.address2 + country: $scope.data.country + state: $scope.data.state + postal_code: $scope.date.postal_code + zip: $scope.data.zip $http.post("/user/subscription/create", postData) .success (data, status, headers)-> sixpack.convert "in-editor-free-trial-plan", pricing.items.plan.code, (err)-> diff --git a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee index e05040772d..143085b402 100644 --- a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee @@ -329,5 +329,31 @@ describe "RecurlyWrapper", -> @apiRequest.called.should.equal true + describe "_addressToXml", -> + + beforeEach -> + @address = + address1: "addr_one" + address2: "addr_two" + country: "some_country" + state: "some_state" + zip: "some_zip" + nonsenseKey: "rubbish" + + it 'should generate the correct xml', () -> + result = RecurlyWrapper._addressToXml @address + should.equal( + result, + """ + + addr_one + addr_two + some_country + some_state + some_zip + \n + """ + ) + From 9938787e4acfeb266519cfb9d85c5bd0aef4df4b Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Mon, 27 Jun 2016 10:38:10 +0100 Subject: [PATCH 12/34] fix a few silly issues. Appears to work now --- .../coffee/Features/Subscription/RecurlyWrapper.coffee | 10 +++++----- .../web/public/coffee/main/new-subscription.coffee | 2 +- .../coffee/Subscription/RecurlyWrapperTests.coffee | 2 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee index e49cb12b39..69210cbd52 100644 --- a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee +++ b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee @@ -10,7 +10,7 @@ module.exports = RecurlyWrapper = apiUrl : "https://api.recurly.com/v2" _addressToXml: (address) -> - allowedKeys = ['address1', 'address2', 'city', 'country', 'state', 'zip', 'postal_code'] + allowedKeys = ['address1', 'address2', 'city', 'country', 'state', 'zip'] resultString = "\n" for k, v of address if v and (k in allowedKeys) @@ -27,13 +27,13 @@ module.exports = RecurlyWrapper = url: "accounts/#{user._id}" method: "GET" }, (error, response, responseBody) -> + result = {userExists: true} if error + if response.statusCode == 404 # actually not an error in this case, just no existing account + result.userExists = false + return next(null, result) logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while checking account" return next(error) - result = {userExists: true} - if response.statusCode == 404 - result.userExists = false - return next(null, result) logger.log {user_id: user._id, recurly_token_id}, "user appears to exist in recurly" RecurlyWrapper._parseAccountXml responseBody, (err, account) -> if err diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index 0dc2d68e52..b507690f4e 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -121,7 +121,7 @@ define [ address2: $scope.data.address2 country: $scope.data.country state: $scope.data.state - postal_code: $scope.date.postal_code + postal_code: $scope.data.postal_code zip: $scope.data.zip $http.post("/user/subscription/create", postData) .success (data, status, headers)-> diff --git a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee index 143085b402..3fb5590018 100644 --- a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee @@ -338,6 +338,7 @@ describe "RecurlyWrapper", -> country: "some_country" state: "some_state" zip: "some_zip" + postal_code: "some_postal_code" nonsenseKey: "rubbish" it 'should generate the correct xml', () -> @@ -351,6 +352,7 @@ describe "RecurlyWrapper", -> some_country some_state some_zip + some_postal_code \n """ ) From eb92cfe8e09dde49957c1160a16bc4f44f502f89 Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Mon, 27 Jun 2016 10:40:08 +0100 Subject: [PATCH 13/34] Remove the postal_code from test, until recurly get back to us. --- .../UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee | 2 -- 1 file changed, 2 deletions(-) diff --git a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee index 3fb5590018..143085b402 100644 --- a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee @@ -338,7 +338,6 @@ describe "RecurlyWrapper", -> country: "some_country" state: "some_state" zip: "some_zip" - postal_code: "some_postal_code" nonsenseKey: "rubbish" it 'should generate the correct xml', () -> @@ -352,7 +351,6 @@ describe "RecurlyWrapper", -> some_country some_state some_zip - some_postal_code \n """ ) From 81b93ab5a9f7a8ec5ca8c34ffbd6d6dfb135682a Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Mon, 27 Jun 2016 11:34:24 +0100 Subject: [PATCH 14/34] Disable links to the docs when the wiki is not available. --- services/web/app/views/project/editor.jade | 1 + services/web/app/views/project/editor/pdf.jade | 8 +++++--- .../coffee/ide/pdf/controllers/PdfController.coffee | 8 +++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/services/web/app/views/project/editor.jade b/services/web/app/views/project/editor.jade index e666724b09..bcb69597eb 100644 --- a/services/web/app/views/project/editor.jade +++ b/services/web/app/views/project/editor.jade @@ -97,6 +97,7 @@ block content window.csrfToken = "!{csrfToken}"; window.anonymous = #{anonymous}; window.maxDocLength = #{maxDocLength}; + window.wikiEnabled = #{!!(settings.apis.wiki && settings.apis.wiki.url)}; window.requirejs = { "paths" : { "mathjax": "/js/libs/mathjax/MathJax.js?config=TeX-AMS_HTML", diff --git a/services/web/app/views/project/editor/pdf.jade b/services/web/app/views/project/editor/pdf.jade index 54f7c6c0af..091831a22d 100644 --- a/services/web/app/views/project/editor/pdf.jade +++ b/services/web/app/views/project/editor/pdf.jade @@ -114,9 +114,11 @@ div.full-size.pdf(ng-controller="PdfController") ) figure.card-hint-icon-container i.fa.fa-lightbulb-o(aria-hidden="true") - p.card-hint-text(ng-show="entry.humanReadableHint", ng-bind-html="entry.humanReadableHint") - .card-hint-actions - .card-hint-ext-link + p.card-hint-text( + ng-show="entry.humanReadableHint", + ng-bind-html="wikiEnabled ? entry.humanReadableHint : stripHTMLFromString(entry.humanReadableHint)") + .card-hint-actions.clearfix + .card-hint-ext-link(ng-if="wikiEnabled") a(ng-href="{{ entry.extraInfoURL }}", target="_blank") i.fa.fa-external-link | #{translate("log_hint_extra_info")} diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index f503437407..05cca37303 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -13,6 +13,7 @@ define [ # pdf.view = uncompiled | pdf | errors $scope.pdf.view = if $scope?.pdf?.url then 'pdf' else 'uncompiled' $scope.shouldShowLogs = false + $scope.wikiEnabled = window.wikiEnabled; if ace.require("ace/lib/useragent").isMac $scope.modifierKey = "Cmd" @@ -24,6 +25,11 @@ define [ qs_args = ("#{k}=#{v}" for k, v of args) if qs_args.length then "?" + qs_args.join("&") else "" + $scope.stripHTMLFromString = (htmlStr) -> + tmp = document.createElement("DIV") + tmp.innerHTML = htmlStr + return tmp.textContent || tmp.innerText || "" + $scope.$on "project:joined", () -> return if !autoCompile autoCompile = false @@ -173,7 +179,7 @@ define [ accumulateResults = (newEntries) -> for key in ['all', 'errors', 'warnings'] logEntries[key] = logEntries[key].concat newEntries[key] - + # use the parsers for each file type processLog = (log) -> $scope.pdf.rawLog = log From 401565ba23df3c2173a9085c8370b328d2966fc2 Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Mon, 27 Jun 2016 12:14:43 +0100 Subject: [PATCH 15/34] Fix references to the RecurlyWrapper object. --- .../Subscription/RecurlyWrapper.coffee | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee index 69210cbd52..41435eabe4 100644 --- a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee +++ b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee @@ -191,13 +191,13 @@ module.exports = RecurlyWrapper =
""" - @apiRequest({ + RecurlyWrapper.apiRequest({ url : "subscriptions" method : "POST" body : requestBody }, (error, response, responseBody) => return callback(error) if error? - @_parseSubscriptionXml responseBody, callback + RecurlyWrapper._parseSubscriptionXml responseBody, callback ) createSubscription: (user, subscriptionDetails, recurly_token_id, callback)-> @@ -207,7 +207,7 @@ module.exports = RecurlyWrapper = fn user, subscriptionDetails, recurly_token_id, callback apiRequest : (options, callback) -> - options.url = @apiUrl + "/" + options.url + options.url = RecurlyWrapper.apiUrl + "/" + options.url options.headers = "Authorization" : "Basic " + new Buffer(Settings.apis.recurly.apiKey).toString("base64") "Accept" : "application/xml" @@ -249,11 +249,11 @@ module.exports = RecurlyWrapper = getSubscriptions: (accountId, callback)-> - @apiRequest({ + RecurlyWrapper.apiRequest({ url: "accounts/#{accountId}/subscriptions" }, (error, response, body) => return callback(error) if error? - @_parseXml body, callback + RecurlyWrapper._parseXml body, callback ) @@ -266,11 +266,11 @@ module.exports = RecurlyWrapper = else url = "subscriptions/#{subscriptionId}" - @apiRequest({ + RecurlyWrapper.apiRequest({ url: url }, (error, response, body) => return callback(error) if error? - @_parseSubscriptionXml body, (error, recurlySubscription) => + RecurlyWrapper._parseSubscriptionXml body, (error, recurlySubscription) => return callback(error) if error? if options.includeAccount if recurlySubscription.account? and recurlySubscription.account.url? @@ -278,7 +278,7 @@ module.exports = RecurlyWrapper = else return callback "I don't understand the response from Recurly" - @getAccount accountId, (error, account) -> + RecurlyWrapper.getAccount accountId, (error, account) -> return callback(error) if error? recurlySubscription.account = account callback null, recurlySubscription @@ -296,9 +296,9 @@ module.exports = RecurlyWrapper = per_page:200 if cursor? opts.qs.cursor = cursor - @apiRequest opts, (error, response, body) => + RecurlyWrapper.apiRequest opts, (error, response, body) => return callback(error) if error? - @_parseXml body, (err, data)-> + RecurlyWrapper._parseXml body, (err, data)-> if err? logger.err err:err, "could not get accoutns" callback(err) @@ -314,19 +314,19 @@ module.exports = RecurlyWrapper = getAccount: (accountId, callback) -> - @apiRequest({ + RecurlyWrapper.apiRequest({ url: "accounts/#{accountId}" }, (error, response, body) => return callback(error) if error? - @_parseAccountXml body, callback + RecurlyWrapper._parseAccountXml body, callback ) getBillingInfo: (accountId, callback)-> - @apiRequest({ + RecurlyWrapper.apiRequest({ url: "accounts/#{accountId}/billing_info" }, (error, response, body) => return callback(error) if error? - @_parseXml body, callback + RecurlyWrapper._parseXml body, callback ) @@ -338,13 +338,13 @@ module.exports = RecurlyWrapper = #{options.timeframe} """ - @apiRequest({ + RecurlyWrapper.apiRequest({ url : "subscriptions/#{subscriptionId}" method : "put" body : requestBody }, (error, response, responseBody) => return callback(error) if error? - @_parseSubscriptionXml responseBody, callback + RecurlyWrapper._parseSubscriptionXml responseBody, callback ) createFixedAmmountCoupon: (coupon_code, name, currencyCode, discount_in_cents, plan_code, callback)-> @@ -363,7 +363,7 @@ module.exports = RecurlyWrapper = """ logger.log coupon_code:coupon_code, requestBody:requestBody, "creating coupon" - @apiRequest({ + RecurlyWrapper.apiRequest({ url : "coupons" method : "post" body : requestBody @@ -375,16 +375,16 @@ module.exports = RecurlyWrapper = lookupCoupon: (coupon_code, callback)-> - @apiRequest({ + RecurlyWrapper.apiRequest({ url: "coupons/#{coupon_code}" }, (error, response, body) => return callback(error) if error? - @_parseXml body, callback + RecurlyWrapper._parseXml body, callback ) cancelSubscription: (subscriptionId, callback) -> logger.log subscriptionId:subscriptionId, "telling recurly to cancel subscription" - @apiRequest({ + RecurlyWrapper.apiRequest({ url: "subscriptions/#{subscriptionId}/cancel", method: "put" }, (error, response, body) -> @@ -393,7 +393,7 @@ module.exports = RecurlyWrapper = reactivateSubscription: (subscriptionId, callback) -> logger.log subscriptionId:subscriptionId, "telling recurly to reactivating subscription" - @apiRequest({ + RecurlyWrapper.apiRequest({ url: "subscriptions/#{subscriptionId}/reactivate", method: "put" }, (error, response, body) -> @@ -409,7 +409,7 @@ module.exports = RecurlyWrapper = """ logger.log account_code:account_code, coupon_code:coupon_code, requestBody:requestBody, "redeeming coupon for user" - @apiRequest({ + RecurlyWrapper.apiRequest({ url : "coupons/#{coupon_code}/redeem" method : "post" body : requestBody @@ -423,7 +423,7 @@ module.exports = RecurlyWrapper = next_renewal_date = new Date() next_renewal_date.setDate(next_renewal_date.getDate() + daysUntilExpire) logger.log subscriptionId:subscriptionId, daysUntilExpire:daysUntilExpire, "Exending Free trial for user" - @apiRequest({ + RecurlyWrapper.apiRequest({ url : "/subscriptions/#{subscriptionId}/postpone?next_renewal_date=#{next_renewal_date}&bulk=false" method : "put" }, (error, response, responseBody) => @@ -433,7 +433,7 @@ module.exports = RecurlyWrapper = ) _parseSubscriptionXml: (xml, callback) -> - @_parseXml xml, (error, data) -> + RecurlyWrapper._parseXml xml, (error, data) -> return callback(error) if error? if data? and data.subscription? recurlySubscription = data.subscription @@ -442,7 +442,7 @@ module.exports = RecurlyWrapper = callback null, recurlySubscription _parseAccountXml: (xml, callback) -> - @_parseXml xml, (error, data) -> + RecurlyWrapper._parseXml xml, (error, data) -> return callback(error) if error? if data? and data.account? account = data.account @@ -451,7 +451,7 @@ module.exports = RecurlyWrapper = callback null, account _parseBillingInfoXml: (xml, callback) -> - @_parseXml xml, (error, data) -> + RecurlyWrapper._parseXml xml, (error, data) -> return callback(error) if error? if data? and data.account? billingInfo = data.billing_info From d853eb5916876ae65a0a4f7397c99b22631dc189 Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Mon, 27 Jun 2016 13:54:54 +0100 Subject: [PATCH 16/34] Update existing RecurlyWrapper tests. --- .../Subscription/RecurlyWrapperTests.coffee | 165 ++++++++++++------ 1 file changed, 115 insertions(+), 50 deletions(-) diff --git a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee index 143085b402..4b1880cf00 100644 --- a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee @@ -2,8 +2,8 @@ should = require('chai').should() sinon = require 'sinon' crypto = require 'crypto' querystring = require 'querystring' -RecurlyWrapper = require "../../../../app/js/Features/Subscription/RecurlyWrapper" -Settings = require "settings-sharelatex" +modulePath = "../../../../app/js/Features/Subscription/RecurlyWrapper" +SandboxedModule = require('sandboxed-module') tk = require("timekeeper") fixtures = @@ -97,22 +97,37 @@ mockApiRequest = (options, callback) -> describe "RecurlyWrapper", -> - beforeEach -> - Settings.plans = [{ - planCode: "collaborator" - name: "Collaborator" - features: - collaborators: -1 - versioning: true - }] - Settings.defaultPlanCode = - collaborators: 0 - versioning: false + + before -> + @settings = + plans: [{ + planCode: "collaborator" + name: "Collaborator" + features: + collaborators: -1 + versioning: true + }] + defaultPlanCode: + collaborators: 0 + versioning: false + apis: + recurly: + apiKey: 'nonsense' + privateKey: 'private_nonsense' + + @RecurlyWrapper = RecurlyWrapper = SandboxedModule.require modulePath, requires: + "settings-sharelatex": @settings + "logger-sharelatex": + err: sinon.stub() + error: sinon.stub() + log: sinon.stub() + "request": sinon.stub() describe "sign", -> + before (done) -> tk.freeze Date.now() # freeze the time for these tests - RecurlyWrapper.sign({ + @RecurlyWrapper.sign({ subscription : plan_code : "gold" name : "$$$" @@ -127,7 +142,7 @@ describe "RecurlyWrapper", -> it "should be signed correctly", -> signed = @signature.split("|")[0] query = @signature.split("|")[1] - crypto.createHmac("sha1", Settings.apis.recurly.privateKey).update(query).digest("hex").should.equal signed + crypto.createHmac("sha1", @settings.apis.recurly.privateKey).update(query).digest("hex").should.equal signed it "should be url escaped", -> query = @signature.split("|")[1] @@ -180,7 +195,7 @@ describe "RecurlyWrapper", -> " " + " " + "" - RecurlyWrapper._parseXml xml, (error, data) -> + @RecurlyWrapper._parseXml xml, (error, data) -> data.subscription.plan.plan_code.should.equal "gold" data.subscription.plan.name.should.equal "Gold plan" data.subscription.uuid.should.equal "44f83d7cba354d5b84812419f923ea96" @@ -188,32 +203,36 @@ describe "RecurlyWrapper", -> data.subscription.unit_amount_in_cents.should.equal 800 data.subscription.currency.should.equal "EUR" data.subscription.quantity.should.equal 1 + data.subscription.activated_at.should.deep.equal new Date("2011-05-27T07:00:00Z") should.equal data.subscription.canceled_at, null should.equal data.subscription.expires_at, null + data.subscription.current_period_started_at.should.deep.equal new Date("2011-06-27T07:00:00Z") + data.subscription.current_period_ends_at.should.deep.equal new Date("2011-07-27T07:00:00Z") should.equal data.subscription.trial_started_at, null should.equal data.subscription.trial_ends_at, null - data.subscription.subscription_add_ons.should.deep.equal [{ + + data.subscription.subscription_add_ons[0].should.deep.equal { add_on_code: "ipaddresses" quantity: "10" unit_amount_in_cents: "150" - }] + } data.subscription.account.url.should.equal "https://api.recurly.com/v2/accounts/1" data.subscription.url.should.equal "https://api.recurly.com/v2/subscriptions/44f83d7cba354d5b84812419f923ea96" data.subscription.plan.url.should.equal "https://api.recurly.com/v2/plans/gold" done() - + describe "getSubscription", -> describe "with proper subscription id", -> before -> - @apiRequest = sinon.stub(RecurlyWrapper, "apiRequest", mockApiRequest) - RecurlyWrapper.getSubscription "44f83d7cba354d5b84812419f923ea96", (error, recurlySubscription) => + @apiRequest = sinon.stub(@RecurlyWrapper, "apiRequest", mockApiRequest) + @RecurlyWrapper.getSubscription "44f83d7cba354d5b84812419f923ea96", (error, recurlySubscription) => @recurlySubscription = recurlySubscription after -> - RecurlyWrapper.apiRequest.restore() - + @RecurlyWrapper.apiRequest.restore() + it "should look up the subscription at the normal API end point", -> @apiRequest.args[0][0].url.should.equal "subscriptions/44f83d7cba354d5b84812419f923ea96" @@ -222,12 +241,12 @@ describe "RecurlyWrapper", -> describe "with ReculyJS token", -> before -> - @apiRequest = sinon.stub(RecurlyWrapper, "apiRequest", mockApiRequest) - RecurlyWrapper.getSubscription "70db44b10f5f4b238669480c9903f6f5", {recurlyJsResult: true}, (error, recurlySubscription) => + @apiRequest = sinon.stub(@RecurlyWrapper, "apiRequest", mockApiRequest) + @RecurlyWrapper.getSubscription "70db44b10f5f4b238669480c9903f6f5", {recurlyJsResult: true}, (error, recurlySubscription) => @recurlySubscription = recurlySubscription after -> - RecurlyWrapper.apiRequest.restore() - + @RecurlyWrapper.apiRequest.restore() + it "should return the subscription", -> @recurlySubscription.uuid.should.equal "44f83d7cba354d5b84812419f923ea96" @@ -236,30 +255,30 @@ describe "RecurlyWrapper", -> describe "with includeAccount", -> beforeEach -> - @apiRequest = sinon.stub(RecurlyWrapper, "apiRequest", mockApiRequest) - RecurlyWrapper.getSubscription "44f83d7cba354d5b84812419f923ea96", {includeAccount: true}, (error, recurlySubscription) => + @apiRequest = sinon.stub(@RecurlyWrapper, "apiRequest", mockApiRequest) + @RecurlyWrapper.getSubscription "44f83d7cba354d5b84812419f923ea96", {includeAccount: true}, (error, recurlySubscription) => @recurlySubscription = recurlySubscription afterEach -> - RecurlyWrapper.apiRequest.restore() + @RecurlyWrapper.apiRequest.restore() it "should request the account from the API", -> @apiRequest.args[1][0].url.should.equal "accounts/104" - + it "should populate the account attribute", -> @recurlySubscription.account.account_code.should.equal "104" - + describe "updateSubscription", -> beforeEach (done) -> @recurlySubscriptionId = "subscription-id-123" - @apiRequest = sinon.stub RecurlyWrapper, "apiRequest", (options, callback) => + @apiRequest = sinon.stub @RecurlyWrapper, "apiRequest", (options, callback) => @requestOptions = options callback null, {}, fixtures["subscriptions/44f83d7cba354d5b84812419f923ea96"] - RecurlyWrapper.updateSubscription @recurlySubscriptionId, { plan_code : "silver", timeframe: "now" }, (error, recurlySubscription) => + @RecurlyWrapper.updateSubscription @recurlySubscriptionId, { plan_code : "silver", timeframe: "now" }, (error, recurlySubscription) => @recurlySubscription = recurlySubscription done() afterEach -> - RecurlyWrapper.apiRequest.restore() + @RecurlyWrapper.apiRequest.restore() it "should send an update request to the API", -> @apiRequest.called.should.equal true @@ -275,59 +294,58 @@ describe "RecurlyWrapper", -> it "should return the updated subscription", -> should.exist @recurlySubscription @recurlySubscription.plan.plan_code.should.equal "gold" - + describe "cancelSubscription", -> beforeEach (done) -> @recurlySubscriptionId = "subscription-id-123" - @apiRequest = sinon.stub RecurlyWrapper, "apiRequest", (options, callback) => + @apiRequest = sinon.stub @RecurlyWrapper, "apiRequest", (options, callback) => options.url.should.equal "subscriptions/#{@recurlySubscriptionId}/cancel" options.method.should.equal "put" callback() - RecurlyWrapper.cancelSubscription(@recurlySubscriptionId, done) + @RecurlyWrapper.cancelSubscription(@recurlySubscriptionId, done) afterEach -> - RecurlyWrapper.apiRequest.restore() + @RecurlyWrapper.apiRequest.restore() it "should send a cancel request to the API", -> @apiRequest.called.should.equal true - + describe "reactivateSubscription", -> beforeEach (done) -> @recurlySubscriptionId = "subscription-id-123" - @apiRequest = sinon.stub RecurlyWrapper, "apiRequest", (options, callback) => + @apiRequest = sinon.stub @RecurlyWrapper, "apiRequest", (options, callback) => options.url.should.equal "subscriptions/#{@recurlySubscriptionId}/reactivate" options.method.should.equal "put" callback() - RecurlyWrapper.reactivateSubscription(@recurlySubscriptionId, done) + @RecurlyWrapper.reactivateSubscription(@recurlySubscriptionId, done) afterEach -> - RecurlyWrapper.apiRequest.restore() + @RecurlyWrapper.apiRequest.restore() it "should send a cancel request to the API", -> @apiRequest.called.should.equal true - - + + describe "redeemCoupon", -> beforeEach (done) -> @recurlyAccountId = "account-id-123" @coupon_code = "312321312" - @apiRequest = sinon.stub RecurlyWrapper, "apiRequest", (options, callback) => + @apiRequest = sinon.stub @RecurlyWrapper, "apiRequest", (options, callback) => options.url.should.equal "coupons/#{@coupon_code}/redeem" options.body.indexOf("#{@recurlyAccountId}").should.not.equal -1 options.body.indexOf("USD").should.not.equal -1 options.method.should.equal "post" callback() - RecurlyWrapper.redeemCoupon(@recurlyAccountId, @coupon_code, done) + @RecurlyWrapper.redeemCoupon(@recurlyAccountId, @coupon_code, done) afterEach -> - RecurlyWrapper.apiRequest.restore() + @RecurlyWrapper.apiRequest.restore() it "should send the request to redem the coupon", -> @apiRequest.called.should.equal true - describe "_addressToXml", -> @@ -341,7 +359,7 @@ describe "RecurlyWrapper", -> nonsenseKey: "rubbish" it 'should generate the correct xml', () -> - result = RecurlyWrapper._addressToXml @address + result = @RecurlyWrapper._addressToXml @address should.equal( result, """ @@ -355,5 +373,52 @@ describe "RecurlyWrapper", -> """ ) + describe 'createSubscription', -> + + beforeEach -> + @user = + _id: 'some_id' + email: 'user@example.com' + @subscriptionDetails = + currencyCode: "EUR" + plan_code: "some_plan_code" + coupon_code: "" + isPaypal: true + address: + address1: "addr_one" + address2: "addr_two" + country: "some_country" + state: "some_state" + zip: "some_zip" + @recurly_token_id = "a-token-id" + describe 'when all goes well', -> + + beforeEach -> + + describe 'when paypal', -> + beforeEach -> + + describe 'when not paypal', -> + beforeEach -> + + describe '_createCreditCardSubscription', -> + + beforeEach -> + + describe 'when all goes well', -> + + beforeEach -> + + describe 'when api request produces an error', -> + + beforeEach -> + + describe '_createPaypalSubscription', -> + + beforeEach -> + + describe 'when all goes well', -> + + beforeEach -> From 95d85538cc1bca4c19699341d9890be6fc846539 Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Mon, 27 Jun 2016 14:00:30 +0100 Subject: [PATCH 17/34] Clean up xml text block in test. --- .../Subscription/RecurlyWrapperTests.coffee | 64 ++++++++++--------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee index 4b1880cf00..821fddb3e9 100644 --- a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee @@ -164,37 +164,38 @@ describe "RecurlyWrapper", -> describe "_parseXml", -> it "should convert different data types into correct representations", (done) -> - xml = - "" + - "" + - " " + - " " + - " gold" + - " Gold plan" + - " " + - " 44f83d7cba354d5b84812419f923ea96" + - " active" + - " 800" + - " EUR" + - " 1" + - " 2011-05-27T07:00:00Z" + - " " + - " " + - " 2011-06-27T07:00:00Z" + - " 2011-07-27T07:00:00Z" + - " " + - " " + - " " + - " " + - " ipaddresses" + - " 10" + - " 150" + - " " + - " " + - " " + - " " + - " " + - "" + xml = """ + + + + + gold + Gold plan + + 44f83d7cba354d5b84812419f923ea96 + active + 800 + EUR + 1 + 2011-05-27T07:00:00Z + + + 2011-06-27T07:00:00Z + 2011-07-27T07:00:00Z + + + + + ipaddresses + 10 + 150 + + + + + + + """ @RecurlyWrapper._parseXml xml, (error, data) -> data.subscription.plan.plan_code.should.equal "gold" data.subscription.plan.name.should.equal "Gold plan" @@ -225,6 +226,7 @@ describe "RecurlyWrapper", -> done() describe "getSubscription", -> + describe "with proper subscription id", -> before -> @apiRequest = sinon.stub(@RecurlyWrapper, "apiRequest", mockApiRequest) From 2c1b3266818c022ed6ef3ce5e9c9f1f3fa6dc130 Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Mon, 27 Jun 2016 14:29:19 +0100 Subject: [PATCH 18/34] test the `createSubscription` function. --- .../Subscription/RecurlyWrapperTests.coffee | 75 ++++++++++++++++++- 1 file changed, 71 insertions(+), 4 deletions(-) diff --git a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee index 821fddb3e9..f19a4389aa 100644 --- a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee @@ -1,4 +1,5 @@ should = require('chai').should() +expect = require('chai').expect sinon = require 'sinon' crypto = require 'crypto' querystring = require 'querystring' @@ -392,18 +393,84 @@ describe "RecurlyWrapper", -> country: "some_country" state: "some_state" zip: "some_zip" + @subscription = {} @recurly_token_id = "a-token-id" + @call = (callback) => + @RecurlyWrapper.createSubscription(@user, @subscriptionDetails, @recurly_token_id, callback) - describe 'when all goes well', -> + describe 'when paypal', -> beforeEach -> + @subscriptionDetails.isPaypal = true + @_createPaypalSubscription = sinon.stub(@RecurlyWrapper, '_createPaypalSubscription') + @_createPaypalSubscription.callsArgWith(3, null, @subscription) - describe 'when paypal', -> - beforeEach -> + afterEach -> + @_createPaypalSubscription.restore() + + it 'should not produce an error', (done) -> + @call (err, sub) => + expect(err).to.equal null + expect(err).to.not.be.instanceof Error + done() + + it 'should produce a subscription object', (done) -> + @call (err, sub) => + expect(sub).to.deep.equal @subscription + done() + + it 'should call _createPaypalSubscription', (done) -> + @call (err, sub) => + @_createPaypalSubscription.callCount.should.equal 1 + done() + + describe "when _createPaypalSubscription produces an error", -> - describe 'when not paypal', -> beforeEach -> + @_createPaypalSubscription.callsArgWith(3, new Error('woops')) + + it 'should produce an error', (done) -> + @call (err, sub) => + expect(err).to.be.instanceof Error + done() + + describe 'when not paypal', -> + + beforeEach -> + @subscriptionDetails.isPaypal = false + @_createCreditCardSubscription = sinon.stub(@RecurlyWrapper, '_createCreditCardSubscription') + @_createCreditCardSubscription.callsArgWith(3, null, @subscription) + + afterEach -> + @_createCreditCardSubscription.restore() + + it 'should not produce an error', (done) -> + @call (err, sub) => + expect(err).to.equal null + expect(err).to.not.be.instanceof Error + done() + + it 'should produce a subscription object', (done) -> + @call (err, sub) => + expect(sub).to.deep.equal @subscription + done() + + it 'should call _createCreditCardSubscription', (done) -> + @call (err, sub) => + @_createCreditCardSubscription.callCount.should.equal 1 + done() + + describe "when _createCreditCardSubscription produces an error", -> + + beforeEach -> + @_createCreditCardSubscription.callsArgWith(3, new Error('woops')) + + it 'should produce an error', (done) -> + @call (err, sub) => + expect(err).to.be.instanceof Error + done() + describe '_createCreditCardSubscription', -> From 3bf8da3e83725faf80b18b75e1861b3967d50a2e Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Mon, 27 Jun 2016 14:45:17 +0100 Subject: [PATCH 19/34] test _createCreditCardSubscription --- .../Subscription/RecurlyWrapperTests.coffee | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee index f19a4389aa..fd8bbe25ed 100644 --- a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee @@ -475,14 +475,66 @@ describe "RecurlyWrapper", -> describe '_createCreditCardSubscription', -> beforeEach -> + @user = + _id: 'some_id' + email: 'user@example.com' + @subscriptionDetails = + currencyCode: "EUR" + plan_code: "some_plan_code" + coupon_code: "" + isPaypal: true + address: + address1: "addr_one" + address2: "addr_two" + country: "some_country" + state: "some_state" + zip: "some_zip" + @subscription = {} + @recurly_token_id = "a-token-id" + @apiRequest = sinon.stub(@RecurlyWrapper, 'apiRequest') + @response = + statusCode: 200 + @body = "is_bad" + @apiRequest.callsArgWith(1, null, @response, @body) + @_parseSubscriptionXml = sinon.stub(@RecurlyWrapper, '_parseSubscriptionXml') + @_parseSubscriptionXml.callsArgWith(1, null, @subscription) + @call = (callback) => + @RecurlyWrapper._createCreditCardSubscription(@user, @subscriptionDetails, @recurly_token_id, callback) - describe 'when all goes well', -> + afterEach -> + @apiRequest.restore() + @_parseSubscriptionXml.restore() - beforeEach -> + it 'should not produce an error', (done) -> + @call (err, sub) => + expect(err).to.not.be.instanceof Error + expect(err).to.equal null + done() + + it 'should produce a subscription', (done) -> + @call (err, sub) => + expect(sub).to.equal @subscription + done() describe 'when api request produces an error', -> beforeEach -> + @apiRequest.callsArgWith(1, new Error('woops')) + + it 'should produce an error', (done) -> + @call (err, sub) => + expect(err).to.be.instanceof Error + done() + + describe 'when parse xml produces an error', -> + + beforeEach -> + @_parseSubscriptionXml.callsArgWith(1, new Error('woops')) + + it 'should produce an error', (done) -> + @call (err, sub) => + expect(err).to.be.instanceof Error + done() describe '_createPaypalSubscription', -> From 709f8f2bea6b273e3b966768b15db427a717fc33 Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Mon, 27 Jun 2016 16:34:00 +0100 Subject: [PATCH 20/34] start testing the paypal workflow. --- .../Subscription/RecurlyWrapper.coffee | 320 +++++++++--------- .../Subscription/RecurlyWrapperTests.coffee | 86 ++++- 2 files changed, 253 insertions(+), 153 deletions(-) diff --git a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee index 41435eabe4..841ee0a77e 100644 --- a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee +++ b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee @@ -18,160 +18,178 @@ module.exports = RecurlyWrapper = resultString += "\n" return resultString + _paypal: + checkAccountExists: (cache, next) -> + user = cache.user + recurly_token_id = cache.recurly_token_id + subscriptionDetails = cache.subscriptionDetails + logger.log {user_id: user._id, recurly_token_id}, "checking if recurly account exists for user" + RecurlyWrapper.apiRequest({ + url: "accounts/#{user._id}" + method: "GET" + }, (error, response, responseBody) -> + if error + if response.statusCode == 404 # actually not an error in this case, just no existing account + cache.userExists = false + return next(null, cache) + logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while checking account" + return next(error) + logger.log {user_id: user._id, recurly_token_id}, "user appears to exist in recurly" + RecurlyWrapper._parseAccountXml responseBody, (err, account) -> + if err + logger.error {err, user_id: user._id, recurly_token_id}, "error parsing account" + return next(err) + cache.account = account + return next(null, cache) + ) + createAccount: (cache, next) -> + user = cache.user + recurly_token_id = cache.recurly_token_id + subscriptionDetails = cache.subscriptionDetails + if cache.userExists + logger.log {user_id: user._id, recurly_token_id}, "user already exists in recurly" + return next(null, cache) + logger.log {user_id: user._id, recurly_token_id}, "creating user in recurly" + address = subscriptionDetails.address + if !address + return next(new Error('no address in subscriptionDetails at createAccount stage')) + requestBody = """ + + #{user._id} + #{user.email} + #{user.first_name} + #{user.last_name} +
+ #{address.address1} + #{address.address2} + #{address.city || ''} + #{address.state || ''} + #{address.zip || ''} + #{address.country} +
+
+ """ + RecurlyWrapper.apiRequest({ + url : "accounts" + method : "POST" + body : requestBody + }, (error, response, responseBody) => + if error + logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while creating account" + return next(error) + RecurlyWrapper._parseAccountXml responseBody, (err, account) -> + if err + logger.error {err, user_id: user._id, recurly_token_id}, "error creating account" + return next(err) + cache.account = account + return next(null, cache) + ) + createBillingInfo: (cache, next) -> + user = cache.user + recurly_token_id = cache.recurly_token_id + subscriptionDetails = cache.subscriptionDetails + logger.log {user_id: user._id, recurly_token_id}, "creating billing info in recurly" + accountCode = cache?.account?.account_code + if !accountCode + return next(new Error('no account code at createBillingInfo stage')) + requestBody = """ + + #{recurly_token_id} + + """ + RecurlyWrapper.apiRequest({ + url: "accounts/#{accountCode}/billing_info" + method: "POST" + body: requestBody + }, (error, response, responseBody) => + if error + logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while creating billing info" + return next(error) + RecurlyWrapper._parseBillingInfoXml responseBody, (err, billingInfo) -> + if err + logger.error {err, user_id: user._id, accountCode, recurly_token_id}, "error creating billing info" + return next(err) + cache.billingInfo = billingInfo + return next(null, cache) + ) + + setAddress: (cache, next) -> + user = cache.user + recurly_token_id = cache.recurly_token_id + subscriptionDetails = cache.subscriptionDetails + logger.log {user_id: user._id, recurly_token_id}, "setting billing address in recurly" + accountCode = cache?.account?.account_code + if !accountCode + return next(new Error('no account code at setAddress stage')) + address = subscriptionDetails.address + if !address + return next(new Error('no address in subscriptionDetails at setAddress stage')) + requestBody = RecurlyWrapper._addressToXml(address) + RecurlyWrapper.apiRequest({ + url: "accounts/#{accountCode}/billing_info" + method: "PUT" + body: requestBody + }, (error, response, responseBody) => + if error + logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while setting address" + return next(error) + RecurlyWrapper._parseBillingInfoXml responseBody, (err, billingInfo) -> + if err + logger.error {err, user_id: user._id, recurly_token_id}, "error updating billing info" + return next(err) + cache.billingInfo = billingInfo + return next(null, cache) + ) + createSubscription: (cache, next) -> + user = cache.user + recurly_token_id = cache.recurly_token_id + subscriptionDetails = cache.subscriptionDetails + logger.log {user_id: user._id, recurly_token_id}, "creating subscription in recurly" + requestBody = """ + + #{subscriptionDetails.plan_code} + #{subscriptionDetails.currencyCode} + #{subscriptionDetails.coupon_code} + + #{user._id} + + + """ # TODO: check account details and billing + RecurlyWrapper.apiRequest({ + url : "subscriptions" + method : "POST" + body : requestBody + }, (error, response, responseBody) => + if error + logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while creating subscription" + return next(error) + RecurlyWrapper._parseSubscriptionXml responseBody, (err, subscription) -> + if err + logger.error {err, user_id: user._id, recurly_token_id}, "error creating subscription" + return next(err) + cache.subscription = subscription + return next(null, cache) + ) + _createPaypalSubscription: (user, subscriptionDetails, recurly_token_id, callback) -> logger.log {user_id: user._id, recurly_token_id}, "starting process of creating paypal subscription" + cache = {user, recurly_token_id, subscriptionDetails} Async.waterfall([ - (next) -> # check if account exists - logger.log {user_id: user._id, recurly_token_id}, "checking if recurly account exists for user" - RecurlyWrapper.apiRequest({ - url: "accounts/#{user._id}" - method: "GET" - }, (error, response, responseBody) -> - result = {userExists: true} - if error - if response.statusCode == 404 # actually not an error in this case, just no existing account - result.userExists = false - return next(null, result) - logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while checking account" - return next(error) - logger.log {user_id: user._id, recurly_token_id}, "user appears to exist in recurly" - RecurlyWrapper._parseAccountXml responseBody, (err, account) -> - if err - logger.error {err, user_id: user._id, recurly_token_id}, "error parsing account" - return next(err) - result.account = account - return next(null, result) - ) - - , (result, next) -> # create account - if result.userExists - logger.log {user_id: user._id, recurly_token_id}, "user already exists in recurly" - return next(null, result) - logger.log {user_id: user._id, recurly_token_id}, "creating user in recurly" - address = subscriptionDetails.address - if !address - return next(new Error('no address in subscriptionDetails at createAccount stage')) - requestBody = """ - - #{user._id} - #{user.email} - #{user.first_name} - #{user.last_name} -
- #{address.address1} - #{address.address2} - #{address.city || ''} - #{address.state || ''} - #{address.zip || ''} - #{address.country} -
-
- """ - RecurlyWrapper.apiRequest({ - url : "accounts" - method : "POST" - body : requestBody - }, (error, response, responseBody) => - if error - logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while creating account" - return next(error) - RecurlyWrapper._parseAccountXml responseBody, (err, account) -> - if err - logger.error {err, user_id: user._id, recurly_token_id}, "error creating account" - return next(err) - result.account = account - return next(null, result) - ) - - , (result, next) -> # create billing info - logger.log {user_id: user._id, recurly_token_id}, "creating billing info in recurly" - accountCode = result?.account?.account_code - if !accountCode - return next(new Error('no account code at createBillingInfo stage')) - requestBody = """ - - #{recurly_token_id} - - """ - RecurlyWrapper.apiRequest({ - url: "accounts/#{accountCode}/billing_info" - method: "POST" - body: requestBody - }, (error, response, responseBody) => - if error - logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while creating billing info" - return next(error) - RecurlyWrapper._parseBillingInfoXml responseBody, (err, billingInfo) -> - if err - logger.error {err, user_id: user._id, accountCode, recurly_token_id}, "error creating billing info" - return next(err) - result.billingInfo = billingInfo - return next(null, result) - ) - - , (result, next) -> # set address - logger.log {user_id: user._id, recurly_token_id}, "setting billing address in recurly" - accountCode = result?.account?.account_code - if !accountCode - return next(new Error('no account code at setAddress stage')) - address = subscriptionDetails.address - if !address - return next(new Error('no address in subscriptionDetails at setAddress stage')) - requestBody = RecurlyWrapper._addressToXml(address) - RecurlyWrapper.apiRequest({ - url: "accounts/#{accountCode}/billing_info" - method: "PUT" - body: requestBody - }, (error, response, responseBody) => - if error - logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while setting address" - return next(error) - RecurlyWrapper._parseBillingInfoXml responseBody, (err, billingInfo) -> - if err - logger.error {err, user_id: user._id, recurly_token_id}, "error updating billing info" - return next(err) - result.billingInfo = billingInfo - return next(null, result) - ) - - , (result, next) -> # create subscription - logger.log {user_id: user._id, recurly_token_id}, "creating subscription in recurly" - requestBody = """ - - #{subscriptionDetails.plan_code} - #{subscriptionDetails.currencyCode} - #{subscriptionDetails.coupon_code} - - #{user._id} - - - """ # TODO: check account details and billing - RecurlyWrapper.apiRequest({ - url : "subscriptions" - method : "POST" - body : requestBody - }, (error, response, responseBody) => - if error - logger.error {error, user_id: user._id, recurly_token_id}, "error response from recurly while creating subscription" - return next(error) - RecurlyWrapper._parseSubscriptionXml responseBody, (err, subscription) -> - if err - logger.error {err, user_id: user._id, recurly_token_id}, "error creating subscription" - return next(err) - result.subscription = subscription - return next(null, result) - ) - - ], (err, result) -> - if err - logger.error {err, user_id: user._id, recurly_token_id}, "error in paypal subscription creation process" - return callback(err) - if !result.subscription - err = new Error('no subscription object in result') - logger.error {err, user_id: user._id, recurly_token_id}, "error in paypal subscription creation process" - return callback(err) - logger.log {user_id: user._id, recurly_token_id}, "done creating paypal subscription for user" - callback(null, result.subscription) + Async.apply(RecurlyWrapper._paypal.checkAccountExists, cache), + RecurlyWrapper._paypal.createAccount, + RecurlyWrapper._paypal.createBillingInfo, + RecurlyWrapper._paypal.setAddress, + RecurlyWrapper._paypal.createSubscription, + ], (err, result) -> + if err + logger.error {err, user_id: user._id, recurly_token_id}, "error in paypal subscription creation process" + return callback(err) + if !result.subscription + err = new Error('no subscription object in result') + logger.error {err, user_id: user._id, recurly_token_id}, "error in paypal subscription creation process" + return callback(err) + logger.log {user_id: user._id, recurly_token_id}, "done creating paypal subscription for user" + callback(null, result.subscription) ) _createCreditCardSubscription: (user, subscriptionDetails, recurly_token_id, callback) -> diff --git a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee index fd8bbe25ed..e9dae2cd66 100644 --- a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee @@ -516,6 +516,16 @@ describe "RecurlyWrapper", -> expect(sub).to.equal @subscription done() + it 'should call apiRequest', (done) -> + @call (err, sub) => + @apiRequest.callCount.should.equal 1 + done() + + it 'should call _parseSubscriptionXml', (done) -> + @call (err, sub) => + @_parseSubscriptionXml.callCount.should.equal 1 + done() + describe 'when api request produces an error', -> beforeEach -> @@ -526,6 +536,16 @@ describe "RecurlyWrapper", -> expect(err).to.be.instanceof Error done() + it 'should call apiRequest', (done) -> + @call (err, sub) => + @apiRequest.callCount.should.equal 1 + done() + + it 'should not _parseSubscriptionXml', (done) -> + @call (err, sub) => + @_parseSubscriptionXml.callCount.should.equal 0 + done() + describe 'when parse xml produces an error', -> beforeEach -> @@ -539,7 +559,69 @@ describe "RecurlyWrapper", -> describe '_createPaypalSubscription', -> beforeEach -> + @checkAccountExists = sinon.stub(@RecurlyWrapper._paypal, 'checkAccountExists') + @createAccount = sinon.stub(@RecurlyWrapper._paypal, 'createAccount') + @createBillingInfo = sinon.stub(@RecurlyWrapper._paypal, 'createBillingInfo') + @setAddress = sinon.stub(@RecurlyWrapper._paypal, 'setAddress') + @createSubscription = sinon.stub(@RecurlyWrapper._paypal, 'createSubscription') + @user = + _id: 'some_id' + email: 'user@example.com' + @subscriptionDetails = + currencyCode: "EUR" + plan_code: "some_plan_code" + coupon_code: "" + isPaypal: true + address: + address1: "addr_one" + address2: "addr_two" + country: "some_country" + state: "some_state" + zip: "some_zip" + @subscription = {} + @recurly_token_id = "a-token-id" - describe 'when all goes well', -> + # set up data callbacks + user = @user + subscriptionDetails = @subscriptionDetails + recurly_token_id = @recurly_token_id - beforeEach -> + @checkAccountExists.callsArgWith(1, null, + {user, subscriptionDetails, recurly_token_id, + userExists: false, account: {accountCode: 'xx'}} + ) + + @createAccount.callsArgWith(1, null, + {user, subscriptionDetails, recurly_token_id, + userExists: false, account: {accountCode: 'xx'}} + ) + + @createBillingInfo.callsArgWith(1, null, + {user, subscriptionDetails, recurly_token_id, + userExists: false, account: {accountCode: 'xx'}, billingInfo: {token_id: 'abc'}} + ) + + @setAddress.callsArgWith(1, null, + {user, subscriptionDetails, recurly_token_id, + userExists: false, account: {accountCode: 'xx'}, billingInfo: {token_id: 'abc'}} + ) + + @createSubscription.callsArgWith(1, null, + {user, subscriptionDetails, recurly_token_id, + userExists: false, account: {accountCode: 'xx'}, billingInfo: {token_id: 'abc'}, subscription: {}} + ) + + @call = (callback) => + @RecurlyWrapper._createPaypalSubscription @user, @subscriptionDetails, @recurly_token_id, callback + + afterEach -> + @checkAccountExists.restore() + @createAccount.restore() + @createBillingInfo.restore() + @setAddress.restore() + @createSubscription.restore() + + it 'should not produce an error', (done) -> + @call (err, sub) => + expect(err).to.not.be.instanceof Error + done() From 8d32fa1e87bd6c39892cf2c8bf28946010e6cb50 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 28 Jun 2016 08:40:30 +0100 Subject: [PATCH 21/34] enable per-user containers by default --- .../coffee/ide/pdf/controllers/PdfController.coffee | 8 ++++---- .../wordcount/controllers/WordCountModalController.coffee | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index 52b243c79b..baa7398074 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -6,8 +6,8 @@ define [ ], (App, Ace, HumanReadableLogs, BibLogParser) -> App.controller "PdfController", ($scope, $http, ide, $modal, synctex, event_tracking, localStorage) -> - # enable per-user containers if querystring includes isolated=true - perUserCompile = window.location?.search?.match(/isolated=true/)? or undefined + # enable per-user containers by default + perUserCompile = true autoCompile = true # pdf.view = uncompiled | pdf | errors @@ -319,8 +319,8 @@ define [ $scope.startedFreeTrial = true App.factory "synctex", ["ide", "$http", "$q", (ide, $http, $q) -> - # enable per-user containers if querystring includes isolated=true - perUserCompile = window.location?.search?.match(/isolated=true/)? or undefined + # enable per-user containers by default + perUserCompile = true synctex = syncToPdf: (cursorPosition) -> diff --git a/services/web/public/coffee/ide/wordcount/controllers/WordCountModalController.coffee b/services/web/public/coffee/ide/wordcount/controllers/WordCountModalController.coffee index 2336de614d..5166a32ae1 100644 --- a/services/web/public/coffee/ide/wordcount/controllers/WordCountModalController.coffee +++ b/services/web/public/coffee/ide/wordcount/controllers/WordCountModalController.coffee @@ -5,7 +5,9 @@ define [ $scope.status = loading:true - perUserCompile = window.location?.search?.match(/isolated=true/)? or undefined + # enable per-user containers by default + perUserCompile = true + opts = url:"/project/#{ide.project_id}/wordcount" method:"GET" From d21eb1b07f0edbc91d6a1f6827416265ca5b9a9b Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Tue, 28 Jun 2016 09:04:19 +0100 Subject: [PATCH 22/34] Add tests --- .../Subscription/RecurlyWrapperTests.coffee | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee index e9dae2cd66..02450ea984 100644 --- a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee @@ -590,25 +590,21 @@ describe "RecurlyWrapper", -> {user, subscriptionDetails, recurly_token_id, userExists: false, account: {accountCode: 'xx'}} ) - @createAccount.callsArgWith(1, null, {user, subscriptionDetails, recurly_token_id, userExists: false, account: {accountCode: 'xx'}} ) - @createBillingInfo.callsArgWith(1, null, {user, subscriptionDetails, recurly_token_id, userExists: false, account: {accountCode: 'xx'}, billingInfo: {token_id: 'abc'}} ) - @setAddress.callsArgWith(1, null, {user, subscriptionDetails, recurly_token_id, userExists: false, account: {accountCode: 'xx'}, billingInfo: {token_id: 'abc'}} ) - @createSubscription.callsArgWith(1, null, {user, subscriptionDetails, recurly_token_id, - userExists: false, account: {accountCode: 'xx'}, billingInfo: {token_id: 'abc'}, subscription: {}} + userExists: false, account: {accountCode: 'xx'}, billingInfo: {token_id: 'abc'}, subscription: @subscription} ) @call = (callback) => @@ -625,3 +621,18 @@ describe "RecurlyWrapper", -> @call (err, sub) => expect(err).to.not.be.instanceof Error done() + + it 'should produce a subscription object', (done) -> + @call (err, sub) => + expect(sub).to.not.equal null + expect(sub).to.equal @subscription + done() + + it 'should call each of the paypal functions', (done) -> + @call (err, sub) => + @checkAccountExists.callCount.should.equal 1 + @createAccount.callCount.should.equal 1 + @createBillingInfo.callCount.should.equal 1 + @setAddress.callCount.should.equal 1 + @createSubscription.callCount.should.equal 1 + done() From 6bdfedc1b0587316ad4900a27432481e2661fd34 Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Tue, 28 Jun 2016 09:09:57 +0100 Subject: [PATCH 23/34] Test when a paypal stage produces an error --- .../Subscription/RecurlyWrapperTests.coffee | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee index 02450ea984..d7099f255c 100644 --- a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee @@ -628,7 +628,7 @@ describe "RecurlyWrapper", -> expect(sub).to.equal @subscription done() - it 'should call each of the paypal functions', (done) -> + it 'should call each of the paypal stages', (done) -> @call (err, sub) => @checkAccountExists.callCount.should.equal 1 @createAccount.callCount.should.equal 1 @@ -636,3 +636,22 @@ describe "RecurlyWrapper", -> @setAddress.callCount.should.equal 1 @createSubscription.callCount.should.equal 1 done() + + describe 'when one of the paypal stages produces an error', -> + + beforeEach -> + @createAccount.callsArgWith(1, new Error('woops')) + + it 'should produce an error', (done) -> + @call (err, sub) => + expect(err).to.be.instanceof Error + done() + + it 'should stop calling the paypal stages after the error', (done) -> + @call (err, sub) => + @checkAccountExists.callCount.should.equal 1 + @createAccount.callCount.should.equal 1 + @createBillingInfo.callCount.should.equal 0 + @setAddress.callCount.should.equal 0 + @createSubscription.callCount.should.equal 0 + done() From da960a721f12156dfea077d356a6d6d110250bac Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Tue, 28 Jun 2016 10:09:12 +0100 Subject: [PATCH 24/34] Vertical layout for LaTeX examples. --- services/web/public/stylesheets/app/wiki.less | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/services/web/public/stylesheets/app/wiki.less b/services/web/public/stylesheets/app/wiki.less index 210230989c..2bc962961f 100644 --- a/services/web/public/stylesheets/app/wiki.less +++ b/services/web/public/stylesheets/app/wiki.less @@ -39,6 +39,13 @@ } .example { + max-width: 100%; + + & > div { + display: block !important; + width: auto !important; + } + .code { pre { background-color: @gray-lightest; @@ -49,6 +56,9 @@ } } .output { + text-align: center; + padding-top: 10px; + img { width: auto !important; height: auto !important; From b8b833b753274d11011b802052d307f8de78b5e9 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Tue, 28 Jun 2016 10:15:52 +0100 Subject: [PATCH 25/34] moved wiki into module --- .../Features/Wiki/WikiController.coffee | 88 ------------------- services/web/app/coffee/router.coffee | 8 -- services/web/app/views/wiki/page.jade | 68 -------------- 3 files changed, 164 deletions(-) delete mode 100644 services/web/app/coffee/Features/Wiki/WikiController.coffee delete mode 100644 services/web/app/views/wiki/page.jade diff --git a/services/web/app/coffee/Features/Wiki/WikiController.coffee b/services/web/app/coffee/Features/Wiki/WikiController.coffee deleted file mode 100644 index e4f85a6c9f..0000000000 --- a/services/web/app/coffee/Features/Wiki/WikiController.coffee +++ /dev/null @@ -1,88 +0,0 @@ -request = require("request") -settings = require("settings-sharelatex") -logger = require("logger-sharelatex") -ErrorController = require "../Errors/ErrorController" -_ = require("underscore") -AuthenticationController = require("../Authentication/AuthenticationController") -async = require("async") -other_lngs = ["es"] - -module.exports = WikiController = - - - _checkIfLoginIsNeeded: (req, res, next)-> - if settings.apis.wiki.requireLogin - AuthenticationController.requireLogin()(req, res, next) - else - next() - - getPage: (req, res, next) -> - WikiController._checkIfLoginIsNeeded req, res, -> - - page = req.url.replace(/^\/learn/, "").replace(/^\//, "") - if page == "" - page = "Main_Page" - - logger.log page: page, "getting page from wiki" - if _.include(other_lngs, req.lng) - lngPage = "#{page}_#{req.lng}" - else - lngPage = page - jobs = - contents: (cb)-> - WikiController._getPageContent "Contents", cb - pageData: (cb)-> - WikiController._getPageContent lngPage, cb - async.parallel jobs, (error, results)-> - return next(error) if error? - {pageData, contents} = results - if pageData.content?.length > 280 - if _.include(other_lngs, req.lng) - pageData.title = pageData.title.slice(0, pageData.title.length - (req.lng.length+1) ) - - if pageData.title?.toLowerCase()?.indexOf("kb") == 0 - pageData.title = pageData.title.slice(3) - - if pageData.title?.toLowerCase()?.indexOf("errors") == 0 - pageData.title = pageData.title.slice(7) - - WikiController._renderPage(pageData, contents, res) - else - WikiController._getPageContent page, (error, pageData) -> - return next(error) if error? - WikiController._renderPage(pageData, contents, res) - - - - - _getPageContent: (page, callback = (error, data = { content: "", title: "" }) ->) -> - request { - url: "#{settings.apis.wiki.url}/learn-scripts/api.php" - qs: { - page: decodeURI(page) - action: "parse" - format: "json" - } - }, (err, response, data)-> - return callback(err) if err? - try - data = JSON.parse(data) - catch err - logger.err err:err, data:data, "error parsing data from wiki" - result = - content: data?.parse?.text?['*'] - title: data?.parse?.title - callback null, result - - - _renderPage: (page, contents, res)-> - if page.title == "Main Page" - title = "Documentation" - else - title = page.title - - res.render "wiki/page", { - page: page - contents: contents - title: title - } \ No newline at end of file diff --git a/services/web/app/coffee/router.coffee b/services/web/app/coffee/router.coffee index 7fc890ebd7..40792ed540 100644 --- a/services/web/app/coffee/router.coffee +++ b/services/web/app/coffee/router.coffee @@ -30,7 +30,6 @@ PasswordResetRouter = require("./Features/PasswordReset/PasswordResetRouter") StaticPagesRouter = require("./Features/StaticPages/StaticPagesRouter") ChatController = require("./Features/Chat/ChatController") BlogController = require("./Features/Blog/BlogController") -WikiController = require("./Features/Wiki/WikiController") Modules = require "./infrastructure/Modules" RateLimiterMiddlewear = require('./Features/Security/RateLimiterMiddlewear') RealTimeProxyRouter = require('./Features/RealTimeProxy/RealTimeProxyRouter') @@ -204,13 +203,6 @@ module.exports = class Router webRouter.get "/project/:Project_id/messages", AuthorizationMiddlewear.ensureUserCanReadProject, ChatController.getMessages webRouter.post "/project/:Project_id/messages", AuthorizationMiddlewear.ensureUserCanReadProject, ChatController.sendMessage - webRouter.get /learn(\/.*)?/, RateLimiterMiddlewear.rateLimit({ - endpointName: "wiki" - params: [] - maxRequests: 60 - timeInterval: 60 - }), WikiController.getPage - webRouter.post "/project/:Project_id/references/index", AuthorizationMiddlewear.ensureUserCanReadProject, ReferencesController.index webRouter.post "/project/:Project_id/references/indexAll", AuthorizationMiddlewear.ensureUserCanReadProject, ReferencesController.indexAll diff --git a/services/web/app/views/wiki/page.jade b/services/web/app/views/wiki/page.jade deleted file mode 100644 index 6a6bea2202..0000000000 --- a/services/web/app/views/wiki/page.jade +++ /dev/null @@ -1,68 +0,0 @@ -extends ../layout - -block content - .content.content-alt(ng-cloak) - .container.wiki - .row.template-page-header - .col-md-8(ng-cloak) - - .row - .col-xs-3.contents(ng-non-bindable) - | !{contents.content} - - .col-xs-9.page - - if(typeof(settings.algolia) != "undefined" && typeof(settings.algolia.indexes) != "undefined" && typeof(settings.algolia.indexes.wiki) != "undefined") - span(ng-controller="SearchWikiController") - .row - form.project-search.form-horizontal.col-md-9(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 help 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-3.text-right - a.btn.btn-primary(ng-click="showMissingTemplateModal()") #{translate("suggest_new_doc")} - - .row - .col-md-12(ng-cloak) - a(ng-href='{{hit.url}}',ng-repeat='hit in hits').search-result.card.card-thin - span(ng-bind-html='hit.name') - div.search-result-content(ng-show="hit.content != ''", ng-bind-html='hit.content') - - .card.row-spaced(ng-non-bindable) - .page-header - h1 #{title} - - | !{page.content} - - - - - script(type="text/ng-template", id="missingWikiPageModal") - .modal-header - button.close( - type="button" - data-dismiss="modal" - ng-click="close()" - ) × - h3 #{translate("suggest_new_doc")} - .modal-body.contact-us-modal - span(ng-show="sent == false") - label.desc - | #{translate("email")} (#{translate("optional")}) - .form-group - 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.desc - | #{translate("suggestion")} - .form-group - textarea.field.text.medium.span8.form-control(ng-model="form.message",type='text', value='', maxlength='255', tabindex='4', onkeyup='') - span(ng-show="sent") - p #{translate("request_sent_thank_you")} - .modal-footer - button.btn.btn-default(ng-click="close()") - span #{translate("dismiss")} - button.btn-success.btn(type='submit', ng-disabled="sending", ng-click="contactUs()") #{translate("contact_us")} - From e194de50cf1e6e3952c54af81955a4ac59ad877c Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Tue, 28 Jun 2016 10:17:06 +0100 Subject: [PATCH 26/34] test `_paypal.checAccountExists`. --- .../Subscription/RecurlyWrapperTests.coffee | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee index d7099f255c..4ab866b408 100644 --- a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee @@ -655,3 +655,103 @@ describe "RecurlyWrapper", -> @setAddress.callCount.should.equal 0 @createSubscription.callCount.should.equal 0 done() + + describe '_paypal.checkAccountExists', -> + + beforeEach -> + @apiRequest = sinon.stub(@RecurlyWrapper, 'apiRequest') + @_parseAccountXml = sinon.spy(@RecurlyWrapper, '_parseAccountXml') + @cache = + user: @user = {_id: 'some_id'} + recurly_token_id: @recurly_token_id = "some_token" + subscriptionDetails: @subscriptionDetails = + currencyCode: "EUR" + plan_code: "some_plan_code" + coupon_code: "" + isPaypal: true + address: + address1: "addr_one" + address2: "addr_two" + country: "some_country" + state: "some_state" + zip: "some_zip" + @call = (callback) => + @RecurlyWrapper._paypal.checkAccountExists @cache, callback + + afterEach -> + @apiRequest.restore() + @_parseAccountXml.restore() + + describe 'when the account exists', -> + + beforeEach -> + resultXml = 'abc' + @apiRequest.callsArgWith(1, null, {statusCode: 200}, resultXml) + + it 'should not produce an error', (done) -> + @call (err, result) => + expect(err).to.not.be.instanceof Error + done() + + it 'should call apiRequest', (done) -> + @call (err, result) => + @apiRequest.callCount.should.equal 1 + done() + + it 'should call _parseAccountXml', (done) -> + @call (err, result) => + @RecurlyWrapper._parseAccountXml.callCount.should.equal 1 + done() + + it 'should add the account to the cumulative result', (done) -> + @call (err, result) => + expect(result.account).to.not.equal null + expect(result.account).to.not.equal undefined + expect(result.account).to.deep.equal { + account_code: 'abc' + } + done() + + describe 'when the account does not exist', -> + + beforeEach -> + @apiRequest.callsArgWith(1, new Error('not found'), {statusCode: 404}, '') + + it 'should not produce an error', (done) -> + @call (err, result) => + expect(err).to.not.be.instanceof Error + done() + + it 'should call apiRequest', (done) -> + @call (err, result) => + @apiRequest.callCount.should.equal 1 + done() + + it 'should not call _parseAccountXml', (done) -> + @call (err, result) => + @RecurlyWrapper._parseAccountXml.callCount.should.equal 0 + done() + + it 'should not add the account to result', (done) -> + @call (err, result) => + expect(result.account).to.equal undefined + done() + + # describe '_paypal.createAccount', -> + + # beforeEach -> + + + # describe '_paypal.createBillingInfo', -> + + # beforeEach -> + + + # describe '_paypal.setAddress', -> + + # beforeEach -> + + + # describe '_paypal.createSubscription', -> + + # beforeEach -> From 6e187e3996f6ed1823397618e28a94008ea301ac Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 28 Jun 2016 10:05:34 +0100 Subject: [PATCH 27/34] added npm shrinkwrap file --- services/web/npm-shrinkwrap.json | 4482 ++++++++++++++++++++++++++++++ 1 file changed, 4482 insertions(+) create mode 100644 services/web/npm-shrinkwrap.json diff --git a/services/web/npm-shrinkwrap.json b/services/web/npm-shrinkwrap.json new file mode 100644 index 0000000000..85c99d39f0 --- /dev/null +++ b/services/web/npm-shrinkwrap.json @@ -0,0 +1,4482 @@ +{ + "name": "web-sharelatex", + "version": "0.1.4", + "dependencies": { + "archiver": { + "version": "0.9.0", + "from": "archiver@0.9.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-0.9.0.tgz", + "dependencies": { + "buffer-crc32": { + "version": "0.2.5", + "from": "buffer-crc32@>=0.2.1 <0.3.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.5.tgz" + }, + "readable-stream": { + "version": "1.0.34", + "from": "readable-stream@>=1.0.24 <1.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0" + } + } + }, + "tar-stream": { + "version": "0.3.3", + "from": "tar-stream@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-0.3.3.tgz", + "dependencies": { + "bl": { + "version": "0.6.0", + "from": "bl@>=0.6.0 <0.7.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.6.0.tgz" + }, + "end-of-stream": { + "version": "0.1.5", + "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", + "dependencies": { + "once": { + "version": "1.3.3", + "from": "once@>=1.3.0 <1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + } + } + } + } + } + }, + "zip-stream": { + "version": "0.3.7", + "from": "zip-stream@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.3.7.tgz", + "dependencies": { + "crc32-stream": { + "version": "0.2.0", + "from": "crc32-stream@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.2.0.tgz" + }, + "debug": { + "version": "1.0.4", + "from": "debug@>=1.0.2 <1.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz", + "dependencies": { + "ms": { + "version": "0.6.2", + "from": "ms@0.6.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" + } + } + }, + "deflate-crc32-stream": { + "version": "0.1.2", + "from": "deflate-crc32-stream@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/deflate-crc32-stream/-/deflate-crc32-stream-0.1.2.tgz" + } + } + }, + "lazystream": { + "version": "0.1.0", + "from": "lazystream@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz" + }, + "file-utils": { + "version": "0.1.5", + "from": "file-utils@>=0.1.5 <0.2.0", + "resolved": "https://registry.npmjs.org/file-utils/-/file-utils-0.1.5.tgz", + "dependencies": { + "lodash": { + "version": "2.1.0", + "from": "lodash@>=2.1.0 <2.2.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.1.0.tgz" + }, + "iconv-lite": { + "version": "0.2.11", + "from": "iconv-lite@>=0.2.11 <0.3.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz" + }, + "glob": { + "version": "3.2.11", + "from": "glob@>=3.2.6 <3.3.0", + "dependencies": { + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.0 <3.0.0" + }, + "minimatch": { + "version": "0.3.0", + "from": "minimatch@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "dependencies": { + "lru-cache": { + "version": "2.7.3", + "from": "lru-cache@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz" + }, + "sigmund": { + "version": "1.0.1", + "from": "sigmund@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" + } + } + } + } + }, + "minimatch": { + "version": "0.2.14", + "from": "minimatch@>=0.2.12 <0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "dependencies": { + "lru-cache": { + "version": "2.7.3", + "from": "lru-cache@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz" + }, + "sigmund": { + "version": "1.0.1", + "from": "sigmund@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" + } + } + }, + "findup-sync": { + "version": "0.1.3", + "from": "findup-sync@>=0.1.2 <0.2.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "dependencies": { + "lodash": { + "version": "2.4.2", + "from": "lodash@>=2.4.1 <2.5.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" + } + } + }, + "isbinaryfile": { + "version": "0.1.9", + "from": "isbinaryfile@>=0.1.9 <0.2.0", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-0.1.9.tgz" + } + } + }, + "lodash": { + "version": "2.4.2", + "from": "lodash@>=2.4.1 <2.5.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" + } + } + }, + "async": { + "version": "0.6.2", + "from": "async@0.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.6.2.tgz" + }, + "base64-stream": { + "version": "0.1.3", + "from": "base64-stream@>=0.1.2 <0.2.0", + "resolved": "https://registry.npmjs.org/base64-stream/-/base64-stream-0.1.3.tgz", + "dependencies": { + "readable-stream": { + "version": "2.1.4", + "from": "readable-stream@>=2.0.0 <3.0.0||>=1.1.13 <2.0.0", + "dependencies": { + "buffer-shims": { + "version": "1.0.0", + "from": "buffer-shims@>=1.0.0 <2.0.0" + }, + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0" + }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "process-nextick-args": { + "version": "1.0.7", + "from": "process-nextick-args@>=1.0.6 <1.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + } + } + } + }, + "basic-auth-connect": { + "version": "1.0.0", + "from": "basic-auth-connect@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz" + }, + "bcrypt": { + "version": "0.8.3", + "from": "bcrypt@0.8.3", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-0.8.3.tgz", + "dependencies": { + "bindings": { + "version": "1.2.1", + "from": "bindings@1.2.1", + "resolved": "http://localhost:8080/bindings/-/bindings-1.2.1.tgz" + }, + "nan": { + "version": "1.8.4", + "from": "nan@1.8.4" + } + } + }, + "body-parser": { + "version": "1.15.2", + "from": "body-parser@>=1.13.1 <2.0.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.15.2.tgz", + "dependencies": { + "bytes": { + "version": "2.4.0", + "from": "bytes@2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz" + }, + "content-type": { + "version": "1.0.2", + "from": "content-type@>=1.0.2 <1.1.0" + }, + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "dependencies": { + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1" + } + } + }, + "depd": { + "version": "1.1.0", + "from": "depd@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" + }, + "http-errors": { + "version": "1.5.0", + "from": "http-errors@>=1.5.0 <1.6.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.0.tgz", + "dependencies": { + "inherits": { + "version": "2.0.1", + "from": "inherits@2.0.1" + }, + "setprototypeof": { + "version": "1.0.1", + "from": "setprototypeof@1.0.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.1.tgz" + }, + "statuses": { + "version": "1.3.0", + "from": "statuses@>=1.3.0 <2.0.0" + } + } + }, + "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" + }, + "on-finished": { + "version": "2.3.0", + "from": "on-finished@>=2.3.0 <2.4.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "dependencies": { + "ee-first": { + "version": "1.1.1", + "from": "ee-first@1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + } + } + }, + "qs": { + "version": "6.2.0", + "from": "qs@6.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz" + }, + "raw-body": { + "version": "2.1.7", + "from": "raw-body@>=2.1.7 <2.2.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "dependencies": { + "unpipe": { + "version": "1.0.0", + "from": "unpipe@1.0.0" + } + } + }, + "type-is": { + "version": "1.6.13", + "from": "type-is@>=1.6.13 <1.7.0", + "dependencies": { + "media-typer": { + "version": "0.3.0", + "from": "media-typer@0.3.0" + }, + "mime-types": { + "version": "2.1.11", + "from": "mime-types@>=2.1.11 <2.2.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz", + "dependencies": { + "mime-db": { + "version": "1.23.0", + "from": "mime-db@>=1.23.0 <1.24.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz" + } + } + } + } + } + } + }, + "bufferedstream": { + "version": "1.6.0", + "from": "bufferedstream@1.6.0", + "resolved": "https://registry.npmjs.org/bufferedstream/-/bufferedstream-1.6.0.tgz" + }, + "connect-redis": { + "version": "2.3.0", + "from": "connect-redis@2.3.0", + "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-2.3.0.tgz", + "dependencies": { + "debug": { + "version": "1.0.4", + "from": "debug@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz", + "dependencies": { + "ms": { + "version": "0.6.2", + "from": "ms@0.6.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" + } + } + }, + "redis": { + "version": "0.12.1", + "from": "redis@>=0.12.1 <0.13.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz" + } + } + }, + "contentful": { + "version": "3.4.1", + "from": "contentful@>=3.3.14 <4.0.0", + "resolved": "https://registry.npmjs.org/contentful/-/contentful-3.4.1.tgz", + "dependencies": { + "babel-runtime": { + "version": "6.9.2", + "from": "babel-runtime@>=6.3.19 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.9.2.tgz", + "dependencies": { + "core-js": { + "version": "2.4.0", + "from": "core-js@>=2.4.0 <3.0.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.0.tgz" + }, + "regenerator-runtime": { + "version": "0.9.5", + "from": "regenerator-runtime@>=0.9.5 <0.10.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.5.tgz" + } + } + }, + "contentful-sdk-core": { + "version": "2.3.0", + "from": "contentful-sdk-core@>=2.3.0 <3.0.0", + "resolved": "https://registry.npmjs.org/contentful-sdk-core/-/contentful-sdk-core-2.3.0.tgz", + "dependencies": { + "babel-plugin-rewire": { + "version": "1.0.0-rc-4", + "from": "babel-plugin-rewire@>=1.0.0-rc-3 <2.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-rewire/-/babel-plugin-rewire-1.0.0-rc-4.tgz" + }, + "follow-redirects": { + "version": "0.0.7", + "from": "follow-redirects@0.0.7", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-0.0.7.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <3.0.0", + "dependencies": { + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1" + } + } + }, + "stream-consume": { + "version": "0.1.0", + "from": "stream-consume@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz" + } + } + }, + "qs": { + "version": "6.2.0", + "from": "qs@>=6.1.0 <7.0.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz" + }, + "babel-core": { + "version": "6.10.4", + "from": "babel-core@>=6.0.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.10.4.tgz", + "dependencies": { + "babel-code-frame": { + "version": "6.11.0", + "from": "babel-code-frame@>=6.8.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.11.0.tgz", + "dependencies": { + "chalk": { + "version": "1.1.3", + "from": "chalk@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "dependencies": { + "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" + }, + "escape-string-regexp": { + "version": "1.0.5", + "from": "escape-string-regexp@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.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", + "dependencies": { + "ansi-regex": { + "version": "2.0.0", + "from": "ansi-regex@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "from": "strip-ansi@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "dependencies": { + "ansi-regex": { + "version": "2.0.0", + "from": "ansi-regex@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + } + } + }, + "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" + } + } + }, + "esutils": { + "version": "2.0.2", + "from": "esutils@>=2.0.2 <3.0.0", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz" + }, + "js-tokens": { + "version": "2.0.0", + "from": "js-tokens@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-2.0.0.tgz" + } + } + }, + "babel-generator": { + "version": "6.11.0", + "from": "babel-generator@>=6.9.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.11.0.tgz", + "dependencies": { + "detect-indent": { + "version": "3.0.1", + "from": "detect-indent@>=3.0.1 <4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-3.0.1.tgz", + "dependencies": { + "get-stdin": { + "version": "4.0.1", + "from": "get-stdin@>=4.0.1 <5.0.0" + }, + "minimist": { + "version": "1.2.0", + "from": "minimist@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" + }, + "repeating": { + "version": "1.1.3", + "from": "repeating@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz", + "dependencies": { + "is-finite": { + "version": "1.0.1", + "from": "is-finite@>=1.0.0 <2.0.0", + "dependencies": { + "number-is-nan": { + "version": "1.0.0", + "from": "number-is-nan@>=1.0.0 <2.0.0" + } + } + } + } + } + } + } + } + }, + "babel-helpers": { + "version": "6.8.0", + "from": "babel-helpers@>=6.8.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.8.0.tgz" + }, + "babel-messages": { + "version": "6.8.0", + "from": "babel-messages@>=6.8.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.8.0.tgz" + }, + "babel-register": { + "version": "6.9.0", + "from": "babel-register@>=6.9.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.9.0.tgz", + "dependencies": { + "core-js": { + "version": "2.4.0", + "from": "core-js@>=2.4.0 <3.0.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.0.tgz" + }, + "home-or-tmp": { + "version": "1.0.0", + "from": "home-or-tmp@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-1.0.0.tgz", + "dependencies": { + "os-tmpdir": { + "version": "1.0.1", + "from": "os-tmpdir@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.1.tgz" + }, + "user-home": { + "version": "1.1.1", + "from": "user-home@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz" + } + } + }, + "mkdirp": { + "version": "0.5.1", + "from": "mkdirp@>=0.5.1 <0.6.0", + "dependencies": { + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "http://localhost:8080/minimist/-/minimist-0.0.8.tgz" + } + } + }, + "source-map-support": { + "version": "0.2.10", + "from": "source-map-support@>=0.2.10 <0.3.0", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.10.tgz", + "dependencies": { + "source-map": { + "version": "0.1.32", + "from": "source-map@0.1.32", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz", + "dependencies": { + "amdefine": { + "version": "1.0.0", + "from": "amdefine@>=0.0.4" + } + } + } + } + } + } + }, + "babel-traverse": { + "version": "6.10.4", + "from": "babel-traverse@>=6.10.4 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.10.4.tgz", + "dependencies": { + "globals": { + "version": "8.18.0", + "from": "globals@>=8.3.0 <9.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-8.18.0.tgz" + }, + "invariant": { + "version": "2.2.1", + "from": "invariant@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.1.tgz", + "dependencies": { + "loose-envify": { + "version": "1.2.0", + "from": "loose-envify@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.2.0.tgz", + "dependencies": { + "js-tokens": { + "version": "1.0.3", + "from": "js-tokens@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.3.tgz" + } + } + } + } + } + } + }, + "babylon": { + "version": "6.8.2", + "from": "babylon@>=6.7.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.8.2.tgz" + }, + "convert-source-map": { + "version": "1.2.0", + "from": "convert-source-map@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.2.0.tgz" + }, + "debug": { + "version": "2.2.0", + "from": "debug@>=2.1.1 <3.0.0", + "dependencies": { + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1" + } + } + }, + "json5": { + "version": "0.4.0", + "from": "json5@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.4.0.tgz" + }, + "minimatch": { + "version": "3.0.2", + "from": "minimatch@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz", + "dependencies": { + "brace-expansion": { + "version": "1.1.5", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz", + "dependencies": { + "balanced-match": { + "version": "0.4.1", + "from": "balanced-match@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "http://localhost:8080/concat-map/-/concat-map-0.0.1.tgz" + } + } + } + } + }, + "path-exists": { + "version": "1.0.0", + "from": "path-exists@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz" + }, + "path-is-absolute": { + "version": "1.0.0", + "from": "path-is-absolute@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz" + }, + "private": { + "version": "0.1.6", + "from": "private@>=0.1.6 <0.2.0", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.6.tgz" + }, + "shebang-regex": { + "version": "1.0.0", + "from": "shebang-regex@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz" + }, + "slash": { + "version": "1.0.0", + "from": "slash@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz" + }, + "source-map": { + "version": "0.5.6", + "from": "source-map@>=0.5.0 <0.6.0" + } + } + }, + "babel-template": { + "version": "6.9.0", + "from": "babel-template@>=6.2.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.9.0.tgz", + "dependencies": { + "babylon": { + "version": "6.8.2", + "from": "babylon@>=6.7.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.8.2.tgz" + }, + "babel-traverse": { + "version": "6.10.4", + "from": "babel-traverse@>=6.9.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.10.4.tgz", + "dependencies": { + "babel-code-frame": { + "version": "6.11.0", + "from": "babel-code-frame@>=6.8.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.11.0.tgz", + "dependencies": { + "chalk": { + "version": "1.1.3", + "from": "chalk@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "dependencies": { + "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" + }, + "escape-string-regexp": { + "version": "1.0.5", + "from": "escape-string-regexp@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.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", + "dependencies": { + "ansi-regex": { + "version": "2.0.0", + "from": "ansi-regex@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "from": "strip-ansi@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "dependencies": { + "ansi-regex": { + "version": "2.0.0", + "from": "ansi-regex@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + } + } + }, + "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" + } + } + }, + "esutils": { + "version": "2.0.2", + "from": "esutils@>=2.0.2 <3.0.0", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz" + }, + "js-tokens": { + "version": "2.0.0", + "from": "js-tokens@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-2.0.0.tgz" + } + } + }, + "babel-messages": { + "version": "6.8.0", + "from": "babel-messages@>=6.8.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.8.0.tgz" + }, + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <3.0.0", + "dependencies": { + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1" + } + } + }, + "globals": { + "version": "8.18.0", + "from": "globals@>=8.3.0 <9.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-8.18.0.tgz" + }, + "invariant": { + "version": "2.2.1", + "from": "invariant@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.1.tgz", + "dependencies": { + "loose-envify": { + "version": "1.2.0", + "from": "loose-envify@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.2.0.tgz", + "dependencies": { + "js-tokens": { + "version": "1.0.3", + "from": "js-tokens@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.3.tgz" + } + } + } + } + } + } + } + } + }, + "babel-types": { + "version": "6.11.1", + "from": "babel-types@>=6.2.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.11.1.tgz", + "dependencies": { + "babel-traverse": { + "version": "6.10.4", + "from": "babel-traverse@>=6.9.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.10.4.tgz", + "dependencies": { + "babel-code-frame": { + "version": "6.11.0", + "from": "babel-code-frame@>=6.8.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.11.0.tgz", + "dependencies": { + "chalk": { + "version": "1.1.3", + "from": "chalk@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "dependencies": { + "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" + }, + "escape-string-regexp": { + "version": "1.0.5", + "from": "escape-string-regexp@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.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", + "dependencies": { + "ansi-regex": { + "version": "2.0.0", + "from": "ansi-regex@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "from": "strip-ansi@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "dependencies": { + "ansi-regex": { + "version": "2.0.0", + "from": "ansi-regex@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + } + } + }, + "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" + } + } + }, + "js-tokens": { + "version": "2.0.0", + "from": "js-tokens@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-2.0.0.tgz" + } + } + }, + "babel-messages": { + "version": "6.8.0", + "from": "babel-messages@>=6.8.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.8.0.tgz" + }, + "babylon": { + "version": "6.8.2", + "from": "babylon@>=6.7.0 <7.0.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.8.2.tgz" + }, + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <3.0.0", + "dependencies": { + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1" + } + } + }, + "globals": { + "version": "8.18.0", + "from": "globals@>=8.3.0 <9.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-8.18.0.tgz" + }, + "invariant": { + "version": "2.2.1", + "from": "invariant@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.1.tgz", + "dependencies": { + "loose-envify": { + "version": "1.2.0", + "from": "loose-envify@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.2.0.tgz", + "dependencies": { + "js-tokens": { + "version": "1.0.3", + "from": "js-tokens@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.3.tgz" + } + } + } + } + } + } + }, + "esutils": { + "version": "2.0.2", + "from": "esutils@>=2.0.2 <3.0.0", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz" + }, + "to-fast-properties": { + "version": "1.0.2", + "from": "to-fast-properties@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.2.tgz" + } + } + } + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "from": "json-stringify-safe@>=5.0.1 <6.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + } + } + }, + "cookie": { + "version": "0.2.4", + "from": "cookie@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.2.4.tgz" + }, + "cookie-parser": { + "version": "1.3.5", + "from": "cookie-parser@1.3.5", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", + "dependencies": { + "cookie": { + "version": "0.1.3", + "from": "cookie@0.1.3", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz" + }, + "cookie-signature": { + "version": "1.0.6", + "from": "cookie-signature@1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + } + } + }, + "csurf": { + "version": "1.9.0", + "from": "csurf@>=1.8.3 <2.0.0", + "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.9.0.tgz", + "dependencies": { + "cookie": { + "version": "0.3.1", + "from": "cookie@0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" + }, + "cookie-signature": { + "version": "1.0.6", + "from": "cookie-signature@1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + }, + "csrf": { + "version": "3.0.3", + "from": "csrf@>=3.0.3 <3.1.0", + "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.3.tgz", + "dependencies": { + "base64-url": { + "version": "1.2.2", + "from": "base64-url@1.2.2", + "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.2.tgz" + }, + "rndm": { + "version": "1.2.0", + "from": "rndm@1.2.0", + "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz" + }, + "tsscmp": { + "version": "1.0.5", + "from": "tsscmp@1.0.5", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz" + }, + "uid-safe": { + "version": "2.1.1", + "from": "uid-safe@2.1.1", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.1.tgz", + "dependencies": { + "random-bytes": { + "version": "1.0.0", + "from": "random-bytes@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz" + } + } + } + } + }, + "http-errors": { + "version": "1.5.0", + "from": "http-errors@>=1.5.0 <1.6.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.0.tgz", + "dependencies": { + "inherits": { + "version": "2.0.1", + "from": "inherits@2.0.1" + }, + "setprototypeof": { + "version": "1.0.1", + "from": "setprototypeof@1.0.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.1.tgz" + }, + "statuses": { + "version": "1.3.0", + "from": "statuses@>=1.3.0 <2.0.0" + } + } + } + } + }, + "dateformat": { + "version": "1.0.4-1.2.3", + "from": "dateformat@1.0.4-1.2.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.4-1.2.3.tgz" + }, + "express": { + "version": "4.13.0", + "from": "express@4.13.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.13.0.tgz", + "dependencies": { + "accepts": { + "version": "1.2.13", + "from": "accepts@>=1.2.9 <1.3.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", + "dependencies": { + "mime-types": { + "version": "2.1.11", + "from": "mime-types@>=2.1.6 <2.2.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz", + "dependencies": { + "mime-db": { + "version": "1.23.0", + "from": "mime-db@>=1.23.0 <1.24.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz" + } + } + }, + "negotiator": { + "version": "0.5.3", + "from": "negotiator@0.5.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz" + } + } + }, + "array-flatten": { + "version": "1.1.0", + "from": "array-flatten@1.1.0", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.0.tgz" + }, + "content-disposition": { + "version": "0.5.0", + "from": "content-disposition@0.5.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.0.tgz" + }, + "content-type": { + "version": "1.0.2", + "from": "content-type@>=1.0.1 <1.1.0" + }, + "cookie": { + "version": "0.1.3", + "from": "cookie@0.1.3", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz" + }, + "cookie-signature": { + "version": "1.0.6", + "from": "cookie-signature@1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + }, + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "dependencies": { + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1" + } + } + }, + "depd": { + "version": "1.0.1", + "from": "depd@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz" + }, + "escape-html": { + "version": "1.0.2", + "from": "escape-html@1.0.2", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz" + }, + "etag": { + "version": "1.7.0", + "from": "etag@>=1.7.0 <1.8.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" + }, + "finalhandler": { + "version": "0.4.0", + "from": "finalhandler@0.4.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", + "dependencies": { + "unpipe": { + "version": "1.0.0", + "from": "unpipe@>=1.0.0 <1.1.0" + } + } + }, + "fresh": { + "version": "0.3.0", + "from": "fresh@0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" + }, + "merge-descriptors": { + "version": "1.0.0", + "from": "merge-descriptors@1.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.0.tgz" + }, + "methods": { + "version": "1.1.2", + "from": "methods@>=1.1.1 <1.2.0", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + }, + "on-finished": { + "version": "2.3.0", + "from": "on-finished@>=2.3.0 <2.4.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "dependencies": { + "ee-first": { + "version": "1.1.1", + "from": "ee-first@1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + } + } + }, + "parseurl": { + "version": "1.3.1", + "from": "parseurl@>=1.3.0 <1.4.0", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" + }, + "path-to-regexp": { + "version": "0.1.6", + "from": "path-to-regexp@0.1.6", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.6.tgz" + }, + "proxy-addr": { + "version": "1.0.10", + "from": "proxy-addr@>=1.0.8 <1.1.0", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.10.tgz", + "dependencies": { + "forwarded": { + "version": "0.1.0", + "from": "forwarded@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" + }, + "ipaddr.js": { + "version": "1.0.5", + "from": "ipaddr.js@1.0.5", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.0.5.tgz" + } + } + }, + "qs": { + "version": "2.4.2", + "from": "qs@2.4.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.4.2.tgz" + }, + "range-parser": { + "version": "1.0.3", + "from": "range-parser@>=1.0.2 <1.1.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz" + }, + "send": { + "version": "0.13.0", + "from": "send@0.13.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.13.0.tgz", + "dependencies": { + "destroy": { + "version": "1.0.3", + "from": "destroy@1.0.3", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz" + }, + "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", + "dependencies": { + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.0 <3.0.0" + } + } + }, + "mime": { + "version": "1.3.4", + "from": "mime@1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1" + }, + "statuses": { + "version": "1.2.1", + "from": "statuses@>=1.2.1 <1.3.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz" + } + } + }, + "serve-static": { + "version": "1.10.3", + "from": "serve-static@>=1.10.0 <1.11.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", + "dependencies": { + "escape-html": { + "version": "1.0.3", + "from": "escape-html@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + }, + "send": { + "version": "0.13.2", + "from": "send@0.13.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", + "dependencies": { + "depd": { + "version": "1.1.0", + "from": "depd@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" + }, + "destroy": { + "version": "1.0.4", + "from": "destroy@>=1.0.4 <1.1.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + }, + "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", + "dependencies": { + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0" + } + } + }, + "mime": { + "version": "1.3.4", + "from": "mime@1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1" + }, + "statuses": { + "version": "1.2.1", + "from": "statuses@>=1.2.1 <1.3.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz" + } + } + } + } + }, + "type-is": { + "version": "1.6.13", + "from": "type-is@>=1.6.3 <1.7.0", + "dependencies": { + "media-typer": { + "version": "0.3.0", + "from": "media-typer@0.3.0" + }, + "mime-types": { + "version": "2.1.11", + "from": "mime-types@>=2.1.6 <2.2.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz", + "dependencies": { + "mime-db": { + "version": "1.23.0", + "from": "mime-db@>=1.23.0 <1.24.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz" + } + } + } + } + }, + "vary": { + "version": "1.0.1", + "from": "vary@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz" + }, + "utils-merge": { + "version": "1.0.0", + "from": "utils-merge@1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" + } + } + }, + "express-session": { + "version": "1.11.3", + "from": "express-session@1.11.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", + "dependencies": { + "cookie": { + "version": "0.1.3", + "from": "cookie@0.1.3", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz" + }, + "cookie-signature": { + "version": "1.0.6", + "from": "cookie-signature@1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + }, + "crc": { + "version": "3.3.0", + "from": "crc@3.3.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz" + }, + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "dependencies": { + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1" + } + } + }, + "depd": { + "version": "1.0.1", + "from": "depd@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz" + }, + "on-headers": { + "version": "1.0.1", + "from": "on-headers@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" + }, + "parseurl": { + "version": "1.3.1", + "from": "parseurl@>=1.3.0 <1.4.0", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" + }, + "uid-safe": { + "version": "2.0.0", + "from": "uid-safe@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", + "dependencies": { + "base64-url": { + "version": "1.2.1", + "from": "base64-url@1.2.1", + "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz" + } + } + }, + "utils-merge": { + "version": "1.0.0", + "from": "utils-merge@1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" + } + } + }, + "grunt": { + "version": "0.4.5", + "from": "grunt@>=0.4.5 <0.5.0", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz", + "dependencies": { + "async": { + "version": "0.1.22", + "from": "async@>=0.1.22 <0.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz" + }, + "coffee-script": { + "version": "1.3.3", + "from": "coffee-script@>=1.3.3 <1.4.0", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz" + }, + "colors": { + "version": "0.6.2", + "from": "colors@>=0.6.2 <0.7.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz" + }, + "dateformat": { + "version": "1.0.2-1.2.3", + "from": "dateformat@1.0.2-1.2.3" + }, + "eventemitter2": { + "version": "0.4.14", + "from": "eventemitter2@>=0.4.13 <0.5.0", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz" + }, + "findup-sync": { + "version": "0.1.3", + "from": "findup-sync@>=0.1.2 <0.2.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "dependencies": { + "glob": { + "version": "3.2.11", + "from": "glob@>=3.2.9 <3.3.0", + "dependencies": { + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.0 <3.0.0" + }, + "minimatch": { + "version": "0.3.0", + "from": "minimatch@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "dependencies": { + "lru-cache": { + "version": "2.7.3", + "from": "lru-cache@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz" + }, + "sigmund": { + "version": "1.0.1", + "from": "sigmund@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" + } + } + } + } + }, + "lodash": { + "version": "2.4.2", + "from": "lodash@>=2.4.1 <2.5.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" + } + } + }, + "glob": { + "version": "3.1.21", + "from": "glob@>=3.1.21 <3.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "dependencies": { + "graceful-fs": { + "version": "1.2.3", + "from": "graceful-fs@>=1.2.0 <1.3.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz" + }, + "inherits": { + "version": "1.0.2", + "from": "inherits@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz" + } + } + }, + "hooker": { + "version": "0.2.3", + "from": "hooker@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz" + }, + "iconv-lite": { + "version": "0.2.11", + "from": "iconv-lite@>=0.2.11 <0.3.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz" + }, + "minimatch": { + "version": "0.2.14", + "from": "minimatch@>=0.2.12 <0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "dependencies": { + "lru-cache": { + "version": "2.7.3", + "from": "lru-cache@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz" + }, + "sigmund": { + "version": "1.0.1", + "from": "sigmund@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" + } + } + }, + "nopt": { + "version": "1.0.10", + "from": "nopt@>=1.0.10 <1.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "dependencies": { + "abbrev": { + "version": "1.0.9", + "from": "abbrev@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz" + } + } + }, + "rimraf": { + "version": "2.2.8", + "from": "rimraf@>=2.2.8 <2.3.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" + }, + "lodash": { + "version": "0.9.2", + "from": "lodash@>=0.9.2 <0.10.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz" + }, + "underscore.string": { + "version": "2.2.1", + "from": "underscore.string@>=2.2.1 <2.3.0", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz" + }, + "which": { + "version": "1.0.9", + "from": "which@>=1.0.5 <1.1.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz" + }, + "js-yaml": { + "version": "2.0.5", + "from": "js-yaml@>=2.0.5 <2.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz", + "dependencies": { + "argparse": { + "version": "0.1.16", + "from": "argparse@>=0.1.11 <0.2.0", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz", + "dependencies": { + "underscore": { + "version": "1.7.0", + "from": "underscore@>=1.7.0 <1.8.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz" + }, + "underscore.string": { + "version": "2.4.0", + "from": "underscore.string@>=2.4.0 <2.5.0", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz" + } + } + }, + "esprima": { + "version": "1.0.4", + "from": "esprima@>=1.0.2 <1.1.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz" + } + } + }, + "exit": { + "version": "0.1.2", + "from": "exit@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" + }, + "getobject": { + "version": "0.1.0", + "from": "getobject@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz" + }, + "grunt-legacy-util": { + "version": "0.2.0", + "from": "grunt-legacy-util@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz" + }, + "grunt-legacy-log": { + "version": "0.1.3", + "from": "grunt-legacy-log@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz", + "dependencies": { + "grunt-legacy-log-utils": { + "version": "0.1.1", + "from": "grunt-legacy-log-utils@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-0.1.1.tgz" + }, + "lodash": { + "version": "2.4.2", + "from": "lodash@>=2.4.1 <2.5.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" + }, + "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" + } + } + } + } + }, + "heapdump": { + "version": "0.3.7", + "from": "heapdump@>=0.3.7 <0.4.0", + "resolved": "https://registry.npmjs.org/heapdump/-/heapdump-0.3.7.tgz" + }, + "http-proxy": { + "version": "1.14.0", + "from": "http-proxy@>=1.8.1 <2.0.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.14.0.tgz", + "dependencies": { + "eventemitter3": { + "version": "1.2.0", + "from": "eventemitter3@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz" + }, + "requires-port": { + "version": "1.0.0", + "from": "requires-port@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" + } + } + }, + "jade": { + "version": "1.3.1", + "from": "jade@>=1.3.1 <1.4.0", + "resolved": "https://registry.npmjs.org/jade/-/jade-1.3.1.tgz", + "dependencies": { + "commander": { + "version": "2.1.0", + "from": "commander@2.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz" + }, + "mkdirp": { + "version": "0.3.5", + "from": "mkdirp@>=0.3.5 <0.4.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" + }, + "transformers": { + "version": "2.1.0", + "from": "transformers@2.1.0", + "resolved": "https://registry.npmjs.org/transformers/-/transformers-2.1.0.tgz", + "dependencies": { + "promise": { + "version": "2.0.0", + "from": "promise@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-2.0.0.tgz", + "dependencies": { + "is-promise": { + "version": "1.0.1", + "from": "is-promise@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz" + } + } + }, + "css": { + "version": "1.0.8", + "from": "css@>=1.0.8 <1.1.0", + "resolved": "https://registry.npmjs.org/css/-/css-1.0.8.tgz", + "dependencies": { + "css-parse": { + "version": "1.0.4", + "from": "css-parse@1.0.4", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz" + }, + "css-stringify": { + "version": "1.0.5", + "from": "css-stringify@1.0.5", + "resolved": "https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz" + } + } + }, + "uglify-js": { + "version": "2.2.5", + "from": "uglify-js@>=2.2.5 <2.3.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", + "dependencies": { + "source-map": { + "version": "0.1.43", + "from": "source-map@>=0.1.7 <0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "dependencies": { + "amdefine": { + "version": "1.0.0", + "from": "amdefine@>=0.0.4" + } + } + }, + "optimist": { + "version": "0.3.7", + "from": "optimist@>=0.3.5 <0.4.0", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "from": "wordwrap@>=0.0.2 <0.1.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz" + } + } + } + } + } + } + }, + "character-parser": { + "version": "1.2.0", + "from": "character-parser@1.2.0", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-1.2.0.tgz" + }, + "monocle": { + "version": "1.1.51", + "from": "monocle@1.1.51", + "resolved": "https://registry.npmjs.org/monocle/-/monocle-1.1.51.tgz", + "dependencies": { + "readdirp": { + "version": "0.2.5", + "from": "readdirp@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-0.2.5.tgz", + "dependencies": { + "minimatch": { + "version": "3.0.2", + "from": "minimatch@>=0.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz", + "dependencies": { + "brace-expansion": { + "version": "1.1.5", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz", + "dependencies": { + "balanced-match": { + "version": "0.4.1", + "from": "balanced-match@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "http://localhost:8080/concat-map/-/concat-map-0.0.1.tgz" + } + } + } + } + } + } + } + } + }, + "with": { + "version": "3.0.1", + "from": "with@>=3.0.0 <3.1.0", + "resolved": "https://registry.npmjs.org/with/-/with-3.0.1.tgz", + "dependencies": { + "uglify-js": { + "version": "2.4.24", + "from": "uglify-js@>=2.4.12 <2.5.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz", + "dependencies": { + "async": { + "version": "0.2.10", + "from": "async@>=0.2.6 <0.3.0" + }, + "source-map": { + "version": "0.1.34", + "from": "source-map@0.1.34", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz", + "dependencies": { + "amdefine": { + "version": "1.0.0", + "from": "amdefine@>=0.0.4" + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "from": "uglify-to-browserify@>=1.0.0 <1.1.0" + }, + "yargs": { + "version": "3.5.4", + "from": "yargs@>=3.5.4 <3.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz", + "dependencies": { + "camelcase": { + "version": "1.2.1", + "from": "camelcase@>=1.0.2 <2.0.0" + }, + "decamelize": { + "version": "1.2.0", + "from": "decamelize@>=1.0.0 <2.0.0" + }, + "window-size": { + "version": "0.1.0", + "from": "window-size@0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz" + }, + "wordwrap": { + "version": "0.0.2", + "from": "wordwrap@0.0.2" + } + } + } + } + } + } + }, + "constantinople": { + "version": "2.0.1", + "from": "constantinople@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-2.0.1.tgz", + "dependencies": { + "uglify-js": { + "version": "2.4.24", + "from": "uglify-js@>=2.4.12 <2.5.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz", + "dependencies": { + "async": { + "version": "0.2.10", + "from": "async@>=0.2.6 <0.3.0" + }, + "source-map": { + "version": "0.1.34", + "from": "source-map@0.1.34", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz", + "dependencies": { + "amdefine": { + "version": "1.0.0", + "from": "amdefine@>=0.0.4" + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "from": "uglify-to-browserify@>=1.0.0 <1.1.0" + }, + "yargs": { + "version": "3.5.4", + "from": "yargs@>=3.5.4 <3.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz", + "dependencies": { + "camelcase": { + "version": "1.2.1", + "from": "camelcase@>=1.0.2 <2.0.0" + }, + "decamelize": { + "version": "1.2.0", + "from": "decamelize@>=1.0.0 <2.0.0" + }, + "window-size": { + "version": "0.1.0", + "from": "window-size@0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz" + }, + "wordwrap": { + "version": "0.0.2", + "from": "wordwrap@0.0.2" + } + } + } + } + } + } + } + } + }, + "ldapjs": { + "version": "1.0.0", + "from": "ldapjs@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-1.0.0.tgz", + "dependencies": { + "asn1": { + "version": "0.2.3", + "from": "asn1@0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz" + }, + "assert-plus": { + "version": "0.1.5", + "from": "assert-plus@0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" + }, + "bunyan": { + "version": "1.5.1", + "from": "bunyan@1.5.1", + "resolved": "http://localhost:8080/bunyan/-/bunyan-1.5.1.tgz", + "dependencies": { + "mv": { + "version": "2.1.1", + "from": "mv@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "dependencies": { + "mkdirp": { + "version": "0.5.1", + "from": "mkdirp@>=0.5.1 <0.6.0", + "dependencies": { + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "http://localhost:8080/minimist/-/minimist-0.0.8.tgz" + } + } + }, + "ncp": { + "version": "2.0.0", + "from": "ncp@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz" + }, + "rimraf": { + "version": "2.4.5", + "from": "rimraf@>=2.4.0 <2.5.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "dependencies": { + "glob": { + "version": "6.0.4", + "from": "glob@>=6.0.1 <7.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "dependencies": { + "inflight": { + "version": "1.0.5", + "from": "inflight@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + } + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.0 <3.0.0" + }, + "minimatch": { + "version": "3.0.2", + "from": "minimatch@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz", + "dependencies": { + "brace-expansion": { + "version": "1.1.5", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz", + "dependencies": { + "balanced-match": { + "version": "0.4.1", + "from": "balanced-match@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "http://localhost:8080/concat-map/-/concat-map-0.0.1.tgz" + } + } + } + } + }, + "path-is-absolute": { + "version": "1.0.0", + "from": "path-is-absolute@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz" + } + } + } + } + } + } + }, + "safe-json-stringify": { + "version": "1.0.3", + "from": "safe-json-stringify@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.0.3.tgz" + } + } + }, + "dashdash": { + "version": "1.10.1", + "from": "dashdash@1.10.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.10.1.tgz" + }, + "backoff": { + "version": "2.4.1", + "from": "backoff@2.4.1", + "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.4.1.tgz", + "dependencies": { + "precond": { + "version": "0.2.3", + "from": "precond@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz" + } + } + }, + "ldap-filter": { + "version": "0.2.2", + "from": "ldap-filter@0.2.2", + "resolved": "https://registry.npmjs.org/ldap-filter/-/ldap-filter-0.2.2.tgz" + }, + "once": { + "version": "1.3.2", + "from": "once@1.3.2", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.2.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + } + }, + "vasync": { + "version": "1.6.3", + "from": "vasync@1.6.3", + "resolved": "https://registry.npmjs.org/vasync/-/vasync-1.6.3.tgz" + }, + "verror": { + "version": "1.6.0", + "from": "verror@1.6.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.6.0.tgz", + "dependencies": { + "extsprintf": { + "version": "1.2.0", + "from": "extsprintf@1.2.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.2.0.tgz" + } + } + }, + "dtrace-provider": { + "version": "0.6.0", + "from": "dtrace-provider@0.6.0", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.6.0.tgz", + "dependencies": { + "nan": { + "version": "2.3.5", + "from": "nan@>=2.0.8 <3.0.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.3.5.tgz" + } + } + } + } + }, + "lodash": { + "version": "4.13.1", + "from": "lodash@>=4.13.1 <5.0.0" + }, + "logger-sharelatex": { + "version": "1.3.1", + "from": "git+https://github.com/sharelatex/logger-sharelatex.git#v1.3.1", + "resolved": "git+https://github.com/sharelatex/logger-sharelatex.git#bf413ec621a000cf0e08c939de38d5e24541a08c", + "dependencies": { + "bunyan": { + "version": "1.5.1", + "from": "bunyan@1.5.1", + "resolved": "http://localhost:8080/bunyan/-/bunyan-1.5.1.tgz", + "dependencies": { + "dtrace-provider": { + "version": "0.6.0", + "from": "dtrace-provider@0.6.0", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.6.0.tgz", + "dependencies": { + "nan": { + "version": "2.3.5", + "from": "nan@>=2.0.8 <3.0.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.3.5.tgz" + } + } + }, + "mv": { + "version": "2.1.1", + "from": "mv@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "dependencies": { + "mkdirp": { + "version": "0.5.1", + "from": "mkdirp@>=0.5.1 <0.6.0", + "dependencies": { + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "http://localhost:8080/minimist/-/minimist-0.0.8.tgz" + } + } + }, + "ncp": { + "version": "2.0.0", + "from": "ncp@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz" + }, + "rimraf": { + "version": "2.4.5", + "from": "rimraf@>=2.4.0 <2.5.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "dependencies": { + "glob": { + "version": "6.0.4", + "from": "glob@>=6.0.1 <7.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "dependencies": { + "inflight": { + "version": "1.0.5", + "from": "inflight@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + } + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.0 <3.0.0" + }, + "minimatch": { + "version": "3.0.2", + "from": "minimatch@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz", + "dependencies": { + "brace-expansion": { + "version": "1.1.5", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz", + "dependencies": { + "balanced-match": { + "version": "0.4.1", + "from": "balanced-match@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "http://localhost:8080/concat-map/-/concat-map-0.0.1.tgz" + } + } + } + } + }, + "once": { + "version": "1.3.3", + "from": "once@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + } + }, + "path-is-absolute": { + "version": "1.0.0", + "from": "path-is-absolute@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz" + } + } + } + } + } + } + }, + "safe-json-stringify": { + "version": "1.0.3", + "from": "safe-json-stringify@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.0.3.tgz" + } + } + }, + "coffee-script": { + "version": "1.4.0", + "from": "coffee-script@1.4.0", + "resolved": "http://localhost:8080/coffee-script/-/coffee-script-1.4.0.tgz" + }, + "raven": { + "version": "0.8.1", + "from": "raven@>=0.8.0 <0.9.0", + "resolved": "https://registry.npmjs.org/raven/-/raven-0.8.1.tgz", + "dependencies": { + "cookie": { + "version": "0.1.0", + "from": "cookie@0.1.0", + "resolved": "http://localhost:8080/cookie/-/cookie-0.1.0.tgz" + }, + "lsmod": { + "version": "0.0.3", + "from": "lsmod@>=0.0.3 <0.1.0", + "resolved": "https://registry.npmjs.org/lsmod/-/lsmod-0.0.3.tgz" + }, + "stack-trace": { + "version": "0.0.7", + "from": "stack-trace@0.0.7", + "resolved": "http://localhost:8080/stack-trace/-/stack-trace-0.0.7.tgz" + } + } + } + } + }, + "lynx": { + "version": "0.1.1", + "from": "lynx@0.1.1", + "resolved": "https://registry.npmjs.org/lynx/-/lynx-0.1.1.tgz", + "dependencies": { + "mersenne": { + "version": "0.0.3", + "from": "mersenne@>=0.0.3 <0.1.0", + "resolved": "https://registry.npmjs.org/mersenne/-/mersenne-0.0.3.tgz" + }, + "statsd-parser": { + "version": "0.0.4", + "from": "statsd-parser@>=0.0.4 <0.1.0", + "resolved": "https://registry.npmjs.org/statsd-parser/-/statsd-parser-0.0.4.tgz" + } + } + }, + "marked": { + "version": "0.3.5", + "from": "marked@>=0.3.5 <0.4.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.5.tgz" + }, + "method-override": { + "version": "2.3.6", + "from": "method-override@>=2.3.3 <3.0.0", + "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.6.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "dependencies": { + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1" + } + } + }, + "methods": { + "version": "1.1.2", + "from": "methods@>=1.1.2 <1.2.0", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + }, + "parseurl": { + "version": "1.3.1", + "from": "parseurl@>=1.3.1 <1.4.0", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" + }, + "vary": { + "version": "1.1.0", + "from": "vary@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.0.tgz" + } + } + }, + "metrics-sharelatex": { + "version": "1.3.0", + "from": "git+https://github.com/sharelatex/metrics-sharelatex.git#v1.3.0", + "resolved": "git+https://github.com/sharelatex/metrics-sharelatex.git#080c4aeb696edcd5d6d86f202f2c528f0661d7a6", + "dependencies": { + "coffee-script": { + "version": "1.6.0", + "from": "coffee-script@1.6.0", + "resolved": "http://localhost:8080/coffee-script/-/coffee-script-1.6.0.tgz" + } + } + }, + "mimelib": { + "version": "0.2.14", + "from": "mimelib@0.2.14", + "resolved": "https://registry.npmjs.org/mimelib/-/mimelib-0.2.14.tgz", + "dependencies": { + "encoding": { + "version": "0.1.12", + "from": "encoding@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "dependencies": { + "iconv-lite": { + "version": "0.4.13", + "from": "iconv-lite@>=0.4.13 <0.5.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz" + } + } + }, + "addressparser": { + "version": "0.2.1", + "from": "addressparser@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-0.2.1.tgz" + } + } + }, + "mocha": { + "version": "1.17.1", + "from": "mocha@1.17.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-1.17.1.tgz", + "dependencies": { + "commander": { + "version": "2.0.0", + "from": "commander@2.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.0.0.tgz" + }, + "growl": { + "version": "1.7.0", + "from": "growl@>=1.7.0 <1.8.0", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.7.0.tgz" + }, + "jade": { + "version": "0.26.3", + "from": "jade@0.26.3", + "dependencies": { + "commander": { + "version": "0.6.1", + "from": "commander@0.6.1" + }, + "mkdirp": { + "version": "0.3.0", + "from": "mkdirp@0.3.0" + } + } + }, + "diff": { + "version": "1.0.7", + "from": "diff@1.0.7", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.7.tgz" + }, + "debug": { + "version": "2.2.0", + "from": "debug@*", + "dependencies": { + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1" + } + } + }, + "mkdirp": { + "version": "0.3.5", + "from": "mkdirp@0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" + }, + "glob": { + "version": "3.2.3", + "from": "glob@3.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", + "dependencies": { + "minimatch": { + "version": "0.2.14", + "from": "minimatch@>=0.2.11 <0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "dependencies": { + "lru-cache": { + "version": "2.7.3", + "from": "lru-cache@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz" + }, + "sigmund": { + "version": "1.0.1", + "from": "sigmund@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" + } + } + }, + "graceful-fs": { + "version": "2.0.3", + "from": "graceful-fs@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.0 <3.0.0" + } + } + } + } + }, + "mongojs": { + "version": "0.18.2", + "from": "mongojs@0.18.2", + "dependencies": { + "thunky": { + "version": "0.1.0", + "from": "thunky@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-0.1.0.tgz" + }, + "readable-stream": { + "version": "1.1.14", + "from": "readable-stream@>=1.1.9 <1.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0" + } + } + }, + "mongodb": { + "version": "1.4.32", + "from": "mongodb@1.4.32", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-1.4.32.tgz", + "dependencies": { + "bson": { + "version": "0.2.22", + "from": "bson@>=0.2.0 <0.3.0", + "dependencies": { + "nan": { + "version": "1.8.4", + "from": "nan@>=1.8.0 <1.9.0" + } + } + }, + "kerberos": { + "version": "0.0.9", + "from": "kerberos@0.0.9", + "resolved": "https://registry.npmjs.org/kerberos/-/kerberos-0.0.9.tgz", + "dependencies": { + "nan": { + "version": "1.6.2", + "from": "nan@1.6.2" + } + } + }, + "readable-stream": { + "version": "2.1.4", + "from": "readable-stream@latest", + "dependencies": { + "buffer-shims": { + "version": "1.0.0", + "from": "buffer-shims@>=1.0.0 <2.0.0" + }, + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0" + }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "process-nextick-args": { + "version": "1.0.7", + "from": "process-nextick-args@>=1.0.6 <1.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + } + } + } + } + } + }, + "mongoose": { + "version": "4.1.0", + "from": "mongoose@4.1.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-4.1.0.tgz", + "dependencies": { + "async": { + "version": "0.9.0", + "from": "async@0.9.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.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", + "dependencies": { + "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", + "dependencies": { + "bindings": { + "version": "1.2.1", + "from": "bindings@>=1.2.1 <2.0.0", + "resolved": "http://localhost:8080/bindings/-/bindings-1.2.1.tgz" + }, + "nan": { + "version": "2.0.9", + "from": "nan@>=2.0.9 <2.1.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.0.9.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" + }, + "kareem": { + "version": "1.0.1", + "from": "kareem@1.0.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-1.0.1.tgz" + }, + "mongodb": { + "version": "2.0.34", + "from": "mongodb@2.0.34", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.0.34.tgz", + "dependencies": { + "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" + }, + "kerberos": { + "version": "0.0.21", + "from": "kerberos@>=0.0.0 <0.1.0", + "resolved": "https://registry.npmjs.org/kerberos/-/kerberos-0.0.21.tgz", + "dependencies": { + "nan": { + "version": "2.3.5", + "from": "nan@>=2.3.0 <2.4.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.3.5.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", + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0" + } + } + } + } + }, + "mpath": { + "version": "0.1.1", + "from": "mpath@0.1.1", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.1.1.tgz" + }, + "mpromise": { + "version": "0.5.4", + "from": "mpromise@0.5.4", + "resolved": "https://registry.npmjs.org/mpromise/-/mpromise-0.5.4.tgz" + }, + "mquery": { + "version": "1.6.1", + "from": "mquery@1.6.1", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-1.6.1.tgz", + "dependencies": { + "bluebird": { + "version": "2.9.26", + "from": "bluebird@2.9.26", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.9.26.tgz" + }, + "debug": { + "version": "2.2.0", + "from": "debug@2.2.0", + "dependencies": { + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1" + } + } + } + } + }, + "ms": { + "version": "0.1.0", + "from": "ms@0.1.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.1.0.tgz" + }, + "muri": { + "version": "1.0.0", + "from": "muri@1.0.0", + "resolved": "https://registry.npmjs.org/muri/-/muri-1.0.0.tgz" + }, + "regexp-clone": { + "version": "0.0.1", + "from": "regexp-clone@0.0.1", + "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz" + }, + "sliced": { + "version": "0.0.5", + "from": "sliced@0.0.5", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz" + } + } + }, + "multer": { + "version": "0.1.8", + "from": "multer@>=0.1.8 <0.2.0", + "resolved": "https://registry.npmjs.org/multer/-/multer-0.1.8.tgz", + "dependencies": { + "busboy": { + "version": "0.2.13", + "from": "busboy@>=0.2.9 <0.3.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.13.tgz", + "dependencies": { + "dicer": { + "version": "0.2.5", + "from": "dicer@0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "dependencies": { + "streamsearch": { + "version": "0.1.2", + "from": "streamsearch@0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz" + } + } + }, + "readable-stream": { + "version": "1.1.14", + "from": "readable-stream@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0" + } + } + } + } + }, + "mkdirp": { + "version": "0.3.5", + "from": "mkdirp@>=0.3.5 <0.4.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" + }, + "qs": { + "version": "1.2.2", + "from": "qs@>=1.2.2 <1.3.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz" + }, + "type-is": { + "version": "1.5.7", + "from": "type-is@>=1.5.2 <1.6.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.5.7.tgz", + "dependencies": { + "media-typer": { + "version": "0.3.0", + "from": "media-typer@0.3.0" + }, + "mime-types": { + "version": "2.0.14", + "from": "mime-types@>=2.0.9 <2.1.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz", + "dependencies": { + "mime-db": { + "version": "1.12.0", + "from": "mime-db@>=1.12.0 <1.13.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz" + } + } + } + } + } + } + }, + "node-uuid": { + "version": "1.4.1", + "from": "node-uuid@1.4.1", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.1.tgz" + }, + "nodemailer": { + "version": "2.1.0", + "from": "nodemailer@2.1.0", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.1.0.tgz", + "dependencies": { + "libmime": { + "version": "2.0.0", + "from": "libmime@2.0.0", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-2.0.0.tgz", + "dependencies": { + "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" + }, + "libbase64": { + "version": "0.1.0", + "from": "libbase64@0.1.0", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz" + }, + "libqp": { + "version": "1.1.0", + "from": "libqp@1.1.0", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz" + } + } + }, + "mailcomposer": { + "version": "3.3.2", + "from": "mailcomposer@3.3.2", + "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-3.3.2.tgz", + "dependencies": { + "buildmail": { + "version": "3.3.2", + "from": "buildmail@3.3.2", + "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-3.3.2.tgz", + "dependencies": { + "addressparser": { + "version": "1.0.0", + "from": "addressparser@1.0.0", + "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.0.tgz" + }, + "libbase64": { + "version": "0.1.0", + "from": "libbase64@0.1.0", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz" + }, + "libqp": { + "version": "1.1.0", + "from": "libqp@1.1.0", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz" + }, + "nodemailer-fetch": { + "version": "1.2.1", + "from": "nodemailer-fetch@1.2.1", + "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.2.1.tgz" + } + } + } + } + }, + "nodemailer-direct-transport": { + "version": "2.0.1", + "from": "nodemailer-direct-transport@2.0.1", + "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-2.0.1.tgz", + "dependencies": { + "smtp-connection": { + "version": "2.0.1", + "from": "smtp-connection@2.0.1", + "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.0.1.tgz" + } + } + }, + "nodemailer-shared": { + "version": "1.0.3", + "from": "nodemailer-shared@1.0.3", + "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.0.3.tgz", + "dependencies": { + "nodemailer-fetch": { + "version": "1.2.1", + "from": "nodemailer-fetch@1.2.1", + "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.2.1.tgz" + } + } + }, + "nodemailer-smtp-pool": { + "version": "2.1.0", + "from": "nodemailer-smtp-pool@2.1.0", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.1.0.tgz", + "dependencies": { + "clone": { + "version": "1.0.2", + "from": "clone@1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz" + }, + "nodemailer-wellknown": { + "version": "0.1.7", + "from": "nodemailer-wellknown@0.1.7", + "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.7.tgz" + }, + "smtp-connection": { + "version": "2.0.1", + "from": "smtp-connection@2.0.1", + "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.0.1.tgz" + } + } + }, + "nodemailer-smtp-transport": { + "version": "2.0.1", + "from": "nodemailer-smtp-transport@2.0.1", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.0.1.tgz", + "dependencies": { + "clone": { + "version": "1.0.2", + "from": "clone@1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz" + }, + "nodemailer-wellknown": { + "version": "0.1.7", + "from": "nodemailer-wellknown@0.1.7", + "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.7.tgz" + }, + "smtp-connection": { + "version": "2.0.1", + "from": "smtp-connection@2.0.1", + "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.0.1.tgz" + } + } + } + } + }, + "nodemailer-sendgrid-transport": { + "version": "0.2.0", + "from": "nodemailer-sendgrid-transport@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/nodemailer-sendgrid-transport/-/nodemailer-sendgrid-transport-0.2.0.tgz", + "dependencies": { + "sendgrid": { + "version": "1.9.2", + "from": "sendgrid@>=1.8.0 <2.0.0", + "resolved": "https://registry.npmjs.org/sendgrid/-/sendgrid-1.9.2.tgz", + "dependencies": { + "mime": { + "version": "1.3.4", + "from": "mime@>=1.2.9 <2.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" + }, + "lodash": { + "version": "3.10.1", + "from": "lodash@>=3.0.1 <4.0.0||>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz" + }, + "smtpapi": { + "version": "1.2.0", + "from": "smtpapi@>=1.2.0 <2.0.0", + "resolved": "https://registry.npmjs.org/smtpapi/-/smtpapi-1.2.0.tgz" + } + } + } + } + }, + "nodemailer-ses-transport": { + "version": "1.4.0", + "from": "nodemailer-ses-transport@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/nodemailer-ses-transport/-/nodemailer-ses-transport-1.4.0.tgz", + "dependencies": { + "aws-sdk": { + "version": "2.4.2", + "from": "aws-sdk@>=2.4.2 <3.0.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.4.2.tgz", + "dependencies": { + "sax": { + "version": "1.1.5", + "from": "sax@1.1.5", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.5.tgz" + }, + "xml2js": { + "version": "0.4.15", + "from": "xml2js@0.4.15", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.15.tgz" + }, + "xmlbuilder": { + "version": "2.6.2", + "from": "xmlbuilder@2.6.2", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.6.2.tgz", + "dependencies": { + "lodash": { + "version": "3.5.0", + "from": "lodash@>=3.5.0 <3.6.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.5.0.tgz" + } + } + }, + "jmespath": { + "version": "0.15.0", + "from": "jmespath@0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz" + } + } + } + } + }, + "optimist": { + "version": "0.6.1", + "from": "optimist@0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "from": "wordwrap@>=0.0.2 <0.1.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz" + }, + "minimist": { + "version": "0.0.10", + "from": "minimist@>=0.0.1 <0.1.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" + } + } + }, + "redback": { + "version": "0.4.0", + "from": "redback@0.4.0", + "resolved": "https://registry.npmjs.org/redback/-/redback-0.4.0.tgz" + }, + "redis": { + "version": "0.10.1", + "from": "redis@0.10.1", + "resolved": "https://registry.npmjs.org/redis/-/redis-0.10.1.tgz" + }, + "redis-sharelatex": { + "version": "0.0.9", + "from": "redis-sharelatex@0.0.9", + "resolved": "https://registry.npmjs.org/redis-sharelatex/-/redis-sharelatex-0.0.9.tgz", + "dependencies": { + "chai": { + "version": "1.9.1", + "from": "chai@1.9.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-1.9.1.tgz", + "dependencies": { + "assertion-error": { + "version": "1.0.0", + "from": "assertion-error@1.0.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz" + }, + "deep-eql": { + "version": "0.1.3", + "from": "deep-eql@>=0.1.3 <0.2.0", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "dependencies": { + "type-detect": { + "version": "0.1.1", + "from": "type-detect@0.1.1" + } + } + } + } + }, + "coffee-script": { + "version": "1.8.0", + "from": "coffee-script@1.8.0", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.8.0.tgz", + "dependencies": { + "mkdirp": { + "version": "0.3.5", + "from": "mkdirp@>=0.3.5 <0.4.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" + } + } + }, + "grunt-contrib-coffee": { + "version": "0.11.1", + "from": "grunt-contrib-coffee@0.11.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-coffee/-/grunt-contrib-coffee-0.11.1.tgz", + "dependencies": { + "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", + "dependencies": { + "mkdirp": { + "version": "0.3.5", + "from": "mkdirp@>=0.3.5 <0.4.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" + } + } + }, + "chalk": { + "version": "0.5.1", + "from": "chalk@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "dependencies": { + "ansi-styles": { + "version": "1.1.0", + "from": "ansi-styles@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" + }, + "escape-string-regexp": { + "version": "1.0.5", + "from": "escape-string-regexp@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + }, + "has-ansi": { + "version": "0.1.0", + "from": "has-ansi@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "dependencies": { + "ansi-regex": { + "version": "0.2.1", + "from": "ansi-regex@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" + } + } + }, + "strip-ansi": { + "version": "0.3.0", + "from": "strip-ansi@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "dependencies": { + "ansi-regex": { + "version": "0.2.1", + "from": "ansi-regex@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" + } + } + }, + "supports-color": { + "version": "0.2.0", + "from": "supports-color@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" + } + } + }, + "lodash": { + "version": "2.4.2", + "from": "lodash@>=2.4.1 <2.5.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" + } + } + }, + "grunt-mocha-test": { + "version": "0.12.0", + "from": "grunt-mocha-test@0.12.0", + "resolved": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.12.0.tgz", + "dependencies": { + "hooker": { + "version": "0.2.3", + "from": "hooker@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz" + }, + "fs-extra": { + "version": "0.11.1", + "from": "fs-extra@>=0.11.1 <0.12.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.11.1.tgz", + "dependencies": { + "ncp": { + "version": "0.6.0", + "from": "ncp@>=0.6.0 <0.7.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.6.0.tgz" + }, + "mkdirp": { + "version": "0.5.1", + "from": "mkdirp@>=0.5.0 <0.6.0", + "dependencies": { + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "http://localhost:8080/minimist/-/minimist-0.0.8.tgz" + } + } + }, + "jsonfile": { + "version": "2.3.1", + "from": "jsonfile@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.3.1.tgz" + }, + "rimraf": { + "version": "2.5.2", + "from": "rimraf@>=2.2.8 <3.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.2.tgz", + "dependencies": { + "glob": { + "version": "7.0.5", + "from": "glob@>=7.0.0 <8.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "dependencies": { + "fs.realpath": { + "version": "1.0.0", + "from": "fs.realpath@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + }, + "inflight": { + "version": "1.0.5", + "from": "inflight@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + } + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.0 <3.0.0" + }, + "minimatch": { + "version": "3.0.2", + "from": "minimatch@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz", + "dependencies": { + "brace-expansion": { + "version": "1.1.5", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz", + "dependencies": { + "balanced-match": { + "version": "0.4.1", + "from": "balanced-match@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "http://localhost:8080/concat-map/-/concat-map-0.0.1.tgz" + } + } + } + } + }, + "once": { + "version": "1.3.3", + "from": "once@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + } + }, + "path-is-absolute": { + "version": "1.0.0", + "from": "path-is-absolute@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz" + } + } + } + } + } + } + } + } + }, + "mocha": { + "version": "1.21.4", + "from": "mocha@1.21.4", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-1.21.4.tgz", + "dependencies": { + "commander": { + "version": "2.0.0", + "from": "commander@2.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.0.0.tgz" + }, + "growl": { + "version": "1.8.1", + "from": "growl@>=1.8.0 <1.9.0", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.8.1.tgz" + }, + "jade": { + "version": "0.26.3", + "from": "jade@0.26.3", + "dependencies": { + "commander": { + "version": "0.6.1", + "from": "commander@0.6.1" + }, + "mkdirp": { + "version": "0.3.0", + "from": "mkdirp@0.3.0" + } + } + }, + "diff": { + "version": "1.0.7", + "from": "diff@1.0.7", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.7.tgz" + }, + "debug": { + "version": "2.2.0", + "from": "debug@*", + "dependencies": { + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1" + } + } + }, + "mkdirp": { + "version": "0.3.5", + "from": "mkdirp@0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" + }, + "glob": { + "version": "3.2.3", + "from": "glob@3.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", + "dependencies": { + "minimatch": { + "version": "0.2.14", + "from": "minimatch@>=0.2.11 <0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "dependencies": { + "lru-cache": { + "version": "2.7.3", + "from": "lru-cache@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz" + }, + "sigmund": { + "version": "1.0.1", + "from": "sigmund@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" + } + } + }, + "graceful-fs": { + "version": "2.0.3", + "from": "graceful-fs@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0" + } + } + } + } + }, + "redis": { + "version": "0.12.1", + "from": "redis@0.12.1", + "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz" + }, + "redis-sentinel": { + "version": "0.1.1", + "from": "redis-sentinel@0.1.1", + "resolved": "https://registry.npmjs.org/redis-sentinel/-/redis-sentinel-0.1.1.tgz", + "dependencies": { + "redis": { + "version": "0.11.0", + "from": "redis@>=0.11.0 <0.12.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-0.11.0.tgz" + }, + "q": { + "version": "0.9.2", + "from": "q@0.9.2", + "resolved": "https://registry.npmjs.org/q/-/q-0.9.2.tgz" + } + } + }, + "sandboxed-module": { + "version": "1.0.1", + "from": "sandboxed-module@1.0.1", + "resolved": "https://registry.npmjs.org/sandboxed-module/-/sandboxed-module-1.0.1.tgz", + "dependencies": { + "require-like": { + "version": "0.1.2", + "from": "require-like@0.1.2" + }, + "stack-trace": { + "version": "0.0.9", + "from": "stack-trace@0.0.9" + } + } + }, + "sinon": { + "version": "1.10.3", + "from": "sinon@1.10.3", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.10.3.tgz", + "dependencies": { + "formatio": { + "version": "1.0.2", + "from": "formatio@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.0.2.tgz", + "dependencies": { + "samsam": { + "version": "1.1.3", + "from": "samsam@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.3.tgz" + } + } + }, + "util": { + "version": "0.10.3", + "from": "util@>=0.10.3 <1.0.0", + "dependencies": { + "inherits": { + "version": "2.0.1", + "from": "inherits@2.0.1" + } + } + } + } + }, + "underscore": { + "version": "1.7.0", + "from": "underscore@1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz" + } + } + }, + "request": { + "version": "2.72.0", + "from": "request@>=2.69.0 <3.0.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.72.0.tgz", + "dependencies": { + "aws-sign2": { + "version": "0.6.0", + "from": "aws-sign2@>=0.6.0 <0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz" + }, + "aws4": { + "version": "1.4.1", + "from": "aws4@>=1.2.1 <2.0.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz" + }, + "bl": { + "version": "1.1.2", + "from": "bl@>=1.1.2 <1.2.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "from": "readable-stream@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0" + }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "process-nextick-args": { + "version": "1.0.7", + "from": "process-nextick-args@>=1.0.6 <1.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + } + } + } + }, + "caseless": { + "version": "0.11.0", + "from": "caseless@>=0.11.0 <0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz" + }, + "combined-stream": { + "version": "1.0.5", + "from": "combined-stream@>=1.0.5 <1.1.0", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "dependencies": { + "delayed-stream": { + "version": "1.0.0", + "from": "delayed-stream@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + } + } + }, + "extend": { + "version": "3.0.0", + "from": "extend@>=3.0.0 <3.1.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" + }, + "forever-agent": { + "version": "0.6.1", + "from": "forever-agent@>=0.6.1 <0.7.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" + }, + "form-data": { + "version": "1.0.0-rc4", + "from": "form-data@>=1.0.0-rc3 <1.1.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz", + "dependencies": { + "async": { + "version": "1.5.2", + "from": "async@>=1.5.2 <2.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz" + } + } + }, + "har-validator": { + "version": "2.0.6", + "from": "har-validator@>=2.0.6 <2.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "dependencies": { + "chalk": { + "version": "1.1.3", + "from": "chalk@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "dependencies": { + "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" + }, + "escape-string-regexp": { + "version": "1.0.5", + "from": "escape-string-regexp@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.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", + "dependencies": { + "ansi-regex": { + "version": "2.0.0", + "from": "ansi-regex@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "from": "strip-ansi@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "dependencies": { + "ansi-regex": { + "version": "2.0.0", + "from": "ansi-regex@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + } + } + }, + "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" + } + } + }, + "commander": { + "version": "2.9.0", + "from": "commander@>=2.9.0 <3.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "dependencies": { + "graceful-readlink": { + "version": "1.0.1", + "from": "graceful-readlink@>=1.0.0", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" + } + } + }, + "is-my-json-valid": { + "version": "2.13.1", + "from": "is-my-json-valid@>=2.12.4 <3.0.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz", + "dependencies": { + "generate-function": { + "version": "2.0.0", + "from": "generate-function@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz" + }, + "generate-object-property": { + "version": "1.2.0", + "from": "generate-object-property@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "dependencies": { + "is-property": { + "version": "1.0.2", + "from": "is-property@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" + } + } + }, + "jsonpointer": { + "version": "2.0.0", + "from": "jsonpointer@2.0.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz" + }, + "xtend": { + "version": "4.0.1", + "from": "xtend@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + } + } + }, + "pinkie-promise": { + "version": "2.0.1", + "from": "pinkie-promise@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "dependencies": { + "pinkie": { + "version": "2.0.4", + "from": "pinkie@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" + } + } + } + } + }, + "hawk": { + "version": "3.1.3", + "from": "hawk@>=3.1.3 <3.2.0", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "dependencies": { + "hoek": { + "version": "2.16.3", + "from": "hoek@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" + }, + "boom": { + "version": "2.10.1", + "from": "boom@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" + }, + "cryptiles": { + "version": "2.0.5", + "from": "cryptiles@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz" + }, + "sntp": { + "version": "1.0.9", + "from": "sntp@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" + } + } + }, + "http-signature": { + "version": "1.1.1", + "from": "http-signature@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "dependencies": { + "assert-plus": { + "version": "0.2.0", + "from": "assert-plus@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz" + }, + "jsprim": { + "version": "1.3.0", + "from": "jsprim@>=1.2.2 <2.0.0", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.0.tgz", + "dependencies": { + "extsprintf": { + "version": "1.0.2", + "from": "extsprintf@1.0.2", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz" + }, + "json-schema": { + "version": "0.2.2", + "from": "json-schema@0.2.2", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz" + }, + "verror": { + "version": "1.3.6", + "from": "verror@1.3.6", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz" + } + } + }, + "sshpk": { + "version": "1.8.3", + "from": "sshpk@>=1.7.0 <2.0.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.8.3.tgz", + "dependencies": { + "asn1": { + "version": "0.2.3", + "from": "asn1@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz" + }, + "assert-plus": { + "version": "1.0.0", + "from": "assert-plus@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + }, + "dashdash": { + "version": "1.14.0", + "from": "dashdash@>=1.12.0 <2.0.0", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz" + }, + "getpass": { + "version": "0.1.6", + "from": "getpass@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz" + }, + "jsbn": { + "version": "0.1.0", + "from": "jsbn@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz" + }, + "tweetnacl": { + "version": "0.13.3", + "from": "tweetnacl@>=0.13.0 <0.14.0", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.13.3.tgz" + }, + "jodid25519": { + "version": "1.0.2", + "from": "jodid25519@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz" + }, + "ecc-jsbn": { + "version": "0.1.1", + "from": "ecc-jsbn@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz" + } + } + } + } + }, + "is-typedarray": { + "version": "1.0.0", + "from": "is-typedarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + }, + "isstream": { + "version": "0.1.2", + "from": "isstream@>=0.1.2 <0.2.0", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" + }, + "json-stringify-safe": { + "version": "5.0.1", + "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" + }, + "mime-types": { + "version": "2.1.11", + "from": "mime-types@>=2.1.7 <2.2.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz", + "dependencies": { + "mime-db": { + "version": "1.23.0", + "from": "mime-db@>=1.23.0 <1.24.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz" + } + } + }, + "node-uuid": { + "version": "1.4.7", + "from": "node-uuid@>=1.4.7 <1.5.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz" + }, + "oauth-sign": { + "version": "0.8.2", + "from": "oauth-sign@>=0.8.1 <0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz" + }, + "qs": { + "version": "6.1.0", + "from": "qs@>=6.1.0 <6.2.0" + }, + "stringstream": { + "version": "0.0.5", + "from": "stringstream@>=0.0.4 <0.1.0", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz" + }, + "tough-cookie": { + "version": "2.2.2", + "from": "tough-cookie@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz" + }, + "tunnel-agent": { + "version": "0.4.3", + "from": "tunnel-agent@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz" + } + } + }, + "requests": { + "version": "0.1.7", + "from": "requests@>=0.1.7 <0.2.0", + "resolved": "https://registry.npmjs.org/requests/-/requests-0.1.7.tgz", + "dependencies": { + "axo": { + "version": "0.0.1", + "from": "axo@>=0.0.0 <0.1.0", + "resolved": "https://registry.npmjs.org/axo/-/axo-0.0.1.tgz" + }, + "eventemitter3": { + "version": "1.1.1", + "from": "eventemitter3@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz" + }, + "extendible": { + "version": "0.1.1", + "from": "extendible@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/extendible/-/extendible-0.1.1.tgz" + }, + "hang": { + "version": "1.0.0", + "from": "hang@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/hang/-/hang-1.0.0.tgz" + }, + "loads": { + "version": "0.0.4", + "from": "loads@>=0.0.0 <0.1.0", + "resolved": "https://registry.npmjs.org/loads/-/loads-0.0.4.tgz", + "dependencies": { + "failure": { + "version": "1.1.1", + "from": "failure@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/failure/-/failure-1.1.1.tgz" + }, + "one-time": { + "version": "0.0.4", + "from": "one-time@>=0.0.0 <0.1.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz" + }, + "xhr-response": { + "version": "1.0.1", + "from": "xhr-response@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/xhr-response/-/xhr-response-1.0.1.tgz" + }, + "xhr-status": { + "version": "1.0.0", + "from": "xhr-status@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/xhr-status/-/xhr-status-1.0.0.tgz" + } + } + }, + "xhr-send": { + "version": "1.0.0", + "from": "xhr-send@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/xhr-send/-/xhr-send-1.0.0.tgz" + } + } + }, + "rimraf": { + "version": "2.2.6", + "from": "rimraf@2.2.6", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz" + }, + "sanitizer": { + "version": "0.1.1", + "from": "sanitizer@0.1.1", + "resolved": "https://registry.npmjs.org/sanitizer/-/sanitizer-0.1.1.tgz" + }, + "settings-sharelatex": { + "version": "1.0.0", + "from": "git+https://github.com/sharelatex/settings-sharelatex.git#v1.0.0", + "resolved": "git+https://github.com/sharelatex/settings-sharelatex.git#cbc5e41c1dbe6789721a14b3fdae05bf22546559", + "dependencies": { + "coffee-script": { + "version": "1.6.0", + "from": "coffee-script@1.6.0", + "resolved": "http://localhost:8080/coffee-script/-/coffee-script-1.6.0.tgz" + } + } + }, + "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" + }, + "temp": { + "version": "0.8.3", + "from": "temp@>=0.8.3 <0.9.0", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "dependencies": { + "os-tmpdir": { + "version": "1.0.1", + "from": "os-tmpdir@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.1.tgz" + } + } + }, + "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#80fc5f140a5bddbe758cfc60651fb411e5b0ca5d", + "dependencies": { + "coffee-script": { + "version": "1.10.0", + "from": "coffee-script@>=1.7.1 <2.0.0", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.10.0.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", + "dependencies": { + "cookies": { + "version": "0.6.1", + "from": "cookies@>=0.2.2", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.6.1.tgz", + "dependencies": { + "depd": { + "version": "1.1.0", + "from": "depd@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" + }, + "keygrip": { + "version": "1.0.1", + "from": "keygrip@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.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" + } + } + }, + "onesky": { + "version": "0.1.6", + "from": "onesky@>=0.1.5 <0.2.0", + "resolved": "https://registry.npmjs.org/onesky/-/onesky-0.1.6.tgz", + "dependencies": { + "request": { + "version": "2.40.0", + "from": "request@>=2.40.0 <2.41.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.40.0.tgz", + "dependencies": { + "qs": { + "version": "1.0.2", + "from": "qs@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.0.2.tgz" + }, + "json-stringify-safe": { + "version": "5.0.1", + "from": "json-stringify-safe@>=5.0.0 <5.1.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + }, + "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" + }, + "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" + }, + "tough-cookie": { + "version": "2.2.2", + "from": "tough-cookie@>=0.12.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz" + }, + "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", + "dependencies": { + "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", + "dependencies": { + "delayed-stream": { + "version": "0.0.5", + "from": "delayed-stream@0.0.5", + "resolved": "http://localhost:8080/delayed-stream/-/delayed-stream-0.0.5.tgz" + } + } + }, + "mime": { + "version": "1.2.11", + "from": "mime@>=1.2.11 <1.3.0" + }, + "async": { + "version": "0.9.2", + "from": "async@>=0.9.0 <0.10.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz" + } + } + }, + "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" + }, + "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", + "dependencies": { + "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" + }, + "asn1": { + "version": "0.1.11", + "from": "asn1@0.1.11", + "resolved": "http://localhost:8080/asn1/-/asn1-0.1.11.tgz" + }, + "ctype": { + "version": "0.5.3", + "from": "ctype@0.5.3", + "resolved": "http://localhost:8080/ctype/-/ctype-0.5.3.tgz" + } + } + }, + "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" + }, + "hawk": { + "version": "1.1.1", + "from": "hawk@1.1.1", + "resolved": "http://localhost:8080/hawk/-/hawk-1.1.1.tgz", + "dependencies": { + "hoek": { + "version": "0.9.1", + "from": "hoek@>=0.9.0 <0.10.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" + }, + "boom": { + "version": "0.4.2", + "from": "boom@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" + }, + "cryptiles": { + "version": "0.2.2", + "from": "cryptiles@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" + }, + "sntp": { + "version": "0.2.4", + "from": "sntp@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" + } + } + }, + "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" + }, + "stringstream": { + "version": "0.0.5", + "from": "stringstream@>=0.0.4 <0.1.0", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz" + } + } + } + } + } + } + }, + "underscore": { + "version": "1.6.0", + "from": "underscore@1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz" + }, + "v8-profiler": { + "version": "5.6.5", + "from": "v8-profiler@>=5.2.3 <6.0.0", + "resolved": "https://registry.npmjs.org/v8-profiler/-/v8-profiler-5.6.5.tgz", + "dependencies": { + "nan": { + "version": "2.3.5", + "from": "nan@>=2.3.2 <3.0.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.3.5.tgz" + }, + "node-pre-gyp": { + "version": "0.6.28", + "from": "node-pre-gyp@>=0.6.5 <0.7.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.28.tgz", + "dependencies": { + "mkdirp": { + "version": "0.5.1", + "from": "mkdirp@>=0.5.0 <0.6.0", + "dependencies": { + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "http://localhost:8080/minimist/-/minimist-0.0.8.tgz" + } + } + }, + "nopt": { + "version": "3.0.6", + "from": "nopt@>=3.0.1 <3.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "dependencies": { + "abbrev": { + "version": "1.0.9", + "from": "abbrev@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz" + } + } + }, + "npmlog": { + "version": "2.0.4", + "from": "npmlog@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", + "dependencies": { + "ansi": { + "version": "0.3.1", + "from": "ansi@>=0.3.1 <0.4.0", + "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz" + }, + "are-we-there-yet": { + "version": "1.1.2", + "from": "are-we-there-yet@>=1.1.2 <1.2.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz", + "dependencies": { + "delegates": { + "version": "1.0.0", + "from": "delegates@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" + }, + "readable-stream": { + "version": "2.1.4", + "from": "readable-stream@>=2.0.0 <3.0.0||>=1.1.13 <2.0.0", + "dependencies": { + "buffer-shims": { + "version": "1.0.0", + "from": "buffer-shims@>=1.0.0 <2.0.0" + }, + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0" + }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "process-nextick-args": { + "version": "1.0.7", + "from": "process-nextick-args@>=1.0.6 <1.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + } + } + } + }, + "gauge": { + "version": "1.2.7", + "from": "gauge@>=1.2.5 <1.3.0", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", + "dependencies": { + "has-unicode": { + "version": "2.0.1", + "from": "has-unicode@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" + }, + "lodash.pad": { + "version": "4.4.0", + "from": "lodash.pad@>=4.1.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.4.0.tgz", + "dependencies": { + "lodash._baseslice": { + "version": "4.0.0", + "from": "lodash._baseslice@>=4.0.0 <4.1.0", + "resolved": "https://registry.npmjs.org/lodash._baseslice/-/lodash._baseslice-4.0.0.tgz" + }, + "lodash._basetostring": { + "version": "4.12.0", + "from": "lodash._basetostring@>=4.12.0 <4.13.0", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz" + }, + "lodash.tostring": { + "version": "4.1.3", + "from": "lodash.tostring@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.3.tgz" + } + } + }, + "lodash.padend": { + "version": "4.5.0", + "from": "lodash.padend@>=4.1.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.5.0.tgz", + "dependencies": { + "lodash._baseslice": { + "version": "4.0.0", + "from": "lodash._baseslice@>=4.0.0 <4.1.0", + "resolved": "https://registry.npmjs.org/lodash._baseslice/-/lodash._baseslice-4.0.0.tgz" + }, + "lodash._basetostring": { + "version": "4.12.0", + "from": "lodash._basetostring@>=4.12.0 <4.13.0", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz" + }, + "lodash.tostring": { + "version": "4.1.3", + "from": "lodash.tostring@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.3.tgz" + } + } + }, + "lodash.padstart": { + "version": "4.5.0", + "from": "lodash.padstart@>=4.1.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.5.0.tgz", + "dependencies": { + "lodash._baseslice": { + "version": "4.0.0", + "from": "lodash._baseslice@>=4.0.0 <4.1.0", + "resolved": "https://registry.npmjs.org/lodash._baseslice/-/lodash._baseslice-4.0.0.tgz" + }, + "lodash._basetostring": { + "version": "4.12.0", + "from": "lodash._basetostring@>=4.12.0 <4.13.0", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz" + }, + "lodash.tostring": { + "version": "4.1.3", + "from": "lodash.tostring@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.3.tgz" + } + } + } + } + } + } + }, + "rc": { + "version": "1.1.6", + "from": "rc@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.1.6.tgz", + "dependencies": { + "deep-extend": { + "version": "0.4.1", + "from": "deep-extend@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.1.tgz" + }, + "ini": { + "version": "1.3.4", + "from": "ini@>=1.3.0 <1.4.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz" + }, + "minimist": { + "version": "1.2.0", + "from": "minimist@>=1.2.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" + }, + "strip-json-comments": { + "version": "1.0.4", + "from": "strip-json-comments@>=1.0.4 <1.1.0", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz" + } + } + }, + "rimraf": { + "version": "2.5.2", + "from": "rimraf@>=2.5.0 <2.6.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.2.tgz", + "dependencies": { + "glob": { + "version": "7.0.5", + "from": "glob@>=7.0.0 <8.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "dependencies": { + "fs.realpath": { + "version": "1.0.0", + "from": "fs.realpath@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + }, + "inflight": { + "version": "1.0.5", + "from": "inflight@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + } + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.0 <3.0.0" + }, + "minimatch": { + "version": "3.0.2", + "from": "minimatch@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz", + "dependencies": { + "brace-expansion": { + "version": "1.1.5", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz", + "dependencies": { + "balanced-match": { + "version": "0.4.1", + "from": "balanced-match@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "http://localhost:8080/concat-map/-/concat-map-0.0.1.tgz" + } + } + } + } + }, + "once": { + "version": "1.3.3", + "from": "once@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + } + }, + "path-is-absolute": { + "version": "1.0.0", + "from": "path-is-absolute@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz" + } + } + } + } + }, + "semver": { + "version": "5.1.1", + "from": "semver@>=5.1.0 <5.2.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.1.1.tgz" + }, + "tar": { + "version": "2.2.1", + "from": "tar@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "dependencies": { + "block-stream": { + "version": "0.0.9", + "from": "block-stream@*", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz" + }, + "fstream": { + "version": "1.0.10", + "from": "fstream@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.10.tgz", + "dependencies": { + "graceful-fs": { + "version": "4.1.4", + "from": "graceful-fs@>=4.1.2 <5.0.0" + } + } + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.0 <3.0.0" + } + } + }, + "tar-pack": { + "version": "3.1.4", + "from": "tar-pack@>=3.1.0 <3.2.0", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.1.4.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "dependencies": { + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1" + } + } + }, + "fstream": { + "version": "1.0.10", + "from": "fstream@>=1.0.10 <1.1.0", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.10.tgz", + "dependencies": { + "graceful-fs": { + "version": "4.1.4", + "from": "graceful-fs@>=4.1.2 <5.0.0" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.0 <2.1.0" + } + } + }, + "fstream-ignore": { + "version": "1.0.5", + "from": "fstream-ignore@>=1.0.5 <1.1.0", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "dependencies": { + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.0 <3.0.0" + }, + "minimatch": { + "version": "3.0.2", + "from": "minimatch@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz", + "dependencies": { + "brace-expansion": { + "version": "1.1.5", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz", + "dependencies": { + "balanced-match": { + "version": "0.4.1", + "from": "balanced-match@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "http://localhost:8080/concat-map/-/concat-map-0.0.1.tgz" + } + } + } + } + } + } + }, + "once": { + "version": "1.3.3", + "from": "once@>=1.3.3 <1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + } + }, + "readable-stream": { + "version": "2.1.4", + "from": "readable-stream@>=2.1.4 <2.2.0", + "dependencies": { + "buffer-shims": { + "version": "1.0.0", + "from": "buffer-shims@>=1.0.0 <2.0.0" + }, + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0" + }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "process-nextick-args": { + "version": "1.0.7", + "from": "process-nextick-args@>=1.0.6 <1.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + } + }, + "uid-number": { + "version": "0.0.6", + "from": "uid-number@>=0.0.6 <0.1.0", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz" + } + } + } + } + } + } + }, + "xml2js": { + "version": "0.2.0", + "from": "xml2js@0.2.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.0.tgz", + "dependencies": { + "sax": { + "version": "1.2.1", + "from": "sax@>=0.1.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz" + } + } + } + } +} From afc89d8d27005333b98ddeb658b9983892d94a3b Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 28 Jun 2016 10:12:40 +0100 Subject: [PATCH 28/34] added missing package grunt-execute --- services/web/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/services/web/package.json b/services/web/package.json index 3f077d61fd..8d14a350dc 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -76,6 +76,7 @@ "grunt-contrib-watch": "^1.0.0", "grunt-env": "0.4.4", "grunt-exec": "^0.4.7", + "grunt-execute": "^0.2.2", "grunt-file-append": "0.0.6", "grunt-git-rev-parse": "^0.1.4", "grunt-mocha-test": "0.9.0", From e0d262a6d81efb882e9699c26cfa823fed1af6b2 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 28 Jun 2016 11:18:09 +0100 Subject: [PATCH 29/34] fix shrinkwrap file --- services/web/npm-shrinkwrap.json | 380 ++++++++++++++++++++----------- 1 file changed, 250 insertions(+), 130 deletions(-) diff --git a/services/web/npm-shrinkwrap.json b/services/web/npm-shrinkwrap.json index 85c99d39f0..f9d99d0cc8 100644 --- a/services/web/npm-shrinkwrap.json +++ b/services/web/npm-shrinkwrap.json @@ -24,7 +24,8 @@ }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1" + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", @@ -33,7 +34,8 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0" + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, @@ -120,10 +122,12 @@ "glob": { "version": "3.2.11", "from": "glob@>=3.2.6 <3.3.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.0 <3.0.0" + "from": "inherits@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", @@ -182,7 +186,7 @@ }, "lodash": { "version": "2.4.2", - "from": "lodash@>=2.4.1 <2.5.0", + "from": "lodash@>=2.4.0 <2.5.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz" } } @@ -199,11 +203,13 @@ "dependencies": { "readable-stream": { "version": "2.1.4", - "from": "readable-stream@>=2.0.0 <3.0.0||>=1.1.13 <2.0.0", + "from": "readable-stream@>=2.0.2 <3.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz", "dependencies": { "buffer-shims": { "version": "1.0.0", - "from": "buffer-shims@>=1.0.0 <2.0.0" + "from": "buffer-shims@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" }, "core-util-is": { "version": "1.0.2", @@ -212,7 +218,8 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0" + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "isarray": { "version": "1.0.0", @@ -251,11 +258,12 @@ "bindings": { "version": "1.2.1", "from": "bindings@1.2.1", - "resolved": "http://localhost:8080/bindings/-/bindings-1.2.1.tgz" + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" }, "nan": { "version": "1.8.4", - "from": "nan@1.8.4" + "from": "nan@1.8.4", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.8.4.tgz" } } }, @@ -271,15 +279,18 @@ }, "content-type": { "version": "1.0.2", - "from": "content-type@>=1.0.2 <1.1.0" + "from": "content-type@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" }, "debug": { "version": "2.2.0", "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "dependencies": { "ms": { "version": "0.7.1", - "from": "ms@0.7.1" + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } } }, @@ -295,7 +306,8 @@ "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@2.0.1" + "from": "inherits@2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "setprototypeof": { "version": "1.0.1", @@ -304,13 +316,14 @@ }, "statuses": { "version": "1.3.0", - "from": "statuses@>=1.3.0 <2.0.0" + "from": "statuses@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.0.tgz" } } }, "iconv-lite": { "version": "0.4.13", - "from": "iconv-lite@0.4.13", + "from": "iconv-lite@>=0.4.13 <0.5.0", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz" }, "on-finished": { @@ -337,17 +350,20 @@ "dependencies": { "unpipe": { "version": "1.0.0", - "from": "unpipe@1.0.0" + "from": "unpipe@1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" } } }, "type-is": { "version": "1.6.13", "from": "type-is@>=1.6.13 <1.7.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.13.tgz", "dependencies": { "media-typer": { "version": "0.3.0", - "from": "media-typer@0.3.0" + "from": "media-typer@0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" }, "mime-types": { "version": "2.1.11", @@ -434,10 +450,12 @@ "debug": { "version": "2.2.0", "from": "debug@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "dependencies": { "ms": { "version": "0.7.1", - "from": "ms@0.7.1" + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } } }, @@ -533,7 +551,8 @@ "dependencies": { "get-stdin": { "version": "4.0.1", - "from": "get-stdin@>=4.0.1 <5.0.0" + "from": "get-stdin@>=4.0.1 <5.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" }, "minimist": { "version": "1.2.0", @@ -548,10 +567,12 @@ "is-finite": { "version": "1.0.1", "from": "is-finite@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.1.tgz", "dependencies": { "number-is-nan": { "version": "1.0.0", - "from": "number-is-nan@>=1.0.0 <2.0.0" + "from": "number-is-nan@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz" } } } @@ -601,11 +622,12 @@ "mkdirp": { "version": "0.5.1", "from": "mkdirp@>=0.5.1 <0.6.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "dependencies": { "minimist": { "version": "0.0.8", "from": "minimist@0.0.8", - "resolved": "http://localhost:8080/minimist/-/minimist-0.0.8.tgz" + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, @@ -621,7 +643,8 @@ "dependencies": { "amdefine": { "version": "1.0.0", - "from": "amdefine@>=0.0.4" + "from": "amdefine@>=0.0.4", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz" } } } @@ -673,10 +696,12 @@ "debug": { "version": "2.2.0", "from": "debug@>=2.1.1 <3.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "dependencies": { "ms": { "version": "0.7.1", - "from": "ms@0.7.1" + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } } }, @@ -687,7 +712,7 @@ }, "minimatch": { "version": "3.0.2", - "from": "minimatch@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0", + "from": "minimatch@>=3.0.2 <4.0.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz", "dependencies": { "brace-expansion": { @@ -703,7 +728,7 @@ "concat-map": { "version": "0.0.1", "from": "concat-map@0.0.1", - "resolved": "http://localhost:8080/concat-map/-/concat-map-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" } } } @@ -736,7 +761,8 @@ }, "source-map": { "version": "0.5.6", - "from": "source-map@>=0.5.0 <0.6.0" + "from": "source-map@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz" } } }, @@ -826,10 +852,12 @@ "debug": { "version": "2.2.0", "from": "debug@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "dependencies": { "ms": { "version": "0.7.1", - "from": "ms@0.7.1" + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } } }, @@ -942,10 +970,12 @@ "debug": { "version": "2.2.0", "from": "debug@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "dependencies": { "ms": { "version": "0.7.1", - "from": "ms@0.7.1" + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } } }, @@ -1074,7 +1104,8 @@ "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@2.0.1" + "from": "inherits@2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "setprototypeof": { "version": "1.0.1", @@ -1083,7 +1114,8 @@ }, "statuses": { "version": "1.3.0", - "from": "statuses@>=1.3.0 <2.0.0" + "from": "statuses@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.0.tgz" } } } @@ -1135,7 +1167,8 @@ }, "content-type": { "version": "1.0.2", - "from": "content-type@>=1.0.1 <1.1.0" + "from": "content-type@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" }, "cookie": { "version": "0.1.3", @@ -1150,10 +1183,12 @@ "debug": { "version": "2.2.0", "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "dependencies": { "ms": { "version": "0.7.1", - "from": "ms@0.7.1" + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } } }, @@ -1179,7 +1214,8 @@ "dependencies": { "unpipe": { "version": "1.0.0", - "from": "unpipe@>=1.0.0 <1.1.0" + "from": "unpipe@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" } } }, @@ -1264,7 +1300,8 @@ "dependencies": { "inherits": { "version": "2.0.1", - "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.1.tgz" } } }, @@ -1275,7 +1312,8 @@ }, "ms": { "version": "0.7.1", - "from": "ms@0.7.1" + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" }, "statuses": { "version": "1.2.1", @@ -1316,7 +1354,8 @@ "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0" + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, @@ -1327,7 +1366,8 @@ }, "ms": { "version": "0.7.1", - "from": "ms@0.7.1" + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" }, "statuses": { "version": "1.2.1", @@ -1341,14 +1381,16 @@ "type-is": { "version": "1.6.13", "from": "type-is@>=1.6.3 <1.7.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.13.tgz", "dependencies": { "media-typer": { "version": "0.3.0", - "from": "media-typer@0.3.0" + "from": "media-typer@0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" }, "mime-types": { "version": "2.1.11", - "from": "mime-types@>=2.1.6 <2.2.0", + "from": "mime-types@>=2.1.11 <2.2.0", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz", "dependencies": { "mime-db": { @@ -1395,10 +1437,12 @@ "debug": { "version": "2.2.0", "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "dependencies": { "ms": { "version": "0.7.1", - "from": "ms@0.7.1" + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } } }, @@ -1458,7 +1502,8 @@ }, "dateformat": { "version": "1.0.2-1.2.3", - "from": "dateformat@1.0.2-1.2.3" + "from": "dateformat@1.0.2-1.2.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz" }, "eventemitter2": { "version": "0.4.14", @@ -1473,10 +1518,12 @@ "glob": { "version": "3.2.11", "from": "glob@>=3.2.9 <3.3.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.0 <3.0.0" + "from": "inherits@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", @@ -1533,7 +1580,7 @@ }, "minimatch": { "version": "0.2.14", - "from": "minimatch@>=0.2.12 <0.3.0", + "from": "minimatch@>=0.2.9 <0.3.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "dependencies": { "lru-cache": { @@ -1731,7 +1778,8 @@ "dependencies": { "amdefine": { "version": "1.0.0", - "from": "amdefine@>=0.0.4" + "from": "amdefine@>=0.0.4", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz" } } }, @@ -1784,7 +1832,7 @@ "concat-map": { "version": "0.0.1", "from": "concat-map@0.0.1", - "resolved": "http://localhost:8080/concat-map/-/concat-map-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" } } } @@ -1806,7 +1854,8 @@ "dependencies": { "async": { "version": "0.2.10", - "from": "async@>=0.2.6 <0.3.0" + "from": "async@>=0.2.6 <0.3.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "source-map": { "version": "0.1.34", @@ -1815,13 +1864,15 @@ "dependencies": { "amdefine": { "version": "1.0.0", - "from": "amdefine@>=0.0.4" + "from": "amdefine@>=0.0.4", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz" } } }, "uglify-to-browserify": { "version": "1.0.2", - "from": "uglify-to-browserify@>=1.0.0 <1.1.0" + "from": "uglify-to-browserify@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz" }, "yargs": { "version": "3.5.4", @@ -1830,11 +1881,13 @@ "dependencies": { "camelcase": { "version": "1.2.1", - "from": "camelcase@>=1.0.2 <2.0.0" + "from": "camelcase@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz" }, "decamelize": { "version": "1.2.0", - "from": "decamelize@>=1.0.0 <2.0.0" + "from": "decamelize@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" }, "window-size": { "version": "0.1.0", @@ -1843,7 +1896,8 @@ }, "wordwrap": { "version": "0.0.2", - "from": "wordwrap@0.0.2" + "from": "wordwrap@0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" } } } @@ -1863,7 +1917,8 @@ "dependencies": { "async": { "version": "0.2.10", - "from": "async@>=0.2.6 <0.3.0" + "from": "async@>=0.2.6 <0.3.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "source-map": { "version": "0.1.34", @@ -1872,13 +1927,15 @@ "dependencies": { "amdefine": { "version": "1.0.0", - "from": "amdefine@>=0.0.4" + "from": "amdefine@>=0.0.4", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz" } } }, "uglify-to-browserify": { "version": "1.0.2", - "from": "uglify-to-browserify@>=1.0.0 <1.1.0" + "from": "uglify-to-browserify@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz" }, "yargs": { "version": "3.5.4", @@ -1887,11 +1944,13 @@ "dependencies": { "camelcase": { "version": "1.2.1", - "from": "camelcase@>=1.0.2 <2.0.0" + "from": "camelcase@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz" }, "decamelize": { "version": "1.2.0", - "from": "decamelize@>=1.0.0 <2.0.0" + "from": "decamelize@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" }, "window-size": { "version": "0.1.0", @@ -1900,7 +1959,8 @@ }, "wordwrap": { "version": "0.0.2", - "from": "wordwrap@0.0.2" + "from": "wordwrap@0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" } } } @@ -1928,7 +1988,7 @@ "bunyan": { "version": "1.5.1", "from": "bunyan@1.5.1", - "resolved": "http://localhost:8080/bunyan/-/bunyan-1.5.1.tgz", + "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.5.1.tgz", "dependencies": { "mv": { "version": "2.1.1", @@ -1938,11 +1998,12 @@ "mkdirp": { "version": "0.5.1", "from": "mkdirp@>=0.5.1 <0.6.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "dependencies": { "minimist": { "version": "0.0.8", "from": "minimist@0.0.8", - "resolved": "http://localhost:8080/minimist/-/minimist-0.0.8.tgz" + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, @@ -1975,7 +2036,8 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.0 <3.0.0" + "from": "inherits@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "3.0.2", @@ -1995,7 +2057,7 @@ "concat-map": { "version": "0.0.1", "from": "concat-map@0.0.1", - "resolved": "http://localhost:8080/concat-map/-/concat-map-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" } } } @@ -2072,7 +2134,7 @@ }, "dtrace-provider": { "version": "0.6.0", - "from": "dtrace-provider@0.6.0", + "from": "dtrace-provider@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.6.0.tgz", "dependencies": { "nan": { @@ -2086,7 +2148,8 @@ }, "lodash": { "version": "4.13.1", - "from": "lodash@>=4.13.1 <5.0.0" + "from": "lodash@>=4.13.1 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.13.1.tgz" }, "logger-sharelatex": { "version": "1.3.1", @@ -2096,11 +2159,11 @@ "bunyan": { "version": "1.5.1", "from": "bunyan@1.5.1", - "resolved": "http://localhost:8080/bunyan/-/bunyan-1.5.1.tgz", + "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.5.1.tgz", "dependencies": { "dtrace-provider": { "version": "0.6.0", - "from": "dtrace-provider@0.6.0", + "from": "dtrace-provider@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.6.0.tgz", "dependencies": { "nan": { @@ -2118,11 +2181,12 @@ "mkdirp": { "version": "0.5.1", "from": "mkdirp@>=0.5.1 <0.6.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "dependencies": { "minimist": { "version": "0.0.8", "from": "minimist@0.0.8", - "resolved": "http://localhost:8080/minimist/-/minimist-0.0.8.tgz" + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, @@ -2155,7 +2219,8 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.0 <3.0.0" + "from": "inherits@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "3.0.2", @@ -2175,7 +2240,7 @@ "concat-map": { "version": "0.0.1", "from": "concat-map@0.0.1", - "resolved": "http://localhost:8080/concat-map/-/concat-map-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" } } } @@ -2214,7 +2279,7 @@ "coffee-script": { "version": "1.4.0", "from": "coffee-script@1.4.0", - "resolved": "http://localhost:8080/coffee-script/-/coffee-script-1.4.0.tgz" + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.4.0.tgz" }, "raven": { "version": "0.8.1", @@ -2224,7 +2289,7 @@ "cookie": { "version": "0.1.0", "from": "cookie@0.1.0", - "resolved": "http://localhost:8080/cookie/-/cookie-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.0.tgz" }, "lsmod": { "version": "0.0.3", @@ -2234,7 +2299,7 @@ "stack-trace": { "version": "0.0.7", "from": "stack-trace@0.0.7", - "resolved": "http://localhost:8080/stack-trace/-/stack-trace-0.0.7.tgz" + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.7.tgz" } } } @@ -2270,10 +2335,12 @@ "debug": { "version": "2.2.0", "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "dependencies": { "ms": { "version": "0.7.1", - "from": "ms@0.7.1" + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } } }, @@ -2284,7 +2351,7 @@ }, "parseurl": { "version": "1.3.1", - "from": "parseurl@>=1.3.1 <1.4.0", + "from": "parseurl@>=1.3.0 <1.4.0", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" }, "vary": { @@ -2302,7 +2369,7 @@ "coffee-script": { "version": "1.6.0", "from": "coffee-script@1.6.0", - "resolved": "http://localhost:8080/coffee-script/-/coffee-script-1.6.0.tgz" + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.6.0.tgz" } } }, @@ -2348,14 +2415,17 @@ "jade": { "version": "0.26.3", "from": "jade@0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", "dependencies": { "commander": { "version": "0.6.1", - "from": "commander@0.6.1" + "from": "commander@0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz" }, "mkdirp": { "version": "0.3.0", - "from": "mkdirp@0.3.0" + "from": "mkdirp@0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz" } } }, @@ -2367,10 +2437,12 @@ "debug": { "version": "2.2.0", "from": "debug@*", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "dependencies": { "ms": { "version": "0.7.1", - "from": "ms@0.7.1" + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } } }, @@ -2408,7 +2480,8 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.0 <3.0.0" + "from": "inherits@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } } @@ -2417,6 +2490,7 @@ "mongojs": { "version": "0.18.2", "from": "mongojs@0.18.2", + "resolved": "https://registry.npmjs.org/mongojs/-/mongojs-0.18.2.tgz", "dependencies": { "thunky": { "version": "0.1.0", @@ -2425,7 +2499,7 @@ }, "readable-stream": { "version": "1.1.14", - "from": "readable-stream@>=1.1.9 <1.2.0", + "from": "readable-stream@>=1.1.0 <1.2.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "dependencies": { "core-util-is": { @@ -2435,7 +2509,8 @@ }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1" + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", @@ -2444,7 +2519,8 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0" + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, @@ -2456,10 +2532,12 @@ "bson": { "version": "0.2.22", "from": "bson@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-0.2.22.tgz", "dependencies": { "nan": { "version": "1.8.4", - "from": "nan@>=1.8.0 <1.9.0" + "from": "nan@>=1.8.0 <1.9.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.8.4.tgz" } } }, @@ -2470,17 +2548,20 @@ "dependencies": { "nan": { "version": "1.6.2", - "from": "nan@1.6.2" + "from": "nan@1.6.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.6.2.tgz" } } }, "readable-stream": { "version": "2.1.4", "from": "readable-stream@latest", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz", "dependencies": { "buffer-shims": { "version": "1.0.0", - "from": "buffer-shims@>=1.0.0 <2.0.0" + "from": "buffer-shims@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" }, "core-util-is": { "version": "1.0.2", @@ -2489,7 +2570,8 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0" + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "isarray": { "version": "1.0.0", @@ -2540,7 +2622,7 @@ "bindings": { "version": "1.2.1", "from": "bindings@>=1.2.1 <2.0.0", - "resolved": "http://localhost:8080/bindings/-/bindings-1.2.1.tgz" + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" }, "nan": { "version": "2.0.9", @@ -2602,7 +2684,8 @@ }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1" + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", @@ -2611,7 +2694,8 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0" + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } } @@ -2640,10 +2724,12 @@ "debug": { "version": "2.2.0", "from": "debug@2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "dependencies": { "ms": { "version": "0.7.1", - "from": "ms@0.7.1" + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } } } @@ -2705,7 +2791,8 @@ }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1" + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", @@ -2714,7 +2801,8 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0" + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } } @@ -2737,7 +2825,8 @@ "dependencies": { "media-typer": { "version": "0.3.0", - "from": "media-typer@0.3.0" + "from": "media-typer@0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" }, "mime-types": { "version": "2.0.14", @@ -3005,12 +3094,13 @@ }, "deep-eql": { "version": "0.1.3", - "from": "deep-eql@>=0.1.3 <0.2.0", + "from": "deep-eql@0.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", "dependencies": { "type-detect": { "version": "0.1.1", - "from": "type-detect@0.1.1" + "from": "type-detect@0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz" } } } @@ -3120,12 +3210,13 @@ }, "mkdirp": { "version": "0.5.1", - "from": "mkdirp@>=0.5.0 <0.6.0", + "from": "mkdirp@>=0.5.1 <0.6.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "dependencies": { "minimist": { "version": "0.0.8", "from": "minimist@0.0.8", - "resolved": "http://localhost:8080/minimist/-/minimist-0.0.8.tgz" + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, @@ -3163,7 +3254,8 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.0 <3.0.0" + "from": "inherits@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "3.0.2", @@ -3183,7 +3275,7 @@ "concat-map": { "version": "0.0.1", "from": "concat-map@0.0.1", - "resolved": "http://localhost:8080/concat-map/-/concat-map-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" } } } @@ -3232,14 +3324,17 @@ "jade": { "version": "0.26.3", "from": "jade@0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", "dependencies": { "commander": { "version": "0.6.1", - "from": "commander@0.6.1" + "from": "commander@0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz" }, "mkdirp": { "version": "0.3.0", - "from": "mkdirp@0.3.0" + "from": "mkdirp@0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz" } } }, @@ -3251,10 +3346,12 @@ "debug": { "version": "2.2.0", "from": "debug@*", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "dependencies": { "ms": { "version": "0.7.1", - "from": "ms@0.7.1" + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } } }, @@ -3292,7 +3389,8 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0" + "from": "inherits@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } } @@ -3300,7 +3398,7 @@ }, "redis": { "version": "0.12.1", - "from": "redis@0.12.1", + "from": "redis@>=0.12.1 <0.13.0", "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz" }, "redis-sentinel": { @@ -3327,11 +3425,13 @@ "dependencies": { "require-like": { "version": "0.1.2", - "from": "require-like@0.1.2" + "from": "require-like@0.1.2", + "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz" }, "stack-trace": { "version": "0.0.9", - "from": "stack-trace@0.0.9" + "from": "stack-trace@0.0.9", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz" } } }, @@ -3355,10 +3455,12 @@ "util": { "version": "0.10.3", "from": "util@>=0.10.3 <1.0.0", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@2.0.1" + "from": "inherits@2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } } @@ -3393,7 +3495,7 @@ "dependencies": { "readable-stream": { "version": "2.0.6", - "from": "readable-stream@>=2.0.0 <2.1.0", + "from": "readable-stream@>=2.0.5 <2.1.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "dependencies": { "core-util-is": { @@ -3403,7 +3505,8 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0" + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "isarray": { "version": "1.0.0", @@ -3699,7 +3802,7 @@ }, "json-stringify-safe": { "version": "5.0.1", - "from": "json-stringify-safe@>=5.0.1 <5.1.0", + "from": "json-stringify-safe@>=5.0.1 <6.0.0", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" }, "mime-types": { @@ -3726,7 +3829,8 @@ }, "qs": { "version": "6.1.0", - "from": "qs@>=6.1.0 <6.2.0" + "from": "qs@>=6.1.0 <6.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.1.0.tgz" }, "stringstream": { "version": "0.0.5", @@ -3822,7 +3926,7 @@ "coffee-script": { "version": "1.6.0", "from": "coffee-script@1.6.0", - "resolved": "http://localhost:8080/coffee-script/-/coffee-script-1.6.0.tgz" + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.6.0.tgz" } } }, @@ -3930,13 +4034,14 @@ "delayed-stream": { "version": "0.0.5", "from": "delayed-stream@0.0.5", - "resolved": "http://localhost:8080/delayed-stream/-/delayed-stream-0.0.5.tgz" + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" } } }, "mime": { "version": "1.2.11", - "from": "mime@>=1.2.11 <1.3.0" + "from": "mime@>=1.2.11 <1.3.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "async": { "version": "0.9.2", @@ -3963,12 +4068,12 @@ "asn1": { "version": "0.1.11", "from": "asn1@0.1.11", - "resolved": "http://localhost:8080/asn1/-/asn1-0.1.11.tgz" + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" }, "ctype": { "version": "0.5.3", "from": "ctype@0.5.3", - "resolved": "http://localhost:8080/ctype/-/ctype-0.5.3.tgz" + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" } } }, @@ -3980,7 +4085,7 @@ "hawk": { "version": "1.1.1", "from": "hawk@1.1.1", - "resolved": "http://localhost:8080/hawk/-/hawk-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", "dependencies": { "hoek": { "version": "0.9.1", @@ -4043,11 +4148,12 @@ "mkdirp": { "version": "0.5.1", "from": "mkdirp@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "dependencies": { "minimist": { "version": "0.0.8", "from": "minimist@0.0.8", - "resolved": "http://localhost:8080/minimist/-/minimist-0.0.8.tgz" + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, @@ -4086,10 +4192,12 @@ "readable-stream": { "version": "2.1.4", "from": "readable-stream@>=2.0.0 <3.0.0||>=1.1.13 <2.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz", "dependencies": { "buffer-shims": { "version": "1.0.0", - "from": "buffer-shims@>=1.0.0 <2.0.0" + "from": "buffer-shims@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" }, "core-util-is": { "version": "1.0.2", @@ -4098,7 +4206,8 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0" + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "isarray": { "version": "1.0.0", @@ -4260,7 +4369,8 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.0 <3.0.0" + "from": "inherits@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "3.0.2", @@ -4280,7 +4390,7 @@ "concat-map": { "version": "0.0.1", "from": "concat-map@0.0.1", - "resolved": "http://localhost:8080/concat-map/-/concat-map-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" } } } @@ -4329,13 +4439,15 @@ "dependencies": { "graceful-fs": { "version": "4.1.4", - "from": "graceful-fs@>=4.1.2 <5.0.0" + "from": "graceful-fs@>=4.1.2 <5.0.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.4.tgz" } } }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.0 <3.0.0" + "from": "inherits@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, @@ -4347,25 +4459,29 @@ "debug": { "version": "2.2.0", "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "dependencies": { "ms": { "version": "0.7.1", - "from": "ms@0.7.1" + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } } }, "fstream": { "version": "1.0.10", - "from": "fstream@>=1.0.10 <1.1.0", + "from": "fstream@>=1.0.2 <2.0.0", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.10.tgz", "dependencies": { "graceful-fs": { "version": "4.1.4", - "from": "graceful-fs@>=4.1.2 <5.0.0" + "from": "graceful-fs@>=4.1.2 <5.0.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.4.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.0 <2.1.0" + "from": "inherits@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, @@ -4376,7 +4492,8 @@ "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.0 <3.0.0" + "from": "inherits@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "3.0.2", @@ -4396,7 +4513,7 @@ "concat-map": { "version": "0.0.1", "from": "concat-map@0.0.1", - "resolved": "http://localhost:8080/concat-map/-/concat-map-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" } } } @@ -4419,10 +4536,12 @@ "readable-stream": { "version": "2.1.4", "from": "readable-stream@>=2.1.4 <2.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz", "dependencies": { "buffer-shims": { "version": "1.0.0", - "from": "buffer-shims@>=1.0.0 <2.0.0" + "from": "buffer-shims@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" }, "core-util-is": { "version": "1.0.2", @@ -4431,7 +4550,8 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0" + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "isarray": { "version": "1.0.0", From 465d09dcfed10add64a7e14a8b3be9f5d675d055 Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Tue, 28 Jun 2016 11:10:51 +0100 Subject: [PATCH 30/34] Test the createSubscription action (+4 squashed commits) Squashed commits: [fc9c8f9] Add tests for createBillingInfo [db9f90e] Test the createSubscription stage [c17151d] Check that userExists gets set [1367c96] Act on buddy-check feedback --- .../Subscription/RecurlyWrapper.coffee | 14 +- .../Subscription/RecurlyWrapperTests.coffee | 364 +++++++++++++++--- 2 files changed, 321 insertions(+), 57 deletions(-) diff --git a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee index 841ee0a77e..0d7aa99131 100644 --- a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee +++ b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee @@ -39,6 +39,7 @@ module.exports = RecurlyWrapper = if err logger.error {err, user_id: user._id, recurly_token_id}, "error parsing account" return next(err) + cache.userExists = true cache.account = account return next(null, cache) ) @@ -46,13 +47,13 @@ module.exports = RecurlyWrapper = user = cache.user recurly_token_id = cache.recurly_token_id subscriptionDetails = cache.subscriptionDetails + address = subscriptionDetails.address + if !address + return next(new Error('no address in subscriptionDetails at createAccount stage')) if cache.userExists logger.log {user_id: user._id, recurly_token_id}, "user already exists in recurly" return next(null, cache) logger.log {user_id: user._id, recurly_token_id}, "creating user in recurly" - address = subscriptionDetails.address - if !address - return next(new Error('no address in subscriptionDetails at createAccount stage')) requestBody = """ #{user._id} @@ -173,6 +174,9 @@ module.exports = RecurlyWrapper = _createPaypalSubscription: (user, subscriptionDetails, recurly_token_id, callback) -> logger.log {user_id: user._id, recurly_token_id}, "starting process of creating paypal subscription" + # We use `async.waterfall` to run each of these actions in sequence + # passing a `cache` object along the way. The cache is initialized + # with required data, and `async.apply` to pass the cache to the first function cache = {user, recurly_token_id, subscriptionDetails} Async.waterfall([ Async.apply(RecurlyWrapper._paypal.checkAccountExists, cache), @@ -471,9 +475,7 @@ module.exports = RecurlyWrapper = _parseBillingInfoXml: (xml, callback) -> RecurlyWrapper._parseXml xml, (error, data) -> return callback(error) if error? - if data? and data.account? - billingInfo = data.billing_info - else if data? and data.billing_info? + if data? and data.billing_info? billingInfo = data.billing_info else return callback "I don't understand the response from Recurly" diff --git a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee index 4ab866b408..549f6e0250 100644 --- a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee @@ -656,11 +656,13 @@ describe "RecurlyWrapper", -> @createSubscription.callCount.should.equal 0 done() - describe '_paypal.checkAccountExists', -> + describe 'paypal actions', -> beforeEach -> @apiRequest = sinon.stub(@RecurlyWrapper, 'apiRequest') @_parseAccountXml = sinon.spy(@RecurlyWrapper, '_parseAccountXml') + @_parseBillingInfoXml = sinon.spy(@RecurlyWrapper, '_parseBillingInfoXml') + @_parseSubscriptionXml = sinon.spy(@RecurlyWrapper, '_parseSubscriptionXml') @cache = user: @user = {_id: 'some_id'} recurly_token_id: @recurly_token_id = "some_token" @@ -675,83 +677,343 @@ describe "RecurlyWrapper", -> country: "some_country" state: "some_state" zip: "some_zip" - @call = (callback) => - @RecurlyWrapper._paypal.checkAccountExists @cache, callback afterEach -> @apiRequest.restore() @_parseAccountXml.restore() + @_parseBillingInfoXml.restore() + @_parseSubscriptionXml.restore() - describe 'when the account exists', -> + describe '_paypal.checkAccountExists', -> beforeEach -> - resultXml = 'abc' - @apiRequest.callsArgWith(1, null, {statusCode: 200}, resultXml) + @call = (callback) => + @RecurlyWrapper._paypal.checkAccountExists @cache, callback - it 'should not produce an error', (done) -> - @call (err, result) => - expect(err).to.not.be.instanceof Error - done() + describe 'when the account exists', -> - it 'should call apiRequest', (done) -> - @call (err, result) => - @apiRequest.callCount.should.equal 1 - done() + beforeEach -> + resultXml = 'abc' + @apiRequest.callsArgWith(1, null, {statusCode: 200}, resultXml) - it 'should call _parseAccountXml', (done) -> - @call (err, result) => - @RecurlyWrapper._parseAccountXml.callCount.should.equal 1 - done() + it 'should not produce an error', (done) -> + @call (err, result) => + expect(err).to.not.be.instanceof Error + done() - it 'should add the account to the cumulative result', (done) -> - @call (err, result) => - expect(result.account).to.not.equal null - expect(result.account).to.not.equal undefined - expect(result.account).to.deep.equal { + it 'should call apiRequest', (done) -> + @call (err, result) => + @apiRequest.callCount.should.equal 1 + done() + + it 'should call _parseAccountXml', (done) -> + @call (err, result) => + @RecurlyWrapper._parseAccountXml.callCount.should.equal 1 + done() + + it 'should add the account to the cumulative result', (done) -> + @call (err, result) => + expect(result.account).to.not.equal null + expect(result.account).to.not.equal undefined + expect(result.account).to.deep.equal { + account_code: 'abc' + } + done() + + it 'should set userExists to true', (done) -> + @call (err, result) => + expect(result.userExists).to.equal true + done() + + describe 'when the account does not exist', -> + + beforeEach -> + @apiRequest.callsArgWith(1, new Error('not found'), {statusCode: 404}, '') + + it 'should not produce an error', (done) -> + @call (err, result) => + expect(err).to.not.be.instanceof Error + done() + + it 'should call apiRequest', (done) -> + @call (err, result) => + @apiRequest.callCount.should.equal 1 + @apiRequest.firstCall.args[0].method.should.equal 'GET' + done() + + it 'should not call _parseAccountXml', (done) -> + @call (err, result) => + @RecurlyWrapper._parseAccountXml.callCount.should.equal 0 + done() + + it 'should not add the account to result', (done) -> + @call (err, result) => + expect(result.account).to.equal undefined + done() + + it 'should set userExists to false', (done) -> + @call (err, result) => + expect(result.userExists).to.equal false + done() + + describe 'when apiRequest produces an error', -> + + beforeEach -> + @apiRequest.callsArgWith(1, new Error('woops'), {statusCode: 500}) + + it 'should produce an error', (done) -> + @call (err, result) => + expect(err).to.be.instanceof Error + done() + + describe '_paypal.createAccount', -> + + beforeEach -> + @call = (callback) => + @RecurlyWrapper._paypal.createAccount @cache, callback + + describe 'when address is missing from subscriptionDetails', -> + + beforeEach -> + @cache.subscriptionDetails.address = null + + it 'should produce an error', (done) -> + @call (err, result) => + expect(err).to.be.instanceof Error + done() + + describe 'when account already exists', -> + + beforeEach -> + @cache.userExists = true + @cache.account = account_code: 'abc' - } - done() - describe 'when the account does not exist', -> + it 'should not produce an error', (done) -> + @call (err, result) => + expect(err).to.not.be.instanceof Error + done() + + it 'should produce cache object', (done) -> + @call (err, result) => + expect(result).to.deep.equal @cache + expect(result.account).to.deep.equal { + account_code: 'abc' + } + done() + + it 'should not call apiRequest', (done) -> + @call (err, result) => + @apiRequest.callCount.should.equal 0 + done() + + it 'should not call _parseAccountXml', (done) -> + @call (err, result) => + @RecurlyWrapper._parseAccountXml.callCount.should.equal 0 + done() + + describe 'when account does not exist', -> + + beforeEach -> + @cache.userExists = false + resultXml = 'abc' + @apiRequest.callsArgWith(1, null, {statusCode: 200}, resultXml) + + it 'should not produce an error', (done) -> + @call (err, result) => + expect(err).to.not.be.instanceof Error + done() + + it 'should call apiRequest', (done) -> + @call (err, result) => + @apiRequest.callCount.should.equal 1 + @apiRequest.firstCall.args[0].method.should.equal 'POST' + done() + + it 'should call _parseAccountXml', (done) -> + @call (err, result) => + @RecurlyWrapper._parseAccountXml.callCount.should.equal 1 + done() + + describe 'when apiRequest produces an error', -> + + beforeEach -> + @apiRequest.callsArgWith(1, new Error('woops'), {statusCode: 500}) + + it 'should produce an error', (done) -> + @call (err, result) => + expect(err).to.be.instanceof Error + done() + + describe '_paypal.createBillingInfo', -> beforeEach -> - @apiRequest.callsArgWith(1, new Error('not found'), {statusCode: 404}, '') + @cache.account = + account_code: 'abc' + @call = (callback) => + @RecurlyWrapper._paypal.createBillingInfo @cache, callback - it 'should not produce an error', (done) -> - @call (err, result) => - expect(err).to.not.be.instanceof Error - done() + describe 'when account_code is missing from cache', -> - it 'should call apiRequest', (done) -> - @call (err, result) => - @apiRequest.callCount.should.equal 1 - done() + beforeEach -> + @cache.account.account_code = null - it 'should not call _parseAccountXml', (done) -> - @call (err, result) => - @RecurlyWrapper._parseAccountXml.callCount.should.equal 0 - done() + it 'should produce an error', (done) -> + @call (err, result) => + expect(err).to.be.instanceof Error + done() - it 'should not add the account to result', (done) -> - @call (err, result) => - expect(result.account).to.equal undefined - done() + describe 'when all goes well', -> - # describe '_paypal.createAccount', -> + beforeEach -> + resultXml = '
1' + @apiRequest.callsArgWith(1, null, {statusCode: 200}, resultXml) - # beforeEach -> + it 'should not produce an error', (done) -> + @call (err, result) => + expect(err).to.not.be.instanceof Error + done() + it 'should call apiRequest', (done) -> + @call (err, result) => + @apiRequest.callCount.should.equal 1 + @apiRequest.firstCall.args[0].method.should.equal 'POST' + done() - # describe '_paypal.createBillingInfo', -> + it 'should call _parseBillingInfoXml', (done) -> + @call (err, result) => + @RecurlyWrapper._parseBillingInfoXml.callCount.should.equal 1 + done() - # beforeEach -> + it 'should set billingInfo on cache', (done) -> + @call (err, result) => + expect(result.billingInfo).to.deep.equal { + a: "1" + } + done() + describe 'when apiRequest produces an error', -> - # describe '_paypal.setAddress', -> + beforeEach -> + @apiRequest.callsArgWith(1, new Error('woops'), {statusCode: 500}) - # beforeEach -> + it 'should produce an error', (done) -> + @call (err, result) => + expect(err).to.be.instanceof Error + done() + describe '_paypal.setAddress', -> - # describe '_paypal.createSubscription', -> + beforeEach -> + @cache.account = + account_code: 'abc' + @cache.billingInfo = {} + @call = (callback) => + @RecurlyWrapper._paypal.setAddress @cache, callback - # beforeEach -> + describe 'when account_code is missing from cache', -> + + beforeEach -> + @cache.account.account_code = null + + it 'should produce an error', (done) -> + @call (err, result) => + expect(err).to.be.instanceof Error + done() + + describe 'when address is missing from subscriptionDetails', -> + + beforeEach -> + @cache.subscriptionDetails.address = null + + it 'should produce an error', (done) -> + @call (err, result) => + expect(err).to.be.instanceof Error + done() + + describe 'when all goes well', -> + + beforeEach -> + resultXml = 'London' + @apiRequest.callsArgWith(1, null, {statusCode: 200}, resultXml) + + it 'should not produce an error', (done) -> + @call (err, result) => + expect(err).to.not.be.instanceof Error + done() + + it 'should call apiRequest', (done) -> + @call (err, result) => + @apiRequest.callCount.should.equal 1 + @apiRequest.firstCall.args[0].method.should.equal 'PUT' + done() + + it 'should call _parseBillingInfoXml', (done) -> + @call (err, result) => + @RecurlyWrapper._parseBillingInfoXml.callCount.should.equal 1 + done() + + it 'should set billingInfo on cache', (done) -> + @call (err, result) => + expect(result.billingInfo).to.deep.equal { + city: 'London' + } + done() + + describe 'when apiRequest produces an error', -> + + beforeEach -> + @apiRequest.callsArgWith(1, new Error('woops'), {statusCode: 500}) + + it 'should produce an error', (done) -> + @call (err, result) => + expect(err).to.be.instanceof Error + done() + + describe '_paypal.createSubscription', -> + + beforeEach -> + @cache.account = + account_code: 'abc' + @cache.billingInfo = {} + @call = (callback) => + @RecurlyWrapper._paypal.createSubscription @cache, callback + + describe 'when all goes well', -> + + beforeEach -> + resultXml = '1' + @apiRequest.callsArgWith(1, null, {statusCode: 200}, resultXml) + + it 'should not produce an error', (done) -> + @call (err, result) => + expect(err).to.not.be.instanceof Error + done() + + it 'should call apiRequest', (done) -> + @call (err, result) => + @apiRequest.callCount.should.equal 1 + @apiRequest.firstCall.args[0].method.should.equal 'POST' + done() + + it 'should call _parseSubscriptionXml', (done) -> + @call (err, result) => + @RecurlyWrapper._parseSubscriptionXml.callCount.should.equal 1 + done() + + it 'should set subscription on cache', (done) -> + @call (err, result) => + expect(result.subscription).to.deep.equal { + a: "1" + } + done() + + describe 'when apiRequest produces an error', -> + + beforeEach -> + @apiRequest.callsArgWith(1, new Error('woops'), {statusCode: 500}) + + it 'should produce an error', (done) -> + @call (err, result) => + expect(err).to.be.instanceof Error + done() From 6581bc4ecfc85437333ad5bdf8537d17b4c21a7d Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Tue, 28 Jun 2016 14:15:47 +0100 Subject: [PATCH 31/34] set postal_code as zip --- .../coffee/Features/Subscription/RecurlyWrapper.coffee | 4 +++- .../web/public/coffee/main/new-subscription.coffee | 1 - .../coffee/Subscription/RecurlyWrapperTests.coffee | 10 +++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee index 0d7aa99131..059c5fb02c 100644 --- a/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee +++ b/services/web/app/coffee/Features/Subscription/RecurlyWrapper.coffee @@ -10,9 +10,11 @@ module.exports = RecurlyWrapper = apiUrl : "https://api.recurly.com/v2" _addressToXml: (address) -> - allowedKeys = ['address1', 'address2', 'city', 'country', 'state', 'zip'] + allowedKeys = ['address1', 'address2', 'city', 'country', 'state', 'zip', 'postal_code'] resultString = "\n" for k, v of address + if k == 'postal_code' + k = 'zip' if v and (k in allowedKeys) resultString += "<#{k}#{if k == 'address2' then ' nil="nil"' else ''}>#{v || ''}\n" resultString += "\n" diff --git a/services/web/public/coffee/main/new-subscription.coffee b/services/web/public/coffee/main/new-subscription.coffee index b507690f4e..93c2c0a7cc 100644 --- a/services/web/public/coffee/main/new-subscription.coffee +++ b/services/web/public/coffee/main/new-subscription.coffee @@ -122,7 +122,6 @@ define [ country: $scope.data.country state: $scope.data.state postal_code: $scope.data.postal_code - zip: $scope.data.zip $http.post("/user/subscription/create", postData) .success (data, status, headers)-> sixpack.convert "in-editor-free-trial-plan", pricing.items.plan.code, (err)-> diff --git a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee index 549f6e0250..5a5e9fc40c 100644 --- a/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee @@ -354,11 +354,11 @@ describe "RecurlyWrapper", -> beforeEach -> @address = - address1: "addr_one" - address2: "addr_two" - country: "some_country" - state: "some_state" - zip: "some_zip" + address1: "addr_one" + address2: "addr_two" + country: "some_country" + state: "some_state" + postal_code: "some_zip" nonsenseKey: "rubbish" it 'should generate the correct xml', () -> From 88fb9558843446199c3bafa16755f146071ca357 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Tue, 28 Jun 2016 16:07:11 +0100 Subject: [PATCH 32/34] hook notifications handler up to make request which doesn't make request if url not set --- .../Features/Notifications/NotificationsHandler.coffee | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/web/app/coffee/Features/Notifications/NotificationsHandler.coffee b/services/web/app/coffee/Features/Notifications/NotificationsHandler.coffee index d3e2cb3cb9..a7cf6a4672 100644 --- a/services/web/app/coffee/Features/Notifications/NotificationsHandler.coffee +++ b/services/web/app/coffee/Features/Notifications/NotificationsHandler.coffee @@ -6,7 +6,7 @@ oneSecond = 1000 makeRequest = (opts, callback)-> if !settings.apis.notifications?.url? - return callback() + return callback(null, statusCode:200) else request(opts, callback) @@ -18,7 +18,7 @@ module.exports = json: true timeout: oneSecond method: "GET" - request opts, (err, res, unreadNotifications)-> + makeRequest opts, (err, res, unreadNotifications)-> statusCode = if res? then res.statusCode else 500 if err? or statusCode != 200 e = new Error("something went wrong getting notifications, #{err}, #{statusCode}") @@ -40,7 +40,7 @@ module.exports = templateKey:templateKey } logger.log opts:opts, "creating notification for user" - request opts, callback + makeRequest opts, callback markAsReadWithKey: (user_id, key, callback)-> opts = @@ -51,7 +51,7 @@ module.exports = key:key } logger.log user_id:user_id, key:key, "sending mark notification as read with key to notifications api" - request opts, callback + makeRequest opts, callback markAsRead: (user_id, notification_id, callback)-> @@ -60,4 +60,4 @@ module.exports = uri: "#{settings.apis.notifications?.url}/user/#{user_id}/notification/#{notification_id}" timeout:oneSecond logger.log user_id:user_id, notification_id:notification_id, "sending mark notification as read to notifications api" - request opts, callback + makeRequest opts, callback From 8f14526354c904531a4a2aaf3ac5c6205695f493 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Tue, 28 Jun 2016 17:07:27 +0100 Subject: [PATCH 33/34] added custom footer in email option --- services/web/app/coffee/Features/Email/EmailBuilder.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/web/app/coffee/Features/Email/EmailBuilder.coffee b/services/web/app/coffee/Features/Email/EmailBuilder.coffee index e14b9e4582..4bcf0c671d 100644 --- a/services/web/app/coffee/Features/Email/EmailBuilder.coffee +++ b/services/web/app/coffee/Features/Email/EmailBuilder.coffee @@ -3,6 +3,8 @@ PersonalEmailLayout = require("./Layouts/PersonalEmailLayout") NotificationEmailLayout = require("./Layouts/NotificationEmailLayout") settings = require("settings-sharelatex") + + templates = {} templates.registered = @@ -114,6 +116,8 @@ module.exports = template = templates[templateName] opts.siteUrl = settings.siteUrl opts.body = template.compiledTemplate(opts) + if settings.email?.templates?.customFooter? + opts.body += settings.email?.templates?.customFooter return { subject : template.subject(opts) html: template.layout(opts) From d037cb93a9f0a3330ffe28f7c56902fdcd49167d Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Wed, 29 Jun 2016 10:42:51 +0100 Subject: [PATCH 34/34] Wiki styles clean-up. --- services/web/public/stylesheets/app/wiki.less | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/services/web/public/stylesheets/app/wiki.less b/services/web/public/stylesheets/app/wiki.less index 2bc962961f..5f7462d02c 100644 --- a/services/web/public/stylesheets/app/wiki.less +++ b/services/web/public/stylesheets/app/wiki.less @@ -41,11 +41,6 @@ .example { max-width: 100%; - & > div { - display: block !important; - width: auto !important; - } - .code { pre { background-color: @gray-lightest; @@ -60,9 +55,9 @@ padding-top: 10px; img { - width: auto !important; - height: auto !important; - max-width: 100% !important; + width: auto; + height: auto; + max-width: 100%; box-shadow: 0 1px 3px @gray-light; border-radius: 6px; }