diff --git a/client/coral-embed-stream/src/graphql/index.js b/client/coral-embed-stream/src/graphql/index.js
index d9f6b4f64..5c9da6751 100644
--- a/client/coral-embed-stream/src/graphql/index.js
+++ b/client/coral-embed-stream/src/graphql/index.js
@@ -247,5 +247,17 @@ export default {
},
},
}),
+ DownloadCommentHistory: () => ({
+ updateQueries: {
+ CoralEmbedStream_Profile: previousData =>
+ update(previousData, {
+ me: {
+ lastAccountDownload: {
+ $set: new Date().toISOString(),
+ },
+ },
+ }),
+ },
+ }),
},
};
diff --git a/client/coral-embed-stream/src/tabs/profile/components/DownloadCommentHistorySection.css b/client/coral-embed-stream/src/tabs/profile/components/DownloadCommentHistorySection.css
new file mode 100644
index 000000000..55ea39969
--- /dev/null
+++ b/client/coral-embed-stream/src/tabs/profile/components/DownloadCommentHistorySection.css
@@ -0,0 +1,12 @@
+.button {
+ margin: 0;
+
+ i {
+ font-size: inherit;
+ vertical-align: sub;
+ }
+}
+
+.most_recent {
+ color: #808080;
+}
diff --git a/client/coral-embed-stream/src/tabs/profile/components/DownloadCommentHistorySection.js b/client/coral-embed-stream/src/tabs/profile/components/DownloadCommentHistorySection.js
new file mode 100644
index 000000000..494e79d9e
--- /dev/null
+++ b/client/coral-embed-stream/src/tabs/profile/components/DownloadCommentHistorySection.js
@@ -0,0 +1,109 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { Button } from 'coral-ui';
+import { compose, gql } from 'react-apollo';
+import { t } from 'plugin-api/beta/client/services';
+import styles from './DownloadCommentHistorySection.css';
+import { withFragments, withMutation } from 'coral-framework/hocs';
+
+export const readableDuration = durAsHours => {
+ const durAsDays = Math.ceil(durAsHours / 24);
+
+ return durAsHours > 23
+ ? durAsDays > 1
+ ? t('download_request.days', durAsDays)
+ : t('download_request.day', durAsDays)
+ : durAsHours > 1
+ ? t('download_request.hours', durAsHours)
+ : t('download_request.hour', durAsHours);
+};
+
+class DownloadCommentHistorySection extends Component {
+ static propTypes = {
+ requestDownloadLink: PropTypes.func.isRequired,
+ root: PropTypes.object.isRequired,
+ };
+
+ render() {
+ const {
+ root: { me: { lastAccountDownload } },
+ requestDownloadLink,
+ } = this.props;
+
+ const now = new Date();
+ const lastAccountDownloadDate =
+ lastAccountDownload && new Date(lastAccountDownload);
+ const hoursLeft = lastAccountDownloadDate
+ ? Math.ceil(
+ 24 - (now.getTime() - lastAccountDownloadDate.getTime()) / 3.6e6
+ )
+ : 0;
+ const canRequestDownload = !lastAccountDownloadDate || hoursLeft <= 0;
+
+ return (
+
+ {t('download_request.section_title')}
+
+ {t('download_request.you_will_get_a_copy')}{' '}
+ {t('download_request.download_rate')}.
+
+ {lastAccountDownloadDate && (
+
+ {t('download_request.most_recent_request')}:{' '}
+ {lastAccountDownloadDate.toLocaleString()}
+
+ )}
+ {canRequestDownload ? (
+
+ ) : (
+
+ )}
+
+ );
+ }
+}
+
+const withDownloadCommentHistorySectionFragments = withFragments({
+ root: gql`
+ fragment TalkDownloadCommentHistory_DownloadCommentHistorySection_root on RootQuery {
+ me {
+ id
+ lastAccountDownload
+ }
+ }
+ `,
+});
+
+const withRequestDownloadLink = withMutation(
+ gql`
+ mutation DownloadCommentHistory {
+ requestDownloadLink {
+ errors {
+ translation_key
+ }
+ }
+ }
+ `,
+ {
+ props: ({ mutate }) => ({
+ requestDownloadLink: () => mutate({ variables: {} }),
+ }),
+ }
+);
+
+const enhance = compose(
+ withDownloadCommentHistorySectionFragments,
+ withRequestDownloadLink
+);
+
+export default enhance(DownloadCommentHistorySection);
diff --git a/client/coral-embed-stream/src/tabs/profile/components/Settings.js b/client/coral-embed-stream/src/tabs/profile/components/Settings.js
index c61a09a92..c07dbfcd6 100644
--- a/client/coral-embed-stream/src/tabs/profile/components/Settings.js
+++ b/client/coral-embed-stream/src/tabs/profile/components/Settings.js
@@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Slot } from 'coral-framework/components';
+import DownloadCommentHistorySection from './DownloadCommentHistorySection';
class Settings extends React.Component {
render() {
@@ -9,6 +10,7 @@ class Settings extends React.Component {
return (
+
);
}
diff --git a/client/coral-embed-stream/src/tabs/profile/containers/Settings.js b/client/coral-embed-stream/src/tabs/profile/containers/Settings.js
index 795a3c10a..8535d95ca 100644
--- a/client/coral-embed-stream/src/tabs/profile/containers/Settings.js
+++ b/client/coral-embed-stream/src/tabs/profile/containers/Settings.js
@@ -3,6 +3,8 @@ import { compose, gql } from 'react-apollo';
import Settings from '../components/Settings';
import { withFragments } from 'coral-framework/hocs';
import { getSlotFragmentSpreads } from 'coral-framework/utils';
+import { getDefinitionName } from 'coral-framework/utils';
+import DownloadCommentHistorySection from '../components/DownloadCommentHistorySection';
const slots = ['profileSettings'];
@@ -18,7 +20,9 @@ const enhance = compose(
fragment TalkEmbedStream_ProfileSettings_root on RootQuery {
__typename
${getSlotFragmentSpreads(slots, 'root')}
+ ...${getDefinitionName(DownloadCommentHistorySection.fragments.root)}
}
+ ${DownloadCommentHistorySection.fragments.root}
`,
})
);
diff --git a/graph/resolvers/user.js b/graph/resolvers/user.js
index 46fe0ac3c..1305a0746 100644
--- a/graph/resolvers/user.js
+++ b/graph/resolvers/user.js
@@ -12,6 +12,7 @@ const {
LIST_OWN_TOKENS,
VIEW_USER_STATUS,
VIEW_USER_EMAIL,
+ VIEW_LAST_DOWNLOADED_DATE,
} = require('../../perms/constants');
const { property } = require('lodash');
@@ -64,6 +65,7 @@ decorateWithPermissionCheck(
tokens: [LIST_OWN_TOKENS],
profiles: [SEARCH_OTHER_USERS],
comments: [SEARCH_OTHERS_COMMENTS],
+ lastAccountDownload: [VIEW_LAST_DOWNLOADED_DATE],
},
checkSelfField('id')
);
diff --git a/graph/typeDefs.graphql b/graph/typeDefs.graphql
index c86db06df..714c9e2f9 100644
--- a/graph/typeDefs.graphql
+++ b/graph/typeDefs.graphql
@@ -238,6 +238,10 @@ type User {
# returns user status
state: UserState
+
+ # lastAccountDownload is the date that the user last requested a comment
+ # download.
+ lastAccountDownload: Date
}
# UserConnection represents a paginable subset of a user list.
diff --git a/locales/en.yml b/locales/en.yml
index b33ba24b2..f9fa56632 100644
--- a/locales/en.yml
+++ b/locales/en.yml
@@ -483,6 +483,17 @@ en:
admin_sidebar:
view_options: "View Options"
sort_comments: "Sort Comments"
+ download_request:
+ section_title: "Download My Comment History"
+ you_will_get_a_copy: "You will recieve an email with a link to download your comment history. You can make"
+ download_rate: "one download request every 24 hours"
+ most_recent_request: "Your most recent request"
+ request: "Request Comment History"
+ rate_limit: "You can submit another Comment History request in {0}"
+ hours: "{0} hours"
+ days: "{0} days"
+ hour: "{0} hour"
+ day: "{0} day"
download_landing:
download_your_account: "Download Your Account"
click_to_download: "Click below to download your account"
diff --git a/models/user.js b/models/user.js
index 717e43a88..9ab60c983 100644
--- a/models/user.js
+++ b/models/user.js
@@ -191,6 +191,13 @@ const UserSchema = new Schema(
// Tags are added by the self or by administrators.
tags: [TagLinkSchema],
+ // lastAccountDownload is the date that the user last downloaded their
+ // account details.
+ lastAccountDownload: {
+ type: Date,
+ default: null,
+ },
+
// Additional metadata stored on the field.
metadata: {
default: {},
diff --git a/perms/constants/query.js b/perms/constants/query.js
index b846b15ce..531cf7aae 100644
--- a/perms/constants/query.js
+++ b/perms/constants/query.js
@@ -10,4 +10,5 @@ module.exports = {
LIST_OWN_TOKENS: 'LIST_OWN_TOKENS',
VIEW_USER_ROLE: 'VIEW_USER_ROLE',
VIEW_USER_EMAIL: 'VIEW_USER_EMAIL',
+ VIEW_LAST_DOWNLOADED_DATE: 'VIEW_LAST_DOWNLOADED_DATE',
};
diff --git a/perms/reducers/query.js b/perms/reducers/query.js
index 0852d8e2b..cbd789c6a 100644
--- a/perms/reducers/query.js
+++ b/perms/reducers/query.js
@@ -13,6 +13,7 @@ module.exports = (user, perm) => {
case types.VIEW_PROTECTED_SETTINGS:
case types.VIEW_USER_ROLE:
case types.VIEW_USER_EMAIL:
+ case types.VIEW_LAST_DOWNLOADED_DATE:
return check(user, ['ADMIN', 'MODERATOR']);
case types.LIST_OWN_TOKENS:
return check(user, ['ADMIN']);
diff --git a/services/users.js b/services/users.js
index cecbc32c5..b59224676 100644
--- a/services/users.js
+++ b/services/users.js
@@ -14,6 +14,7 @@ const i18n = require('./i18n');
const Wordlist = require('./wordlist');
const DomainList = require('./domain_list');
const Limit = require('./limit');
+const moment = require('moment');
const EMAIL_CONFIRM_JWT_SUBJECT = 'email_confirm';
const PASSWORD_RESET_JWT_SUBJECT = 'password_reset';
@@ -479,6 +480,16 @@ class Users {
throw errors.ErrMaxRateLimit;
}
+ // Check if the lastAccountDownload time is within 24 hours.
+ if (
+ user.lastAccountDownload &&
+ moment(user.lastAccountDownload)
+ .add(24, 'hours')
+ .isAfter(moment())
+ ) {
+ throw errors.ErrMaxRateLimit;
+ }
+
// The account currently does not have a download link, let's record the
// download. This will throw an error if a race ocurred and we should stop
// now.
@@ -498,6 +509,12 @@ class Users {
},
subject: i18n.t('email.download.subject'),
});
+
+ // Amend the lastAccountDownload on the user.
+ await User.update(
+ { id: user.id },
+ { $set: { lastAccountDownload: new Date() } }
+ );
}
static async verifyDownloadToken(token) {
diff --git a/yarn.lock b/yarn.lock
index 07786f9c9..ba8e393c5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -68,7 +68,7 @@
lodash "^4.2.0"
to-fast-properties "^2.0.0"
-"@coralproject/eslint-config-talk@^0.1.0":
+"@coralproject/eslint-config-talk@^0.1.0", "@coralproject/eslint-config-talk@^0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@coralproject/eslint-config-talk/-/eslint-config-talk-0.1.1.tgz#71991b4937a3ffe657128d7f1170da4b5fb75c9e"
dependencies:
@@ -174,6 +174,13 @@ accepts@^1.3.4, accepts@~1.3.4:
mime-types "~2.1.16"
negotiator "0.6.1"
+accepts@~1.3.5:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2"
+ dependencies:
+ mime-types "~2.1.18"
+ negotiator "0.6.1"
+
acorn-dynamic-import@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4"
@@ -228,6 +235,10 @@ acorn@^5.3.0:
version "5.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.4.1.tgz#fdc58d9d17f4a4e98d102ded826a9b9759125102"
+acorn@^5.5.0:
+ version "5.5.3"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9"
+
addressparser@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/addressparser/-/addressparser-1.0.1.tgz#47afbe1a2a9262191db6838e4fd1d39b40821746"
@@ -1794,6 +1805,13 @@ caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+casual@^1.5.19:
+ version "1.5.19"
+ resolved "https://registry.yarnpkg.com/casual/-/casual-1.5.19.tgz#66fac46f7ae463f468f5913eb139f9c41c58bbf2"
+ dependencies:
+ mersenne-twister "^1.0.1"
+ moment "^2.15.2"
+
center-align@^0.1.1:
version "0.1.3"
resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad"
@@ -2467,6 +2485,10 @@ crc32-stream@^2.0.0:
crc "^3.4.4"
readable-stream "^2.0.0"
+crc@3.4.4:
+ version "3.4.4"
+ resolved "https://registry.yarnpkg.com/crc/-/crc-3.4.4.tgz#9da1e980e3bd44fc5c93bf5ab3da3378d85e466b"
+
crc@^3.4.4:
version "3.5.0"
resolved "https://registry.yarnpkg.com/crc/-/crc-3.5.0.tgz#98b8ba7d489665ba3979f59b21381374101a1964"
@@ -2966,7 +2988,7 @@ dns-prefetch-control@0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz#60ddb457774e178f1f9415f0cabb0e85b0b300b2"
-doctrine@^2.0.0:
+doctrine@^2.0.0, doctrine@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
dependencies:
@@ -3107,6 +3129,10 @@ ejs@2.5.7, ejs@^2.5.7:
version "2.5.7"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.7.tgz#cc872c168880ae3c7189762fd5ffc00896c9518a"
+ejs@^2.5.8:
+ version "2.5.8"
+ resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.8.tgz#2ab6954619f225e6193b7ac5f7c39c48fefe4380"
+
electron-to-chromium@^1.2.7:
version "1.3.26"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.26.tgz#996427294861a74d9c7c82b9260ea301e8c02d66"
@@ -3402,6 +3428,49 @@ eslint-visitor-keys@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
+eslint@^4.19.1:
+ version "4.19.1"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300"
+ dependencies:
+ ajv "^5.3.0"
+ babel-code-frame "^6.22.0"
+ chalk "^2.1.0"
+ concat-stream "^1.6.0"
+ cross-spawn "^5.1.0"
+ debug "^3.1.0"
+ doctrine "^2.1.0"
+ eslint-scope "^3.7.1"
+ eslint-visitor-keys "^1.0.0"
+ espree "^3.5.4"
+ esquery "^1.0.0"
+ esutils "^2.0.2"
+ file-entry-cache "^2.0.0"
+ functional-red-black-tree "^1.0.1"
+ glob "^7.1.2"
+ globals "^11.0.1"
+ ignore "^3.3.3"
+ imurmurhash "^0.1.4"
+ inquirer "^3.0.6"
+ is-resolvable "^1.0.0"
+ js-yaml "^3.9.1"
+ json-stable-stringify-without-jsonify "^1.0.1"
+ levn "^0.3.0"
+ lodash "^4.17.4"
+ minimatch "^3.0.2"
+ mkdirp "^0.5.1"
+ natural-compare "^1.4.0"
+ optionator "^0.8.2"
+ path-is-inside "^1.0.2"
+ pluralize "^7.0.0"
+ progress "^2.0.0"
+ regexpp "^1.0.1"
+ require-uncached "^1.0.3"
+ semver "^5.3.0"
+ strip-ansi "^4.0.0"
+ strip-json-comments "~2.0.1"
+ table "4.0.2"
+ text-table "~0.2.0"
+
eslint@^4.5.0:
version "4.13.1"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.13.1.tgz#0055e0014464c7eb7878caf549ef2941992b444f"
@@ -3451,6 +3520,13 @@ espree@^3.5.2:
acorn "^5.2.1"
acorn-jsx "^3.0.0"
+espree@^3.5.4:
+ version "3.5.4"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7"
+ dependencies:
+ acorn "^5.5.0"
+ acorn-jsx "^3.0.0"
+
esprima@3.x.x, esprima@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
@@ -3625,6 +3701,20 @@ exports-loader@^0.6.4:
loader-utils "^1.0.2"
source-map "0.5.x"
+express-session@^1.15.6:
+ version "1.15.6"
+ resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.15.6.tgz#47b4160c88f42ab70fe8a508e31cbff76757ab0a"
+ dependencies:
+ cookie "0.3.1"
+ cookie-signature "1.0.6"
+ crc "3.4.4"
+ debug "2.6.9"
+ depd "~1.1.1"
+ on-headers "~1.0.1"
+ parseurl "~1.3.2"
+ uid-safe "~2.1.5"
+ utils-merge "1.0.1"
+
express-static-gzip@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/express-static-gzip/-/express-static-gzip-0.3.2.tgz#89ede84547a5717de3146315f62dc996c071a88d"
@@ -3666,6 +3756,41 @@ express@4.16.0, express@^4.12.2:
utils-merge "1.0.1"
vary "~1.1.2"
+express@^4.16.3:
+ version "4.16.3"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53"
+ dependencies:
+ accepts "~1.3.5"
+ array-flatten "1.1.1"
+ body-parser "1.18.2"
+ content-disposition "0.5.2"
+ content-type "~1.0.4"
+ cookie "0.3.1"
+ cookie-signature "1.0.6"
+ debug "2.6.9"
+ depd "~1.1.2"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ finalhandler "1.1.1"
+ fresh "0.5.2"
+ merge-descriptors "1.0.1"
+ methods "~1.1.2"
+ on-finished "~2.3.0"
+ parseurl "~1.3.2"
+ path-to-regexp "0.1.7"
+ proxy-addr "~2.0.3"
+ qs "6.5.1"
+ range-parser "~1.2.0"
+ safe-buffer "5.1.1"
+ send "0.16.2"
+ serve-static "1.13.2"
+ setprototypeof "1.1.0"
+ statuses "~1.4.0"
+ type-is "~1.6.16"
+ utils-merge "1.0.1"
+ vary "~1.1.2"
+
extend-shallow@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
@@ -3863,6 +3988,18 @@ finalhandler@1.1.0:
statuses "~1.3.1"
unpipe "~1.0.0"
+finalhandler@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105"
+ dependencies:
+ debug "2.6.9"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ on-finished "~2.3.0"
+ parseurl "~1.3.2"
+ statuses "~1.4.0"
+ unpipe "~1.0.0"
+
find-cache-dir@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f"
@@ -5169,6 +5306,10 @@ ipaddr.js@1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.5.2.tgz#d4b505bde9946987ccf0fc58d9010ff9607e3fa0"
+ipaddr.js@1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.6.0.tgz#e3fa357b773da619f26e95f049d055c72796f86b"
+
is-absolute-url@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
@@ -7031,6 +7172,10 @@ merge@^1.1.3:
version "1.2.0"
resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da"
+mersenne-twister@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/mersenne-twister/-/mersenne-twister-1.1.0.tgz#f916618ee43d7179efcf641bec4531eb9670978a"
+
metascraper-author@^3.9.2:
version "3.9.2"
resolved "https://registry.yarnpkg.com/metascraper-author/-/metascraper-author-3.9.2.tgz#ff2020ac428f59a875d655df3b0d4bea171fde19"
@@ -7171,7 +7316,7 @@ miller-rabin@^4.0.0:
version "1.30.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01"
-"mime-db@>= 1.33.0 < 2":
+"mime-db@>= 1.33.0 < 2", mime-db@~1.33.0:
version "1.33.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
@@ -7181,6 +7326,12 @@ mime-types@^2.1.10, mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16,
dependencies:
mime-db "~1.30.0"
+mime-types@~2.1.18:
+ version "2.1.18"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8"
+ dependencies:
+ mime-db "~1.33.0"
+
mime@1.4.1, mime@^1.3.4, mime@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
@@ -7313,6 +7464,10 @@ moment@^2.10.3:
version "2.19.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.1.tgz#56da1a2d1cbf01d38b7e1afc31c10bcfa1929167"
+moment@^2.15.2:
+ version "2.22.0"
+ resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.0.tgz#7921ade01017dd45186e7fee5f424f0b8663a730"
+
mongodb-core@2.1.17:
version "2.1.17"
resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.17.tgz#a418b337a14a14990fb510b923dee6a813173df8"
@@ -8270,6 +8425,15 @@ passport-oauth2@1.x.x, passport-oauth2@^1.1.2:
uid2 "0.0.x"
utils-merge "1.x.x"
+passport-openidconnect@^0.0.2:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/passport-openidconnect/-/passport-openidconnect-0.0.2.tgz#e488f8bdb386c9a9fd39c91d5ab8c880156e8153"
+ dependencies:
+ oauth "0.9.x"
+ passport-strategy "1.x.x"
+ request "^2.75.0"
+ webfinger "0.4.x"
+
passport-strategy@1.x.x, passport-strategy@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
@@ -8994,6 +9158,13 @@ proxy-addr@~2.0.2:
forwarded "~0.1.2"
ipaddr.js "1.5.2"
+proxy-addr@~2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.3.tgz#355f262505a621646b3130a728eb647e22055341"
+ dependencies:
+ forwarded "~0.1.2"
+ ipaddr.js "1.6.0"
+
proxy-agent@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-2.0.0.tgz#57eb5347aa805d74ec681cb25649dba39c933499"
@@ -9244,6 +9415,10 @@ randexp@^0.4.2:
discontinuous-range "1.0.0"
ret "~0.1.10"
+random-bytes@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b"
+
randomatic@^1.1.3:
version "1.1.7"
resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c"
@@ -9714,6 +9889,10 @@ regexp-clone@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/regexp-clone/-/regexp-clone-0.0.1.tgz#a7c2e09891fdbf38fbb10d376fb73003e68ac589"
+regexpp@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab"
+
regexpu-core@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b"
@@ -9864,6 +10043,33 @@ request@2.81.0:
tunnel-agent "^0.6.0"
uuid "^3.0.0"
+request@^2.75.0:
+ version "2.85.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa"
+ dependencies:
+ aws-sign2 "~0.7.0"
+ aws4 "^1.6.0"
+ caseless "~0.12.0"
+ combined-stream "~1.0.5"
+ extend "~3.0.1"
+ forever-agent "~0.6.1"
+ form-data "~2.3.1"
+ har-validator "~5.0.3"
+ hawk "~6.0.2"
+ http-signature "~1.2.0"
+ is-typedarray "~1.0.0"
+ isstream "~0.1.2"
+ json-stringify-safe "~5.0.1"
+ mime-types "~2.1.17"
+ oauth-sign "~0.8.2"
+ performance-now "^2.1.0"
+ qs "~6.5.1"
+ safe-buffer "^5.1.1"
+ stringstream "~0.0.5"
+ tough-cookie "~2.3.3"
+ tunnel-agent "^0.6.0"
+ uuid "^3.1.0"
+
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
@@ -10078,7 +10284,7 @@ sax@0.5.x:
version "0.5.8"
resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1"
-sax@^1.1.4, sax@^1.2.1, sax@^1.2.4, sax@~1.2.1:
+sax@>=0.1.1, sax@^1.1.4, sax@^1.2.1, sax@^1.2.4, sax@~1.2.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
@@ -10217,7 +10423,7 @@ serve-static@1.13.0:
parseurl "~1.3.2"
send "0.16.0"
-serve-static@^1.10.0:
+serve-static@1.13.2, serve-static@^1.10.0:
version "1.13.2"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1"
dependencies:
@@ -10634,6 +10840,10 @@ stealthy-require@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
+step@0.0.x:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/step/-/step-0.0.6.tgz#143e7849a5d7d3f4a088fe29af94915216eeede2"
+
stream-browserify@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"
@@ -10931,7 +11141,7 @@ symbol-observable@^1.0.2, symbol-observable@^1.0.3, symbol-observable@^1.0.4:
version "3.2.2"
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
-table@^4.0.1:
+table@4.0.2, table@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36"
dependencies:
@@ -11260,6 +11470,13 @@ type-is@~1.6.15:
media-typer "0.3.0"
mime-types "~2.1.15"
+type-is@~1.6.16:
+ version "1.6.16"
+ resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194"
+ dependencies:
+ media-typer "0.3.0"
+ mime-types "~2.1.18"
+
typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
@@ -11334,6 +11551,12 @@ uid-number@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
+uid-safe@~2.1.5:
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a"
+ dependencies:
+ random-bytes "~1.0.0"
+
uid2@0.0.x:
version "0.0.3"
resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82"
@@ -11624,6 +11847,13 @@ watchpack@^1.4.0:
chokidar "^1.7.0"
graceful-fs "^4.1.2"
+webfinger@0.4.x:
+ version "0.4.2"
+ resolved "https://registry.yarnpkg.com/webfinger/-/webfinger-0.4.2.tgz#3477a6d97799461896039fcffc650b73468ee76d"
+ dependencies:
+ step "0.0.x"
+ xml2js "0.1.x"
+
webidl-conversions@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-2.0.1.tgz#3bf8258f7d318c7443c36f2e169402a1a6703506"
@@ -11860,6 +12090,12 @@ xml-name-validator@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
+xml2js@0.1.x:
+ version "0.1.14"
+ resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.1.14.tgz#5274e67f5a64c5f92974cd85139e0332adc6b90c"
+ dependencies:
+ sax ">=0.1.1"
+
xml@^1.0.0, xml@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5"