From e9d3ea7b2b55ff6bb12cbfc2e382d6d3851cff23 Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 2 Nov 2020 03:33:39 +1100 Subject: [PATCH 01/37] Update CloudCode.react.js --- src/dashboard/Data/CloudCode/CloudCode.react.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/dashboard/Data/CloudCode/CloudCode.react.js b/src/dashboard/Data/CloudCode/CloudCode.react.js index 9387271680..5afef158b1 100644 --- a/src/dashboard/Data/CloudCode/CloudCode.react.js +++ b/src/dashboard/Data/CloudCode/CloudCode.react.js @@ -15,7 +15,8 @@ import styles from 'dashboard/Data/CloudCode/CloudCode.scss'; import Toolbar from 'components/Toolbar/Toolbar.react'; function getPath(params) { - return params.splat; + const last = params.location.pathname.split('cloud_code/')[1] + return last; } export default class CloudCode extends DashboardView { @@ -31,12 +32,12 @@ export default class CloudCode extends DashboardView { } componentWillMount() { - this.fetchSource(this.context.currentApp, getPath(this.props.params)); + this.fetchSource(this.context.currentApp, getPath(this.props)); } componentWillReceiveProps(nextProps, nextContext) { if (this.context !== nextContext) { - this.fetchSource(nextContext.currentApp, getPath(nextProps.params)); + this.fetchSource(nextContext.currentApp, getPath(nextProps)); } } @@ -52,7 +53,7 @@ export default class CloudCode extends DashboardView { if (!fileName || release.files[fileName] === undefined) { // Means we're still in /cloud_code/. Let's redirect to /cloud_code/main.js - history.replace(this.context.generatePath('cloud_code/main.js')) + history.replace(this.context.generatePath(`cloud_code/${Object.keys(release.files)[0]}`)) } else { // Means we can load /cloud_code/ app.getSource(fileName).then( @@ -66,7 +67,7 @@ export default class CloudCode extends DashboardView { } renderSidebar() { - let current = getPath(this.props.params) || ''; + let current = getPath(this.props) || ''; let files = this.state.files; if (!files) { return null; @@ -90,7 +91,7 @@ export default class CloudCode extends DashboardView { renderContent() { let toolbar = null; let content = null; - let fileName = getPath(this.props.params); + let fileName = getPath(this.props); if (!this.state.files || Object.keys(this.state.files).length === 0) { content = ( From 2a5c0503e8aaccb4e33dbecb62be38ea0489cde8 Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 2 Nov 2020 14:24:15 +1100 Subject: [PATCH 02/37] Allow Writing Cloud Code --- .../SaveButton/SaveButton.example.js | 3 ++ src/components/SaveButton/SaveButton.react.js | 2 +- .../Data/CloudCode/CloudCode.react.js | 47 ++++++++++++++++--- src/lib/ParseApp.js | 22 ++++----- 4 files changed, 55 insertions(+), 19 deletions(-) diff --git a/src/components/SaveButton/SaveButton.example.js b/src/components/SaveButton/SaveButton.example.js index f7e55af774..bd2d50a3f6 100644 --- a/src/components/SaveButton/SaveButton.example.js +++ b/src/components/SaveButton/SaveButton.example.js @@ -55,6 +55,9 @@ export const demos = [
+
+ +
) }, { diff --git a/src/components/SaveButton/SaveButton.react.js b/src/components/SaveButton/SaveButton.react.js index 0bb741fa86..f7aced23db 100644 --- a/src/components/SaveButton/SaveButton.react.js +++ b/src/components/SaveButton/SaveButton.react.js @@ -52,7 +52,7 @@ let SaveButton = ({ ; }; -SaveButton.States = keyMirror(['SAVING', 'SUCCEEDED', 'FAILED']); +SaveButton.States = keyMirror(['SAVING', 'SUCCEEDED', 'FAILED', 'WAITING']); let {...forwardedButtonProps} = Button.propTypes; delete forwardedButtonProps.value; diff --git a/src/dashboard/Data/CloudCode/CloudCode.react.js b/src/dashboard/Data/CloudCode/CloudCode.react.js index 5afef158b1..f07aa84704 100644 --- a/src/dashboard/Data/CloudCode/CloudCode.react.js +++ b/src/dashboard/Data/CloudCode/CloudCode.react.js @@ -5,7 +5,7 @@ * This source code is licensed under the license found in the LICENSE file in * the root directory of this source tree. */ -import CodeSnippet from 'components/CodeSnippet/CodeSnippet.react'; +import CodeEditor from 'components/CodeEditor/CodeEditor.react'; import DashboardView from 'dashboard/DashboardView.react'; import EmptyState from 'components/EmptyState/EmptyState.react'; import FileTree from 'components/FileTree/FileTree.react'; @@ -13,6 +13,7 @@ import history from 'dashboard/history'; import React from 'react'; import styles from 'dashboard/Data/CloudCode/CloudCode.scss'; import Toolbar from 'components/Toolbar/Toolbar.react'; +import SaveButton from 'components/SaveButton/SaveButton.react'; function getPath(params) { const last = params.location.pathname.split('cloud_code/')[1] @@ -27,7 +28,9 @@ export default class CloudCode extends DashboardView { this.state = { files: undefined, - source: undefined + source: undefined, + saveState: SaveButton.States.WAITING, + saveError: '', }; } @@ -56,8 +59,14 @@ export default class CloudCode extends DashboardView { history.replace(this.context.generatePath(`cloud_code/${Object.keys(release.files)[0]}`)) } else { // Means we can load /cloud_code/ + this.setState({ source: undefined }) app.getSource(fileName).then( - (source) => this.setState({ source: source }), + (source) => { + this.setState({ source: source }) + if (this.editor) { + this.editor.value = source; + } + }, () => this.setState({ source: undefined }) ); } @@ -87,7 +96,23 @@ export default class CloudCode extends DashboardView { ); } - + async getCode() { + if (!this.editor) { + return; + } + this.setState({ saveState: SaveButton.States.SAVING }); + let fileName = getPath(this.props); + try { + await this.context.currentApp.saveSource(fileName,this.editor.value); + this.setState({ saveState: SaveButton.States.SUCCEEDED }); + setTimeout(()=> { + this.setState({ saveState: SaveButton.States.WAITING }); + },2000); + } catch (e) { + this.setState({ saveState: SaveButton.States.FAILED }); + this.setState({ saveError: e.message || e }); + } + } renderContent() { let toolbar = null; let content = null; @@ -111,10 +136,20 @@ export default class CloudCode extends DashboardView { subsection={fileName} />; let source = this.state.files[fileName]; - if (source && source.source) { + if ((source && source.source) || this.state.source) { content = (
- + (this.editor = editor)} + fontSize={'14px'} + /> + this.getCode(this)}>
); } diff --git a/src/lib/ParseApp.js b/src/lib/ParseApp.js index 0065109f06..f0b5f0110a 100644 --- a/src/lib/ParseApp.js +++ b/src/lib/ParseApp.js @@ -117,6 +117,15 @@ export default class ParseApp { return this.apiRequest('GET', path, {}, { useMasterKey: true }); } + /** + * Saves source of a Cloud Code hosted file from api.parse.com + * fileName - the name of the file to be fetched + * data - the text to save to the cloud file + */ + saveSource(fileName,data) { + return this.apiRequest('POST', `scripts/${fileName}`, {data}, { useMasterKey: true }); + } + /** * Fetches source of a Cloud Code hosted file from api.parse.com * fileName - the name of the file to be fetched @@ -127,22 +136,11 @@ export default class ParseApp { // No release yet return Promise.resolve(null); } - - let fileMetaData = release.files[fileName]; - if (fileMetaData && fileMetaData.source) { - return Promise.resolve(fileMetaData.source); - } - - let params = { - version: fileMetaData.version, - checksum: fileMetaData.checksum - } - return this.apiRequest('GET', `scripts/${fileName}`, params, { useMasterKey: true }); + return this.apiRequest('GET', `scripts/${fileName}`, {}, { useMasterKey: true }); }).then((source) => { if (this.latestRelease.files) { this.latestRelease.files[fileName].source = source; } - return Promise.resolve(source); }); } From 0cb78945f8f9968d1a2274d37d37385a05b4eeda Mon Sep 17 00:00:00 2001 From: dblythy Date: Wed, 18 Nov 2020 09:07:51 +1100 Subject: [PATCH 03/37] Add MFA to Dashboard --- Parse-Dashboard/Authentication.js | 19 +++++++++++++++---- Parse-Dashboard/index.js | 10 ++++++++++ package.json | 1 + src/dashboard/Dashboard.js | 1 + src/login/Login.js | 3 +++ 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/Parse-Dashboard/Authentication.js b/Parse-Dashboard/Authentication.js index ef6bf88bae..636ed76391 100644 --- a/Parse-Dashboard/Authentication.js +++ b/Parse-Dashboard/Authentication.js @@ -3,6 +3,7 @@ var bcrypt = require('bcryptjs'); var csrf = require('csurf'); var passport = require('passport'); var LocalStrategy = require('passport-local').Strategy; +const authenticator = require('otplib').authenticator; /** * Constructor for Authentication class @@ -21,10 +22,12 @@ function initialize(app, options) { options = options || {}; var self = this; passport.use('local', new LocalStrategy( - function(username, password, cb) { + {passReqToCallback:true}, + function(req, username, password, cb) { var match = self.authenticate({ name: username, - pass: password + pass: password, + otpCode: req.body.otpCode }); if (!match.matchingUsername) { return cb(null, false, { message: 'Invalid username or password' }); @@ -90,16 +93,24 @@ function authenticate(userToTest, usernameOnly) { //the provided auth matches one of the users this.validUsers.find(user => { let isAuthenticated = false; + let otpValidated = true; + if (user.mfa && !usernameOnly) { + if (!userToTest.otpCode) { + otpValidated = false; + } + if (!authenticator.verify({ token:userToTest.otpCode, secret: user.mfa })) { + otpValidated = false; + } + } let usernameMatches = userToTest.name == user.user; let passwordMatches = this.useEncryptedPasswords && !usernameOnly ? bcrypt.compareSync(userToTest.pass, user.pass) : userToTest.pass == user.pass; - if (usernameMatches && (usernameOnly || passwordMatches)) { + if (usernameMatches && (usernameOnly || passwordMatches) && otpValidated) { isAuthenticated = true; matchingUsername = user.user; // User restricted apps appsUserHasAccessTo = user.apps || null; isReadOnly = !!user.readOnly; // make it true/false } - return isAuthenticated; }) ? true : false; diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js index 42484d5fce..56d8b66e91 100644 --- a/Parse-Dashboard/index.js +++ b/Parse-Dashboard/index.js @@ -11,6 +11,7 @@ const path = require('path'); const jsonFile = require('json-file-plus'); const express = require('express'); const parseDashboard = require('./app'); +const authenticator = require('otplib').authenticator; const program = require('commander'); program.option('--appId [appId]', 'the app Id of the app you would like to manage.'); @@ -26,6 +27,7 @@ program.option('--mountPath [mountPath]', 'the mount path to run parse-dashboard program.option('--allowInsecureHTTP [allowInsecureHTTP]', 'set this flag when you are running the dashboard behind an HTTPS load balancer or proxy with early SSL termination.'); program.option('--sslKey [sslKey]', 'the path to the SSL private key.'); program.option('--sslCert [sslCert]', 'the path to the SSL certificate.'); +program.option('--generateMFA [username]', 'helper tool to allow you to generate secure MFA secrets.'); program.option('--trustProxy [trustProxy]', 'set this flag when you are behind a front-facing proxy, such as when hosting on Heroku. Uses X-Forwarded-* headers to determine the client\'s connection and IP address.'); program.option('--cookieSessionSecret [cookieSessionSecret]', 'set the cookie session secret, defaults to a random string. You should set that value if you want sessions to work across multiple server, or across restarts'); @@ -57,6 +59,14 @@ let configUserPassword = program.userPassword || process.env.PARSE_DASHBOARD_USE let configSSLKey = program.sslKey || process.env.PARSE_DASHBOARD_SSL_KEY; let configSSLCert = program.sslCert || process.env.PARSE_DASHBOARD_SSL_CERT; +if (program.generateMFA) { + // I can't seem to get this working. + const secret = authenticator.generateSecret(); + const otpauth = authenticator.keyuri(program.generateMFA, configAppName, secret); + console.log(`MFA secret for ${program.generateMFA} is ${secret}\nDo not share this code. Set it as mfa for this user in parse-dashboard-config.json`); + console.log(`OTPAUTH URL for ${program.generateMFA} is ${otpauth}\nShare this with ${program.generateMFA}`); +} + function handleSIGs(server) { const signals = { 'SIGINT': 2, diff --git a/package.json b/package.json index 8845ecef76..a48a9d9308 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "immutable-devtools": "0.1.5", "js-beautify": "1.11.0", "json-file-plus": "3.2.0", + "otplib": "^12.0.1", "package-json": "6.5.0", "parse": "2.17.0", "passport": "0.4.1", diff --git a/src/dashboard/Dashboard.js b/src/dashboard/Dashboard.js index 6ccc04bc2b..41c643d3d6 100644 --- a/src/dashboard/Dashboard.js +++ b/src/dashboard/Dashboard.js @@ -57,6 +57,7 @@ import { Route, Redirect } from 'react-router-dom'; import createClass from 'create-react-class'; import { Helmet } from 'react-helmet'; import Playground from './Data/Playground/Playground.react'; +import { authenticator } from 'otplib'; const ShowSchemaOverview = false; //In progress features. Change false to true to work on this feature. diff --git a/src/login/Login.js b/src/login/Login.js index 74994d0600..0a0b5dc75a 100644 --- a/src/login/Login.js +++ b/src/login/Login.js @@ -41,6 +41,9 @@ export default class Login extends React.Component { } /> + } /> {this.errors ?
{this.errors} From a7af2f456f043731fb674bafbfa77ec734ba3026 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 15:43:09 +1000 Subject: [PATCH 04/37] add inquirer --- Parse-Dashboard/Authentication.js | 12 +- Parse-Dashboard/index.js | 64 +- package-lock.json | 2217 ++++++++++++++++++++--------- package.json | 2 + src/dashboard/Dashboard.js | 1 - 5 files changed, 1589 insertions(+), 707 deletions(-) diff --git a/Parse-Dashboard/Authentication.js b/Parse-Dashboard/Authentication.js index 636ed76391..34ae9820df 100644 --- a/Parse-Dashboard/Authentication.js +++ b/Parse-Dashboard/Authentication.js @@ -32,6 +32,9 @@ function initialize(app, options) { if (!match.matchingUsername) { return cb(null, false, { message: 'Invalid username or password' }); } + if (!match.otpValid) { + return cb(null, false, { message: 'Invalid OTP code.' }); + } cb(null, match.matchingUsername); }) ); @@ -85,6 +88,7 @@ function authenticate(userToTest, usernameOnly) { let appsUserHasAccessTo = null; let matchingUsername = null; let isReadOnly = false; + let otpValid = true; //they provided auth let isAuthenticated = userToTest && @@ -93,18 +97,17 @@ function authenticate(userToTest, usernameOnly) { //the provided auth matches one of the users this.validUsers.find(user => { let isAuthenticated = false; - let otpValidated = true; if (user.mfa && !usernameOnly) { if (!userToTest.otpCode) { - otpValidated = false; + otpValid = false; } if (!authenticator.verify({ token:userToTest.otpCode, secret: user.mfa })) { - otpValidated = false; + otpValid = false; } } let usernameMatches = userToTest.name == user.user; let passwordMatches = this.useEncryptedPasswords && !usernameOnly ? bcrypt.compareSync(userToTest.pass, user.pass) : userToTest.pass == user.pass; - if (usernameMatches && (usernameOnly || passwordMatches) && otpValidated) { + if (usernameMatches && (usernameOnly || passwordMatches)) { isAuthenticated = true; matchingUsername = user.user; // User restricted apps @@ -117,6 +120,7 @@ function authenticate(userToTest, usernameOnly) { return { isAuthenticated, matchingUsername, + otpValid, appsUserHasAccessTo, isReadOnly, }; diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js index 56d8b66e91..6e66b98445 100644 --- a/Parse-Dashboard/index.js +++ b/Parse-Dashboard/index.js @@ -27,9 +27,9 @@ program.option('--mountPath [mountPath]', 'the mount path to run parse-dashboard program.option('--allowInsecureHTTP [allowInsecureHTTP]', 'set this flag when you are running the dashboard behind an HTTPS load balancer or proxy with early SSL termination.'); program.option('--sslKey [sslKey]', 'the path to the SSL private key.'); program.option('--sslCert [sslCert]', 'the path to the SSL certificate.'); -program.option('--generateMFA [username]', 'helper tool to allow you to generate secure MFA secrets.'); program.option('--trustProxy [trustProxy]', 'set this flag when you are behind a front-facing proxy, such as when hosting on Heroku. Uses X-Forwarded-* headers to determine the client\'s connection and IP address.'); program.option('--cookieSessionSecret [cookieSessionSecret]', 'set the cookie session secret, defaults to a random string. You should set that value if you want sessions to work across multiple server, or across restarts'); +program.option('--createUser', 'helper tool to allow you to generate secure user passwords and secrets. Use this once on a trusted device only.'); program.parse(process.argv); @@ -59,12 +59,62 @@ let configUserPassword = program.userPassword || process.env.PARSE_DASHBOARD_USE let configSSLKey = program.sslKey || process.env.PARSE_DASHBOARD_SSL_KEY; let configSSLCert = program.sslCert || process.env.PARSE_DASHBOARD_SSL_CERT; -if (program.generateMFA) { - // I can't seem to get this working. - const secret = authenticator.generateSecret(); - const otpauth = authenticator.keyuri(program.generateMFA, configAppName, secret); - console.log(`MFA secret for ${program.generateMFA} is ${secret}\nDo not share this code. Set it as mfa for this user in parse-dashboard-config.json`); - console.log(`OTPAUTH URL for ${program.generateMFA} is ${otpauth}\nShare this with ${program.generateMFA}`); +if (program.createUser) { + (async () => { + const inquirer = require('inquirer'); + const result = {} + const displayResult = {}; + const {username, password} = await inquirer.prompt([{ + type: 'input', + name: 'username', + message: 'Please enter the username.', + }, { + type: 'confirm', + name: 'password', + message: 'Would you like to generate a secure password?', + }]); + displayResult.username = username; + result.user = username; + if (!password) { + const {password} = await inquirer.prompt([{ + type: 'password', + name: 'password', + message: `Please enter the password for ${username}`, + }]); + displayResult.password = password; + result.pass = password + } else { + const password = require('crypto').randomBytes(20).toString('hex'); + const bcrypt = require('bcryptjs'); + const salt = bcrypt.genSaltSync(10); + const hash = bcrypt.hashSync(password, salt); + result.pass = hash; + displayResult.password = password; + } + const {mfa} = await inquirer.prompt([{ + type: 'confirm', + name: 'mfa', + message: `Would you like to an MFA secret for ${username}?`, + }]) + if (mfa) { + const secret = authenticator.generateSecret(); + result.mfa = secret; + displayResult.mfa = authenticator.keyuri(username, configAppName || 'Parse Dashboard', secret); + } + const proc = require('child_process').spawn('pbcopy'); + proc.stdin.write(JSON.stringify(displayResult)); + proc.stdin.end(); + console.log(`\n\nYour new user details' raw credentials have been copied to your clipboard. Add the following to your Parse Dashboard config:\n\n${JSON.stringify(result)}\n\n`); + + if (displayResult.mfa) { + const QRCode = require('qrcode') + QRCode.toString(displayResult.mfa, {type:'terminal'}, function (err, url) { + console.log(url) + }) + } + + })(); + return; } function handleSIGs(server) { diff --git a/package-lock.json b/package-lock.json index 5df5c122ad..4ff7812810 100644 --- a/package-lock.json +++ b/package-lock.json @@ -107,15 +107,6 @@ "integrity": "sha512-ZII+/xUFfb9ezDU2gad114+zScxVFMVlZ91f8fGApMzlS1kkqoyLnC4AJaQ1Ya/X+b63I20B4Gd+eCL8QuB4sA==", "dev": true }, - "@apollographql/graphql-playground-html": { - "version": "1.6.29", - "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.29.tgz", - "integrity": "sha512-xCcXpoz52rI4ksJSdOCxeOCn2DLocxwHf9dVT/Q90Pte1LX+LY+91SFtJF3KXVHH8kEin+g1KKCQPKBjZJfWNA==", - "dev": true, - "requires": { - "xss": "^1.0.8" - } - }, "@apollographql/graphql-upload-8-fork": { "version": "8.1.3", "resolved": "https://registry.npmjs.org/@apollographql/graphql-upload-8-fork/-/graphql-upload-8-fork-8.1.3.tgz", @@ -1409,11 +1400,33 @@ "integrity": "sha512-ufmI5mJQa8NJczzfkh0pUttKvspqDcT5LLakA3jUmOrrE4d4NVj6onZlazdTzF5sAepSNqanFnwhrxZpCAJMKg==", "dev": true, "requires": { + "@graphql-tools/merge": "^8.1.0", "@graphql-tools/utils": "^8.2.0", "tslib": "~2.3.0", "value-or-promise": "1.0.10" }, "dependencies": { + "@graphql-tools/merge": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.1.1.tgz", + "integrity": "sha512-zyeUbFG5zasSQC6LnBxzhmPTLYeeT3c0ijYfmFlIlOLiTAdRgCjIba03l6kKHcCiMDJYr+P+Nz5kKYLGqPSSjQ==", + "dev": true, + "requires": { + "@graphql-tools/utils": "^8.2.2", + "tslib": "~2.3.0" + }, + "dependencies": { + "@graphql-tools/utils": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.2.2.tgz", + "integrity": "sha512-29FFY5U4lpXuBiW9dRvuWnBVwGhWbGLa2leZcAMU/Pz47Cr/QLZGVgpLBV9rt+Gbs7wyIJM7t7EuksPs0RDm3g==", + "dev": true, + "requires": { + "tslib": "~2.3.0" + } + } + } + }, "@graphql-tools/utils": { "version": "8.2.1", "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.2.1.tgz", @@ -1753,103 +1766,46 @@ "integrity": "sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg==", "dev": true }, - "@napi-rs/triples": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@napi-rs/triples/-/triples-1.0.3.tgz", - "integrity": "sha512-jDJTpta+P4p1NZTFVLHJ/TLFVYVcOqv6l8xwOeBKNPMgY/zDYH/YH7SJbvrr/h1RcS9GzbPcLKGzpuK9cV56UA==", - "dev": true, - "optional": true + "@otplib/core": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@otplib/core/-/core-12.0.1.tgz", + "integrity": "sha512-4sGntwbA/AC+SbPhbsziRiD+jNDdIzsZ3JUyfZwjtKyc/wufl1pnSIaG4Uqx8ymPagujub0o92kgBnB89cuAMA==" }, - "@node-rs/bcrypt": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt/-/bcrypt-1.1.0.tgz", - "integrity": "sha512-5vjztYYcPCyvamO3C+hrNaVplZC9yEMzGxJECliQR5hkUOQdrtulCpigNOr1POWpC1YsJH0ZL+ktWop+cl5Qqw==", - "dev": true, - "optional": true, + "@otplib/plugin-crypto": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@otplib/plugin-crypto/-/plugin-crypto-12.0.1.tgz", + "integrity": "sha512-qPuhN3QrT7ZZLcLCyKOSNhuijUi9G5guMRVrxq63r9YNOxxQjPm59gVxLM+7xGnHnM6cimY57tuKsjK7y9LM1g==", "requires": { - "@node-rs/bcrypt-android-arm64": "^1.1.0", - "@node-rs/bcrypt-darwin-arm64": "^1.1.0", - "@node-rs/bcrypt-darwin-x64": "^1.1.0", - "@node-rs/bcrypt-linux-arm-gnueabihf": "^1.1.0", - "@node-rs/bcrypt-linux-arm64-gnu": "^1.1.0", - "@node-rs/bcrypt-linux-x64-gnu": "^1.1.0", - "@node-rs/bcrypt-linux-x64-musl": "^1.1.0", - "@node-rs/bcrypt-win32-ia32-msvc": "^1.1.0", - "@node-rs/bcrypt-win32-x64-msvc": "^1.1.0", - "@node-rs/helper": "^1.1.0" + "@otplib/core": "^12.0.1" } }, - "@node-rs/bcrypt-android-arm64": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm64/-/bcrypt-android-arm64-1.4.1.tgz", - "integrity": "sha512-CP/8CbrhLUjHW2OrOd6tgcx2FKMTWqUDAUCDtUq4ZBlUIn7P/e+/iosNK9QNBcT8AUMNr4TD1n5QW+SKM2Zk/Q==", - "dev": true, - "optional": true - }, - "@node-rs/bcrypt-darwin-arm64": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-arm64/-/bcrypt-darwin-arm64-1.4.1.tgz", - "integrity": "sha512-6Digb49rzOS36X6qXaU4a6JxDsxPlWj09AFyF/kBhhmRocDKHyO2dnR8vexhjlzLyMlS00VL2q8kPei2Q8IAYQ==", - "dev": true, - "optional": true - }, - "@node-rs/bcrypt-darwin-x64": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-x64/-/bcrypt-darwin-x64-1.4.1.tgz", - "integrity": "sha512-Rs/ySQ0CHRXJCOrSWod0b4fmF3Z+EP4RygSXBsV/NTVggHB2TrSdHRYajG9ZHB7P0acs2HHb1GcP5jOpggpMvA==", - "dev": true, - "optional": true - }, - "@node-rs/bcrypt-linux-arm-gnueabihf": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm-gnueabihf/-/bcrypt-linux-arm-gnueabihf-1.4.1.tgz", - "integrity": "sha512-oiRR4vJUtwO2DG91oyWDHYx9oU79190l0FIgYKwfXjt9ge5ZFr+fVjXbayuANxWCAtt178u3HYwWR1ayHhRpUQ==", - "dev": true, - "optional": true - }, - "@node-rs/bcrypt-linux-arm64-gnu": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-gnu/-/bcrypt-linux-arm64-gnu-1.4.1.tgz", - "integrity": "sha512-oA/WNbHZ/RZ5Sm/NhbprkDRUMVzekpzrigYEC+XJaJSaVpSL5Qyif1mZLZW+AWNIoEM0LZ7/UFe8KyS2+gcW5Q==", - "dev": true, - "optional": true - }, - "@node-rs/bcrypt-linux-x64-gnu": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-gnu/-/bcrypt-linux-x64-gnu-1.4.1.tgz", - "integrity": "sha512-CvG1gBTAg0Vv9MUbESH/3g2k+oak+NB3jVv4vreTsQu8jI7AVk4PSCMygiV+oWaoNA4Yhu6H+M+M6JccvtaYtg==", - "dev": true, - "optional": true - }, - "@node-rs/bcrypt-linux-x64-musl": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-musl/-/bcrypt-linux-x64-musl-1.4.1.tgz", - "integrity": "sha512-Q71g6aJ88VDz8ljIhFd8g3Uj+k+n7vhe6h1o/aO/Atqv2+YcRuZlrGohXvwf4Vu4RYNi99EkQu+uK46QjPJTmQ==", - "dev": true, - "optional": true - }, - "@node-rs/bcrypt-win32-ia32-msvc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-ia32-msvc/-/bcrypt-win32-ia32-msvc-1.4.1.tgz", - "integrity": "sha512-A8S9557mVubI6o6dlYPZwdOKQBmA2sEzzwFIIxx257Mv5Zwt44x7hXwy9DBc98NaIyVBrC9eG5zxpAu/12r2lQ==", - "dev": true, - "optional": true + "@otplib/plugin-thirty-two": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@otplib/plugin-thirty-two/-/plugin-thirty-two-12.0.1.tgz", + "integrity": "sha512-MtT+uqRso909UkbrrYpJ6XFjj9D+x2Py7KjTO9JDPhL0bJUYVu5kFP4TFZW4NFAywrAtFRxOVY261u0qwb93gA==", + "requires": { + "@otplib/core": "^12.0.1", + "thirty-two": "^1.0.2" + } }, - "@node-rs/bcrypt-win32-x64-msvc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-x64-msvc/-/bcrypt-win32-x64-msvc-1.4.1.tgz", - "integrity": "sha512-24xUag1/BwuBviRpozXnYQKGsqfriQw3VaCBQb6chvUTwQVjrndYmZfW+TMrCWLgnD1qRT3T0u3cZoOY9QxknA==", - "dev": true, - "optional": true + "@otplib/preset-default": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@otplib/preset-default/-/preset-default-12.0.1.tgz", + "integrity": "sha512-xf1v9oOJRyXfluBhMdpOkr+bsE+Irt+0D5uHtvg6x1eosfmHCsCC6ej/m7FXiWqdo0+ZUI6xSKDhJwc8yfiOPQ==", + "requires": { + "@otplib/core": "^12.0.1", + "@otplib/plugin-crypto": "^12.0.1", + "@otplib/plugin-thirty-two": "^12.0.1" + } }, - "@node-rs/helper": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@node-rs/helper/-/helper-1.2.1.tgz", - "integrity": "sha512-R5wEmm8nbuQU0YGGmYVjEc0OHtYsuXdpRG+Ut/3wZ9XAvQWyThN08bTh2cBJgoZxHQUPtvRfeQuxcAgLuiBISg==", - "dev": true, - "optional": true, + "@otplib/preset-v11": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@otplib/preset-v11/-/preset-v11-12.0.1.tgz", + "integrity": "sha512-9hSetMI7ECqbFiKICrNa4w70deTUfArtwXykPUvSHWOdzOlfa9ajglu7mNCntlvxycTiOAXkQGwjQCzzDEMRMg==", "requires": { - "@napi-rs/triples": "^1.0.3" + "@otplib/core": "^12.0.1", + "@otplib/plugin-crypto": "^12.0.1", + "@otplib/plugin-thirty-two": "^12.0.1" } }, "@parse/fs-files-adapter": { @@ -1858,35 +1814,6 @@ "integrity": "sha512-kr7Ti2eYOm14p05S86yriJdMtawL6qln3Dn5eekrwY14ih4jrjH/E+QlEpBUSBzN64fluFxciFOyjdbwDGWsGw==", "dev": true }, - "@parse/node-apn": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-4.1.1.tgz", - "integrity": "sha512-stWlQE95w5T0vkVYscoq/S3eXPQ1qzdQbKKQ8GAdw4CSNxRWLWgOH50byUR30thnQ93RshLCH5ROkvXMqzzLtw==", - "dev": true, - "requires": { - "debug": "4.3.2", - "jsonwebtoken": "8.5.1", - "node-forge": "0.10.0", - "verror": "1.10.0" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, "@parse/node-gcm": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@parse/node-gcm/-/node-gcm-1.0.2.tgz", @@ -1971,16 +1898,65 @@ } } }, - "@parse/push-adapter": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-3.4.1.tgz", - "integrity": "sha512-iev69kbwhXbez5nfEwB2GkCWBLUmRlImQTmHPpLnHBJfATYKyXf/H41WQhBPuwwScZBVp9ABsIsjjKy8iKg3fw==", + "@parse/s3-files-adapter": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@parse/s3-files-adapter/-/s3-files-adapter-1.6.0.tgz", + "integrity": "sha512-t/91hlZ4+GIA68zmJIX9lkIAxPZVRJROPYWGGyxE9CLGsSvBr/eaIHs6LnKyM012lBHzwJwoLxMkN4RvJADgbg==", + "dev": true, + "requires": { + "aws-sdk": "2.761.0", + "parse": "2.17.0" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", + "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/runtime-corejs3": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz", + "integrity": "sha512-qh5IR+8VgFz83VBa6OkaET6uN/mJOhHONuy3m1sgF0CV6mXdPSEBdA7e1eUbVvyNtANjMbg22JUv71BaDXLY6A==", + "dev": true, + "requires": { + "core-js-pure": "^3.0.0", + "regenerator-runtime": "^0.13.4" + } + }, + "parse": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/parse/-/parse-2.17.0.tgz", + "integrity": "sha512-1hWoMNW39LH5YV3xCds9LyD8SsKD6FUwlD1Kn8ZlXNosg6WgF+s3ZSQUzT5AJ/9YPUoC/y1PoCO79FumrBYftA==", + "dev": true, + "requires": { + "@babel/runtime": "7.11.2", + "@babel/runtime-corejs3": "7.11.2", + "crypto-js": "4.0.0", + "react-native-crypto-js": "1.0.0", + "uuid": "3.4.0", + "ws": "7.3.1", + "xmlhttprequest": "1.8.0" + } + }, + "ws": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", + "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", + "dev": true + } + } + }, + "@parse/simple-mailgun-adapter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@parse/simple-mailgun-adapter/-/simple-mailgun-adapter-1.1.0.tgz", + "integrity": "sha512-9Eaj25HQ7RpcA6gsTnimXtlLcyLpP9PKSFE9DF79ahgndbdyCjpNd9jQxpBaBlsCsDE+D5LlXfckMqqJPo+pjQ==", "dev": true, "requires": { - "@parse/node-apn": "4.1.1", - "@parse/node-gcm": "1.0.2", - "npmlog": "4.1.2", - "parse": "3.3.0" + "mailgun-js": "0.18.0" } }, "@popperjs/core": { @@ -2173,12 +2149,6 @@ "@types/node": "*" } }, - "@types/cors": { - "version": "2.8.10", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.10.tgz", - "integrity": "sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ==", - "dev": true - }, "@types/express": { "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", @@ -2840,7 +2810,6 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, "requires": { "type-fest": "^0.21.3" }, @@ -2848,16 +2817,14 @@ "type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" } } }, "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "ansi-styles": { "version": "3.2.1", @@ -3082,42 +3049,6 @@ "integrity": "sha512-lO5oTjgiC3vlVg2RKr3RiXIIQ5pGXBFxYGGUkKDhTud3jMIhs+gel8L8zsEjKaKxkjHhCQAA/bcEfYiKkGQIvA==", "dev": true }, - "apollo-server-express": { - "version": "2.25.2", - "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.25.2.tgz", - "integrity": "sha512-A2gF2e85vvDugPlajbhr0A14cDFDIGX0mteNOJ8P3Z3cIM0D4hwrWxJidI+SzobefDIyIHu1dynFedJVhV0euQ==", - "dev": true, - "requires": { - "@apollographql/graphql-playground-html": "1.6.27", - "@types/accepts": "^1.3.5", - "@types/body-parser": "1.19.0", - "@types/cors": "2.8.10", - "@types/express": "^4.17.12", - "@types/express-serve-static-core": "^4.17.21", - "accepts": "^1.3.5", - "apollo-server-core": "^2.25.2", - "apollo-server-types": "^0.9.0", - "body-parser": "^1.18.3", - "cors": "^2.8.5", - "express": "^4.17.1", - "graphql-subscriptions": "^1.0.0", - "graphql-tools": "^4.0.8", - "parseurl": "^1.3.2", - "subscriptions-transport-ws": "^0.9.19", - "type-is": "^1.6.16" - }, - "dependencies": { - "@apollographql/graphql-playground-html": { - "version": "1.6.27", - "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.27.tgz", - "integrity": "sha512-tea2LweZvn6y6xFV11K0KC8ETjmm52mQrW+ezgB2O/aTQf8JGyFmMcRPFgUaQZeHbWdm8iisDC6EjOKsXu0nfw==", - "dev": true, - "requires": { - "xss": "^1.0.8" - } - } - } - }, "apollo-server-plugin-base": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.13.0.tgz", @@ -3309,12 +3240,6 @@ } } }, - "assert-options": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.7.0.tgz", - "integrity": "sha512-7q9uNH/Dh8gFgpIIb9ja8PJEWA5AQy3xnBC8jtKs8K/gNVCr1K6kIvlm59HUyYgvM7oEDoLzGgPcGd9FqhtXEQ==", - "dev": true - }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -3327,6 +3252,23 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "ast-types": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", + "integrity": "sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==", + "dev": true, + "requires": { + "tslib": "^2.0.1" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true + } + } + }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", @@ -3381,6 +3323,98 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, + "aws-sdk": { + "version": "2.761.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.761.0.tgz", + "integrity": "sha512-mSzdiqlnruFlJYrQVWPMyPQ8ynJe9P5QVD+edv8HFlYDQNOwpPCjlqI9kE1VE3cVcxkh0j2Q2kfLQa/pAY2w7Q==", + "dev": true, + "requires": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + }, + "dependencies": { + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=", + "dev": true + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "dev": true + } + } + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -3393,15 +3427,6 @@ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", "dev": true }, - "axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", - "dev": true, - "requires": { - "follow-redirects": "^1.10.0" - } - }, "babel-eslint": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", @@ -3627,8 +3652,7 @@ "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "basic-auth": { "version": "1.1.0", @@ -3948,12 +3972,25 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "requires": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -3966,11 +4003,15 @@ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", "dev": true }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "buffer-writer": { "version": "2.0.0", @@ -4132,8 +4173,7 @@ "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "camelcase-keys": { "version": "2.1.0", @@ -4192,8 +4232,7 @@ "chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, "check-types": { "version": "7.4.0", @@ -4330,48 +4369,28 @@ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" }, - "cli-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.0.tgz", - "integrity": "sha512-a0VZ8LeraW0jTuCkuAGMNufareGHhyZU9z8OGsW0gXd1hZGi1SRuNRXdbGkraBBKnhyUhyebFWnRbp+dIn0f0A==", - "dev": true, - "requires": { - "ansi-regex": "^2.1.1", - "d": "^1.0.1", - "es5-ext": "^0.10.51", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.14", - "timers-ext": "^0.1.7" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - } - } - }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, "requires": { "restore-cursor": "^3.1.0" } }, + "cli-spinners": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz", + "integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==" + }, "cli-width": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" }, "cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, "requires": { "string-width": "^3.1.0", "strip-ansi": "^5.2.0", @@ -4381,20 +4400,17 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -4403,6 +4419,11 @@ } } }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, "clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -4445,8 +4466,8 @@ "integrity": "sha512-zZAyOfN8TU67ngqrxhOgtkSAGV9jSpN1snbl8elPtnh9Z5A11daR405+dhLzLnuXrwX0WCShWlybxPN3QC/9Pg==" }, "codemirror-graphql": { - "version": "0.6.12", - "resolved": "github:timsuchanek/codemirror-graphql#801ec32683c38d6dc0f8f7bc19014a111edc9ebd", + "version": "github:timsuchanek/codemirror-graphql#801ec32683c38d6dc0f8f7bc19014a111edc9ebd", + "from": "github:timsuchanek/codemirror-graphql#details-fix", "requires": { "graphql-language-service-interface": "^1.0.18", "graphql-language-service-parser": "^1.0.18" @@ -5010,16 +5031,6 @@ "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", "dev": true }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -5029,6 +5040,12 @@ "assert-plus": "^1.0.0" } }, + "data-uri-to-buffer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", + "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", + "dev": true + }, "data-urls": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", @@ -5070,8 +5087,7 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decode-uri-component": { "version": "0.2.0", @@ -5106,6 +5122,14 @@ "type-detect": "^4.0.8" } }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "requires": { + "clone": "^1.0.2" + } + }, "defer-to-connect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", @@ -5161,12 +5185,31 @@ } } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, + "degenerator": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", + "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", + "dev": true, + "requires": { + "ast-types": "0.x.x", + "escodegen": "1.x.x", + "esprima": "3.x.x" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -5256,6 +5299,11 @@ } } }, + "dijkstrajs": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.2.tgz", + "integrity": "sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==" + }, "dnd-core": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-10.0.2.tgz", @@ -5432,8 +5480,7 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "emojis-list": { "version": "3.0.0", @@ -5560,48 +5607,19 @@ "is-symbol": "^1.0.2" } }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" + "es6-promise": "^4.0.3" } }, "escalade": { @@ -5687,6 +5705,30 @@ "v8-compile-cache": "^2.0.3" }, "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -5726,6 +5768,54 @@ "type-fest": "^0.8.1" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -5738,6 +5828,15 @@ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -5765,6 +5864,15 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -5922,16 +6030,6 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, "eventemitter3": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", @@ -6143,23 +6241,6 @@ } } }, - "ext": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.5.0.tgz", - "integrity": "sha512-+ONcYoWj/SoQwUofMr94aGu05Ou4FepKi7N7b+O8T4jVfyIsZQV1/xeS8jpaBzF0csAk0KLXoHCxU7cKYZjo1Q==", - "dev": true, - "requires": { - "type": "^2.5.0" - }, - "dependencies": { - "type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true - } - } - }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -6191,7 +6272,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, "requires": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", @@ -6412,7 +6492,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, "requires": { "escape-string-regexp": "^1.0.5" } @@ -6462,8 +6541,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true + "dev": true }, "filesize": { "version": "3.6.1", @@ -6527,7 +6605,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, "requires": { "locate-path": "^3.0.0" } @@ -6705,6 +6782,42 @@ "rimraf": "2" } }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "dev": true, + "requires": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", + "dev": true + } + } + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -6787,8 +6900,7 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { "version": "1.1.1", @@ -6815,6 +6927,20 @@ "pump": "^3.0.0" } }, + "get-uri": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.4.tgz", + "integrity": "sha512-v7LT/s8kVjs+Tx0ykk1I+H/rbpzkHvuIq87LmeXptcf5sNWm9uQiwjNAt94SJPA1zOlCntmnOlJvVWKmzsxG8Q==", + "dev": true, + "requires": { + "data-uri-to-buffer": "1", + "debug": "2", + "extend": "~3.0.2", + "file-uri-to-path": "1", + "ftp": "~0.3.10", + "readable-stream": "2" + } + }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -7207,12 +7333,6 @@ } } }, - "graphql-relay": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/graphql-relay/-/graphql-relay-0.8.0.tgz", - "integrity": "sha512-NU7CkwNxPzkqpBgv76Cgycrc3wmWVA2K5Sxm9DHSSLLuQTpaSRAUsX1sf2gITf+XQpkccsv56/z0LojXTyQbUw==", - "dev": true - }, "graphql-request": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-1.8.2.tgz", @@ -7702,8 +7822,7 @@ "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "iferr": { "version": "0.1.5", @@ -7774,6 +7893,12 @@ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "dev": true }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -7794,21 +7919,21 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "inquirer": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", - "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", - "dev": true, + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.1.2.tgz", + "integrity": "sha512-DHLKJwLPNgkfwNmsuEUKSejJFbkv0FMO9SMiQbjI3n5NQuCrSIBqP66ggqyz2a6t2qEolKrMjhQ3+W/xXgUQ+Q==", "requires": { "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", + "chalk": "^4.1.1", "cli-cursor": "^3.1.0", "cli-width": "^3.0.0", "external-editor": "^3.0.3", "figures": "^3.0.0", - "lodash": "^4.17.19", + "lodash": "^4.17.21", "mute-stream": "0.0.8", + "ora": "^5.3.0", "run-async": "^2.4.0", - "rxjs": "^6.6.0", + "rxjs": "^7.2.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6" @@ -7818,7 +7943,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -7827,7 +7951,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -7837,7 +7960,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -7845,20 +7967,17 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, "requires": { "ansi-regex": "^5.0.0" } @@ -7867,7 +7986,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -7911,6 +8029,12 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -8074,8 +8198,7 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-generator-fn": { "version": "2.1.0", @@ -8092,6 +8215,11 @@ "is-extglob": "^2.1.1" } }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" + }, "is-negative-zero": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", @@ -8181,6 +8309,11 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" + }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", @@ -8790,6 +8923,12 @@ } } }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", + "dev": true + }, "js-base64": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", @@ -9014,49 +9153,6 @@ "safe-buffer": "^5.0.1" } }, - "jwks-rsa": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-1.12.3.tgz", - "integrity": "sha512-cFipFDeYYaO9FhhYJcZWX/IyZgc0+g316rcHnDpT2dNRNIE/lMOmWKKqp09TkJoYlNFzrEVODsR4GgXJMgWhnA==", - "dev": true, - "requires": { - "@types/express-jwt": "0.0.42", - "axios": "^0.21.1", - "debug": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "jsonwebtoken": "^8.5.1", - "limiter": "^1.1.5", - "lru-memoizer": "^2.1.2", - "ms": "^2.1.2", - "proxy-from-env": "^1.1.0" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, "jws": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", @@ -9121,22 +9217,6 @@ "assert-plus": "^1.0.0" } }, - "ldapjs": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-2.3.0.tgz", - "integrity": "sha512-3Rbm3CS7vzTccpP1QnzKCEPok60L/b3BFlWU8r93P5oadCAaqCWEH9Td08crPnw4Ti20W8y0+ZKtFFNzxVu4kA==", - "dev": true, - "requires": { - "abstract-logging": "^2.0.0", - "asn1": "^0.2.4", - "assert-plus": "^1.0.0", - "backoff": "^2.5.0", - "ldap-filter": "^0.3.3", - "once": "^1.4.0", - "vasync": "^2.2.0", - "verror": "^1.8.1" - } - }, "left-pad": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", @@ -9226,7 +9306,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -9326,6 +9405,60 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "logform": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", @@ -9430,13 +9563,32 @@ } } }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "mailgun-js": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.18.0.tgz", + "integrity": "sha512-o0P6jjZlx5CQj12tvVgDTbgjTqVN0+5h6/6P1+3c6xmozVKBwniQ6Qt3MkCSF0+ueVTbobAfWyGpWRZMJu8t1g==", "dev": true, "requires": { - "es5-ext": "~0.10.2" + "async": "~2.6.0", + "debug": "~3.1.0", + "form-data": "~2.3.0", + "inflection": "~1.12.0", + "is-stream": "^1.1.0", + "path-proxy": "~1.0.0", + "promisify-call": "^2.0.2", + "proxy-agent": "~3.0.0", + "tsscmp": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } } }, "make-dir": { @@ -9565,36 +9717,6 @@ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" }, - "memoizee": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", - "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", - "dev": true, - "requires": { - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - }, - "dependencies": { - "is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true - }, - "next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true - } - } - }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -9804,8 +9926,7 @@ "mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" }, "mimic-response": { "version": "1.0.1", @@ -9905,28 +10026,6 @@ "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", "dev": true }, - "mongodb": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.10.tgz", - "integrity": "sha512-fvIBQBF7KwCJnDZUnFFy4WqEFP8ibdXeFANnylW19+vOwdjOAvqIzPdsNCEMT6VKTHnYu4K64AWRih0mkFms6Q==", - "dev": true, - "requires": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.0.3", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -9946,17 +10045,10 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "dev": true - }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, "nan": { "version": "2.15.0", @@ -10000,10 +10092,10 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "netmask": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", "dev": true }, "nice-try": { @@ -10569,7 +10661,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "requires": { "mimic-fn": "^2.1.0" } @@ -10607,15 +10698,6 @@ } } }, - "optional-require": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.7.tgz", - "integrity": "sha512-cIeRZocXsZnZYn+SevbtSqNlLbeoS4mLzuNn4fvXRMDRNhTGg0sxuKXl0FnZCtnew85LorNxIbZp5OeliILhMw==", - "dev": true, - "requires": { - "require-at": "^1.0.6" - } - }, "optionator": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", @@ -10630,6 +10712,100 @@ "word-wrap": "~1.2.3" } }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -10654,8 +10830,7 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "osenv": { "version": "0.1.5", @@ -10667,6 +10842,16 @@ "os-tmpdir": "^1.0.0" } }, + "otplib": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/otplib/-/otplib-12.0.1.tgz", + "integrity": "sha512-xDGvUOQjop7RDgxTQ+o4pOol0/3xSZzawTiPKRrHnQWAy0WjhNs/5HdIDJCrqC4MBynmjXgULc6YfioaxZeFgg==", + "requires": { + "@otplib/core": "^12.0.1", + "@otplib/preset-default": "^12.0.1", + "@otplib/preset-v11": "^12.0.1" + } + }, "p-cancelable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", @@ -10703,7 +10888,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -10712,7 +10896,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "requires": { "p-limit": "^2.0.0" } @@ -10726,8 +10909,110 @@ "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "pac-proxy-agent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.1.tgz", + "integrity": "sha512-44DUg21G/liUZ48dJpUSjZnFfZro/0K5JTyFYLBcmh9+T6Ooi4/i4efwUiEy0+4oQusCBqWdhv16XohIj1GqnQ==", + "dev": true, + "requires": { + "agent-base": "^4.2.0", + "debug": "^4.1.1", + "get-uri": "^2.0.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^3.0.0", + "pac-resolver": "^3.0.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "^4.0.1" + }, + "dependencies": { + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "https-proxy-agent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", + "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "pac-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", + "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", + "dev": true, + "requires": { + "co": "^4.6.0", + "degenerator": "^1.0.4", + "ip": "^1.1.5", + "netmask": "^1.0.6", + "thunkify": "^2.1.2" + } }, "package-json": { "version": "6.5.0", @@ -10839,53 +11124,273 @@ "dev": true }, "parse-server": { - "version": "github:parseplatform/parse-server#a967e7921961ea7a33ae9ff02555839cecf2b15f", + "version": "github:parseplatform/parse-server#a9ce02eb74a923a03ee42cef4b8e64870e9d6e32", "from": "github:parseplatform/parse-server#master", "dev": true, "requires": { - "@apollographql/graphql-playground-html": "1.6.29", + "@apollographql/graphql-playground-html": "1.6.26", "@graphql-tools/links": "6.2.5", "@graphql-tools/stitch": "6.2.4", "@graphql-tools/utils": "6.2.4", - "@node-rs/bcrypt": "1.1.0", + "@node-rs/bcrypt": "0.4.1", "@parse/fs-files-adapter": "1.2.0", - "@parse/push-adapter": "3.4.1", - "apollo-server-express": "2.25.2", + "@parse/push-adapter": "3.4.0", + "@parse/s3-files-adapter": "1.6.0", + "@parse/simple-mailgun-adapter": "1.1.0", + "apollo-server-express": "2.19.0", "bcryptjs": "2.4.3", "body-parser": "1.19.0", "commander": "5.1.0", "cors": "2.8.5", "deepcopy": "2.1.0", "express": "4.17.1", - "follow-redirects": "1.14.1", - "graphql": "15.5.1", + "follow-redirects": "1.13.0", + "graphql": "15.4.0", "graphql-list-fields": "2.0.2", - "graphql-relay": "0.8.0", - "graphql-tag": "2.12.5", + "graphql-relay": "0.6.0", "graphql-upload": "11.0.0", "intersect": "1.0.1", "jsonwebtoken": "8.5.1", - "jwks-rsa": "1.12.3", - "ldapjs": "2.3.0", - "lodash": "4.17.21", + "jwks-rsa": "1.11.0", + "ldapjs": "2.2.0", + "lodash": "4.17.20", "lru-cache": "5.1.1", - "mime": "2.5.2", - "mongodb": "3.6.10", - "mustache": "4.2.0", - "parse": "3.3.0", - "pg-monitor": "1.4.1", - "pg-promise": "10.11.0", + "mime": "2.4.6", + "mongodb": "3.6.2", + "parse": "2.17.0", + "pg-promise": "10.7.3", "pluralize": "8.0.0", - "redis": "3.1.2", - "semver": "7.3.4", - "subscriptions-transport-ws": "0.10.0", + "redis": "3.0.2", + "semver": "7.3.2", + "subscriptions-transport-ws": "0.9.18", "tv4": "1.3.0", - "uuid": "8.3.2", + "uuid": "8.3.1", "winston": "3.3.3", - "winston-daily-rotate-file": "4.5.5", - "ws": "7.5.3" + "winston-daily-rotate-file": "4.5.0", + "ws": "7.3.1" }, "dependencies": { + "@apollographql/graphql-playground-html": { + "version": "1.6.26", + "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.26.tgz", + "integrity": "sha512-XAwXOIab51QyhBxnxySdK3nuMEUohhDsHQ5Rbco/V1vjlP75zZ0ZLHD9dTpXTN8uxKxopb2lUvJTq+M4g2Q0HQ==", + "dev": true, + "requires": { + "xss": "^1.0.6" + } + }, + "@babel/runtime": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", + "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/runtime-corejs3": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz", + "integrity": "sha512-qh5IR+8VgFz83VBa6OkaET6uN/mJOhHONuy3m1sgF0CV6mXdPSEBdA7e1eUbVvyNtANjMbg22JUv71BaDXLY6A==", + "dev": true, + "requires": { + "core-js-pure": "^3.0.0", + "regenerator-runtime": "^0.13.4" + } + }, + "@node-rs/bcrypt": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt/-/bcrypt-0.4.1.tgz", + "integrity": "sha512-D5Uq08lbrmwnU3DcqcXWPr/POtUHM5nfzfxt7u7FdrES4kWCOEsRwBZYNHlAMZ22T/JJSQ7npSkoCF44GQCLuw==", + "dev": true, + "optional": true, + "requires": { + "@node-rs/helper": "^0.3.1" + } + }, + "@node-rs/helper": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@node-rs/helper/-/helper-0.3.1.tgz", + "integrity": "sha512-3X6SJOcyFRYv1mjrjtSHiziJuzAsqaz2pFD3uuLxu4qJo4TH6H0gaUb1Bdxl/VtiDy2yR+eMyBOQFCvr/G2oLA==", + "dev": true, + "optional": true, + "requires": { + "tslib": "^2.0.1" + } + }, + "@parse/node-apn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-4.0.0.tgz", + "integrity": "sha512-/Zhz7+AfwuMeBn9kpENF5qbWDG1+0xLBOlAb7O34BhR9R5BSjAKkMxqWmTz3R3nvlsod4XrZ8NuRMUOXVrCCFQ==", + "dev": true, + "requires": { + "debug": "3.1.0", + "jsonwebtoken": "8.1.0", + "node-forge": "0.10.0", + "verror": "1.10.0" + }, + "dependencies": { + "jsonwebtoken": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz", + "integrity": "sha1-xjl80uX9WD1lwAeoPce7eOaYK4M=", + "dev": true, + "requires": { + "jws": "^3.1.4", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.0.0", + "xtend": "^4.0.1" + } + } + } + }, + "@parse/push-adapter": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-3.4.0.tgz", + "integrity": "sha512-ZYf6DKQHpUoi806SIDiuVhstL3BRQC4brcCyTnoLih/u08Cg60Pbkz2B95JU+6xMcM211A2AvPDudEmsMahq7w==", + "dev": true, + "requires": { + "@parse/node-apn": "4.0.0", + "@parse/node-gcm": "1.0.2", + "npmlog": "4.1.2", + "parse": "2.17.0" + } + }, + "@types/cors": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.8.tgz", + "integrity": "sha512-fO3gf3DxU2Trcbr75O7obVndW/X5k8rJNZkLXlQWStTHhP71PkRqjwPIEI0yMnJdg9R9OasjU+Bsr+Hr1xy/0w==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, + "@types/express": { + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.7.tgz", + "integrity": "sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "*", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.13.tgz", + "integrity": "sha512-RgDi5a4nuzam073lRGKTUIaL3eF2+H7LJvJ8eUnCI0wA6SNjXc44DCmWNiTLs/AZ7QlsFWZiw/gTG3nSQGL0fA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "apollo-reporting-protobuf": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/apollo-reporting-protobuf/-/apollo-reporting-protobuf-0.6.2.tgz", + "integrity": "sha512-WJTJxLM+MRHNUxt1RTl4zD0HrLdH44F2mDzMweBj1yHL0kSt8I1WwoiF/wiGVSpnG48LZrBegCaOJeuVbJTbtw==", + "dev": true, + "requires": { + "@apollo/protobufjs": "^1.0.3" + } + }, + "apollo-server-caching": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.3.tgz", + "integrity": "sha512-iMi3087iphDAI0U2iSBE9qtx9kQoMMEWr6w+LwXruBD95ek9DWyj7OeC2U/ngLjRsXM43DoBDXlu7R+uMjahrQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "apollo-server-express": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.19.0.tgz", + "integrity": "sha512-3rgSrTme1SlLoecAYtSa8ThH6vYvz29QecgZCigq5Vdc6bFP2SZrCk0ls6BAdD8OZbVKUtizzRxd0yd/uREPAw==", + "dev": true, + "requires": { + "@apollographql/graphql-playground-html": "1.6.26", + "@types/accepts": "^1.3.5", + "@types/body-parser": "1.19.0", + "@types/cors": "2.8.8", + "@types/express": "4.17.7", + "@types/express-serve-static-core": "4.17.13", + "accepts": "^1.3.5", + "apollo-server-core": "^2.19.0", + "apollo-server-types": "^0.6.1", + "body-parser": "^1.18.3", + "cors": "^2.8.4", + "express": "^4.17.1", + "graphql-subscriptions": "^1.0.0", + "graphql-tools": "^4.0.0", + "parseurl": "^1.3.2", + "subscriptions-transport-ws": "^0.9.16", + "type-is": "^1.6.16" + } + }, + "apollo-server-types": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.6.3.tgz", + "integrity": "sha512-aVR7SlSGGY41E1f11YYz5bvwA89uGmkVUtzMiklDhZ7IgRJhysT5Dflt5IuwDxp+NdQkIhVCErUXakopocFLAg==", + "dev": true, + "requires": { + "apollo-reporting-protobuf": "^0.6.2", + "apollo-server-caching": "^0.5.3", + "apollo-server-env": "^3.0.0" + } + }, + "assert-options": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.6.2.tgz", + "integrity": "sha512-KP9S549XptFAPGYmLRnIjQBL4/Ry8Jx5YNLQZ/l+eejqbTidBMnw4uZSAsUrzBq/lgyqDYqxcTF7cOxZb9gyEw==", + "dev": true + }, + "axios": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", + "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "dev": true, + "requires": { + "follow-redirects": "1.5.10" + }, + "dependencies": { + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "dev": true, + "requires": { + "debug": "=3.1.0" + } + } + } + }, "bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", @@ -10898,50 +11403,269 @@ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", "dev": true }, - "follow-redirects": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", - "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", - "dev": true + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "follow-redirects": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", + "dev": true + }, + "graphql": { + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.4.0.tgz", + "integrity": "sha512-EB3zgGchcabbsU9cFe1j+yxdzKQKAbGUWRb13DsrsMN1yyfmmIq+2+L5MqVWcDCE4V89R5AyUOi7sMOGxdsYtA==", + "dev": true + }, + "graphql-relay": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/graphql-relay/-/graphql-relay-0.6.0.tgz", + "integrity": "sha512-OVDi6C9/qOT542Q3KxZdXja3NrDvqzbihn1B44PH8P/c5s0Q90RyQwT6guhGqXqbYEH6zbeLJWjQqiYvcg2vVw==", + "dev": true, + "requires": { + "prettier": "^1.16.0" + } + }, + "jwks-rsa": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-1.11.0.tgz", + "integrity": "sha512-G7ZgXZ3dlGbOUBQwgF+U/SVzOlI9KxJ9Uzp61bue2S5TV0h7c+kJRCl3bEPkC5PVmeu7/h82B3uQALVJMjzt/Q==", + "dev": true, + "requires": { + "@types/express-jwt": "0.0.42", + "axios": "^0.19.2", + "debug": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "jsonwebtoken": "^8.5.1", + "limiter": "^1.1.5", + "lru-memoizer": "^2.1.2", + "ms": "^2.1.2", + "proxy-from-env": "^1.1.0" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "ldapjs": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-2.2.0.tgz", + "integrity": "sha512-9+ekbj97nxRYQMRgEm/HYFhFLWSRKah2PnReUfhfM5f62XBeUSFolB+AQ2Jij5tqowpksTnrdNCZLP6C+V3uag==", + "dev": true, + "requires": { + "abstract-logging": "^2.0.0", + "asn1": "^0.2.4", + "assert-plus": "^1.0.0", + "backoff": "^2.5.0", + "ldap-filter": "^0.3.3", + "once": "^1.4.0", + "vasync": "^2.2.0", + "verror": "^1.8.1" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true + }, + "mongodb": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.2.tgz", + "integrity": "sha512-sSZOb04w3HcnrrXC82NEh/YGCmBuRgR+C1hZgmmv4L6dBz4BkRse6Y8/q/neXer9i95fKUBbFi4KgeceXmbsOA==", + "dev": true, + "requires": { + "bl": "^2.2.1", + "bson": "^1.1.4", + "denque": "^1.4.1", + "require_optional": "^1.0.1", + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" + } + }, + "parse": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/parse/-/parse-2.17.0.tgz", + "integrity": "sha512-1hWoMNW39LH5YV3xCds9LyD8SsKD6FUwlD1Kn8ZlXNosg6WgF+s3ZSQUzT5AJ/9YPUoC/y1PoCO79FumrBYftA==", + "dev": true, + "requires": { + "@babel/runtime": "7.11.2", + "@babel/runtime-corejs3": "7.11.2", + "crypto-js": "4.0.0", + "react-native-crypto-js": "1.0.0", + "uuid": "3.4.0", + "ws": "7.3.1", + "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } + }, + "pg": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.4.1.tgz", + "integrity": "sha512-NRsH0aGMXmX1z8Dd0iaPCxWUw4ffu+lIAmGm+sTCwuDDWkpEgRCAHZYDwqaNhC5hG5DRMOjSUFasMWhvcmLN1A==", + "dev": true, + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.4.0", + "pg-pool": "^3.2.1", + "pg-protocol": "^1.3.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + } }, - "graphql": { - "version": "15.5.1", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.5.1.tgz", - "integrity": "sha512-FeTRX67T3LoE3LWAxxOlW2K3Bz+rMYAC18rRguK4wgXaTZMiJwSUwDmPFo3UadAKbzirKIg5Qy+sNJXbpPRnQw==", + "pg-minify": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.1.tgz", + "integrity": "sha512-ujanxJJB9CSDUvlAOshtjdKAywOPR2vY0a7D+vvgk5rbrYcthZA7TjpN+Z+UwZsz/G/bUexYDT6huE33vYVN0g==", "dev": true }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "pg-promise": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-10.7.3.tgz", + "integrity": "sha512-RGZpTkQYKUlOI6qHp5UVbhiqDdk+YmfkSmLscbaQd8fIz9lGEUBZHfJJNMKoSa3MWfsN2pg/iAxob6QCma/GaQ==", "dev": true, "requires": { - "yallist": "^3.0.2" + "assert-options": "0.6.2", + "pg": "8.4.1", + "pg-minify": "1.6.1", + "spex": "3.0.2" } }, - "mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "redis": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.0.2.tgz", + "integrity": "sha512-PNhLCrjU6vKVuMOyFu7oSP296mwBkcE6lrAjruBYG5LgdSqtRBoVQIylrMyVZD/lkF24RSNNatzvYag6HRBHjQ==", + "dev": true, + "requires": { + "denque": "^1.4.1", + "redis-commands": "^1.5.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "spex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spex/-/spex-3.0.2.tgz", + "integrity": "sha512-ZNCrOso+oNv5P01HCO4wuxV9Og5rS6ms7gGAqugfBPjx1QwfNXJI3T02ldfaap1O0dlT1sB0Rk+mhDqxt3Z27w==", "dev": true }, "subscriptions-transport-ws": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.10.0.tgz", - "integrity": "sha512-k28LhLn3abJ1mowFW+LP4QGggE0e3hrk55zXbMHyAeZkCUYtC0owepiwqMD3zX8DglQVaxnhE760pESrNSEzpg==", + "version": "0.9.18", + "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.18.tgz", + "integrity": "sha512-tztzcBTNoEbuErsVQpTN2xUNN/efAZXyCyL5m3x4t6SKrEiTL2N8SaKWBFWM4u56pL79ULif3zjyeq+oV+nOaA==", "dev": true, "requires": { "backo2": "^1.0.2", "eventemitter3": "^3.1.0", "iterall": "^1.2.1", "symbol-observable": "^1.0.4", - "ws": "^5.2.0 || ^6.0.0 || ^7.0.0" + "ws": "^5.2.0" + }, + "dependencies": { + "ws": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz", + "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } } }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true, + "optional": true + }, "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", + "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", + "dev": true + }, + "winston-daily-rotate-file": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-4.5.0.tgz", + "integrity": "sha512-/HqeWiU48dzGqcrABRlxYWVMdL6l3uKCtFSJyrqK+E2rLnSFNsgYpvwx15EgTitBLNzH69lQd/+z2ASryV2aqw==", + "dev": true, + "requires": { + "file-stream-rotator": "^0.5.7", + "object-hash": "^2.0.1", + "triple-beam": "^1.3.0", + "winston-transport": "^4.2.0" + } + }, + "ws": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", + "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", "dev": true }, "yallist": { @@ -11025,8 +11749,7 @@ "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-is-absolute": { "version": "1.0.1", @@ -11045,6 +11768,23 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-proxy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", + "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", + "dev": true, + "requires": { + "inflection": "~1.3.0" + }, + "dependencies": { + "inflection": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", + "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", + "dev": true + } + } + }, "path-to-regexp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", @@ -11090,21 +11830,6 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "pg": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.7.1.tgz", - "integrity": "sha512-7bdYcv7V6U3KAtWjpQJJBww0UEsWuh4yQ/EjNf2HeO/NnvKjpvhEIe/A/TleP6wtmSKnUnghs5A9jUoK6iDdkA==", - "dev": true, - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.5.0", - "pg-pool": "^3.4.1", - "pg-protocol": "^1.5.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - } - }, "pg-connection-string": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", @@ -11117,39 +11842,12 @@ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", "dev": true }, - "pg-minify": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.2.tgz", - "integrity": "sha512-1KdmFGGTP6jplJoI8MfvRlfvMiyBivMRP7/ffh4a11RUFJ7kC2J0ZHlipoKiH/1hz+DVgceon9U2qbaHpPeyPg==", - "dev": true - }, - "pg-monitor": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/pg-monitor/-/pg-monitor-1.4.1.tgz", - "integrity": "sha512-HLLPPC/2yn7+fOpvatAAMFQMzk/8JwaVS7ATp70Uy+7aTiTvlzIqsTixc6E14L/EGk8fvhu/FJ7qiFbxygbwIA==", - "dev": true, - "requires": { - "cli-color": "2.0.0" - } - }, "pg-pool": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.4.1.tgz", "integrity": "sha512-TVHxR/gf3MeJRvchgNHxsYsTCHQ+4wm3VIHSS19z8NC0+gioEhq1okDY1sm/TYbfoP6JLFx01s0ShvZ3puP/iQ==", "dev": true }, - "pg-promise": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-10.11.0.tgz", - "integrity": "sha512-UntgHZNv+gpGJKhh+tzGSGHLkniKWV+ZQ8/SNdtvElsg9Aa7ZJ4Fgyl6pl2x0ZtJ7uFNy+OIq3Z+Ei6iplqTDQ==", - "dev": true, - "requires": { - "assert-options": "0.7.0", - "pg": "8.7.1", - "pg-minify": "1.6.2", - "spex": "3.2.0" - } - }, "pg-protocol": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", @@ -11235,6 +11933,11 @@ "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", "dev": true }, + "pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" + }, "portfinder": { "version": "1.0.28", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", @@ -11484,6 +12187,15 @@ "promise-deferred": "^2.0.3" } }, + "promisify-call": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz", + "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", + "dev": true, + "requires": { + "with-callback": "^1.0.2" + } + }, "prompts": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", @@ -11518,6 +12230,85 @@ "ipaddr.js": "1.9.1" } }, + "proxy-agent": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.3.tgz", + "integrity": "sha512-PXVVVuH9tiQuxQltFJVSnXWuDtNr+8aNBP6XVDDCDiUuDN8eRCm+ii4/mFWmXWEA0w8jjJSlePa4LXlM4jIzNA==", + "dev": true, + "requires": { + "agent-base": "^4.2.0", + "debug": "^3.1.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "lru-cache": "^4.1.2", + "pac-proxy-agent": "^3.0.0", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^4.0.1" + }, + "dependencies": { + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -11680,6 +12471,27 @@ "resolved": "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz", "integrity": "sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4=" }, + "qrcode": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.4.4.tgz", + "integrity": "sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q==", + "requires": { + "buffer": "^5.4.3", + "buffer-alloc": "^1.2.0", + "buffer-from": "^1.1.1", + "dijkstrajs": "^1.0.1", + "isarray": "^2.0.1", + "pngjs": "^3.3.0", + "yargs": "^13.2.4" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + } + } + }, "qs": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", @@ -12161,18 +12973,6 @@ "strip-indent": "^1.0.1" } }, - "redis": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", - "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", - "dev": true, - "requires": { - "denque": "^1.5.0", - "redis-commands": "^1.7.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0" - } - }, "redis-commands": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", @@ -12480,23 +13280,39 @@ "tough-cookie": "^2.3.3" } }, - "require-at": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==", - "dev": true - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "dev": true, + "requires": { + "resolve-from": "^2.0.0", + "semver": "^5.1.0" + }, + "dependencies": { + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } }, "requires-port": { "version": "1.0.0", @@ -12588,7 +13404,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, "requires": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -12639,8 +13454,7 @@ "run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" }, "run-queue": { "version": "1.0.3", @@ -12652,12 +13466,18 @@ } }, "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.3.0.tgz", + "integrity": "sha512-p2yuGIg9S1epc3vrjKf6iVb3RCaAYjYskkO+jHIaV0IjOPlJop4UnodOoFb2xeNwlguqLYvGw1b1McillYb5Gw==", "requires": { - "tslib": "^1.9.0" + "tslib": "~2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + } } }, "safe-buffer": { @@ -13077,8 +13897,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "set-value": { "version": "2.0.1", @@ -13177,8 +13996,7 @@ "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, "simple-swizzle": { "version": "0.2.2", @@ -13228,6 +14046,12 @@ } } }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -13335,6 +14159,37 @@ } } }, + "socks": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", + "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", + "dev": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "socks-proxy-agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", + "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", + "dev": true, + "requires": { + "agent-base": "~4.2.1", + "socks": "~2.3.2" + }, + "dependencies": { + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + } + } + }, "source-list-map": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", @@ -13425,12 +14280,6 @@ "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", "dev": true }, - "spex": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spex/-/spex-3.2.0.tgz", - "integrity": "sha512-9srjJM7NaymrpwMHvSmpDeIK5GoRMX/Tq0E8aOlDPS54dDnDUIp30DrP9SphMPEETDLzEM9+4qo+KipmbtPecg==", - "dev": true - }, "split-on-first": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", @@ -13643,7 +14492,6 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -13654,7 +14502,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, "requires": { "ansi-regex": "^5.0.0" } @@ -13701,7 +14548,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" } @@ -13710,7 +14556,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, "requires": { "ansi-regex": "^4.1.0" }, @@ -13718,8 +14563,7 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" } } }, @@ -14034,6 +14878,11 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "thirty-two": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz", + "integrity": "sha1-TKL//AKlEpDSdEueP1V2k8prYno=" + }, "throat": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", @@ -14043,8 +14892,7 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "2.0.5", @@ -14056,6 +14904,12 @@ "xtend": "~4.0.1" } }, + "thunkify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", + "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", + "dev": true + }, "timers-browserify": { "version": "2.0.12", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", @@ -14065,16 +14919,6 @@ "setimmediate": "^1.0.4" } }, - "timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dev": true, - "requires": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } - }, "tiny-invariant": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", @@ -14089,7 +14933,6 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, "requires": { "os-tmpdir": "~1.0.2" } @@ -14293,12 +15136,6 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -14586,8 +15423,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "util.promisify": { "version": "1.1.1", @@ -14798,6 +15634,14 @@ } } }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "requires": { + "defaults": "^1.0.3" + } + }, "webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", @@ -15163,8 +16007,7 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, "wide-align": { "version": "1.1.3", @@ -15250,18 +16093,6 @@ } } }, - "winston-daily-rotate-file": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-4.5.5.tgz", - "integrity": "sha512-ds0WahIjiDhKCiMXmY799pDBW+58ByqIBtUcsqr4oDoXrAI3Zn+hbgFdUxzMfqA93OG0mPLYVMiotqTgE/WeWQ==", - "dev": true, - "requires": { - "file-stream-rotator": "^0.5.7", - "object-hash": "^2.0.1", - "triple-beam": "^1.3.0", - "winston-transport": "^4.4.0" - } - }, "winston-transport": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", @@ -15272,6 +16103,12 @@ "triple-beam": "^1.2.0" } }, + "with-callback": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/with-callback/-/with-callback-1.0.2.tgz", + "integrity": "sha1-oJYpuakgAo1yFAT7Q1vc/1yRvCE=", + "dev": true + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -15297,7 +16134,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, "requires": { "ansi-styles": "^3.2.0", "string-width": "^3.0.0", @@ -15307,20 +16143,17 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -15422,8 +16255,7 @@ "y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" }, "yallist": { "version": "2.1.2", @@ -15434,7 +16266,6 @@ "version": "13.3.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, "requires": { "cliui": "^5.0.0", "find-up": "^3.0.0", @@ -15451,20 +16282,17 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -15477,7 +16305,6 @@ "version": "13.1.2", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" diff --git a/package.json b/package.json index 2a5f4f4c85..6d2ec13cf3 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "history": "4.10.1", "immutable": "4.0.0-rc.9", "immutable-devtools": "0.1.5", + "inquirer": "8.1.2", "js-beautify": "1.14.0", "json-file-plus": "3.2.0", "otplib": "^12.0.1", @@ -60,6 +61,7 @@ "passport-local": "1.0.0", "prismjs": "1.24.1", "prop-types": "15.7.2", + "qrcode": "1.4.4", "query-string": "6.14.1", "react": "16.14.0", "react-ace": "9.4.3", diff --git a/src/dashboard/Dashboard.js b/src/dashboard/Dashboard.js index 41c643d3d6..6ccc04bc2b 100644 --- a/src/dashboard/Dashboard.js +++ b/src/dashboard/Dashboard.js @@ -57,7 +57,6 @@ import { Route, Redirect } from 'react-router-dom'; import createClass from 'create-react-class'; import { Helmet } from 'react-helmet'; import Playground from './Data/Playground/Playground.react'; -import { authenticator } from 'otplib'; const ShowSchemaOverview = false; //In progress features. Change false to true to work on this feature. From 7cf9676dd87e2a9f026a4ed0b6cfd63d7086a630 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 15:57:12 +1000 Subject: [PATCH 05/37] add changelog --- CHANGELOG.md | 2 ++ Parse-Dashboard/index.js | 29 +++++++++++++++++++++++++---- README.md | 14 +++++++------- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c03c791652..54b35b96d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ [Full Changelog](https://github.com/parse-community/parse-dashboard/compare/2.2.0...master) ## New Features +- Add MFA to dashboard login. To use MFA, run `parse-dashboard --createMFA` or `parse-dashboard --createUser`. (Daniel Blyth) [#1624](https://github.com/parse-community/parse-dashboard/pull/1624) + ## Improvements - Add CI check to add changelog entry (Manuel Trezza) [#1764](https://github.com/parse-community/parse-dashboard/pull/1764) - Refactor: uniform issue templates across repos (Manuel Trezza) [#1767](https://github.com/parse-community/parse-dashboard/pull/1767) diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js index 6e66b98445..c9e8ebd46b 100644 --- a/Parse-Dashboard/index.js +++ b/Parse-Dashboard/index.js @@ -30,6 +30,7 @@ program.option('--sslCert [sslCert]', 'the path to the SSL certificate.'); program.option('--trustProxy [trustProxy]', 'set this flag when you are behind a front-facing proxy, such as when hosting on Heroku. Uses X-Forwarded-* headers to determine the client\'s connection and IP address.'); program.option('--cookieSessionSecret [cookieSessionSecret]', 'set the cookie session secret, defaults to a random string. You should set that value if you want sessions to work across multiple server, or across restarts'); program.option('--createUser', 'helper tool to allow you to generate secure user passwords and secrets. Use this once on a trusted device only.'); +program.option('--createMFA', 'helper tool to allow you to generate MFA secrets.'); program.parse(process.argv); @@ -59,6 +60,12 @@ let configUserPassword = program.userPassword || process.env.PARSE_DASHBOARD_USE let configSSLKey = program.sslKey || process.env.PARSE_DASHBOARD_SSL_KEY; let configSSLCert = program.sslCert || process.env.PARSE_DASHBOARD_SSL_CERT; +const showQR = (text) => { + const QRCode = require('qrcode') + QRCode.toString(text, {type:'terminal'}, (err, url) => { + console.log(url) + }) +} if (program.createUser) { (async () => { const inquirer = require('inquirer'); @@ -107,15 +114,29 @@ if (program.createUser) { console.log(`\n\nYour new user details' raw credentials have been copied to your clipboard. Add the following to your Parse Dashboard config:\n\n${JSON.stringify(result)}\n\n`); if (displayResult.mfa) { - const QRCode = require('qrcode') - QRCode.toString(displayResult.mfa, {type:'terminal'}, function (err, url) { - console.log(url) - }) + showQR(displayResult.mfa) + console.log(`After you've shared the QR code ${username}, it is recommended to delete any photos or records of it.\n`) } })(); return; } +if (program.createMFA) { + (async () => { + const inquirer = require('inquirer'); + const {username} = await inquirer.prompt([{ + type: 'input', + name: 'username', + message: 'Please enter the name of the user you would like to create MFA for.', + }]); + const secret = authenticator.generateSecret(); + console.log(`Please add this to your dashboard config for ${username}.\n\n"mfa":"${secret}"\n\n\n\n\nAsk ${username} to install an Authenticator app and scan this QR code on their device:\n`) + const url = authenticator.keyuri(username, configAppName || 'Parse Dashboard', secret); + showQR(url); + console.log(`After you've shared the QR code ${username}, it is recommended to delete any photos or records of it.\n`) + })(); + return +} function handleSIGs(server) { const signals = { diff --git a/README.md b/README.md index c70571214e..9fb02a00d5 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ parse-dashboard --dev --appId yourAppId --masterKey yourMasterKey --serverURL "h You may set the host, port and mount path by supplying the `--host`, `--port` and `--mountPath` options to parse-dashboard. You can use anything you want as the app name, or leave it out in which case the app ID will be used. -NB: the `--dev` parameter is disabling production-ready security features, do not use this parameter when starting the dashboard in production. This parameter is useful if you are running on docker. +NB: the `--dev` parameter is disabling production-ready security features, do not use this parameter when starting the dashboard in production. This parameter is useful if you are running on docker. After starting the dashboard, you can visit http://localhost:4040 in your browser: @@ -245,7 +245,7 @@ You can set `appNameForURL` in the config file for each app to control the url o To change the app to production, simply set `production` to `true` in your config file. The default value is false if not specified. - ### Prevent columns sorting + ### Prevent columns sorting You can prevent some columns to be sortable by adding `preventSort` to columnPreference options in each app configuration @@ -378,7 +378,7 @@ You can configure your dashboard for Basic Authentication by adding usernames an ``` You can store the password in either `plain text` or `bcrypt` formats. To use the `bcrypt` format, you must set the config `useEncryptedPasswords` parameter to `true`. -You can encrypt the password using any online bcrypt tool e.g. [https://www.bcrypt-generator.com](https://www.bcrypt-generator.com). +You can generated encrypted passwords by using `parse-dashboard --createUser`, and pasting the result in your users config. ### Separating App Access Based on User Identity If you have configured your dashboard to manage multiple applications, you can restrict the management of apps based on user identity. @@ -452,7 +452,7 @@ You can mark a user as a read-only user: "appId": "myAppId1", "masterKey": "myMasterKey1", "readOnlyMasterKey": "myReadOnlyMasterKey1", - "serverURL": "myURL1", + "serverURL": "myURL1", "port": 4040, "production": true }, @@ -460,7 +460,7 @@ You can mark a user as a read-only user: "appId": "myAppId2", "masterKey": "myMasterKey2", "readOnlyMasterKey": "myReadOnlyMasterKey2", - "serverURL": "myURL2", + "serverURL": "myURL2", "port": 4041, "production": true } @@ -495,7 +495,7 @@ You can give read only access to a user on a per-app basis: "appId": "myAppId1", "masterKey": "myMasterKey1", "readOnlyMasterKey": "myReadOnlyMasterKey1", - "serverURL": "myURL", + "serverURL": "myURL", "port": 4040, "production": true }, @@ -536,7 +536,7 @@ You can provide a list of locales or languages you want to support for your dash ## Run with Docker -The official docker image is published on [docker hub](https://hub.docker.com/r/parseplatform/parse-dashboard) +The official docker image is published on [docker hub](https://hub.docker.com/r/parseplatform/parse-dashboard) Run the image with your ``config.json`` mounted as a volume From 9a4ffbdd8c1a68b0b0ded52c919b8cbed6714ba7 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 16:02:15 +1000 Subject: [PATCH 06/37] Update index.js --- Parse-Dashboard/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js index c9e8ebd46b..0e83f1964d 100644 --- a/Parse-Dashboard/index.js +++ b/Parse-Dashboard/index.js @@ -112,12 +112,10 @@ if (program.createUser) { proc.stdin.write(JSON.stringify(displayResult)); proc.stdin.end(); console.log(`\n\nYour new user details' raw credentials have been copied to your clipboard. Add the following to your Parse Dashboard config:\n\n${JSON.stringify(result)}\n\n`); - if (displayResult.mfa) { showQR(displayResult.mfa) console.log(`After you've shared the QR code ${username}, it is recommended to delete any photos or records of it.\n`) } - })(); return; } From c4a5c5994002349efec30c93b570c58c00b0bd21 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 16:04:18 +1000 Subject: [PATCH 07/37] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6d2ec13cf3..24ab46e4a9 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "inquirer": "8.1.2", "js-beautify": "1.14.0", "json-file-plus": "3.2.0", - "otplib": "^12.0.1", + "otplib": "12.0.1", "package-json": "6.5.0", "parse": "3.3.0", "passport": "0.4.1", From f6e5a98b266d15cb7d4bd65793881e05b95df17b Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 16:13:59 +1000 Subject: [PATCH 08/37] Revert "Update CloudCode.react.js" This reverts commit e9d3ea7b2b55ff6bb12cbfc2e382d6d3851cff23. --- src/dashboard/Data/CloudCode/CloudCode.react.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/dashboard/Data/CloudCode/CloudCode.react.js b/src/dashboard/Data/CloudCode/CloudCode.react.js index f07aa84704..042702ab6b 100644 --- a/src/dashboard/Data/CloudCode/CloudCode.react.js +++ b/src/dashboard/Data/CloudCode/CloudCode.react.js @@ -16,8 +16,7 @@ import Toolbar from 'components/Toolbar/Toolbar.react'; import SaveButton from 'components/SaveButton/SaveButton.react'; function getPath(params) { - const last = params.location.pathname.split('cloud_code/')[1] - return last; + return params.splat; } export default class CloudCode extends DashboardView { @@ -35,12 +34,12 @@ export default class CloudCode extends DashboardView { } componentWillMount() { - this.fetchSource(this.context.currentApp, getPath(this.props)); + this.fetchSource(this.context.currentApp, getPath(this.props.params)); } componentWillReceiveProps(nextProps, nextContext) { if (this.context !== nextContext) { - this.fetchSource(nextContext.currentApp, getPath(nextProps)); + this.fetchSource(nextContext.currentApp, getPath(nextProps.params)); } } @@ -56,7 +55,7 @@ export default class CloudCode extends DashboardView { if (!fileName || release.files[fileName] === undefined) { // Means we're still in /cloud_code/. Let's redirect to /cloud_code/main.js - history.replace(this.context.generatePath(`cloud_code/${Object.keys(release.files)[0]}`)) + history.replace(this.context.generatePath('cloud_code/main.js')) } else { // Means we can load /cloud_code/ this.setState({ source: undefined }) @@ -76,7 +75,7 @@ export default class CloudCode extends DashboardView { } renderSidebar() { - let current = getPath(this.props) || ''; + let current = getPath(this.props.params) || ''; let files = this.state.files; if (!files) { return null; @@ -116,7 +115,7 @@ export default class CloudCode extends DashboardView { renderContent() { let toolbar = null; let content = null; - let fileName = getPath(this.props); + let fileName = getPath(this.props.params); if (!this.state.files || Object.keys(this.state.files).length === 0) { content = ( From 30540b34705be86356ab42e1861985c9c9853400 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 16:14:10 +1000 Subject: [PATCH 09/37] Revert "Allow Writing Cloud Code" This reverts commit 2a5c0503e8aaccb4e33dbecb62be38ea0489cde8. --- .../SaveButton/SaveButton.example.js | 3 -- src/components/SaveButton/SaveButton.react.js | 2 +- .../Data/CloudCode/CloudCode.react.js | 47 +++---------------- src/lib/ParseApp.js | 22 +++++---- 4 files changed, 19 insertions(+), 55 deletions(-) diff --git a/src/components/SaveButton/SaveButton.example.js b/src/components/SaveButton/SaveButton.example.js index bd2d50a3f6..f7e55af774 100644 --- a/src/components/SaveButton/SaveButton.example.js +++ b/src/components/SaveButton/SaveButton.example.js @@ -55,9 +55,6 @@ export const demos = [
-
- -
) }, { diff --git a/src/components/SaveButton/SaveButton.react.js b/src/components/SaveButton/SaveButton.react.js index f7aced23db..0bb741fa86 100644 --- a/src/components/SaveButton/SaveButton.react.js +++ b/src/components/SaveButton/SaveButton.react.js @@ -52,7 +52,7 @@ let SaveButton = ({ ; }; -SaveButton.States = keyMirror(['SAVING', 'SUCCEEDED', 'FAILED', 'WAITING']); +SaveButton.States = keyMirror(['SAVING', 'SUCCEEDED', 'FAILED']); let {...forwardedButtonProps} = Button.propTypes; delete forwardedButtonProps.value; diff --git a/src/dashboard/Data/CloudCode/CloudCode.react.js b/src/dashboard/Data/CloudCode/CloudCode.react.js index 042702ab6b..9387271680 100644 --- a/src/dashboard/Data/CloudCode/CloudCode.react.js +++ b/src/dashboard/Data/CloudCode/CloudCode.react.js @@ -5,7 +5,7 @@ * This source code is licensed under the license found in the LICENSE file in * the root directory of this source tree. */ -import CodeEditor from 'components/CodeEditor/CodeEditor.react'; +import CodeSnippet from 'components/CodeSnippet/CodeSnippet.react'; import DashboardView from 'dashboard/DashboardView.react'; import EmptyState from 'components/EmptyState/EmptyState.react'; import FileTree from 'components/FileTree/FileTree.react'; @@ -13,7 +13,6 @@ import history from 'dashboard/history'; import React from 'react'; import styles from 'dashboard/Data/CloudCode/CloudCode.scss'; import Toolbar from 'components/Toolbar/Toolbar.react'; -import SaveButton from 'components/SaveButton/SaveButton.react'; function getPath(params) { return params.splat; @@ -27,9 +26,7 @@ export default class CloudCode extends DashboardView { this.state = { files: undefined, - source: undefined, - saveState: SaveButton.States.WAITING, - saveError: '', + source: undefined }; } @@ -58,14 +55,8 @@ export default class CloudCode extends DashboardView { history.replace(this.context.generatePath('cloud_code/main.js')) } else { // Means we can load /cloud_code/ - this.setState({ source: undefined }) app.getSource(fileName).then( - (source) => { - this.setState({ source: source }) - if (this.editor) { - this.editor.value = source; - } - }, + (source) => this.setState({ source: source }), () => this.setState({ source: undefined }) ); } @@ -95,23 +86,7 @@ export default class CloudCode extends DashboardView { ); } - async getCode() { - if (!this.editor) { - return; - } - this.setState({ saveState: SaveButton.States.SAVING }); - let fileName = getPath(this.props); - try { - await this.context.currentApp.saveSource(fileName,this.editor.value); - this.setState({ saveState: SaveButton.States.SUCCEEDED }); - setTimeout(()=> { - this.setState({ saveState: SaveButton.States.WAITING }); - },2000); - } catch (e) { - this.setState({ saveState: SaveButton.States.FAILED }); - this.setState({ saveError: e.message || e }); - } - } + renderContent() { let toolbar = null; let content = null; @@ -135,20 +110,10 @@ export default class CloudCode extends DashboardView { subsection={fileName} />; let source = this.state.files[fileName]; - if ((source && source.source) || this.state.source) { + if (source && source.source) { content = (
- (this.editor = editor)} - fontSize={'14px'} - /> - this.getCode(this)}> +
); } diff --git a/src/lib/ParseApp.js b/src/lib/ParseApp.js index 863689111b..6cf0881f2b 100644 --- a/src/lib/ParseApp.js +++ b/src/lib/ParseApp.js @@ -119,15 +119,6 @@ export default class ParseApp { return this.apiRequest('GET', path, {}, { useMasterKey: true }); } - /** - * Saves source of a Cloud Code hosted file from api.parse.com - * fileName - the name of the file to be fetched - * data - the text to save to the cloud file - */ - saveSource(fileName,data) { - return this.apiRequest('POST', `scripts/${fileName}`, {data}, { useMasterKey: true }); - } - /** * Fetches source of a Cloud Code hosted file from api.parse.com * fileName - the name of the file to be fetched @@ -138,11 +129,22 @@ export default class ParseApp { // No release yet return Promise.resolve(null); } - return this.apiRequest('GET', `scripts/${fileName}`, {}, { useMasterKey: true }); + + let fileMetaData = release.files[fileName]; + if (fileMetaData && fileMetaData.source) { + return Promise.resolve(fileMetaData.source); + } + + let params = { + version: fileMetaData.version, + checksum: fileMetaData.checksum + } + return this.apiRequest('GET', `scripts/${fileName}`, params, { useMasterKey: true }); }).then((source) => { if (this.latestRelease.files) { this.latestRelease.files[fileName].source = source; } + return Promise.resolve(source); }); } From f4a741259fc9affe321078ddb2778740b1186c29 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 16:17:46 +1000 Subject: [PATCH 10/37] Update index.js --- Parse-Dashboard/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js index 0e83f1964d..8d05176e20 100644 --- a/Parse-Dashboard/index.js +++ b/Parse-Dashboard/index.js @@ -74,7 +74,7 @@ if (program.createUser) { const {username, password} = await inquirer.prompt([{ type: 'input', name: 'username', - message: 'Please enter the username.', + message: 'Please enter the username:', }, { type: 'confirm', name: 'password', @@ -86,7 +86,7 @@ if (program.createUser) { const {password} = await inquirer.prompt([{ type: 'password', name: 'password', - message: `Please enter the password for ${username}`, + message: `Please enter the password for ${username}:`, }]); displayResult.password = password; result.pass = password @@ -125,7 +125,7 @@ if (program.createMFA) { const {username} = await inquirer.prompt([{ type: 'input', name: 'username', - message: 'Please enter the name of the user you would like to create MFA for.', + message: 'Please enter the name of the user you would like to create MFA for:', }]); const secret = authenticator.generateSecret(); console.log(`Please add this to your dashboard config for ${username}.\n\n"mfa":"${secret}"\n\n\n\n\nAsk ${username} to install an Authenticator app and scan this QR code on their device:\n`) From 6b1718abfa23197c3014e5b17f48542e87ae044f Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 21:42:29 +1000 Subject: [PATCH 11/37] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9fb02a00d5..8b33df083c 100644 --- a/README.md +++ b/README.md @@ -378,7 +378,7 @@ You can configure your dashboard for Basic Authentication by adding usernames an ``` You can store the password in either `plain text` or `bcrypt` formats. To use the `bcrypt` format, you must set the config `useEncryptedPasswords` parameter to `true`. -You can generated encrypted passwords by using `parse-dashboard --createUser`, and pasting the result in your users config. +You can generate encrypted passwords by using `parse-dashboard --createUser`, and pasting the result in your users config. ### Separating App Access Based on User Identity If you have configured your dashboard to manage multiple applications, you can restrict the management of apps based on user identity. From 79110095a8e96234608a2d140db4dfafde47fe51 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 21:43:21 +1000 Subject: [PATCH 12/37] Update index.js --- Parse-Dashboard/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js index 8d05176e20..e53ec26016 100644 --- a/Parse-Dashboard/index.js +++ b/Parse-Dashboard/index.js @@ -133,7 +133,7 @@ if (program.createMFA) { showQR(url); console.log(`After you've shared the QR code ${username}, it is recommended to delete any photos or records of it.\n`) })(); - return + return; } function handleSIGs(server) { From 40960f5267dc1e33b13c9ad4f679e2b9e12dae5f Mon Sep 17 00:00:00 2001 From: dblythy Date: Sun, 5 Sep 2021 02:40:08 +1000 Subject: [PATCH 13/37] hide otp field by default --- Parse-Dashboard/Authentication.js | 7 +++- src/components/LoginForm/LoginForm.react.js | 1 + src/dashboard/Dashboard.js | 2 ++ src/login/Login.js | 38 ++++++++++++++++++--- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/Parse-Dashboard/Authentication.js b/Parse-Dashboard/Authentication.js index 34ae9820df..597680a3f5 100644 --- a/Parse-Dashboard/Authentication.js +++ b/Parse-Dashboard/Authentication.js @@ -32,6 +32,9 @@ function initialize(app, options) { if (!match.matchingUsername) { return cb(null, false, { message: 'Invalid username or password' }); } + if (match.otpMissing) { + return cb(null, false, { message: 'Please enter your OTP code.' }); + } if (!match.otpValid) { return cb(null, false, { message: 'Invalid OTP code.' }); } @@ -88,6 +91,7 @@ function authenticate(userToTest, usernameOnly) { let appsUserHasAccessTo = null; let matchingUsername = null; let isReadOnly = false; + let otpMissing = false; let otpValid = true; //they provided auth @@ -99,7 +103,7 @@ function authenticate(userToTest, usernameOnly) { let isAuthenticated = false; if (user.mfa && !usernameOnly) { if (!userToTest.otpCode) { - otpValid = false; + otpMissing = true; } if (!authenticator.verify({ token:userToTest.otpCode, secret: user.mfa })) { otpValid = false; @@ -120,6 +124,7 @@ function authenticate(userToTest, usernameOnly) { return { isAuthenticated, matchingUsername, + otpMissing, otpValid, appsUserHasAccessTo, isReadOnly, diff --git a/src/components/LoginForm/LoginForm.react.js b/src/components/LoginForm/LoginForm.react.js index 6312e9ec96..e651658ff1 100644 --- a/src/components/LoginForm/LoginForm.react.js +++ b/src/components/LoginForm/LoginForm.react.js @@ -33,6 +33,7 @@ export default class LoginForm extends React.Component { if (this.props.disableSubmit) { return; } + this.props.formSubmit(); this.refs.form.submit() }} className={styles.submit} diff --git a/src/dashboard/Dashboard.js b/src/dashboard/Dashboard.js index 6ccc04bc2b..0dfe25ce1a 100644 --- a/src/dashboard/Dashboard.js +++ b/src/dashboard/Dashboard.js @@ -117,6 +117,8 @@ export default class Dashboard extends React.Component { newFeaturesInLatestVersion: [], }; setBasePath(props.path); + sessionStorage.removeItem('username'); + sessionStorage.removeItem('password'); } componentDidMount() { diff --git a/src/login/Login.js b/src/login/Login.js index 0a0b5dc75a..59a3748559 100644 --- a/src/login/Login.js +++ b/src/login/Login.js @@ -21,29 +21,59 @@ export default class Login extends React.Component { } this.state = { - forgot: false + forgot: false, + username: sessionStorage.getItem('username') || '', + password: sessionStorage.getItem('password') || '' }; + sessionStorage.clear(); setBasePath(props.path); } render() { const {path} = this.props; + const updateField = (field, e) => { + this.setState({[field]: e.target.value}); + } + const formSubmit = () => { + sessionStorage.setItem('username', this.state.username); + sessionStorage.setItem('password', this.state.password); + } return ( } /> + input={ + updateField('username', e)} + autoFocus + /> + } /> } /> - updateField('password', e)} + /> + } /> + { + this.errors && this.errors.includes('OTP') ? + } /> + : null + } {this.errors ?
{this.errors} From b9b3103aaa50919832a5c83a78b714cc76d31958 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sun, 5 Sep 2021 03:35:29 +1000 Subject: [PATCH 14/37] change to one-time --- Parse-Dashboard/Authentication.js | 4 ++-- src/login/Login.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Parse-Dashboard/Authentication.js b/Parse-Dashboard/Authentication.js index 597680a3f5..9778deefed 100644 --- a/Parse-Dashboard/Authentication.js +++ b/Parse-Dashboard/Authentication.js @@ -33,10 +33,10 @@ function initialize(app, options) { return cb(null, false, { message: 'Invalid username or password' }); } if (match.otpMissing) { - return cb(null, false, { message: 'Please enter your OTP code.' }); + return cb(null, false, { message: 'Please enter your one-time password.' }); } if (!match.otpValid) { - return cb(null, false, { message: 'Invalid OTP code.' }); + return cb(null, false, { message: 'Invalid one-time password.' }); } cb(null, match.matchingUsername); }) diff --git a/src/login/Login.js b/src/login/Login.js index 59a3748559..0fc8b5798a 100644 --- a/src/login/Login.js +++ b/src/login/Login.js @@ -68,7 +68,7 @@ export default class Login extends React.Component { /> } /> { - this.errors && this.errors.includes('OTP') ? + this.errors && this.errors.includes('one-time') ? } /> From 44e72c8453296bad231b797183c0f0b249d4c90b Mon Sep 17 00:00:00 2001 From: dblythy Date: Sun, 5 Sep 2021 03:40:51 +1000 Subject: [PATCH 15/37] change to otp --- CHANGELOG.md | 2 +- Parse-Dashboard/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54b35b96d6..5a9a0f70aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ [Full Changelog](https://github.com/parse-community/parse-dashboard/compare/2.2.0...master) ## New Features -- Add MFA to dashboard login. To use MFA, run `parse-dashboard --createMFA` or `parse-dashboard --createUser`. (Daniel Blyth) [#1624](https://github.com/parse-community/parse-dashboard/pull/1624) +- Add multi-factor authentication to dashboard login. To use one-time passwor, run `parse-dashboard --createMFA` or `parse-dashboard --createUser`. (Daniel Blyth) [#1624](https://github.com/parse-community/parse-dashboard/pull/1624) ## Improvements - Add CI check to add changelog entry (Manuel Trezza) [#1764](https://github.com/parse-community/parse-dashboard/pull/1764) diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js index e53ec26016..1dcd33d407 100644 --- a/Parse-Dashboard/index.js +++ b/Parse-Dashboard/index.js @@ -30,7 +30,7 @@ program.option('--sslCert [sslCert]', 'the path to the SSL certificate.'); program.option('--trustProxy [trustProxy]', 'set this flag when you are behind a front-facing proxy, such as when hosting on Heroku. Uses X-Forwarded-* headers to determine the client\'s connection and IP address.'); program.option('--cookieSessionSecret [cookieSessionSecret]', 'set the cookie session secret, defaults to a random string. You should set that value if you want sessions to work across multiple server, or across restarts'); program.option('--createUser', 'helper tool to allow you to generate secure user passwords and secrets. Use this once on a trusted device only.'); -program.option('--createMFA', 'helper tool to allow you to generate MFA secrets.'); +program.option('--createMFA', 'helper tool to allow you to generate one-time password secrets.'); program.parse(process.argv); From d354063c61ed7346ff5ec9f16320fd867fc0da53 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Sat, 4 Sep 2021 23:27:18 +0200 Subject: [PATCH 16/37] fix package-lock --- package-lock.json | 1591 ++++++++++++++++----------------------------- 1 file changed, 554 insertions(+), 1037 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4ff7812810..8ca4680a79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -107,6 +107,15 @@ "integrity": "sha512-ZII+/xUFfb9ezDU2gad114+zScxVFMVlZ91f8fGApMzlS1kkqoyLnC4AJaQ1Ya/X+b63I20B4Gd+eCL8QuB4sA==", "dev": true }, + "@apollographql/graphql-playground-html": { + "version": "1.6.29", + "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.29.tgz", + "integrity": "sha512-xCcXpoz52rI4ksJSdOCxeOCn2DLocxwHf9dVT/Q90Pte1LX+LY+91SFtJF3KXVHH8kEin+g1KKCQPKBjZJfWNA==", + "dev": true, + "requires": { + "xss": "^1.0.8" + } + }, "@apollographql/graphql-upload-8-fork": { "version": "8.1.3", "resolved": "https://registry.npmjs.org/@apollographql/graphql-upload-8-fork/-/graphql-upload-8-fork-8.1.3.tgz", @@ -1766,6 +1775,105 @@ "integrity": "sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg==", "dev": true }, + "@napi-rs/triples": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/triples/-/triples-1.0.3.tgz", + "integrity": "sha512-jDJTpta+P4p1NZTFVLHJ/TLFVYVcOqv6l8xwOeBKNPMgY/zDYH/YH7SJbvrr/h1RcS9GzbPcLKGzpuK9cV56UA==", + "dev": true, + "optional": true + }, + "@node-rs/bcrypt": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt/-/bcrypt-1.1.0.tgz", + "integrity": "sha512-5vjztYYcPCyvamO3C+hrNaVplZC9yEMzGxJECliQR5hkUOQdrtulCpigNOr1POWpC1YsJH0ZL+ktWop+cl5Qqw==", + "dev": true, + "optional": true, + "requires": { + "@node-rs/bcrypt-android-arm64": "^1.1.0", + "@node-rs/bcrypt-darwin-arm64": "^1.1.0", + "@node-rs/bcrypt-darwin-x64": "^1.1.0", + "@node-rs/bcrypt-linux-arm-gnueabihf": "^1.1.0", + "@node-rs/bcrypt-linux-arm64-gnu": "^1.1.0", + "@node-rs/bcrypt-linux-x64-gnu": "^1.1.0", + "@node-rs/bcrypt-linux-x64-musl": "^1.1.0", + "@node-rs/bcrypt-win32-ia32-msvc": "^1.1.0", + "@node-rs/bcrypt-win32-x64-msvc": "^1.1.0", + "@node-rs/helper": "^1.1.0" + } + }, + "@node-rs/bcrypt-android-arm64": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm64/-/bcrypt-android-arm64-1.4.1.tgz", + "integrity": "sha512-CP/8CbrhLUjHW2OrOd6tgcx2FKMTWqUDAUCDtUq4ZBlUIn7P/e+/iosNK9QNBcT8AUMNr4TD1n5QW+SKM2Zk/Q==", + "dev": true, + "optional": true + }, + "@node-rs/bcrypt-darwin-arm64": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-arm64/-/bcrypt-darwin-arm64-1.4.1.tgz", + "integrity": "sha512-6Digb49rzOS36X6qXaU4a6JxDsxPlWj09AFyF/kBhhmRocDKHyO2dnR8vexhjlzLyMlS00VL2q8kPei2Q8IAYQ==", + "dev": true, + "optional": true + }, + "@node-rs/bcrypt-darwin-x64": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-x64/-/bcrypt-darwin-x64-1.4.1.tgz", + "integrity": "sha512-Rs/ySQ0CHRXJCOrSWod0b4fmF3Z+EP4RygSXBsV/NTVggHB2TrSdHRYajG9ZHB7P0acs2HHb1GcP5jOpggpMvA==", + "dev": true, + "optional": true + }, + "@node-rs/bcrypt-linux-arm-gnueabihf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm-gnueabihf/-/bcrypt-linux-arm-gnueabihf-1.4.1.tgz", + "integrity": "sha512-oiRR4vJUtwO2DG91oyWDHYx9oU79190l0FIgYKwfXjt9ge5ZFr+fVjXbayuANxWCAtt178u3HYwWR1ayHhRpUQ==", + "dev": true, + "optional": true + }, + "@node-rs/bcrypt-linux-arm64-gnu": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-gnu/-/bcrypt-linux-arm64-gnu-1.4.1.tgz", + "integrity": "sha512-oA/WNbHZ/RZ5Sm/NhbprkDRUMVzekpzrigYEC+XJaJSaVpSL5Qyif1mZLZW+AWNIoEM0LZ7/UFe8KyS2+gcW5Q==", + "dev": true, + "optional": true + }, + "@node-rs/bcrypt-linux-x64-gnu": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-gnu/-/bcrypt-linux-x64-gnu-1.4.1.tgz", + "integrity": "sha512-CvG1gBTAg0Vv9MUbESH/3g2k+oak+NB3jVv4vreTsQu8jI7AVk4PSCMygiV+oWaoNA4Yhu6H+M+M6JccvtaYtg==", + "dev": true, + "optional": true + }, + "@node-rs/bcrypt-linux-x64-musl": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-musl/-/bcrypt-linux-x64-musl-1.4.1.tgz", + "integrity": "sha512-Q71g6aJ88VDz8ljIhFd8g3Uj+k+n7vhe6h1o/aO/Atqv2+YcRuZlrGohXvwf4Vu4RYNi99EkQu+uK46QjPJTmQ==", + "dev": true, + "optional": true + }, + "@node-rs/bcrypt-win32-ia32-msvc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-ia32-msvc/-/bcrypt-win32-ia32-msvc-1.4.1.tgz", + "integrity": "sha512-A8S9557mVubI6o6dlYPZwdOKQBmA2sEzzwFIIxx257Mv5Zwt44x7hXwy9DBc98NaIyVBrC9eG5zxpAu/12r2lQ==", + "dev": true, + "optional": true + }, + "@node-rs/bcrypt-win32-x64-msvc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-x64-msvc/-/bcrypt-win32-x64-msvc-1.4.1.tgz", + "integrity": "sha512-24xUag1/BwuBviRpozXnYQKGsqfriQw3VaCBQb6chvUTwQVjrndYmZfW+TMrCWLgnD1qRT3T0u3cZoOY9QxknA==", + "dev": true, + "optional": true + }, + "@node-rs/helper": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@node-rs/helper/-/helper-1.2.1.tgz", + "integrity": "sha512-R5wEmm8nbuQU0YGGmYVjEc0OHtYsuXdpRG+Ut/3wZ9XAvQWyThN08bTh2cBJgoZxHQUPtvRfeQuxcAgLuiBISg==", + "dev": true, + "optional": true, + "requires": { + "@napi-rs/triples": "^1.0.3" + } + }, "@otplib/core": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/@otplib/core/-/core-12.0.1.tgz", @@ -1814,6 +1922,35 @@ "integrity": "sha512-kr7Ti2eYOm14p05S86yriJdMtawL6qln3Dn5eekrwY14ih4jrjH/E+QlEpBUSBzN64fluFxciFOyjdbwDGWsGw==", "dev": true }, + "@parse/node-apn": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-4.1.1.tgz", + "integrity": "sha512-stWlQE95w5T0vkVYscoq/S3eXPQ1qzdQbKKQ8GAdw4CSNxRWLWgOH50byUR30thnQ93RshLCH5ROkvXMqzzLtw==", + "dev": true, + "requires": { + "debug": "4.3.2", + "jsonwebtoken": "8.5.1", + "node-forge": "0.10.0", + "verror": "1.10.0" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "@parse/node-gcm": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@parse/node-gcm/-/node-gcm-1.0.2.tgz", @@ -1898,65 +2035,16 @@ } } }, - "@parse/s3-files-adapter": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@parse/s3-files-adapter/-/s3-files-adapter-1.6.0.tgz", - "integrity": "sha512-t/91hlZ4+GIA68zmJIX9lkIAxPZVRJROPYWGGyxE9CLGsSvBr/eaIHs6LnKyM012lBHzwJwoLxMkN4RvJADgbg==", - "dev": true, - "requires": { - "aws-sdk": "2.761.0", - "parse": "2.17.0" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", - "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/runtime-corejs3": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz", - "integrity": "sha512-qh5IR+8VgFz83VBa6OkaET6uN/mJOhHONuy3m1sgF0CV6mXdPSEBdA7e1eUbVvyNtANjMbg22JUv71BaDXLY6A==", - "dev": true, - "requires": { - "core-js-pure": "^3.0.0", - "regenerator-runtime": "^0.13.4" - } - }, - "parse": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/parse/-/parse-2.17.0.tgz", - "integrity": "sha512-1hWoMNW39LH5YV3xCds9LyD8SsKD6FUwlD1Kn8ZlXNosg6WgF+s3ZSQUzT5AJ/9YPUoC/y1PoCO79FumrBYftA==", - "dev": true, - "requires": { - "@babel/runtime": "7.11.2", - "@babel/runtime-corejs3": "7.11.2", - "crypto-js": "4.0.0", - "react-native-crypto-js": "1.0.0", - "uuid": "3.4.0", - "ws": "7.3.1", - "xmlhttprequest": "1.8.0" - } - }, - "ws": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", - "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", - "dev": true - } - } - }, - "@parse/simple-mailgun-adapter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@parse/simple-mailgun-adapter/-/simple-mailgun-adapter-1.1.0.tgz", - "integrity": "sha512-9Eaj25HQ7RpcA6gsTnimXtlLcyLpP9PKSFE9DF79ahgndbdyCjpNd9jQxpBaBlsCsDE+D5LlXfckMqqJPo+pjQ==", + "@parse/push-adapter": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-3.4.1.tgz", + "integrity": "sha512-iev69kbwhXbez5nfEwB2GkCWBLUmRlImQTmHPpLnHBJfATYKyXf/H41WQhBPuwwScZBVp9ABsIsjjKy8iKg3fw==", "dev": true, "requires": { - "mailgun-js": "0.18.0" + "@parse/node-apn": "4.1.1", + "@parse/node-gcm": "1.0.2", + "npmlog": "4.1.2", + "parse": "3.3.0" } }, "@popperjs/core": { @@ -2149,6 +2237,12 @@ "@types/node": "*" } }, + "@types/cors": { + "version": "2.8.10", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.10.tgz", + "integrity": "sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ==", + "dev": true + }, "@types/express": { "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", @@ -3049,6 +3143,42 @@ "integrity": "sha512-lO5oTjgiC3vlVg2RKr3RiXIIQ5pGXBFxYGGUkKDhTud3jMIhs+gel8L8zsEjKaKxkjHhCQAA/bcEfYiKkGQIvA==", "dev": true }, + "apollo-server-express": { + "version": "2.25.2", + "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.25.2.tgz", + "integrity": "sha512-A2gF2e85vvDugPlajbhr0A14cDFDIGX0mteNOJ8P3Z3cIM0D4hwrWxJidI+SzobefDIyIHu1dynFedJVhV0euQ==", + "dev": true, + "requires": { + "@apollographql/graphql-playground-html": "1.6.27", + "@types/accepts": "^1.3.5", + "@types/body-parser": "1.19.0", + "@types/cors": "2.8.10", + "@types/express": "^4.17.12", + "@types/express-serve-static-core": "^4.17.21", + "accepts": "^1.3.5", + "apollo-server-core": "^2.25.2", + "apollo-server-types": "^0.9.0", + "body-parser": "^1.18.3", + "cors": "^2.8.5", + "express": "^4.17.1", + "graphql-subscriptions": "^1.0.0", + "graphql-tools": "^4.0.8", + "parseurl": "^1.3.2", + "subscriptions-transport-ws": "^0.9.19", + "type-is": "^1.6.16" + }, + "dependencies": { + "@apollographql/graphql-playground-html": { + "version": "1.6.27", + "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.27.tgz", + "integrity": "sha512-tea2LweZvn6y6xFV11K0KC8ETjmm52mQrW+ezgB2O/aTQf8JGyFmMcRPFgUaQZeHbWdm8iisDC6EjOKsXu0nfw==", + "dev": true, + "requires": { + "xss": "^1.0.8" + } + } + } + }, "apollo-server-plugin-base": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.13.0.tgz", @@ -3240,6 +3370,12 @@ } } }, + "assert-options": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.7.0.tgz", + "integrity": "sha512-7q9uNH/Dh8gFgpIIb9ja8PJEWA5AQy3xnBC8jtKs8K/gNVCr1K6kIvlm59HUyYgvM7oEDoLzGgPcGd9FqhtXEQ==", + "dev": true + }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -3252,23 +3388,6 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, - "ast-types": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", - "integrity": "sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==", - "dev": true, - "requires": { - "tslib": "^2.0.1" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - } - } - }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", @@ -3323,98 +3442,6 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, - "aws-sdk": { - "version": "2.761.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.761.0.tgz", - "integrity": "sha512-mSzdiqlnruFlJYrQVWPMyPQ8ynJe9P5QVD+edv8HFlYDQNOwpPCjlqI9kE1VE3cVcxkh0j2Q2kfLQa/pAY2w7Q==", - "dev": true, - "requires": { - "buffer": "4.9.2", - "events": "1.1.1", - "ieee754": "1.1.13", - "jmespath": "0.15.0", - "querystring": "0.2.0", - "sax": "1.2.1", - "url": "0.10.3", - "uuid": "3.3.2", - "xml2js": "0.4.19" - }, - "dependencies": { - "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - }, - "sax": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=", - "dev": true - }, - "url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true - }, - "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" - } - }, - "xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", - "dev": true - } - } - }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -3427,6 +3454,15 @@ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", "dev": true }, + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "dev": true, + "requires": { + "follow-redirects": "^1.10.0" + } + }, "babel-eslint": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", @@ -4369,6 +4405,28 @@ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" }, + "cli-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.0.tgz", + "integrity": "sha512-a0VZ8LeraW0jTuCkuAGMNufareGHhyZU9z8OGsW0gXd1hZGi1SRuNRXdbGkraBBKnhyUhyebFWnRbp+dIn0f0A==", + "dev": true, + "requires": { + "ansi-regex": "^2.1.1", + "d": "^1.0.1", + "es5-ext": "^0.10.51", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.14", + "timers-ext": "^0.1.7" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } + } + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -5031,6 +5089,16 @@ "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", "dev": true }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -5040,12 +5108,6 @@ "assert-plus": "^1.0.0" } }, - "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", - "dev": true - }, "data-urls": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", @@ -5185,25 +5247,6 @@ } } }, - "degenerator": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", - "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", - "dev": true, - "requires": { - "ast-types": "0.x.x", - "escodegen": "1.x.x", - "esprima": "3.x.x" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - } - } - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -5607,19 +5650,48 @@ "is-symbol": "^1.0.2" } }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "dev": true + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", "dev": true, "requires": { - "es6-promise": "^4.0.3" + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" } }, "escalade": { @@ -6030,6 +6102,16 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "eventemitter3": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", @@ -6241,14 +6323,31 @@ } } }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", + "ext": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.5.0.tgz", + "integrity": "sha512-+ONcYoWj/SoQwUofMr94aGu05Ou4FepKi7N7b+O8T4jVfyIsZQV1/xeS8jpaBzF0csAk0KLXoHCxU7cKYZjo1Q==", + "dev": true, + "requires": { + "type": "^2.5.0" + }, + "dependencies": { + "type": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", + "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, @@ -6541,7 +6640,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true + "dev": true, + "optional": true }, "filesize": { "version": "3.6.1", @@ -6782,42 +6882,6 @@ "rimraf": "2" } }, - "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "dev": true, - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", - "dev": true - } - } - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -6927,20 +6991,6 @@ "pump": "^3.0.0" } }, - "get-uri": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.4.tgz", - "integrity": "sha512-v7LT/s8kVjs+Tx0ykk1I+H/rbpzkHvuIq87LmeXptcf5sNWm9uQiwjNAt94SJPA1zOlCntmnOlJvVWKmzsxG8Q==", - "dev": true, - "requires": { - "data-uri-to-buffer": "1", - "debug": "2", - "extend": "~3.0.2", - "file-uri-to-path": "1", - "ftp": "~0.3.10", - "readable-stream": "2" - } - }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -7333,6 +7383,12 @@ } } }, + "graphql-relay": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/graphql-relay/-/graphql-relay-0.8.0.tgz", + "integrity": "sha512-NU7CkwNxPzkqpBgv76Cgycrc3wmWVA2K5Sxm9DHSSLLuQTpaSRAUsX1sf2gITf+XQpkccsv56/z0LojXTyQbUw==", + "dev": true + }, "graphql-request": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-1.8.2.tgz", @@ -7893,12 +7949,6 @@ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "dev": true }, - "inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", - "dev": true - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -8029,12 +8079,6 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -8923,12 +8967,6 @@ } } }, - "jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", - "dev": true - }, "js-base64": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", @@ -9153,6 +9191,49 @@ "safe-buffer": "^5.0.1" } }, + "jwks-rsa": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-1.12.3.tgz", + "integrity": "sha512-cFipFDeYYaO9FhhYJcZWX/IyZgc0+g316rcHnDpT2dNRNIE/lMOmWKKqp09TkJoYlNFzrEVODsR4GgXJMgWhnA==", + "dev": true, + "requires": { + "@types/express-jwt": "0.0.42", + "axios": "^0.21.1", + "debug": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "jsonwebtoken": "^8.5.1", + "limiter": "^1.1.5", + "lru-memoizer": "^2.1.2", + "ms": "^2.1.2", + "proxy-from-env": "^1.1.0" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, "jws": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", @@ -9563,32 +9644,13 @@ } } }, - "mailgun-js": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.18.0.tgz", - "integrity": "sha512-o0P6jjZlx5CQj12tvVgDTbgjTqVN0+5h6/6P1+3c6xmozVKBwniQ6Qt3MkCSF0+ueVTbobAfWyGpWRZMJu8t1g==", + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", "dev": true, "requires": { - "async": "~2.6.0", - "debug": "~3.1.0", - "form-data": "~2.3.0", - "inflection": "~1.12.0", - "is-stream": "^1.1.0", - "path-proxy": "~1.0.0", - "promisify-call": "^2.0.2", - "proxy-agent": "~3.0.0", - "tsscmp": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } + "es5-ext": "~0.10.2" } }, "make-dir": { @@ -9717,6 +9779,36 @@ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" }, + "memoizee": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "dev": true, + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + }, + "dependencies": { + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true + } + } + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -10045,6 +10137,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "dev": true + }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -10092,10 +10190,10 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, "nice-try": { @@ -10698,6 +10796,15 @@ } } }, + "optional-require": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.7.tgz", + "integrity": "sha512-cIeRZocXsZnZYn+SevbtSqNlLbeoS4mLzuNn4fvXRMDRNhTGg0sxuKXl0FnZCtnew85LorNxIbZp5OeliILhMw==", + "dev": true, + "requires": { + "require-at": "^1.0.6" + } + }, "optionator": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", @@ -10911,109 +11018,6 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, - "pac-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.1.tgz", - "integrity": "sha512-44DUg21G/liUZ48dJpUSjZnFfZro/0K5JTyFYLBcmh9+T6Ooi4/i4efwUiEy0+4oQusCBqWdhv16XohIj1GqnQ==", - "dev": true, - "requires": { - "agent-base": "^4.2.0", - "debug": "^4.1.1", - "get-uri": "^2.0.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^3.0.0", - "pac-resolver": "^3.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "^4.0.1" - }, - "dependencies": { - "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "https-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", - "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", - "dev": true, - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "pac-resolver": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", - "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", - "dev": true, - "requires": { - "co": "^4.6.0", - "degenerator": "^1.0.4", - "ip": "^1.1.5", - "netmask": "^1.0.6", - "thunkify": "^2.1.2" - } - }, "package-json": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", @@ -11124,273 +11128,53 @@ "dev": true }, "parse-server": { - "version": "github:parseplatform/parse-server#a9ce02eb74a923a03ee42cef4b8e64870e9d6e32", + "version": "github:parseplatform/parse-server#5ab974dcd47906efb41edb6c709c4e078cabaa7f", "from": "github:parseplatform/parse-server#master", "dev": true, "requires": { - "@apollographql/graphql-playground-html": "1.6.26", + "@apollographql/graphql-playground-html": "1.6.29", "@graphql-tools/links": "6.2.5", "@graphql-tools/stitch": "6.2.4", "@graphql-tools/utils": "6.2.4", - "@node-rs/bcrypt": "0.4.1", + "@node-rs/bcrypt": "1.1.0", "@parse/fs-files-adapter": "1.2.0", - "@parse/push-adapter": "3.4.0", - "@parse/s3-files-adapter": "1.6.0", - "@parse/simple-mailgun-adapter": "1.1.0", - "apollo-server-express": "2.19.0", + "@parse/push-adapter": "3.4.1", + "apollo-server-express": "2.25.2", "bcryptjs": "2.4.3", "body-parser": "1.19.0", "commander": "5.1.0", "cors": "2.8.5", "deepcopy": "2.1.0", "express": "4.17.1", - "follow-redirects": "1.13.0", - "graphql": "15.4.0", + "follow-redirects": "1.14.1", + "graphql": "15.5.1", "graphql-list-fields": "2.0.2", - "graphql-relay": "0.6.0", + "graphql-relay": "0.8.0", + "graphql-tag": "2.12.5", "graphql-upload": "11.0.0", "intersect": "1.0.1", "jsonwebtoken": "8.5.1", - "jwks-rsa": "1.11.0", - "ldapjs": "2.2.0", - "lodash": "4.17.20", + "jwks-rsa": "1.12.3", + "ldapjs": "2.3.1", + "lodash": "4.17.21", "lru-cache": "5.1.1", - "mime": "2.4.6", - "mongodb": "3.6.2", - "parse": "2.17.0", - "pg-promise": "10.7.3", + "mime": "2.5.2", + "mongodb": "3.6.11", + "mustache": "4.2.0", + "parse": "3.3.0", + "pg-monitor": "1.4.1", + "pg-promise": "10.11.0", "pluralize": "8.0.0", - "redis": "3.0.2", - "semver": "7.3.2", - "subscriptions-transport-ws": "0.9.18", + "redis": "3.1.2", + "semver": "7.3.4", + "subscriptions-transport-ws": "0.10.0", "tv4": "1.3.0", - "uuid": "8.3.1", + "uuid": "8.3.2", "winston": "3.3.3", - "winston-daily-rotate-file": "4.5.0", - "ws": "7.3.1" + "winston-daily-rotate-file": "4.5.5", + "ws": "7.5.3" }, "dependencies": { - "@apollographql/graphql-playground-html": { - "version": "1.6.26", - "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.26.tgz", - "integrity": "sha512-XAwXOIab51QyhBxnxySdK3nuMEUohhDsHQ5Rbco/V1vjlP75zZ0ZLHD9dTpXTN8uxKxopb2lUvJTq+M4g2Q0HQ==", - "dev": true, - "requires": { - "xss": "^1.0.6" - } - }, - "@babel/runtime": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", - "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/runtime-corejs3": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz", - "integrity": "sha512-qh5IR+8VgFz83VBa6OkaET6uN/mJOhHONuy3m1sgF0CV6mXdPSEBdA7e1eUbVvyNtANjMbg22JUv71BaDXLY6A==", - "dev": true, - "requires": { - "core-js-pure": "^3.0.0", - "regenerator-runtime": "^0.13.4" - } - }, - "@node-rs/bcrypt": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt/-/bcrypt-0.4.1.tgz", - "integrity": "sha512-D5Uq08lbrmwnU3DcqcXWPr/POtUHM5nfzfxt7u7FdrES4kWCOEsRwBZYNHlAMZ22T/JJSQ7npSkoCF44GQCLuw==", - "dev": true, - "optional": true, - "requires": { - "@node-rs/helper": "^0.3.1" - } - }, - "@node-rs/helper": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@node-rs/helper/-/helper-0.3.1.tgz", - "integrity": "sha512-3X6SJOcyFRYv1mjrjtSHiziJuzAsqaz2pFD3uuLxu4qJo4TH6H0gaUb1Bdxl/VtiDy2yR+eMyBOQFCvr/G2oLA==", - "dev": true, - "optional": true, - "requires": { - "tslib": "^2.0.1" - } - }, - "@parse/node-apn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-4.0.0.tgz", - "integrity": "sha512-/Zhz7+AfwuMeBn9kpENF5qbWDG1+0xLBOlAb7O34BhR9R5BSjAKkMxqWmTz3R3nvlsod4XrZ8NuRMUOXVrCCFQ==", - "dev": true, - "requires": { - "debug": "3.1.0", - "jsonwebtoken": "8.1.0", - "node-forge": "0.10.0", - "verror": "1.10.0" - }, - "dependencies": { - "jsonwebtoken": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz", - "integrity": "sha1-xjl80uX9WD1lwAeoPce7eOaYK4M=", - "dev": true, - "requires": { - "jws": "^3.1.4", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.0.0", - "xtend": "^4.0.1" - } - } - } - }, - "@parse/push-adapter": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-3.4.0.tgz", - "integrity": "sha512-ZYf6DKQHpUoi806SIDiuVhstL3BRQC4brcCyTnoLih/u08Cg60Pbkz2B95JU+6xMcM211A2AvPDudEmsMahq7w==", - "dev": true, - "requires": { - "@parse/node-apn": "4.0.0", - "@parse/node-gcm": "1.0.2", - "npmlog": "4.1.2", - "parse": "2.17.0" - } - }, - "@types/cors": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.8.tgz", - "integrity": "sha512-fO3gf3DxU2Trcbr75O7obVndW/X5k8rJNZkLXlQWStTHhP71PkRqjwPIEI0yMnJdg9R9OasjU+Bsr+Hr1xy/0w==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/express": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.7.tgz", - "integrity": "sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "*", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.13.tgz", - "integrity": "sha512-RgDi5a4nuzam073lRGKTUIaL3eF2+H7LJvJ8eUnCI0wA6SNjXc44DCmWNiTLs/AZ7QlsFWZiw/gTG3nSQGL0fA==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "apollo-reporting-protobuf": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/apollo-reporting-protobuf/-/apollo-reporting-protobuf-0.6.2.tgz", - "integrity": "sha512-WJTJxLM+MRHNUxt1RTl4zD0HrLdH44F2mDzMweBj1yHL0kSt8I1WwoiF/wiGVSpnG48LZrBegCaOJeuVbJTbtw==", - "dev": true, - "requires": { - "@apollo/protobufjs": "^1.0.3" - } - }, - "apollo-server-caching": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.3.tgz", - "integrity": "sha512-iMi3087iphDAI0U2iSBE9qtx9kQoMMEWr6w+LwXruBD95ek9DWyj7OeC2U/ngLjRsXM43DoBDXlu7R+uMjahrQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "apollo-server-express": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.19.0.tgz", - "integrity": "sha512-3rgSrTme1SlLoecAYtSa8ThH6vYvz29QecgZCigq5Vdc6bFP2SZrCk0ls6BAdD8OZbVKUtizzRxd0yd/uREPAw==", - "dev": true, - "requires": { - "@apollographql/graphql-playground-html": "1.6.26", - "@types/accepts": "^1.3.5", - "@types/body-parser": "1.19.0", - "@types/cors": "2.8.8", - "@types/express": "4.17.7", - "@types/express-serve-static-core": "4.17.13", - "accepts": "^1.3.5", - "apollo-server-core": "^2.19.0", - "apollo-server-types": "^0.6.1", - "body-parser": "^1.18.3", - "cors": "^2.8.4", - "express": "^4.17.1", - "graphql-subscriptions": "^1.0.0", - "graphql-tools": "^4.0.0", - "parseurl": "^1.3.2", - "subscriptions-transport-ws": "^0.9.16", - "type-is": "^1.6.16" - } - }, - "apollo-server-types": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.6.3.tgz", - "integrity": "sha512-aVR7SlSGGY41E1f11YYz5bvwA89uGmkVUtzMiklDhZ7IgRJhysT5Dflt5IuwDxp+NdQkIhVCErUXakopocFLAg==", - "dev": true, - "requires": { - "apollo-reporting-protobuf": "^0.6.2", - "apollo-server-caching": "^0.5.3", - "apollo-server-env": "^3.0.0" - } - }, - "assert-options": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.6.2.tgz", - "integrity": "sha512-KP9S549XptFAPGYmLRnIjQBL4/Ry8Jx5YNLQZ/l+eejqbTidBMnw4uZSAsUrzBq/lgyqDYqxcTF7cOxZb9gyEw==", - "dev": true - }, - "axios": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", - "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", - "dev": true, - "requires": { - "follow-redirects": "1.5.10" - }, - "dependencies": { - "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "dev": true, - "requires": { - "debug": "=3.1.0" - } - } - } - }, "bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", @@ -11403,83 +11187,22 @@ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", "dev": true }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "follow-redirects": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", - "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", + "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", "dev": true }, "graphql": { - "version": "15.4.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.4.0.tgz", - "integrity": "sha512-EB3zgGchcabbsU9cFe1j+yxdzKQKAbGUWRb13DsrsMN1yyfmmIq+2+L5MqVWcDCE4V89R5AyUOi7sMOGxdsYtA==", + "version": "15.5.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.5.1.tgz", + "integrity": "sha512-FeTRX67T3LoE3LWAxxOlW2K3Bz+rMYAC18rRguK4wgXaTZMiJwSUwDmPFo3UadAKbzirKIg5Qy+sNJXbpPRnQw==", "dev": true }, - "graphql-relay": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/graphql-relay/-/graphql-relay-0.6.0.tgz", - "integrity": "sha512-OVDi6C9/qOT542Q3KxZdXja3NrDvqzbihn1B44PH8P/c5s0Q90RyQwT6guhGqXqbYEH6zbeLJWjQqiYvcg2vVw==", - "dev": true, - "requires": { - "prettier": "^1.16.0" - } - }, - "jwks-rsa": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-1.11.0.tgz", - "integrity": "sha512-G7ZgXZ3dlGbOUBQwgF+U/SVzOlI9KxJ9Uzp61bue2S5TV0h7c+kJRCl3bEPkC5PVmeu7/h82B3uQALVJMjzt/Q==", - "dev": true, - "requires": { - "@types/express-jwt": "0.0.42", - "axios": "^0.19.2", - "debug": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "jsonwebtoken": "^8.5.1", - "limiter": "^1.1.5", - "lru-memoizer": "^2.1.2", - "ms": "^2.1.2", - "proxy-from-env": "^1.1.0" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, "ldapjs": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-2.2.0.tgz", - "integrity": "sha512-9+ekbj97nxRYQMRgEm/HYFhFLWSRKah2PnReUfhfM5f62XBeUSFolB+AQ2Jij5tqowpksTnrdNCZLP6C+V3uag==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-2.3.1.tgz", + "integrity": "sha512-kf0tHHLrpwKaBAQOhYHXgdeh2PkFuCCxWgLb1MRn67ZQVo787D2pij3mmHVZx193GIdM8xcfi8HF6AIYYnj0fQ==", "dev": true, "requires": { "abstract-logging": "^2.0.0", @@ -11492,12 +11215,6 @@ "verror": "^1.8.1" } }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -11508,164 +11225,48 @@ } }, "mime": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", "dev": true }, "mongodb": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.2.tgz", - "integrity": "sha512-sSZOb04w3HcnrrXC82NEh/YGCmBuRgR+C1hZgmmv4L6dBz4BkRse6Y8/q/neXer9i95fKUBbFi4KgeceXmbsOA==", + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.11.tgz", + "integrity": "sha512-4Y4lTFHDHZZdgMaHmojtNAlqkvddX2QQBEN0K//GzxhGwlI9tZ9R0vhbjr1Decw+TF7qK0ZLjQT292XgHRRQgw==", "dev": true, "requires": { "bl": "^2.2.1", "bson": "^1.1.4", "denque": "^1.4.1", - "require_optional": "^1.0.1", + "optional-require": "^1.0.3", "safe-buffer": "^5.1.2", "saslprep": "^1.0.0" } }, - "parse": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/parse/-/parse-2.17.0.tgz", - "integrity": "sha512-1hWoMNW39LH5YV3xCds9LyD8SsKD6FUwlD1Kn8ZlXNosg6WgF+s3ZSQUzT5AJ/9YPUoC/y1PoCO79FumrBYftA==", - "dev": true, - "requires": { - "@babel/runtime": "7.11.2", - "@babel/runtime-corejs3": "7.11.2", - "crypto-js": "4.0.0", - "react-native-crypto-js": "1.0.0", - "uuid": "3.4.0", - "ws": "7.3.1", - "xmlhttprequest": "1.8.0" - }, - "dependencies": { - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - } - } - }, - "pg": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.4.1.tgz", - "integrity": "sha512-NRsH0aGMXmX1z8Dd0iaPCxWUw4ffu+lIAmGm+sTCwuDDWkpEgRCAHZYDwqaNhC5hG5DRMOjSUFasMWhvcmLN1A==", - "dev": true, - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.4.0", - "pg-pool": "^3.2.1", - "pg-protocol": "^1.3.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - } - }, - "pg-minify": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.1.tgz", - "integrity": "sha512-ujanxJJB9CSDUvlAOshtjdKAywOPR2vY0a7D+vvgk5rbrYcthZA7TjpN+Z+UwZsz/G/bUexYDT6huE33vYVN0g==", - "dev": true - }, - "pg-promise": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-10.7.3.tgz", - "integrity": "sha512-RGZpTkQYKUlOI6qHp5UVbhiqDdk+YmfkSmLscbaQd8fIz9lGEUBZHfJJNMKoSa3MWfsN2pg/iAxob6QCma/GaQ==", - "dev": true, - "requires": { - "assert-options": "0.6.2", - "pg": "8.4.1", - "pg-minify": "1.6.1", - "spex": "3.0.2" - } - }, - "redis": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/redis/-/redis-3.0.2.tgz", - "integrity": "sha512-PNhLCrjU6vKVuMOyFu7oSP296mwBkcE6lrAjruBYG5LgdSqtRBoVQIylrMyVZD/lkF24RSNNatzvYag6HRBHjQ==", - "dev": true, - "requires": { - "denque": "^1.4.1", - "redis-commands": "^1.5.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0" - } - }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true - }, - "spex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spex/-/spex-3.0.2.tgz", - "integrity": "sha512-ZNCrOso+oNv5P01HCO4wuxV9Og5rS6ms7gGAqugfBPjx1QwfNXJI3T02ldfaap1O0dlT1sB0Rk+mhDqxt3Z27w==", - "dev": true - }, "subscriptions-transport-ws": { - "version": "0.9.18", - "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.18.tgz", - "integrity": "sha512-tztzcBTNoEbuErsVQpTN2xUNN/efAZXyCyL5m3x4t6SKrEiTL2N8SaKWBFWM4u56pL79ULif3zjyeq+oV+nOaA==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.10.0.tgz", + "integrity": "sha512-k28LhLn3abJ1mowFW+LP4QGggE0e3hrk55zXbMHyAeZkCUYtC0owepiwqMD3zX8DglQVaxnhE760pESrNSEzpg==", "dev": true, "requires": { "backo2": "^1.0.2", "eventemitter3": "^3.1.0", "iterall": "^1.2.1", "symbol-observable": "^1.0.4", - "ws": "^5.2.0" - }, - "dependencies": { - "ws": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz", - "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } - } + "ws": "^5.2.0 || ^6.0.0 || ^7.0.0" } }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true, - "optional": true - }, "uuid": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", - "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", - "dev": true - }, - "winston-daily-rotate-file": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-4.5.0.tgz", - "integrity": "sha512-/HqeWiU48dzGqcrABRlxYWVMdL6l3uKCtFSJyrqK+E2rLnSFNsgYpvwx15EgTitBLNzH69lQd/+z2ASryV2aqw==", - "dev": true, - "requires": { - "file-stream-rotator": "^0.5.7", - "object-hash": "^2.0.1", - "triple-beam": "^1.3.0", - "winston-transport": "^4.2.0" - } - }, - "ws": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", - "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true }, "yallist": { @@ -11768,23 +11369,6 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "path-proxy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", - "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", - "dev": true, - "requires": { - "inflection": "~1.3.0" - }, - "dependencies": { - "inflection": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", - "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", - "dev": true - } - } - }, "path-to-regexp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", @@ -11830,6 +11414,21 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "pg": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.7.1.tgz", + "integrity": "sha512-7bdYcv7V6U3KAtWjpQJJBww0UEsWuh4yQ/EjNf2HeO/NnvKjpvhEIe/A/TleP6wtmSKnUnghs5A9jUoK6iDdkA==", + "dev": true, + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.5.0", + "pg-pool": "^3.4.1", + "pg-protocol": "^1.5.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + } + }, "pg-connection-string": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", @@ -11842,12 +11441,39 @@ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", "dev": true }, + "pg-minify": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.2.tgz", + "integrity": "sha512-1KdmFGGTP6jplJoI8MfvRlfvMiyBivMRP7/ffh4a11RUFJ7kC2J0ZHlipoKiH/1hz+DVgceon9U2qbaHpPeyPg==", + "dev": true + }, + "pg-monitor": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/pg-monitor/-/pg-monitor-1.4.1.tgz", + "integrity": "sha512-HLLPPC/2yn7+fOpvatAAMFQMzk/8JwaVS7ATp70Uy+7aTiTvlzIqsTixc6E14L/EGk8fvhu/FJ7qiFbxygbwIA==", + "dev": true, + "requires": { + "cli-color": "2.0.0" + } + }, "pg-pool": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.4.1.tgz", "integrity": "sha512-TVHxR/gf3MeJRvchgNHxsYsTCHQ+4wm3VIHSS19z8NC0+gioEhq1okDY1sm/TYbfoP6JLFx01s0ShvZ3puP/iQ==", "dev": true }, + "pg-promise": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-10.11.0.tgz", + "integrity": "sha512-UntgHZNv+gpGJKhh+tzGSGHLkniKWV+ZQ8/SNdtvElsg9Aa7ZJ4Fgyl6pl2x0ZtJ7uFNy+OIq3Z+Ei6iplqTDQ==", + "dev": true, + "requires": { + "assert-options": "0.7.0", + "pg": "8.7.1", + "pg-minify": "1.6.2", + "spex": "3.2.0" + } + }, "pg-protocol": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", @@ -12187,15 +11813,6 @@ "promise-deferred": "^2.0.3" } }, - "promisify-call": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz", - "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", - "dev": true, - "requires": { - "with-callback": "^1.0.2" - } - }, "prompts": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", @@ -12230,85 +11847,6 @@ "ipaddr.js": "1.9.1" } }, - "proxy-agent": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.3.tgz", - "integrity": "sha512-PXVVVuH9tiQuxQltFJVSnXWuDtNr+8aNBP6XVDDCDiUuDN8eRCm+ii4/mFWmXWEA0w8jjJSlePa4LXlM4jIzNA==", - "dev": true, - "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "lru-cache": "^4.1.2", - "pac-proxy-agent": "^3.0.0", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^4.0.1" - }, - "dependencies": { - "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "https-proxy-agent": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", - "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", - "dev": true, - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -12973,6 +12511,18 @@ "strip-indent": "^1.0.1" } }, + "redis": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "dev": true, + "requires": { + "denque": "^1.5.0", + "redis-commands": "^1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" + } + }, "redis-commands": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", @@ -13280,6 +12830,12 @@ "tough-cookie": "^2.3.3" } }, + "require-at": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", + "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==", + "dev": true + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -13290,30 +12846,6 @@ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, - "require_optional": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", - "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", - "dev": true, - "requires": { - "resolve-from": "^2.0.0", - "semver": "^5.1.0" - }, - "dependencies": { - "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -14046,12 +13578,6 @@ } } }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true - }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -14159,37 +13685,6 @@ } } }, - "socks": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", - "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", - "dev": true, - "requires": { - "ip": "1.1.5", - "smart-buffer": "^4.1.0" - } - }, - "socks-proxy-agent": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", - "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", - "dev": true, - "requires": { - "agent-base": "~4.2.1", - "socks": "~2.3.2" - }, - "dependencies": { - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - } - } - }, "source-list-map": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", @@ -14280,6 +13775,12 @@ "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", "dev": true }, + "spex": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spex/-/spex-3.2.0.tgz", + "integrity": "sha512-9srjJM7NaymrpwMHvSmpDeIK5GoRMX/Tq0E8aOlDPS54dDnDUIp30DrP9SphMPEETDLzEM9+4qo+KipmbtPecg==", + "dev": true + }, "split-on-first": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", @@ -14904,12 +14405,6 @@ "xtend": "~4.0.1" } }, - "thunkify": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", - "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", - "dev": true - }, "timers-browserify": { "version": "2.0.12", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", @@ -14919,6 +14414,16 @@ "setimmediate": "^1.0.4" } }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, "tiny-invariant": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", @@ -15136,6 +14641,12 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -16093,6 +15604,18 @@ } } }, + "winston-daily-rotate-file": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-4.5.5.tgz", + "integrity": "sha512-ds0WahIjiDhKCiMXmY799pDBW+58ByqIBtUcsqr4oDoXrAI3Zn+hbgFdUxzMfqA93OG0mPLYVMiotqTgE/WeWQ==", + "dev": true, + "requires": { + "file-stream-rotator": "^0.5.7", + "object-hash": "^2.0.1", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + } + }, "winston-transport": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", @@ -16103,12 +15626,6 @@ "triple-beam": "^1.2.0" } }, - "with-callback": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/with-callback/-/with-callback-1.0.2.tgz", - "integrity": "sha1-oJYpuakgAo1yFAT7Q1vc/1yRvCE=", - "dev": true - }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", From 90b167d4a739a7b88f79cd6c9a1354920358a466 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sun, 5 Sep 2021 15:02:21 +1000 Subject: [PATCH 17/37] add readme --- Parse-Dashboard/index.js | 14 +++++++------- README.md | 27 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js index 1dcd33d407..84e3598193 100644 --- a/Parse-Dashboard/index.js +++ b/Parse-Dashboard/index.js @@ -30,7 +30,7 @@ program.option('--sslCert [sslCert]', 'the path to the SSL certificate.'); program.option('--trustProxy [trustProxy]', 'set this flag when you are behind a front-facing proxy, such as when hosting on Heroku. Uses X-Forwarded-* headers to determine the client\'s connection and IP address.'); program.option('--cookieSessionSecret [cookieSessionSecret]', 'set the cookie session secret, defaults to a random string. You should set that value if you want sessions to work across multiple server, or across restarts'); program.option('--createUser', 'helper tool to allow you to generate secure user passwords and secrets. Use this once on a trusted device only.'); -program.option('--createMFA', 'helper tool to allow you to generate one-time password secrets.'); +program.option('--createMFA', 'helper tool to allow you to generate multi-factor authentication secrets.'); program.parse(process.argv); @@ -71,7 +71,7 @@ if (program.createUser) { const inquirer = require('inquirer'); const result = {} const displayResult = {}; - const {username, password} = await inquirer.prompt([{ + const { username, password } = await inquirer.prompt([{ type: 'input', name: 'username', message: 'Please enter the username:', @@ -83,7 +83,7 @@ if (program.createUser) { displayResult.username = username; result.user = username; if (!password) { - const {password} = await inquirer.prompt([{ + const { password } = await inquirer.prompt([{ type: 'password', name: 'password', message: `Please enter the password for ${username}:`, @@ -98,10 +98,10 @@ if (program.createUser) { result.pass = hash; displayResult.password = password; } - const {mfa} = await inquirer.prompt([{ + const { mfa } = await inquirer.prompt([{ type: 'confirm', name: 'mfa', - message: `Would you like to an MFA secret for ${username}?`, + message: `Would you like to enforce multi-factor authentication for ${username}?`, }]) if (mfa) { const secret = authenticator.generateSecret(); @@ -122,10 +122,10 @@ if (program.createUser) { if (program.createMFA) { (async () => { const inquirer = require('inquirer'); - const {username} = await inquirer.prompt([{ + const { username } = await inquirer.prompt([{ type: 'input', name: 'username', - message: 'Please enter the name of the user you would like to create MFA for:', + message: 'Please enter the name of the user you would like to create a multi-factor authentication secret for:', }]); const secret = authenticator.generateSecret(); console.log(`Please add this to your dashboard config for ${username}.\n\n"mfa":"${secret}"\n\n\n\n\nAsk ${username} to install an Authenticator app and scan this QR code on their device:\n`) diff --git a/README.md b/README.md index 8b33df083c..e09d97ccfe 100644 --- a/README.md +++ b/README.md @@ -380,6 +380,33 @@ You can configure your dashboard for Basic Authentication by adding usernames an You can store the password in either `plain text` or `bcrypt` formats. To use the `bcrypt` format, you must set the config `useEncryptedPasswords` parameter to `true`. You can generate encrypted passwords by using `parse-dashboard --createUser`, and pasting the result in your users config. +### Configuring Multi-factor Authentication (One-time passwords) + +You can configure your dashboard for Multi-factor authentication by adding a `.mfa` secret to your user config. + +Running `parse-dashboard --createMFA` will help you generate a valid multi-factor authentication secret, and generate a QR code to share with your user. + +```json +{ + "apps": [{"...": "..."}], + "users": [ + { + "user":"user1", + "pass":"pass", + "mfa": "AJ4TS4QMHVYTSGB6" + }, + { + "user":"user2", + "pass":"pass", + "mfa": "AJ4TS4QMHVYTSGB6" + } + ], + "useEncryptedPasswords": true | false +} +``` + +If `.mfa` is set, users will have to provide a valid one-time password to login, provided by an Authenticator app, to login. + ### Separating App Access Based on User Identity If you have configured your dashboard to manage multiple applications, you can restrict the management of apps based on user identity. From 4a3a5ed5aa06d384be5c65410c51382e776129ef Mon Sep 17 00:00:00 2001 From: dblythy Date: Sun, 5 Sep 2021 15:25:02 +1000 Subject: [PATCH 18/37] Update Authentication.js --- Parse-Dashboard/Authentication.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Parse-Dashboard/Authentication.js b/Parse-Dashboard/Authentication.js index 9778deefed..716231871e 100644 --- a/Parse-Dashboard/Authentication.js +++ b/Parse-Dashboard/Authentication.js @@ -101,7 +101,8 @@ function authenticate(userToTest, usernameOnly) { //the provided auth matches one of the users this.validUsers.find(user => { let isAuthenticated = false; - if (user.mfa && !usernameOnly) { + let usernameMatches = userToTest.name == user.user; + if (usernameMatches && user.mfa && !usernameOnly) { if (!userToTest.otpCode) { otpMissing = true; } @@ -109,7 +110,6 @@ function authenticate(userToTest, usernameOnly) { otpValid = false; } } - let usernameMatches = userToTest.name == user.user; let passwordMatches = this.useEncryptedPasswords && !usernameOnly ? bcrypt.compareSync(userToTest.pass, user.pass) : userToTest.pass == user.pass; if (usernameMatches && (usernameOnly || passwordMatches)) { isAuthenticated = true; From 9be7467fc96f97ccdbfa218ed3ed2179b9f71722 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sun, 5 Sep 2021 17:17:15 +1000 Subject: [PATCH 19/37] change to SHA256 --- Parse-Dashboard/Authentication.js | 14 ++++-- Parse-Dashboard/index.js | 83 +++++++++++++++++++++++-------- package-lock.json | 64 ++++-------------------- package.json | 2 +- 4 files changed, 84 insertions(+), 79 deletions(-) diff --git a/Parse-Dashboard/Authentication.js b/Parse-Dashboard/Authentication.js index 716231871e..e96102f31b 100644 --- a/Parse-Dashboard/Authentication.js +++ b/Parse-Dashboard/Authentication.js @@ -3,7 +3,7 @@ var bcrypt = require('bcryptjs'); var csrf = require('csurf'); var passport = require('passport'); var LocalStrategy = require('passport-local').Strategy; -const authenticator = require('otplib').authenticator; +const OTPAuth = require('otpauth') /** * Constructor for Authentication class @@ -105,9 +105,15 @@ function authenticate(userToTest, usernameOnly) { if (usernameMatches && user.mfa && !usernameOnly) { if (!userToTest.otpCode) { otpMissing = true; - } - if (!authenticator.verify({ token:userToTest.otpCode, secret: user.mfa })) { - otpValid = false; + } else { + const totp = new OTPAuth.TOTP({ + algorithm: 'SHA256', + secret: OTPAuth.Secret.fromBase32(user.mfa) + }); + const valid = totp.generate() === userToTest.otpCode; + if (!valid) { + otpValid = false; + } } } let passwordMatches = this.useEncryptedPasswords && !usernameOnly ? bcrypt.compareSync(userToTest.pass, user.pass) : userToTest.pass == user.pass; diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js index 84e3598193..ce285305f2 100644 --- a/Parse-Dashboard/index.js +++ b/Parse-Dashboard/index.js @@ -11,7 +11,8 @@ const path = require('path'); const jsonFile = require('json-file-plus'); const express = require('express'); const parseDashboard = require('./app'); -const authenticator = require('otplib').authenticator; +const OTPAuth = require('otpauth'); +const crypto = require('crypto'); const program = require('commander'); program.option('--appId [appId]', 'the app Id of the app you would like to manage.'); @@ -60,12 +61,6 @@ let configUserPassword = program.userPassword || process.env.PARSE_DASHBOARD_USE let configSSLKey = program.sslKey || process.env.PARSE_DASHBOARD_SSL_KEY; let configSSLCert = program.sslCert || process.env.PARSE_DASHBOARD_SSL_CERT; -const showQR = (text) => { - const QRCode = require('qrcode') - QRCode.toString(text, {type:'terminal'}, (err, url) => { - console.log(url) - }) -} if (program.createUser) { (async () => { const inquirer = require('inquirer'); @@ -91,7 +86,7 @@ if (program.createUser) { displayResult.password = password; result.pass = password } else { - const password = require('crypto').randomBytes(20).toString('hex'); + const password = crypto.randomBytes(20).toString('base64'); const bcrypt = require('bcryptjs'); const salt = bcrypt.genSaltSync(10); const hash = bcrypt.hashSync(password, salt); @@ -104,38 +99,86 @@ if (program.createUser) { message: `Would you like to enforce multi-factor authentication for ${username}?`, }]) if (mfa) { - const secret = authenticator.generateSecret(); + const { app } = await inquirer.prompt([{ + type: 'input', + name: 'app', + message: "What is your app's name?", + }]) + const {secret, url} = generateSecret({app, username}); result.mfa = secret; - displayResult.mfa = authenticator.keyuri(username, configAppName || 'Parse Dashboard', secret); + displayResult.mfa = url + showQR(displayResult.mfa) + console.log(`Ask ${username} to install an Authenticator app and scan this QR code on their device, or open this URL: + +${url} + +After you've shared the QR code ${username}, it is recommended to delete any photos or records of it.`) } const proc = require('child_process').spawn('pbcopy'); proc.stdin.write(JSON.stringify(displayResult)); proc.stdin.end(); - console.log(`\n\nYour new user details' raw credentials have been copied to your clipboard. Add the following to your Parse Dashboard config:\n\n${JSON.stringify(result)}\n\n`); - if (displayResult.mfa) { - showQR(displayResult.mfa) - console.log(`After you've shared the QR code ${username}, it is recommended to delete any photos or records of it.\n`) - } + console.log(` +Your new user details' raw credentials have been copied to your clipboard. Add the following to your Parse Dashboard config: + +${JSON.stringify(result)} + +`); })(); return; } if (program.createMFA) { (async () => { const inquirer = require('inquirer'); - const { username } = await inquirer.prompt([{ + const { username, app } = await inquirer.prompt([{ type: 'input', name: 'username', message: 'Please enter the name of the user you would like to create a multi-factor authentication secret for:', + }, { + type: 'input', + name: 'app', + message: "What is your app's name?", }]); - const secret = authenticator.generateSecret(); - console.log(`Please add this to your dashboard config for ${username}.\n\n"mfa":"${secret}"\n\n\n\n\nAsk ${username} to install an Authenticator app and scan this QR code on their device:\n`) - const url = authenticator.keyuri(username, configAppName || 'Parse Dashboard', secret); + const { url, secret } = generateSecret({app, username}) showQR(url); - console.log(`After you've shared the QR code ${username}, it is recommended to delete any photos or records of it.\n`) + console.log(`Ask ${username} to install an Authenticator app and scan this QR code on their device, or open this URL: + +${url} + +After you've shared the QR code ${username}, it is recommended to delete any photos or records of it. + +Please add this to your dashboard config for ${username}. + +"mfa":"${secret}" + +`) })(); return; } +function generateSecret({app, username}) { + let secret = '' + while (secret.length < 20) { + secret += crypto.randomBytes(20).toString('base64').replace(/[^a-zA-Z]/g, ''); + } + const totp = new OTPAuth.TOTP({ + issuer: app, + label: username, + algorithm: 'SHA256', + digits: 6, + period: 30, + secret: OTPAuth.Secret.fromBase32(secret) + }); + const url = totp.toString(); + return { secret, url } +} + +function showQR(text) { + const QRCode = require('qrcode') + QRCode.toString(text, {type:'terminal'}, (err, url) => { + console.log(url) + }) +} + function handleSIGs(server) { const signals = { 'SIGINT': 2, diff --git a/package-lock.json b/package-lock.json index 8ca4680a79..f2ceb7fdd6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1874,48 +1874,6 @@ "@napi-rs/triples": "^1.0.3" } }, - "@otplib/core": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/@otplib/core/-/core-12.0.1.tgz", - "integrity": "sha512-4sGntwbA/AC+SbPhbsziRiD+jNDdIzsZ3JUyfZwjtKyc/wufl1pnSIaG4Uqx8ymPagujub0o92kgBnB89cuAMA==" - }, - "@otplib/plugin-crypto": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/@otplib/plugin-crypto/-/plugin-crypto-12.0.1.tgz", - "integrity": "sha512-qPuhN3QrT7ZZLcLCyKOSNhuijUi9G5guMRVrxq63r9YNOxxQjPm59gVxLM+7xGnHnM6cimY57tuKsjK7y9LM1g==", - "requires": { - "@otplib/core": "^12.0.1" - } - }, - "@otplib/plugin-thirty-two": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/@otplib/plugin-thirty-two/-/plugin-thirty-two-12.0.1.tgz", - "integrity": "sha512-MtT+uqRso909UkbrrYpJ6XFjj9D+x2Py7KjTO9JDPhL0bJUYVu5kFP4TFZW4NFAywrAtFRxOVY261u0qwb93gA==", - "requires": { - "@otplib/core": "^12.0.1", - "thirty-two": "^1.0.2" - } - }, - "@otplib/preset-default": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/@otplib/preset-default/-/preset-default-12.0.1.tgz", - "integrity": "sha512-xf1v9oOJRyXfluBhMdpOkr+bsE+Irt+0D5uHtvg6x1eosfmHCsCC6ej/m7FXiWqdo0+ZUI6xSKDhJwc8yfiOPQ==", - "requires": { - "@otplib/core": "^12.0.1", - "@otplib/plugin-crypto": "^12.0.1", - "@otplib/plugin-thirty-two": "^12.0.1" - } - }, - "@otplib/preset-v11": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/@otplib/preset-v11/-/preset-v11-12.0.1.tgz", - "integrity": "sha512-9hSetMI7ECqbFiKICrNa4w70deTUfArtwXykPUvSHWOdzOlfa9ajglu7mNCntlvxycTiOAXkQGwjQCzzDEMRMg==", - "requires": { - "@otplib/core": "^12.0.1", - "@otplib/plugin-crypto": "^12.0.1", - "@otplib/plugin-thirty-two": "^12.0.1" - } - }, "@parse/fs-files-adapter": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-1.2.0.tgz", @@ -9165,6 +9123,11 @@ "verror": "1.10.0" } }, + "jssha": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jssha/-/jssha-3.2.0.tgz", + "integrity": "sha512-QuruyBENDWdN4tZwJbQq7/eAK85FqrI4oDbXjy5IBhYD+2pTJyBUWZe8ctWaCkrV0gy6AaelgOZZBMeswEa/6Q==" + }, "jsx-ast-utils": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz", @@ -10949,14 +10912,12 @@ "os-tmpdir": "^1.0.0" } }, - "otplib": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/otplib/-/otplib-12.0.1.tgz", - "integrity": "sha512-xDGvUOQjop7RDgxTQ+o4pOol0/3xSZzawTiPKRrHnQWAy0WjhNs/5HdIDJCrqC4MBynmjXgULc6YfioaxZeFgg==", + "otpauth": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/otpauth/-/otpauth-7.0.5.tgz", + "integrity": "sha512-P+9FA5ohVljT0ED00DlSnTFYVkverW4KGh69zcJq4IepianSjL1t/X7zy8ABMBE480dAotZ5KlpOyQwglSJUrg==", "requires": { - "@otplib/core": "^12.0.1", - "@otplib/preset-default": "^12.0.1", - "@otplib/preset-v11": "^12.0.1" + "jssha": "~3.2.0" } }, "p-cancelable": { @@ -14379,11 +14340,6 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "thirty-two": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz", - "integrity": "sha1-TKL//AKlEpDSdEueP1V2k8prYno=" - }, "throat": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", diff --git a/package.json b/package.json index 24ab46e4a9..3ec396bd82 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "inquirer": "8.1.2", "js-beautify": "1.14.0", "json-file-plus": "3.2.0", - "otplib": "12.0.1", + "otpauth": "7.0.5", "package-json": "6.5.0", "parse": "3.3.0", "passport": "0.4.1", From d1b0295f8c8079fa5937e253d74bcc4c8c47e6a3 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sun, 5 Sep 2021 17:17:57 +1000 Subject: [PATCH 20/37] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a9a0f70aa..eaf629500d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ [Full Changelog](https://github.com/parse-community/parse-dashboard/compare/2.2.0...master) ## New Features -- Add multi-factor authentication to dashboard login. To use one-time passwor, run `parse-dashboard --createMFA` or `parse-dashboard --createUser`. (Daniel Blyth) [#1624](https://github.com/parse-community/parse-dashboard/pull/1624) +- Add multi-factor authentication to dashboard login. To use one-time password, run `parse-dashboard --createMFA` or `parse-dashboard --createUser`. (Daniel Blyth) [#1624](https://github.com/parse-community/parse-dashboard/pull/1624) ## Improvements - Add CI check to add changelog entry (Manuel Trezza) [#1764](https://github.com/parse-community/parse-dashboard/pull/1764) From 7b7b921c44745f898447a95823143a10dffb8f08 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sun, 5 Sep 2021 17:27:16 +1000 Subject: [PATCH 21/37] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e09d97ccfe..e1a0f36f20 100644 --- a/README.md +++ b/README.md @@ -393,12 +393,12 @@ Running `parse-dashboard --createMFA` will help you generate a valid multi-facto { "user":"user1", "pass":"pass", - "mfa": "AJ4TS4QMHVYTSGB6" + "mfa": "lmvmOIZGMTQklhOIhveqkumss" }, { "user":"user2", "pass":"pass", - "mfa": "AJ4TS4QMHVYTSGB6" + "mfa": "KHHEWxHcvAboDvaUUsIVbo" } ], "useEncryptedPasswords": true | false From 15c5a11dd4a44077f31ac2d30ff65a41d5f81dc8 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sun, 5 Sep 2021 19:17:41 +1000 Subject: [PATCH 22/37] use OTPAuth secrets --- Parse-Dashboard/Authentication.js | 6 ++++-- Parse-Dashboard/index.js | 26 ++++++++++++++++---------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Parse-Dashboard/Authentication.js b/Parse-Dashboard/Authentication.js index e96102f31b..d52b38a9aa 100644 --- a/Parse-Dashboard/Authentication.js +++ b/Parse-Dashboard/Authentication.js @@ -110,8 +110,10 @@ function authenticate(userToTest, usernameOnly) { algorithm: 'SHA256', secret: OTPAuth.Secret.fromBase32(user.mfa) }); - const valid = totp.generate() === userToTest.otpCode; - if (!valid) { + const valid = totp.validate({ + token: userToTest.otpCode + }); + if (valid === null) { otpValid = false; } } diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js index ce285305f2..6eb3dd2168 100644 --- a/Parse-Dashboard/index.js +++ b/Parse-Dashboard/index.js @@ -87,17 +87,23 @@ if (program.createUser) { result.pass = password } else { const password = crypto.randomBytes(20).toString('base64'); - const bcrypt = require('bcryptjs'); - const salt = bcrypt.genSaltSync(10); - const hash = bcrypt.hashSync(password, salt); - result.pass = hash; + result.pass = password; displayResult.password = password; } - const { mfa } = await inquirer.prompt([{ + const { mfa, encrypt } = await inquirer.prompt([{ + type: 'confirm', + name: 'encrypt', + message: `Would you like to use encrypted passwords?`, + }, { type: 'confirm', name: 'mfa', message: `Would you like to enforce multi-factor authentication for ${username}?`, - }]) + }]); + if (encrypt) { + const bcrypt = require('bcryptjs'); + const salt = bcrypt.genSaltSync(10); + result.pass = bcrypt.hashSync(result.pass, salt); + } if (mfa) { const { app } = await inquirer.prompt([{ type: 'input', @@ -123,6 +129,9 @@ Your new user details' raw credentials have been copied to your clipboard. Add t ${JSON.stringify(result)} `); + if (encrypt) { + console.log(`Be sure to set "useEncryptedPasswords": true in your config\n\n`); + } })(); return; } @@ -156,10 +165,7 @@ Please add this to your dashboard config for ${username}. } function generateSecret({app, username}) { - let secret = '' - while (secret.length < 20) { - secret += crypto.randomBytes(20).toString('base64').replace(/[^a-zA-Z]/g, ''); - } + const secret = new OTPAuth.Secret().base32; const totp = new OTPAuth.TOTP({ issuer: app, label: username, From 56b208482b5eb0446b47e30a65ae88d4d60382af Mon Sep 17 00:00:00 2001 From: dblythy Date: Sun, 5 Sep 2021 19:20:11 +1000 Subject: [PATCH 23/37] Update index.js --- Parse-Dashboard/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js index 6eb3dd2168..be60589783 100644 --- a/Parse-Dashboard/index.js +++ b/Parse-Dashboard/index.js @@ -30,7 +30,7 @@ program.option('--sslKey [sslKey]', 'the path to the SSL private key.'); program.option('--sslCert [sslCert]', 'the path to the SSL certificate.'); program.option('--trustProxy [trustProxy]', 'set this flag when you are behind a front-facing proxy, such as when hosting on Heroku. Uses X-Forwarded-* headers to determine the client\'s connection and IP address.'); program.option('--cookieSessionSecret [cookieSessionSecret]', 'set the cookie session secret, defaults to a random string. You should set that value if you want sessions to work across multiple server, or across restarts'); -program.option('--createUser', 'helper tool to allow you to generate secure user passwords and secrets. Use this once on a trusted device only.'); +program.option('--createUser', 'helper tool to allow you to generate secure user passwords and secrets. Use this on trusted devices only.'); program.option('--createMFA', 'helper tool to allow you to generate multi-factor authentication secrets.'); program.parse(process.argv); From 2564cbf459e01d1fd88d75c92c9e98482ac66507 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sun, 5 Sep 2021 19:23:59 +1000 Subject: [PATCH 24/37] Update index.js --- Parse-Dashboard/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js index be60589783..8261f9a73e 100644 --- a/Parse-Dashboard/index.js +++ b/Parse-Dashboard/index.js @@ -165,17 +165,17 @@ Please add this to your dashboard config for ${username}. } function generateSecret({app, username}) { - const secret = new OTPAuth.Secret().base32; + const secret = new OTPAuth.Secret(); const totp = new OTPAuth.TOTP({ issuer: app, label: username, algorithm: 'SHA256', digits: 6, period: 30, - secret: OTPAuth.Secret.fromBase32(secret) + secret }); const url = totp.toString(); - return { secret, url } + return { secret: secret.base32, url } } function showQR(text) { From eebf734706c73f74438997525bc83c8c3ad613fa Mon Sep 17 00:00:00 2001 From: dblythy Date: Sun, 5 Sep 2021 23:37:07 +1000 Subject: [PATCH 25/37] add cli helper --- Parse-Dashboard/Authentication.js | 2 +- Parse-Dashboard/CLI/mfa.js | 61 ++++++++++++++ Parse-Dashboard/CLIHelper.js | 122 +++++++++++++++++++++++++++ Parse-Dashboard/index.js | 134 ++---------------------------- 4 files changed, 193 insertions(+), 126 deletions(-) create mode 100644 Parse-Dashboard/CLI/mfa.js create mode 100644 Parse-Dashboard/CLIHelper.js diff --git a/Parse-Dashboard/Authentication.js b/Parse-Dashboard/Authentication.js index d52b38a9aa..2541713632 100644 --- a/Parse-Dashboard/Authentication.js +++ b/Parse-Dashboard/Authentication.js @@ -107,7 +107,7 @@ function authenticate(userToTest, usernameOnly) { otpMissing = true; } else { const totp = new OTPAuth.TOTP({ - algorithm: 'SHA256', + algorithm: user.mfaAlgorithm || 'SHA256', secret: OTPAuth.Secret.fromBase32(user.mfa) }); const valid = totp.validate({ diff --git a/Parse-Dashboard/CLI/mfa.js b/Parse-Dashboard/CLI/mfa.js new file mode 100644 index 0000000000..348b93164b --- /dev/null +++ b/Parse-Dashboard/CLI/mfa.js @@ -0,0 +1,61 @@ +const inquirer = require('inquirer'); +const OTPAuth = require('otpauth'); +module.exports = { + async getAlgorithm() { + let { algorithm } = await inquirer.prompt([ + { + type: 'list', + name: 'algorithm', + message: 'What hashing algorithm would you like to use?', + default: 'SHA256', + choices: [ + 'SHA1', + 'SHA224', + 'SHA256', + 'SHA384', + 'SHA512', + 'SHA3-224', + 'SHA3-256', + 'SHA3-384', + 'SHA3-512', + 'Other' + ] + } + ]); + if (algorithm === 'Other') { + const result = await inquirer.prompt([ + { + type: 'input', + name: 'algorithm', + message: "Please enter the hashing algorithm you would like to use:" + } + ]); + algorithm = result.algorithm; + } + return { algorithm } + }, + generateSecret({app, username, algorithm}) { + const secret = new OTPAuth.Secret(); + const totp = new OTPAuth.TOTP({ + issuer: app, + label: username, + algorithm, + digits: 6, + period: 30, + secret + }); + const url = totp.toString(); + return { secret: secret.base32, url } + }, + showQR(text) { + const QRCode = require('qrcode') + QRCode.toString(text, {type:'terminal'}, (err, url) => { + console.log(url) + }) + }, + copy(text) { + const proc = require('child_process').spawn('pbcopy'); + proc.stdin.write(text); + proc.stdin.end(); + } +}; diff --git a/Parse-Dashboard/CLIHelper.js b/Parse-Dashboard/CLIHelper.js new file mode 100644 index 0000000000..384a553342 --- /dev/null +++ b/Parse-Dashboard/CLIHelper.js @@ -0,0 +1,122 @@ +const crypto = require('crypto'); +const inquirer = require('inquirer'); +const { getAlgorithm, generateSecret, showQR, copy } = require('./CLI/mfa'); + +module.exports = { + async createUser() { + const result = {}; + const displayResult = {}; + const { username, password } = await inquirer.prompt([ + { + type: 'input', + name: 'username', + message: 'Please enter the username:' + }, + { + type: 'confirm', + name: 'password', + message: 'Would you like to generate a secure password?' + } + ]); + displayResult.username = username; + result.user = username; + if (!password) { + const { password } = await inquirer.prompt([ + { + type: 'password', + name: 'password', + message: `Please enter the password for ${username}:` + } + ]); + displayResult.password = password; + result.pass = password; + } else { + const password = crypto.randomBytes(20).toString('base64'); + result.pass = password; + displayResult.password = password; + } + const { mfa, encrypt } = await inquirer.prompt([ + { + type: 'confirm', + name: 'encrypt', + message: `Would you like to use encrypted passwords?` + }, + { + type: 'confirm', + name: 'mfa', + message: `Would you like to enforce multi-factor authentication for ${username}?` + } + ]); + if (encrypt) { + const bcrypt = require('bcryptjs'); + const salt = bcrypt.genSaltSync(10); + result.pass = bcrypt.hashSync(result.pass, salt); + } + if (mfa) { + const { app } = await inquirer.prompt([ + { + type: 'input', + name: 'app', + message: "What is your app's name?" + } + ]); + const { algorithm } = await getAlgorithm(); + const { secret, url } = generateSecret({ app, username, algorithm }); + result.mfa = secret; + displayResult.mfa = url; + if (algorithm !== 'SHA256') { + result.mfaAlgorithm = algorithm; + } + showQR(displayResult.mfa); + console.log(`Ask ${username} to install an Authenticator app and scan this QR code on their device, or open this URL: + +${url} + +After you've shared the QR code ${username}, it is recommended to delete any photos or records of it.`); + } + copy(JSON.stringify(displayResult)); + console.log(` +Your new user details' raw credentials have been copied to your clipboard. Add the following to your Parse Dashboard config: + +${JSON.stringify(result)} + +`); + if (encrypt) { + console.log( + `Be sure to set "useEncryptedPasswords": true in your config\n\n` + ); + } + }, + async createMFA() { + const { username, app } = await inquirer.prompt([ + { + type: 'input', + name: 'username', + message: + 'Please enter the name of the user you would like to create a multi-factor authentication secret for:' + }, + { + type: 'input', + name: 'app', + message: "What is your app's name?" + } + ]); + const { algorithm } = await getAlgorithm(); + + const { url, secret } = generateSecret({ app, username, algorithm }); + showQR(url); + console.log(`Ask ${username} to install an Authenticator app and scan this QR code on their device, or open this URL: + +${url} + +After you've shared the QR code ${username}, it is recommended to delete any photos or records of it. + +Please add this to your dashboard config for ${username}. + +"mfa":"${secret}"${ + algorithm !== 'SHA256' ? `,\n"mfaAlgorithm":"${algorithm}"` : '' + } + +`); + } +}; diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js index 8261f9a73e..17e7fa2f68 100644 --- a/Parse-Dashboard/index.js +++ b/Parse-Dashboard/index.js @@ -11,8 +11,7 @@ const path = require('path'); const jsonFile = require('json-file-plus'); const express = require('express'); const parseDashboard = require('./app'); -const OTPAuth = require('otpauth'); -const crypto = require('crypto'); +const CLIHelper = require('./CLIHelper.js'); const program = require('commander'); program.option('--appId [appId]', 'the app Id of the app you would like to manage.'); @@ -35,6 +34,14 @@ program.option('--createMFA', 'helper tool to allow you to generate multi-factor program.parse(process.argv); +for (const key in program) { + const func = CLIHelper[key]; + if (func && typeof func === 'function') { + func(); + return; + } +} + const host = program.host || process.env.HOST || '0.0.0.0'; const port = program.port || process.env.PORT || 4040; const mountPath = program.mountPath || process.env.MOUNT_PATH || '/'; @@ -61,129 +68,6 @@ let configUserPassword = program.userPassword || process.env.PARSE_DASHBOARD_USE let configSSLKey = program.sslKey || process.env.PARSE_DASHBOARD_SSL_KEY; let configSSLCert = program.sslCert || process.env.PARSE_DASHBOARD_SSL_CERT; -if (program.createUser) { - (async () => { - const inquirer = require('inquirer'); - const result = {} - const displayResult = {}; - const { username, password } = await inquirer.prompt([{ - type: 'input', - name: 'username', - message: 'Please enter the username:', - }, { - type: 'confirm', - name: 'password', - message: 'Would you like to generate a secure password?', - }]); - displayResult.username = username; - result.user = username; - if (!password) { - const { password } = await inquirer.prompt([{ - type: 'password', - name: 'password', - message: `Please enter the password for ${username}:`, - }]); - displayResult.password = password; - result.pass = password - } else { - const password = crypto.randomBytes(20).toString('base64'); - result.pass = password; - displayResult.password = password; - } - const { mfa, encrypt } = await inquirer.prompt([{ - type: 'confirm', - name: 'encrypt', - message: `Would you like to use encrypted passwords?`, - }, { - type: 'confirm', - name: 'mfa', - message: `Would you like to enforce multi-factor authentication for ${username}?`, - }]); - if (encrypt) { - const bcrypt = require('bcryptjs'); - const salt = bcrypt.genSaltSync(10); - result.pass = bcrypt.hashSync(result.pass, salt); - } - if (mfa) { - const { app } = await inquirer.prompt([{ - type: 'input', - name: 'app', - message: "What is your app's name?", - }]) - const {secret, url} = generateSecret({app, username}); - result.mfa = secret; - displayResult.mfa = url - showQR(displayResult.mfa) - console.log(`Ask ${username} to install an Authenticator app and scan this QR code on their device, or open this URL: - -${url} - -After you've shared the QR code ${username}, it is recommended to delete any photos or records of it.`) - } - const proc = require('child_process').spawn('pbcopy'); - proc.stdin.write(JSON.stringify(displayResult)); - proc.stdin.end(); - console.log(` -Your new user details' raw credentials have been copied to your clipboard. Add the following to your Parse Dashboard config: - -${JSON.stringify(result)} - -`); - if (encrypt) { - console.log(`Be sure to set "useEncryptedPasswords": true in your config\n\n`); - } - })(); - return; -} -if (program.createMFA) { - (async () => { - const inquirer = require('inquirer'); - const { username, app } = await inquirer.prompt([{ - type: 'input', - name: 'username', - message: 'Please enter the name of the user you would like to create a multi-factor authentication secret for:', - }, { - type: 'input', - name: 'app', - message: "What is your app's name?", - }]); - const { url, secret } = generateSecret({app, username}) - showQR(url); - console.log(`Ask ${username} to install an Authenticator app and scan this QR code on their device, or open this URL: - -${url} - -After you've shared the QR code ${username}, it is recommended to delete any photos or records of it. - -Please add this to your dashboard config for ${username}. - -"mfa":"${secret}" - -`) - })(); - return; -} - -function generateSecret({app, username}) { - const secret = new OTPAuth.Secret(); - const totp = new OTPAuth.TOTP({ - issuer: app, - label: username, - algorithm: 'SHA256', - digits: 6, - period: 30, - secret - }); - const url = totp.toString(); - return { secret: secret.base32, url } -} - -function showQR(text) { - const QRCode = require('qrcode') - QRCode.toString(text, {type:'terminal'}, (err, url) => { - console.log(url) - }) -} function handleSIGs(server) { const signals = { From 07a2448c2ce4a9d1e64193b0020e180663323139 Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 6 Sep 2021 11:14:16 +1000 Subject: [PATCH 26/37] change to SHA1 --- Parse-Dashboard/Authentication.js | 2 +- Parse-Dashboard/CLI/mfa.js | 2 +- Parse-Dashboard/CLIHelper.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Parse-Dashboard/Authentication.js b/Parse-Dashboard/Authentication.js index 2541713632..6a859fa546 100644 --- a/Parse-Dashboard/Authentication.js +++ b/Parse-Dashboard/Authentication.js @@ -107,7 +107,7 @@ function authenticate(userToTest, usernameOnly) { otpMissing = true; } else { const totp = new OTPAuth.TOTP({ - algorithm: user.mfaAlgorithm || 'SHA256', + algorithm: user.mfaAlgorithm || 'SHA1', secret: OTPAuth.Secret.fromBase32(user.mfa) }); const valid = totp.validate({ diff --git a/Parse-Dashboard/CLI/mfa.js b/Parse-Dashboard/CLI/mfa.js index 348b93164b..8077e371f5 100644 --- a/Parse-Dashboard/CLI/mfa.js +++ b/Parse-Dashboard/CLI/mfa.js @@ -7,7 +7,7 @@ module.exports = { type: 'list', name: 'algorithm', message: 'What hashing algorithm would you like to use?', - default: 'SHA256', + default: 'SHA1', choices: [ 'SHA1', 'SHA224', diff --git a/Parse-Dashboard/CLIHelper.js b/Parse-Dashboard/CLIHelper.js index 384a553342..c361e7e176 100644 --- a/Parse-Dashboard/CLIHelper.js +++ b/Parse-Dashboard/CLIHelper.js @@ -64,7 +64,7 @@ module.exports = { const { secret, url } = generateSecret({ app, username, algorithm }); result.mfa = secret; displayResult.mfa = url; - if (algorithm !== 'SHA256') { + if (algorithm !== 'SHA1') { result.mfaAlgorithm = algorithm; } showQR(displayResult.mfa); @@ -114,7 +114,7 @@ After you've shared the QR code ${username}, it is recommended to delete any pho Please add this to your dashboard config for ${username}. "mfa":"${secret}"${ - algorithm !== 'SHA256' ? `,\n"mfaAlgorithm":"${algorithm}"` : '' + algorithm !== 'SHA1' ? `,\n"mfaAlgorithm":"${algorithm}"` : '' } `); From 1a17255d6f5b44e5b5988b065981b2a958cf08ab Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 6 Sep 2021 12:46:59 +1000 Subject: [PATCH 27/37] add digits option --- Parse-Dashboard/CLI/mfa.js | 222 +++++++++++++++++++++++++++-------- Parse-Dashboard/CLI/utils.js | 7 ++ Parse-Dashboard/CLIHelper.js | 122 +------------------ 3 files changed, 185 insertions(+), 166 deletions(-) create mode 100644 Parse-Dashboard/CLI/utils.js diff --git a/Parse-Dashboard/CLI/mfa.js b/Parse-Dashboard/CLI/mfa.js index 8077e371f5..99c539f081 100644 --- a/Parse-Dashboard/CLI/mfa.js +++ b/Parse-Dashboard/CLI/mfa.js @@ -1,61 +1,189 @@ +const crypto = require('crypto'); const inquirer = require('inquirer'); const OTPAuth = require('otpauth'); -module.exports = { - async getAlgorithm() { - let { algorithm } = await inquirer.prompt([ +const { copy } = require('./utils.js'); +const getAlgorithm = async () => { + let { algorithm } = await inquirer.prompt([ + { + type: 'list', + name: 'algorithm', + message: 'What hashing algorithm would you like to use?', + default: 'SHA1', + choices: [ + 'SHA1', + 'SHA224', + 'SHA256', + 'SHA384', + 'SHA512', + 'SHA3-224', + 'SHA3-256', + 'SHA3-384', + 'SHA3-512', + 'Other' + ] + } + ]); + if (algorithm === 'Other') { + const result = await inquirer.prompt([ { - type: 'list', + type: 'input', name: 'algorithm', - message: 'What hashing algorithm would you like to use?', - default: 'SHA1', - choices: [ - 'SHA1', - 'SHA224', - 'SHA256', - 'SHA384', - 'SHA512', - 'SHA3-224', - 'SHA3-256', - 'SHA3-384', - 'SHA3-512', - 'Other' - ] + message: 'Please enter the hashing algorithm you would like to use:' + } + ]); + algorithm = result.algorithm; + } + const { digits, period } = await inquirer.prompt([ + { + type: 'number', + name: 'digits', + default: 6, + message: 'How many digits should the OTP contain?' + }, + { + type: 'number', + name: 'period', + default: 30, + message: 'How many seconds should the OTP last for?' + } + ]) + return { algorithm, digits, period}; +}; +const generateSecret = ({ app, username, algorithm, digits, period }) => { + const secret = new OTPAuth.Secret(); + const totp = new OTPAuth.TOTP({ + issuer: app, + label: username, + algorithm, + digits, + period, + secret + }); + const url = totp.toString(); + return { secret: secret.base32, url }; +}; +const showQR = text => { + const QRCode = require('qrcode'); + QRCode.toString(text, { type: 'terminal' }, (err, url) => { + console.log(url); + }); +}; + +module.exports = { + async createUser() { + const result = {}; + const displayResult = {}; + const { username, password } = await inquirer.prompt([ + { + type: 'input', + name: 'username', + message: 'Please enter the username:' + }, + { + type: 'confirm', + name: 'password', + message: 'Would you like to generate a secure password?' + } + ]); + displayResult.username = username; + result.user = username; + if (!password) { + const { password } = await inquirer.prompt([ + { + type: 'password', + name: 'password', + message: `Please enter the password for ${username}:` + } + ]); + displayResult.password = password; + result.pass = password; + } else { + const password = crypto.randomBytes(20).toString('base64'); + result.pass = password; + displayResult.password = password; + } + const { mfa, encrypt } = await inquirer.prompt([ + { + type: 'confirm', + name: 'encrypt', + message: 'Would you like to use encrypted passwords?' + }, + { + type: 'confirm', + name: 'mfa', + message: `Would you like to enforce multi-factor authentication for ${username}?` } ]); - if (algorithm === 'Other') { - const result = await inquirer.prompt([ + if (encrypt) { + const bcrypt = require('bcryptjs'); + const salt = bcrypt.genSaltSync(10); + result.pass = bcrypt.hashSync(result.pass, salt); + } + if (mfa) { + const { app } = await inquirer.prompt([ { type: 'input', - name: 'algorithm', - message: "Please enter the hashing algorithm you would like to use:" + name: 'app', + message: "What is your app's name?" } ]); - algorithm = result.algorithm; + const { algorithm, digits, period } = await getAlgorithm(); + const { secret, url } = generateSecret({ app, username, algorithm, digits, period }); + result.mfa = secret; + displayResult.mfa = url; + if (algorithm !== 'SHA1') { + result.mfaAlgorithm = algorithm; + } + showQR(displayResult.mfa); + console.log(`Ask ${username} to install an Authenticator app and scan this QR code on their device, or open this URL: + +${url} + +After you've shared the QR code ${username}, it is recommended to delete any photos or records of it.`); + } + copy(JSON.stringify(displayResult)); + console.log(` +Your new user details' raw credentials have been copied to your clipboard. Add the following to your Parse Dashboard config: + +${JSON.stringify(result)} + +`); + if (encrypt) { + console.log( + 'Be sure to set "useEncryptedPasswords": true in your config\n\n' + ); } - return { algorithm } - }, - generateSecret({app, username, algorithm}) { - const secret = new OTPAuth.Secret(); - const totp = new OTPAuth.TOTP({ - issuer: app, - label: username, - algorithm, - digits: 6, - period: 30, - secret - }); - const url = totp.toString(); - return { secret: secret.base32, url } - }, - showQR(text) { - const QRCode = require('qrcode') - QRCode.toString(text, {type:'terminal'}, (err, url) => { - console.log(url) - }) }, - copy(text) { - const proc = require('child_process').spawn('pbcopy'); - proc.stdin.write(text); - proc.stdin.end(); + async createMFA() { + const { username, app } = await inquirer.prompt([ + { + type: 'input', + name: 'username', + message: + 'Please enter the name of the user you would like to create a multi-factor authentication secret for:' + }, + { + type: 'input', + name: 'app', + message: "What is your app's name?" + } + ]); + const { algorithm, digits, period } = await getAlgorithm(); + + const { url, secret } = generateSecret({ app, username, algorithm, digits, period }); + showQR(url); + console.log(`Ask ${username} to install an Authenticator app and scan this QR code on their device, or open this URL: + +${url} + +After you've shared the QR code ${username}, it is recommended to delete any photos or records of it. + +Please add this to your dashboard config for ${username}. + +"mfa":"${secret}"${ + algorithm !== 'SHA1' ? `,\n"mfaAlgorithm":"${algorithm}"` : '' + } + +`); } }; diff --git a/Parse-Dashboard/CLI/utils.js b/Parse-Dashboard/CLI/utils.js new file mode 100644 index 0000000000..f5f5f5ad29 --- /dev/null +++ b/Parse-Dashboard/CLI/utils.js @@ -0,0 +1,7 @@ +module.exports = { + copy(text) { + const proc = require('child_process').spawn('pbcopy'); + proc.stdin.write(text); + proc.stdin.end(); + } +} diff --git a/Parse-Dashboard/CLIHelper.js b/Parse-Dashboard/CLIHelper.js index c361e7e176..ac6f6659dc 100644 --- a/Parse-Dashboard/CLIHelper.js +++ b/Parse-Dashboard/CLIHelper.js @@ -1,122 +1,6 @@ -const crypto = require('crypto'); -const inquirer = require('inquirer'); -const { getAlgorithm, generateSecret, showQR, copy } = require('./CLI/mfa'); +const { createUser, createMFA } = require('./CLI/mfa'); module.exports = { - async createUser() { - const result = {}; - const displayResult = {}; - const { username, password } = await inquirer.prompt([ - { - type: 'input', - name: 'username', - message: 'Please enter the username:' - }, - { - type: 'confirm', - name: 'password', - message: 'Would you like to generate a secure password?' - } - ]); - displayResult.username = username; - result.user = username; - if (!password) { - const { password } = await inquirer.prompt([ - { - type: 'password', - name: 'password', - message: `Please enter the password for ${username}:` - } - ]); - displayResult.password = password; - result.pass = password; - } else { - const password = crypto.randomBytes(20).toString('base64'); - result.pass = password; - displayResult.password = password; - } - const { mfa, encrypt } = await inquirer.prompt([ - { - type: 'confirm', - name: 'encrypt', - message: `Would you like to use encrypted passwords?` - }, - { - type: 'confirm', - name: 'mfa', - message: `Would you like to enforce multi-factor authentication for ${username}?` - } - ]); - if (encrypt) { - const bcrypt = require('bcryptjs'); - const salt = bcrypt.genSaltSync(10); - result.pass = bcrypt.hashSync(result.pass, salt); - } - if (mfa) { - const { app } = await inquirer.prompt([ - { - type: 'input', - name: 'app', - message: "What is your app's name?" - } - ]); - const { algorithm } = await getAlgorithm(); - const { secret, url } = generateSecret({ app, username, algorithm }); - result.mfa = secret; - displayResult.mfa = url; - if (algorithm !== 'SHA1') { - result.mfaAlgorithm = algorithm; - } - showQR(displayResult.mfa); - console.log(`Ask ${username} to install an Authenticator app and scan this QR code on their device, or open this URL: - -${url} - -After you've shared the QR code ${username}, it is recommended to delete any photos or records of it.`); - } - copy(JSON.stringify(displayResult)); - console.log(` -Your new user details' raw credentials have been copied to your clipboard. Add the following to your Parse Dashboard config: - -${JSON.stringify(result)} - -`); - if (encrypt) { - console.log( - `Be sure to set "useEncryptedPasswords": true in your config\n\n` - ); - } - }, - async createMFA() { - const { username, app } = await inquirer.prompt([ - { - type: 'input', - name: 'username', - message: - 'Please enter the name of the user you would like to create a multi-factor authentication secret for:' - }, - { - type: 'input', - name: 'app', - message: "What is your app's name?" - } - ]); - const { algorithm } = await getAlgorithm(); - - const { url, secret } = generateSecret({ app, username, algorithm }); - showQR(url); - console.log(`Ask ${username} to install an Authenticator app and scan this QR code on their device, or open this URL: - -${url} - -After you've shared the QR code ${username}, it is recommended to delete any photos or records of it. - -Please add this to your dashboard config for ${username}. - -"mfa":"${secret}"${ - algorithm !== 'SHA1' ? `,\n"mfaAlgorithm":"${algorithm}"` : '' - } - -`); - } + createUser, + createMFA }; From bf2d615d3dcc8aeca507b9bcad340b4f05235369 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Tue, 7 Sep 2021 21:11:39 +0200 Subject: [PATCH 28/37] refactoring mfa flow --- Parse-Dashboard/CLI/mfa.js | 110 +++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 42 deletions(-) diff --git a/Parse-Dashboard/CLI/mfa.js b/Parse-Dashboard/CLI/mfa.js index 99c539f081..262fec9ac2 100644 --- a/Parse-Dashboard/CLI/mfa.js +++ b/Parse-Dashboard/CLI/mfa.js @@ -2,12 +2,18 @@ const crypto = require('crypto'); const inquirer = require('inquirer'); const OTPAuth = require('otpauth'); const { copy } = require('./utils.js'); +const phrases = { + enterPassword: 'Enter a password:', + enterUsername: 'Enter a username:', + enterAppName: 'Enter the app name:', + +} const getAlgorithm = async () => { let { algorithm } = await inquirer.prompt([ { type: 'list', name: 'algorithm', - message: 'What hashing algorithm would you like to use?', + message: 'Which hashing algorithm do you want to use?', default: 'SHA1', choices: [ 'SHA1', @@ -28,7 +34,7 @@ const getAlgorithm = async () => { { type: 'input', name: 'algorithm', - message: 'Please enter the hashing algorithm you would like to use:' + message: 'Enter the hashing algorithm you want to use:' } ]); algorithm = result.algorithm; @@ -38,13 +44,13 @@ const getAlgorithm = async () => { type: 'number', name: 'digits', default: 6, - message: 'How many digits should the OTP contain?' + message: 'Enter the number of digits the one-time password should have:' }, { type: 'number', name: 'period', default: 30, - message: 'How many seconds should the OTP last for?' + message: 'Enter how long the one-time password should be valid (in seconds):' } ]) return { algorithm, digits, period}; @@ -65,10 +71,51 @@ const generateSecret = ({ app, username, algorithm, digits, period }) => { const showQR = text => { const QRCode = require('qrcode'); QRCode.toString(text, { type: 'terminal' }, (err, url) => { - console.log(url); + console.log( + '\n------------------------------------------------------------------------------' + + `\n\n${url}` + ); }); }; +const showInstructions = ({ app, username, mfaUrl, encrypt, config }) => { + let orderCounter = 0; + const getOrder = () => { + orderCounter++; + return orderCounter; + } + console.log( + '------------------------------------------------------------------------------' + + '\n\nFollow these steps to complete the set-up:' + ); + + copy(JSON.stringify(config)); + console.log( + `\n${getOrder()}. Add the following settings for user "${username}" ${app ? `in app "${app}" ` : '' }to the Parse Dashboard configuration.` + + '\n The settings have been copied to your clipboard.' + + `\n\n ${JSON.stringify(config)}` + ); + + if (mfaUrl) { + console.log( + `\n${getOrder()}. Ask the user to install an authenticator app and scan the QR code above, or open this link:` + + `\n\n ${mfaUrl}` + + `\n\n${getOrder()}. After you have shared these details, make sure to destroy any records of it.` + ); + } + + if (encrypt) { + console.log( + `\n${getOrder()}. Make sure that "useEncryptedPasswords" is set to "true" in your dashboard configuration.` + + '\n You chose to generate an encrypted password for this user.' + + '\n If there are existing users with non-encrypted passwords, you need to create new passwords for them.' + ); + } + console.log( + '\n------------------------------------------------------------------------------\n' + ); +} + module.exports = { async createUser() { const result = {}; @@ -77,12 +124,12 @@ module.exports = { { type: 'input', name: 'username', - message: 'Please enter the username:' + message: phrases.enterUsername }, { type: 'confirm', name: 'password', - message: 'Would you like to generate a secure password?' + message: 'Do you want to auto-generate a password?' } ]); displayResult.username = username; @@ -92,7 +139,7 @@ module.exports = { { type: 'password', name: 'password', - message: `Please enter the password for ${username}:` + message: phrases.enterPassword } ]); displayResult.password = password; @@ -106,12 +153,12 @@ module.exports = { { type: 'confirm', name: 'encrypt', - message: 'Would you like to use encrypted passwords?' + message: 'Should the password be encrypted? (strongly recommended, otherwise it is stored in clear-text)' }, { type: 'confirm', name: 'mfa', - message: `Would you like to enforce multi-factor authentication for ${username}?` + message: 'Do you want to enable multi-factor authentication?' } ]); if (encrypt) { @@ -124,35 +171,20 @@ module.exports = { { type: 'input', name: 'app', - message: "What is your app's name?" + message: phrases.enterAppName } ]); const { algorithm, digits, period } = await getAlgorithm(); const { secret, url } = generateSecret({ app, username, algorithm, digits, period }); result.mfa = secret; + result.app = app; displayResult.mfa = url; if (algorithm !== 'SHA1') { result.mfaAlgorithm = algorithm; } showQR(displayResult.mfa); - console.log(`Ask ${username} to install an Authenticator app and scan this QR code on their device, or open this URL: - -${url} - -After you've shared the QR code ${username}, it is recommended to delete any photos or records of it.`); - } - copy(JSON.stringify(displayResult)); - console.log(` -Your new user details' raw credentials have been copied to your clipboard. Add the following to your Parse Dashboard config: - -${JSON.stringify(result)} - -`); - if (encrypt) { - console.log( - 'Be sure to set "useEncryptedPasswords": true in your config\n\n' - ); } + showInstructions({ app: result.app, username, mfaUrl: displayResult.mfa, encrypt, config: displayResult }); }, async createMFA() { const { username, app } = await inquirer.prompt([ @@ -160,30 +192,24 @@ ${JSON.stringify(result)} type: 'input', name: 'username', message: - 'Please enter the name of the user you would like to create a multi-factor authentication secret for:' + 'Enter the username for which you want to enable multi-factor authentication:' }, { type: 'input', name: 'app', - message: "What is your app's name?" + message: phrases.enterAppName } ]); const { algorithm, digits, period } = await getAlgorithm(); const { url, secret } = generateSecret({ app, username, algorithm, digits, period }); showQR(url); - console.log(`Ask ${username} to install an Authenticator app and scan this QR code on their device, or open this URL: - -${url} - -After you've shared the QR code ${username}, it is recommended to delete any photos or records of it. - -Please add this to your dashboard config for ${username}. - -"mfa":"${secret}"${ - algorithm !== 'SHA1' ? `,\n"mfaAlgorithm":"${algorithm}"` : '' + + // Compose config + const config = { mfa: secret }; + if (algorithm !== 'SHA1') { + config.mfaAlgorithm = algorithm; } - -`); + showInstructions({ app, username, url, config: config }); } }; From 981d0962bc4dc3657c5f17deb3deea57681bc405 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Tue, 7 Sep 2021 22:05:35 +0200 Subject: [PATCH 29/37] more simplification --- Parse-Dashboard/CLI/mfa.js | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/Parse-Dashboard/CLI/mfa.js b/Parse-Dashboard/CLI/mfa.js index 262fec9ac2..97f4d67336 100644 --- a/Parse-Dashboard/CLI/mfa.js +++ b/Parse-Dashboard/CLI/mfa.js @@ -98,7 +98,7 @@ const showInstructions = ({ app, username, mfaUrl, encrypt, config }) => { if (mfaUrl) { console.log( - `\n${getOrder()}. Ask the user to install an authenticator app and scan the QR code above, or open this link:` + + `\n${getOrder()}. Ask the user to install an authenticator app and scan the QR code above, or to open this link:` + `\n\n ${mfaUrl}` + `\n\n${getOrder()}. After you have shared these details, make sure to destroy any records of it.` ); @@ -118,8 +118,7 @@ const showInstructions = ({ app, username, mfaUrl, encrypt, config }) => { module.exports = { async createUser() { - const result = {}; - const displayResult = {}; + const data = {}; const { username, password } = await inquirer.prompt([ { type: 'input', @@ -132,8 +131,7 @@ module.exports = { message: 'Do you want to auto-generate a password?' } ]); - displayResult.username = username; - result.user = username; + data.user = username; if (!password) { const { password } = await inquirer.prompt([ { @@ -142,12 +140,10 @@ module.exports = { message: phrases.enterPassword } ]); - displayResult.password = password; - result.pass = password; + data.pass = password; } else { const password = crypto.randomBytes(20).toString('base64'); - result.pass = password; - displayResult.password = password; + data.pass = password; } const { mfa, encrypt } = await inquirer.prompt([ { @@ -164,7 +160,7 @@ module.exports = { if (encrypt) { const bcrypt = require('bcryptjs'); const salt = bcrypt.genSaltSync(10); - result.pass = bcrypt.hashSync(result.pass, salt); + data.pass = bcrypt.hashSync(data.pass, salt); } if (mfa) { const { app } = await inquirer.prompt([ @@ -176,15 +172,16 @@ module.exports = { ]); const { algorithm, digits, period } = await getAlgorithm(); const { secret, url } = generateSecret({ app, username, algorithm, digits, period }); - result.mfa = secret; - result.app = app; - displayResult.mfa = url; + data.mfa = secret; + data.app = app; + data.url = url; if (algorithm !== 'SHA1') { - result.mfaAlgorithm = algorithm; + data.mfaAlgorithm = algorithm; } - showQR(displayResult.mfa); + showQR(data.url); } - showInstructions({ app: result.app, username, mfaUrl: displayResult.mfa, encrypt, config: displayResult }); + const config = { mfa: data.mfa, user: data.user, pass: data.pass }; + showInstructions({ app: data.app, username, mfaUrl: data.url, encrypt, config }); }, async createMFA() { const { username, app } = await inquirer.prompt([ @@ -210,6 +207,6 @@ module.exports = { if (algorithm !== 'SHA1') { config.mfaAlgorithm = algorithm; } - showInstructions({ app, username, url, config: config }); + showInstructions({ app, username, url, config }); } }; From c2cd85fc4bcb879396cfc970eaa144c4317ad395 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Tue, 7 Sep 2021 22:10:41 +0200 Subject: [PATCH 30/37] fixed unsafe instructions --- Parse-Dashboard/CLI/mfa.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Parse-Dashboard/CLI/mfa.js b/Parse-Dashboard/CLI/mfa.js index 97f4d67336..32ecdd91bd 100644 --- a/Parse-Dashboard/CLI/mfa.js +++ b/Parse-Dashboard/CLI/mfa.js @@ -98,9 +98,9 @@ const showInstructions = ({ app, username, mfaUrl, encrypt, config }) => { if (mfaUrl) { console.log( - `\n${getOrder()}. Ask the user to install an authenticator app and scan the QR code above, or to open this link:` + + `\n${getOrder()}. Install an authenticator app and scan the QR code above, or open this link:` + `\n\n ${mfaUrl}` + - `\n\n${getOrder()}. After you have shared these details, make sure to destroy any records of it.` + `\n\n${getOrder()}. Destroy any records of the QR code and the link, as they allow anyone to generate a one-time password.` ); } From 3e3bcad08ebe34a6742c916d050419b4aae69225 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Tue, 7 Sep 2021 22:50:52 +0200 Subject: [PATCH 31/37] fixed password copy to clipboard --- Parse-Dashboard/CLI/mfa.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Parse-Dashboard/CLI/mfa.js b/Parse-Dashboard/CLI/mfa.js index 32ecdd91bd..7baa626c29 100644 --- a/Parse-Dashboard/CLI/mfa.js +++ b/Parse-Dashboard/CLI/mfa.js @@ -78,7 +78,7 @@ const showQR = text => { }); }; -const showInstructions = ({ app, username, mfaUrl, encrypt, config }) => { +const showInstructions = ({ app, username, passwordCopied, mfaUrl, encrypt, config }) => { let orderCounter = 0; const getOrder = () => { orderCounter++; @@ -89,13 +89,17 @@ const showInstructions = ({ app, username, mfaUrl, encrypt, config }) => { '\n\nFollow these steps to complete the set-up:' ); - copy(JSON.stringify(config)); console.log( `\n${getOrder()}. Add the following settings for user "${username}" ${app ? `in app "${app}" ` : '' }to the Parse Dashboard configuration.` + - '\n The settings have been copied to your clipboard.' + `\n\n ${JSON.stringify(config)}` ); + if (passwordCopied) { + console.log( + `\n${getOrder()}. Securely store the auto-generated login password that has been copied to your clipboard.` + ); + } + if (mfaUrl) { console.log( `\n${getOrder()}. Install an authenticator app and scan the QR code above, or open this link:` + @@ -108,7 +112,7 @@ const showInstructions = ({ app, username, mfaUrl, encrypt, config }) => { console.log( `\n${getOrder()}. Make sure that "useEncryptedPasswords" is set to "true" in your dashboard configuration.` + '\n You chose to generate an encrypted password for this user.' + - '\n If there are existing users with non-encrypted passwords, you need to create new passwords for them.' + '\n Any existing users with non-encrypted passwords will require newly created, encrypted passwords.' ); } console.log( @@ -158,6 +162,10 @@ module.exports = { } ]); if (encrypt) { + // Copy the raw password to clipboard + copy(data.pass); + + // Encrypt password const bcrypt = require('bcryptjs'); const salt = bcrypt.genSaltSync(10); data.pass = bcrypt.hashSync(data.pass, salt); @@ -180,8 +188,9 @@ module.exports = { } showQR(data.url); } + const config = { mfa: data.mfa, user: data.user, pass: data.pass }; - showInstructions({ app: data.app, username, mfaUrl: data.url, encrypt, config }); + showInstructions({ app: data.app, username, passwordCopied: true, mfaUrl: data.url, encrypt, config }); }, async createMFA() { const { username, app } = await inquirer.prompt([ From 6d206e64f66941454c9caece88a4bef215f524a5 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Tue, 7 Sep 2021 22:56:25 +0200 Subject: [PATCH 32/37] add newline before CLI questions --- Parse-Dashboard/CLI/mfa.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Parse-Dashboard/CLI/mfa.js b/Parse-Dashboard/CLI/mfa.js index 7baa626c29..77260c0fa6 100644 --- a/Parse-Dashboard/CLI/mfa.js +++ b/Parse-Dashboard/CLI/mfa.js @@ -123,6 +123,8 @@ const showInstructions = ({ app, username, passwordCopied, mfaUrl, encrypt, conf module.exports = { async createUser() { const data = {}; + + console.log(''); const { username, password } = await inquirer.prompt([ { type: 'input', @@ -193,6 +195,7 @@ module.exports = { showInstructions({ app: data.app, username, passwordCopied: true, mfaUrl: data.url, encrypt, config }); }, async createMFA() { + console.log(''); const { username, app } = await inquirer.prompt([ { type: 'input', From 63b4a6a802d01f9cf44798e69155a7b155d91c48 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Tue, 7 Sep 2021 22:58:31 +0200 Subject: [PATCH 33/37] style --- Parse-Dashboard/CLI/mfa.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Parse-Dashboard/CLI/mfa.js b/Parse-Dashboard/CLI/mfa.js index 77260c0fa6..010fa44f2d 100644 --- a/Parse-Dashboard/CLI/mfa.js +++ b/Parse-Dashboard/CLI/mfa.js @@ -6,7 +6,6 @@ const phrases = { enterPassword: 'Enter a password:', enterUsername: 'Enter a username:', enterAppName: 'Enter the app name:', - } const getAlgorithm = async () => { let { algorithm } = await inquirer.prompt([ From e30c22a54b011b7961b13f7e219d04ad1ead98a0 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Tue, 7 Sep 2021 23:32:34 +0200 Subject: [PATCH 34/37] refactored readme --- Parse-Dashboard/index.js | 1 - README.md | 22 +++++++++++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js index 17e7fa2f68..d5ed2019fc 100644 --- a/Parse-Dashboard/index.js +++ b/Parse-Dashboard/index.js @@ -68,7 +68,6 @@ let configUserPassword = program.userPassword || process.env.PARSE_DASHBOARD_USE let configSSLKey = program.sslKey || process.env.PARSE_DASHBOARD_SSL_KEY; let configSSLCert = program.sslCert || process.env.PARSE_DASHBOARD_SSL_CERT; - function handleSIGs(server) { const signals = { 'SIGINT': 2, diff --git a/README.md b/README.md index e1a0f36f20..7fb2c7a1c3 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Parse Dashboard is a standalone dashboard for managing your [Parse Server](https - [Preparing for Deployment](#preparing-for-deployment) - [Security Considerations](#security-considerations) - [Configuring Basic Authentication](#configuring-basic-authentication) + - [Multi-Factor Authentication (One-Time Password)](#multi-factor-authentication-one-time-password) - [Separating App Access Based on User Identity](#separating-app-access-based-on-user-identity) - [Use Read-Only masterKey](#use-read-only-masterkey) - [Making an app read-only for all users](#making-an-app-read-only-for-all-users) @@ -380,11 +381,16 @@ You can configure your dashboard for Basic Authentication by adding usernames an You can store the password in either `plain text` or `bcrypt` formats. To use the `bcrypt` format, you must set the config `useEncryptedPasswords` parameter to `true`. You can generate encrypted passwords by using `parse-dashboard --createUser`, and pasting the result in your users config. -### Configuring Multi-factor Authentication (One-time passwords) +### Multi-Factor Authentication (One-Time Password) -You can configure your dashboard for Multi-factor authentication by adding a `.mfa` secret to your user config. +You can add an additional layer of security for a user account by requiring multi-factor authentication (MFA) for the user to login. -Running `parse-dashboard --createMFA` will help you generate a valid multi-factor authentication secret, and generate a QR code to share with your user. +With MFA enabled, a user must provide a one-time password that is typically bound to a physical device, in addition to their login password. This means in addition to knowing the login password, the user needs to have physical access to a device to generate the one-time password. This one-time password is time-based (TOTP) and only valid for a short amount of time, typically 30 seconds, until it expires. + +The user requires an authenticator app to generate the one-time password. These apps are provided by many 3rd parties and mostly for free. + +If you create a new user by running `parse-dashboard --createUser`, you will be asked whether you want to enable MFA for the new user. To enable MFA for an existing user, +run `parse-dashboard --createMFA` to generate a `mfa` secret that you then add to the existing user configuration, for example: ```json { @@ -394,18 +400,12 @@ Running `parse-dashboard --createMFA` will help you generate a valid multi-facto "user":"user1", "pass":"pass", "mfa": "lmvmOIZGMTQklhOIhveqkumss" - }, - { - "user":"user2", - "pass":"pass", - "mfa": "KHHEWxHcvAboDvaUUsIVbo" } - ], - "useEncryptedPasswords": true | false + ] } ``` -If `.mfa` is set, users will have to provide a valid one-time password to login, provided by an Authenticator app, to login. + Parse Dashboard follows the industry standard and supports the common OTP algorithm `SHA-1` by default, to be compatible with most authenticator apps. If you have specific security requirements regarding TOTP characteristics (algorithm, digit length, time period) you can customize them by using the guided configuration mentioned above. ### Separating App Access Based on User Identity If you have configured your dashboard to manage multiple applications, you can restrict the management of apps based on user identity. From 0654d8d1b7ec5a0e7e39aaee32704fd32c763691 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Tue, 7 Sep 2021 23:53:17 +0200 Subject: [PATCH 35/37] removed RASS --- src/login/Login.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/login/Login.js b/src/login/Login.js index 0fc8b5798a..ac174f3365 100644 --- a/src/login/Login.js +++ b/src/login/Login.js @@ -70,7 +70,7 @@ export default class Login extends React.Component { { this.errors && this.errors.includes('one-time') ? } /> : null } From 032375259bafe5eee93993b2c1225c67fea979b6 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Wed, 8 Sep 2021 00:08:50 +0200 Subject: [PATCH 36/37] replaced URL with secret --- Parse-Dashboard/CLI/mfa.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Parse-Dashboard/CLI/mfa.js b/Parse-Dashboard/CLI/mfa.js index 010fa44f2d..98cb3f3a0f 100644 --- a/Parse-Dashboard/CLI/mfa.js +++ b/Parse-Dashboard/CLI/mfa.js @@ -77,7 +77,7 @@ const showQR = text => { }); }; -const showInstructions = ({ app, username, passwordCopied, mfaUrl, encrypt, config }) => { +const showInstructions = ({ app, username, passwordCopied, secret, encrypt, config }) => { let orderCounter = 0; const getOrder = () => { orderCounter++; @@ -95,15 +95,15 @@ const showInstructions = ({ app, username, passwordCopied, mfaUrl, encrypt, conf if (passwordCopied) { console.log( - `\n${getOrder()}. Securely store the auto-generated login password that has been copied to your clipboard.` + `\n${getOrder()}. Securely store the generated login password that has been copied to your clipboard.` ); } - if (mfaUrl) { + if (secret) { console.log( - `\n${getOrder()}. Install an authenticator app and scan the QR code above, or open this link:` + - `\n\n ${mfaUrl}` + - `\n\n${getOrder()}. Destroy any records of the QR code and the link, as they allow anyone to generate a one-time password.` + `\n${getOrder()}. Open the authenticator app to scan the QR code above or enter this secret code:` + + `\n\n ${secret}` + + `\n\n${getOrder()}. Destroy any records of the QR code and the secret code to secure the account.` ); } @@ -191,7 +191,7 @@ module.exports = { } const config = { mfa: data.mfa, user: data.user, pass: data.pass }; - showInstructions({ app: data.app, username, passwordCopied: true, mfaUrl: data.url, encrypt, config }); + showInstructions({ app: data.app, username, passwordCopied: true, secret: data.mfa, encrypt, config }); }, async createMFA() { console.log(''); From 312a84251426c1f13b1e7c001bd7c29228ba5935 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Wed, 8 Sep 2021 00:30:38 +0200 Subject: [PATCH 37/37] added url and secret to output --- Parse-Dashboard/CLI/mfa.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Parse-Dashboard/CLI/mfa.js b/Parse-Dashboard/CLI/mfa.js index 98cb3f3a0f..f862f2cf45 100644 --- a/Parse-Dashboard/CLI/mfa.js +++ b/Parse-Dashboard/CLI/mfa.js @@ -77,7 +77,7 @@ const showQR = text => { }); }; -const showInstructions = ({ app, username, passwordCopied, secret, encrypt, config }) => { +const showInstructions = ({ app, username, passwordCopied, secret, url, encrypt, config }) => { let orderCounter = 0; const getOrder = () => { orderCounter++; @@ -103,6 +103,8 @@ const showInstructions = ({ app, username, passwordCopied, secret, encrypt, conf console.log( `\n${getOrder()}. Open the authenticator app to scan the QR code above or enter this secret code:` + `\n\n ${secret}` + + '\n\n If the secret code generates incorrect one-time passwords, try this alternative:' + + `\n\n ${url}` + `\n\n${getOrder()}. Destroy any records of the QR code and the secret code to secure the account.` ); } @@ -191,7 +193,7 @@ module.exports = { } const config = { mfa: data.mfa, user: data.user, pass: data.pass }; - showInstructions({ app: data.app, username, passwordCopied: true, secret: data.mfa, encrypt, config }); + showInstructions({ app: data.app, username, passwordCopied: true, secret: data.mfa, url: data.url, encrypt, config }); }, async createMFA() { console.log(''); @@ -218,6 +220,6 @@ module.exports = { if (algorithm !== 'SHA1') { config.mfaAlgorithm = algorithm; } - showInstructions({ app, username, url, config }); + showInstructions({ app, username, secret, url, config }); } };