From 5941bfac7cb919d5ef8295a271afc3b56e1f1e51 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Mon, 9 Apr 2018 15:52:40 -0600 Subject: [PATCH] pulled data download into seperate plugin --- .../coral-embed-stream/src/graphql/index.js | 12 - .../DownloadCommentHistorySection.css | 12 - .../DownloadCommentHistorySection.js | 109 -------- .../src/tabs/profile/components/Settings.js | 2 - .../src/tabs/profile/containers/Settings.js | 4 - graph/mutators/user.js | 10 - graph/resolvers/comment.js | 4 + graph/resolvers/root_mutation.js | 3 - graph/resolvers/user.js | 2 - graph/typeDefs.graphql | 14 - locales/en.yml | 19 -- models/user.js | 7 - package.json | 2 - perms/constants/mutation.js | 1 - perms/constants/query.js | 1 - perms/reducers/mutation.js | 1 - perms/reducers/query.js | 1 - plugins.default.json | 6 +- routes/account/index.js | 4 - routes/api/v1/account.js | 140 ---------- services/mailer/templates/download.html.ejs | 1 - services/mailer/templates/download.txt.ejs | 3 - services/users.js | 59 ---- views/account/download.ejs | 47 ---- yarn.lock | 254 +----------------- 25 files changed, 17 insertions(+), 701 deletions(-) delete mode 100644 client/coral-embed-stream/src/tabs/profile/components/DownloadCommentHistorySection.css delete mode 100644 client/coral-embed-stream/src/tabs/profile/components/DownloadCommentHistorySection.js delete mode 100644 services/mailer/templates/download.html.ejs delete mode 100644 services/mailer/templates/download.txt.ejs delete mode 100644 views/account/download.ejs diff --git a/client/coral-embed-stream/src/graphql/index.js b/client/coral-embed-stream/src/graphql/index.js index 5c9da6751..d9f6b4f64 100644 --- a/client/coral-embed-stream/src/graphql/index.js +++ b/client/coral-embed-stream/src/graphql/index.js @@ -247,17 +247,5 @@ 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 deleted file mode 100644 index 55ea39969..000000000 --- a/client/coral-embed-stream/src/tabs/profile/components/DownloadCommentHistorySection.css +++ /dev/null @@ -1,12 +0,0 @@ -.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 deleted file mode 100644 index 494e79d9e..000000000 --- a/client/coral-embed-stream/src/tabs/profile/components/DownloadCommentHistorySection.js +++ /dev/null @@ -1,109 +0,0 @@ -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 c07dbfcd6..c61a09a92 100644 --- a/client/coral-embed-stream/src/tabs/profile/components/Settings.js +++ b/client/coral-embed-stream/src/tabs/profile/components/Settings.js @@ -1,7 +1,6 @@ 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() { @@ -10,7 +9,6 @@ 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 8535d95ca..795a3c10a 100644 --- a/client/coral-embed-stream/src/tabs/profile/containers/Settings.js +++ b/client/coral-embed-stream/src/tabs/profile/containers/Settings.js @@ -3,8 +3,6 @@ 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']; @@ -20,9 +18,7 @@ const enhance = compose( fragment TalkEmbedStream_ProfileSettings_root on RootQuery { __typename ${getSlotFragmentSpreads(slots, 'root')} - ...${getDefinitionName(DownloadCommentHistorySection.fragments.root)} } - ${DownloadCommentHistorySection.fragments.root} `, }) ); diff --git a/graph/mutators/user.js b/graph/mutators/user.js index d9e3374a5..19cf4b55e 100644 --- a/graph/mutators/user.js +++ b/graph/mutators/user.js @@ -9,7 +9,6 @@ const { SET_USER_SUSPENSION_STATUS, UPDATE_USER_ROLES, DELETE_USER, - REQUEST_DOWNLOAD_LINK, } = require('../../perms/constants'); const setUserUsernameStatus = async (ctx, id, status) => { @@ -144,10 +143,6 @@ const delUser = async (ctx, id) => { await user.remove(); }; -// requestDownloadLink will request the current user's account be available via -// a download link sent to their email address. -const requestDownloadLink = async ({ user }) => Users.sendDownloadLink(user); - module.exports = ctx => { let mutators = { User: { @@ -160,7 +155,6 @@ module.exports = ctx => { setUsername: () => Promise.reject(errors.ErrNotAuthorized), stopIgnoringUser: () => Promise.reject(errors.ErrNotAuthorized), del: () => Promise.reject(errors.ErrNotAuthorized), - requestDownloadLink: () => Promise.reject(errors.ErrNotAuthorized), }, }; @@ -200,10 +194,6 @@ module.exports = ctx => { if (ctx.user.can(DELETE_USER)) { mutators.User.del = id => delUser(ctx, id); } - - if (ctx.user.can(REQUEST_DOWNLOAD_LINK)) { - mutators.User.requestDownloadLink = () => requestDownloadLink(ctx); - } } return mutators; diff --git a/graph/resolvers/comment.js b/graph/resolvers/comment.js index 2e4d9a08d..a8d524dba 100644 --- a/graph/resolvers/comment.js +++ b/graph/resolvers/comment.js @@ -58,6 +58,10 @@ const Comment = { }, async url(comment, args, { loaders: { Assets } }) { const asset = await Assets.getByID.load(comment.asset_id); + if (!asset) { + return null; + } + const assetURL = new URL(asset.url); assetURL.searchParams.set('commentId', comment.id); return assetURL.href; diff --git a/graph/resolvers/root_mutation.js b/graph/resolvers/root_mutation.js index eea296196..2838f0f99 100644 --- a/graph/resolvers/root_mutation.js +++ b/graph/resolvers/root_mutation.js @@ -139,9 +139,6 @@ const RootMutation = { delUser: async (_, { id }, { mutators: { User } }) => { await User.del(id); }, - requestDownloadLink: async (_, args, { mutators: { User } }) => { - await User.requestDownloadLink(); - }, }; module.exports = RootMutation; diff --git a/graph/resolvers/user.js b/graph/resolvers/user.js index 1305a0746..46fe0ac3c 100644 --- a/graph/resolvers/user.js +++ b/graph/resolvers/user.js @@ -12,7 +12,6 @@ const { LIST_OWN_TOKENS, VIEW_USER_STATUS, VIEW_USER_EMAIL, - VIEW_LAST_DOWNLOADED_DATE, } = require('../../perms/constants'); const { property } = require('lodash'); @@ -65,7 +64,6 @@ 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 714c9e2f9..588ad08dc 100644 --- a/graph/typeDefs.graphql +++ b/graph/typeDefs.graphql @@ -238,10 +238,6 @@ 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. @@ -1439,12 +1435,6 @@ type DelUserResponse implements Response { errors: [UserError!] } -type RequestDownloadLinkResponse implements Response { - - # An array of errors relating to the mutation that occurred. - errors: [UserError!] -} - # All mutations for the application are defined on this object. type RootMutation { @@ -1545,10 +1535,6 @@ type RootMutation { # delUser will delete the user with the specified id. delUser(id: ID!): DelUserResponse - - # requestDownloadLink will request a download link be sent to the primary - # users email address. - requestDownloadLink: RequestDownloadLinkResponse } type UsernameChangedPayload { diff --git a/locales/en.yml b/locales/en.yml index f9fa56632..08d64ddc8 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -201,10 +201,6 @@ en: we_received_a_request: "We received a request to reset your password. If you did not request this change, you can ignore this email." if_you_did: "If you did," please_click: "please click here to reset password" - download: - subject: "Your download link is ready" # TODO: replace - download_link_ready: "Your download link is now ready, visit the following to download an archive of your account:" # TODO: replace - download_archive: "Download Archive" # TODO: replace embedlink: copy: "Copy to Clipboard" error: @@ -483,18 +479,3 @@ 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" - confirm: "Download" diff --git a/models/user.js b/models/user.js index 9ab60c983..717e43a88 100644 --- a/models/user.js +++ b/models/user.js @@ -191,13 +191,6 @@ 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/package.json b/package.json index 314104032..d331f62b4 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,6 @@ "apollo-server-express": "^1.2.0", "apollo-utilities": "^1.0.3", "app-module-path": "^2.2.0", - "archiver": "^2.1.1", "autoprefixer": "^6.5.2", "babel-cli": "6.26.0", "babel-core": "6.26.0", @@ -93,7 +92,6 @@ "copy-webpack-plugin": "^4.0.0", "cross-spawn": "^5.1.0", "css-loader": "^0.28.5", - "csv-stringify": "^2.0.4", "dataloader": "^1.3.0", "debug": "3.1.0", "dialog-polyfill": "^0.4.9", diff --git a/perms/constants/mutation.js b/perms/constants/mutation.js index 94736b419..d2ebe73f1 100644 --- a/perms/constants/mutation.js +++ b/perms/constants/mutation.js @@ -19,5 +19,4 @@ module.exports = { UPDATE_ASSET_STATUS: 'UPDATE_ASSET_STATUS', UPDATE_SETTINGS: 'UPDATE_SETTINGS', DELETE_USER: 'DELETE_USER', - REQUEST_DOWNLOAD_LINK: 'REQUEST_DOWNLOAD_LINK', }; diff --git a/perms/constants/query.js b/perms/constants/query.js index 531cf7aae..b846b15ce 100644 --- a/perms/constants/query.js +++ b/perms/constants/query.js @@ -10,5 +10,4 @@ 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/mutation.js b/perms/reducers/mutation.js index ab01da4e4..73ee7ef28 100644 --- a/perms/reducers/mutation.js +++ b/perms/reducers/mutation.js @@ -13,7 +13,6 @@ module.exports = (user, perm) => { case types.CREATE_ACTION: case types.DELETE_ACTION: case types.EDIT_COMMENT: - case types.REQUEST_DOWNLOAD_LINK: // Anyone can do these things if they aren't suspended, banned, or blocked // as they're editing their username. return !['UNSET', 'REJECTED', 'CHANGED'].includes( diff --git a/perms/reducers/query.js b/perms/reducers/query.js index cbd789c6a..0852d8e2b 100644 --- a/perms/reducers/query.js +++ b/perms/reducers/query.js @@ -13,7 +13,6 @@ 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/plugins.default.json b/plugins.default.json index ca17c79d8..e1011aa87 100644 --- a/plugins.default.json +++ b/plugins.default.json @@ -2,7 +2,8 @@ "server": [ "talk-plugin-auth", "talk-plugin-featured-comments", - "talk-plugin-respect" + "talk-plugin-respect", + "talk-plugin-profile-data" ], "client": [ "talk-plugin-auth", @@ -18,6 +19,7 @@ "talk-plugin-sort-most-respected", "talk-plugin-sort-newest", "talk-plugin-sort-oldest", - "talk-plugin-viewing-options" + "talk-plugin-viewing-options", + "talk-plugin-profile-data" ] } diff --git a/routes/account/index.js b/routes/account/index.js index 575ae7883..70e62accc 100644 --- a/routes/account/index.js +++ b/routes/account/index.js @@ -9,8 +9,4 @@ router.get('/password/reset', (req, res) => { res.render('account/password/reset'); }); -router.get('/download', (req, res) => { - res.render('account/download'); -}); - module.exports = router; diff --git a/routes/api/v1/account.js b/routes/api/v1/account.js index afeaafdb6..561134885 100644 --- a/routes/api/v1/account.js +++ b/routes/api/v1/account.js @@ -4,10 +4,6 @@ const UsersService = require('../../../services/users'); const mailer = require('../../../services/mailer'); const authorization = require('../../../middleware/authorization'); const errors = require('../../../errors'); -const archiver = require('archiver'); -const stringify = require('csv-stringify'); -const moment = require('moment'); -const { pick, get, kebabCase } = require('lodash'); // Return the current logged in user. router.get('/', authorization.needed(), (req, res, next) => { @@ -131,140 +127,4 @@ router.put( } ); -// loadCommentsBatch will load a batch of the comments and write them to the -// stream. -async function loadCommentsBatch(ctx, csv, variables = {}) { - let result = await ctx.graphql( - ` - query GetMyComments($cursor: Cursor) { - me { - comments(query: { - limit: 100, - cursor: $cursor - }) { - hasNextPage - endCursor - nodes { - id - created_at - asset { - url - } - body - url - } - } - } - } - `, - variables - ); - if (result.errors) { - throw result.errors; - } - - for (const comment of get(result, 'data.me.comments.nodes', [])) { - csv.write([ - comment.id, - moment(comment.created_at).format('YYYY-MM-DD HH:mm:ss'), - comment.asset.url, - comment.url, - comment.body, - ]); - } - - return pick(result.data.me.comments, ['hasNextPage', 'endCursor']); -} - -// loadComments will load batches of the comments and write them to the csv -// stream. Once the comments have finished writing, it will close the stream. -async function loadComments(ctx, archive, latestContentDate) { - // Create all the csv writers that'll write the data to the archive. - const csv = stringify(); - - // Add all the streams as files to the archive. - archive.append(csv, { name: 'talk-export/my_comments.csv' }); - - csv.write(['ID', 'Timestamp', 'Article', 'Link', 'Body']); - - // Load the first batch's comments from the latest date that we were provided - // from the token. - let connection = await loadCommentsBatch(ctx, csv, { - cursor: latestContentDate, - }); - - // As long as there's more comments, keep paginating. - while (connection.hasNextPage) { - connection = await loadCommentsBatch(ctx, csv, { - cursor: connection.endCursor, - }); - } - - csv.end(); -} - -// /download will send back a zipped archive of the users account. -router.post( - '/download', - express.urlencoded({ extended: false }), - tokenCheck(UsersService.verifyDownloadToken, new Error('invalid token')), - async (req, res, next) => { - try { - const { token } = req.body; - - // Pull the userID and the date that the token was issued out of the - // provided token. - const { user: userID, iat } = await UsersService.verifyDownloadToken( - token - ); - - // Unpack the date that the token was issued, and use it as a source for the - // earliest comment we should include in the download. - const latestContentDate = new Date(iat * 1000); - - // Grab the user that we're generating the export from. We'll use it to - // create a new context. - const user = await UsersService.findById(userID); - - // Base a new context off of the new user. - const ctx = req.context.masqueradeAs(user); - - // Get the current user's username. We need it for the generated filenames. - const result = await ctx.graphql('{ me { username } }'); - if (result.errors) { - throw result.errors; - } - const username = get(result, 'data.me.username'); - - // Generate the filename of the file that the user will download. - const filename = `talk-${kebabCase(username)}-${kebabCase( - moment(latestContentDate).format('YYYY-MM-DD HH:mm:ss') - )}.zip`; - - res.writeHead(200, { - 'Content-Type': 'application/octet-stream', - 'Content-Disposition': `attachment; filename=${filename}`, - }); - - // Create the zip archive we'll use to write all the exported files to. - const archive = archiver('zip', { - zlib: { level: 9 }, - }); - - // Pipe this to the response writer directly. - archive.pipe(res); - - // Load the comments csv up with the user's comments. - await loadComments(ctx, archive, latestContentDate); - - // Mark the end of adding files, no more files can be added after this. Once - // all the stream readers have finished writing, and have closed, the - // archiver will close which will finish the HTTP request. - archive.finalize(); - } catch (err) { - return next(err); - } - } -); - module.exports = router; diff --git a/services/mailer/templates/download.html.ejs b/services/mailer/templates/download.html.ejs deleted file mode 100644 index c6aeb8e1e..000000000 --- a/services/mailer/templates/download.html.ejs +++ /dev/null @@ -1 +0,0 @@ -

<%= t('email.download.download_link_ready') %> <%= t('email.download.download_archive') %>

diff --git a/services/mailer/templates/download.txt.ejs b/services/mailer/templates/download.txt.ejs deleted file mode 100644 index 4f719bc06..000000000 --- a/services/mailer/templates/download.txt.ejs +++ /dev/null @@ -1,3 +0,0 @@ -<%= t('email.download.download_link_ready') %> - - <%= BASE_URL %>account/download#<%= token %> diff --git a/services/users.js b/services/users.js index b59224676..e2c4fb61b 100644 --- a/services/users.js +++ b/services/users.js @@ -14,11 +14,9 @@ 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'; -const DOWNLOAD_LINK_SUBJECT = 'download_link'; // SALT_ROUNDS is the number of rounds that the bcrypt algorithm will run // through during the salting process. @@ -31,10 +29,6 @@ const loginRateLimiter = new Limit( RECAPTCHA_WINDOW ); -// downloadLinkLimiter can be used to limit downloads for the user's data to -// once every 24 hours. -const downloadLinkLimiter = new Limit('downloadLinkLimiter', 1, '1d'); - // Users is the interface for the application to interact with the // User through. class Users { @@ -472,59 +466,6 @@ class Users { }); } - static async sendDownloadLink(user) { - // Check that the user has not already requested a download within the last - // 24 hours. - const attempts = await downloadLinkLimiter.get(user.id); - if (attempts && attempts >= 1) { - 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. - await downloadLinkLimiter.test(user.id); - - // Generate a token for the download link. - const token = await JWT_SECRET.sign( - { user: user.id }, - { jwtid: uuid.v4(), expiresIn: '1d', subject: DOWNLOAD_LINK_SUBJECT } - ); - - // Send the download link via the user's attached email account. - await Users.sendEmail(user, { - template: 'download', - locals: { - token, - }, - 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) { - const jwt = await Users.verifyToken(token, { - subject: DOWNLOAD_LINK_SUBJECT, - }); - - return jwt; - } - static async sendEmail(user, options) { return mailer.send( merge({}, options, { diff --git a/views/account/download.ejs b/views/account/download.ejs deleted file mode 100644 index d8bdc6e27..000000000 --- a/views/account/download.ejs +++ /dev/null @@ -1,47 +0,0 @@ - - - - - <%= t('download_landing.download_your_account') %> - - - <%- include ../partials/head %> - - -
-
-
- <%= t('download_landing.click_to_download') %> - -
-
- - - - diff --git a/yarn.lock b/yarn.lock index ba8e393c5..47ce8caa0 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.1": +"@coralproject/eslint-config-talk@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@coralproject/eslint-config-talk/-/eslint-config-talk-0.1.1.tgz#71991b4937a3ffe657128d7f1170da4b5fb75c9e" dependencies: @@ -174,13 +174,6 @@ 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" @@ -235,10 +228,6 @@ 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" @@ -1805,13 +1794,6 @@ 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" @@ -2485,10 +2467,6 @@ 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" @@ -2723,9 +2701,9 @@ cssom@0.3.x, "cssom@>= 0.3.0 < 0.4.0", "cssom@>= 0.3.2 < 0.4.0": dependencies: cssom "0.3.x" -csv-stringify@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/csv-stringify/-/csv-stringify-2.0.4.tgz#9ace220df98ffa7ca91314ac77ff8cba0a08c863" +csv-stringify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/csv-stringify/-/csv-stringify-3.0.0.tgz#ed2b4eaae5a3be382309f7864168458970307d7f" dependencies: lodash.get "~4.4.2" @@ -2988,7 +2966,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.1.0: +doctrine@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" dependencies: @@ -3129,10 +3107,6 @@ 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" @@ -3428,49 +3402,6 @@ 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" @@ -3520,13 +3451,6 @@ 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" @@ -3701,20 +3625,6 @@ 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" @@ -3756,41 +3666,6 @@ 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" @@ -3988,18 +3863,6 @@ 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" @@ -5306,10 +5169,6 @@ 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" @@ -7172,10 +7031,6 @@ 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" @@ -7316,7 +7171,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: +"mime-db@>= 1.33.0 < 2": version "1.33.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" @@ -7326,12 +7181,6 @@ 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" @@ -7464,10 +7313,6 @@ 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" @@ -8425,15 +8270,6 @@ 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" @@ -9158,13 +8994,6 @@ 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" @@ -9415,10 +9244,6 @@ 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" @@ -9889,10 +9714,6 @@ 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" @@ -10043,33 +9864,6 @@ 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" @@ -10284,7 +10078,7 @@ sax@0.5.x: version "0.5.8" resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1" -sax@>=0.1.1, sax@^1.1.4, sax@^1.2.1, sax@^1.2.4, sax@~1.2.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" @@ -10423,7 +10217,7 @@ serve-static@1.13.0: parseurl "~1.3.2" send "0.16.0" -serve-static@1.13.2, serve-static@^1.10.0: +serve-static@^1.10.0: version "1.13.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" dependencies: @@ -10840,10 +10634,6 @@ 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" @@ -11141,7 +10931,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.2, table@^4.0.1: +table@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" dependencies: @@ -11470,13 +11260,6 @@ 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" @@ -11551,12 +11334,6 @@ 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" @@ -11847,13 +11624,6 @@ 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" @@ -12090,12 +11860,6 @@ 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"