itterated on copy

This commit is contained in:
Wyatt Johnson
2018-04-13 18:24:46 -06:00
parent 392d7177f6
commit 12bb886032
14 changed files with 158 additions and 78 deletions
+3 -1
View File
@@ -20,11 +20,13 @@ en:
bio_offensive: "This bio is offensive"
cancel: "Cancel"
confirm_email:
click_to_confirm: "Click below to confirm your email address"
email_confirmation: "Email Confirmation"
click_to_confirm: "Click below to confirm your email address."
confirm: "Confirm"
password_reset:
mail_sent: 'If you have a registered account, a password reset link was sent to that email'
set_new_password: "Change Your Password"
change_password_help: "Please enter a new password to use to login. Make it secure!"
new_password: "New Password"
new_password_help: "Password must be at least 8 characters"
confirm_new_password: "Confirm New Password"
@@ -1 +1 @@
<p><%= t('email.download.download_link_ready') %> <a href="<%= BASE_URL %>account/download#<%= token %>"><%= t('email.download.download_archive') %></a></p>
<p><%= t('email.download.download_link_ready', organizationName, now.toLocaleString()) %> <a href="<%= BASE_URL %>account/download#<%= token %>"><%= t('email.download.download_archive') %></a></p>
@@ -1,3 +1,3 @@
<%= t('email.download.download_link_ready') %>
<%= t('email.download.download_link_ready', organizationName, now.toLocaleString()) %>
<%= BASE_URL %>account/download#<%= token %>
@@ -0,0 +1,18 @@
const { TalkError } = require('errors');
// ErrDownloadToken is returned in the event that the download is requested
// without a valid token.
class ErrDownloadToken extends TalkError {
constructor(err) {
super(
'Token is invalid',
{
translation_key: 'DOWNLOAD_TOKEN_INVALID',
status: 400,
},
{ err }
);
}
}
module.exports = { ErrDownloadToken };
@@ -4,6 +4,7 @@ const { DOWNLOAD_LINK_SUBJECT } = require('./constants');
async function sendDownloadLink({
user,
loaders: { Settings },
connectors: {
errors,
secrets,
@@ -43,19 +44,25 @@ async function sendDownloadLink({
{ jwtid: uuid.v4(), expiresIn: '1d', subject: DOWNLOAD_LINK_SUBJECT }
);
const now = new Date();
const { organizationName } = await Settings.load('organizationName');
// Send the download link via the user's attached email account.
await Users.sendEmail(user, {
template: 'download',
locals: {
token,
organizationName,
now,
},
subject: I18n.t('email.download.subject'),
subject: I18n.t('email.download.subject', organizationName),
});
// Amend the lastAccountDownload on the user.
await User.update(
{ id: user.id },
{ $set: { 'metadata.lastAccountDownload': new Date() } }
{ $set: { 'metadata.lastAccountDownload': now } }
);
}
@@ -5,6 +5,7 @@ const { get, pick, kebabCase } = require('lodash');
const moment = require('moment');
const archiver = require('archiver');
const stringify = require('csv-stringify');
const { ErrDownloadToken } = require('./errors');
async function verifyDownloadToken(
{ connectors: { services: { Users } } },
@@ -109,10 +110,7 @@ module.exports = router => {
// Verify the token
await verifyDownloadToken(req.context, token);
} catch (err) {
// Log out the error, slurp it and send out the predefined error to the
// error handler.
console.error(err);
return next(new Error('invalid token'));
return next(new ErrDownloadToken(err));
}
res.status(204).end();
@@ -1,19 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<title><%= t('download_landing.download_your_account') %></title>
<link rel="stylesheet" href="https://code.getmdl.io/1.2.1/material.indigo-pink.min.css">
<link rel="stylesheet" href="<%= BASE_PATH %>public/css/admin.css">
<%- include(root + '/partials/head') %>
<%- include(root + '/partials/account') %>
</head>
<body class="confirm-email-page">
<body>
<div id="root">
<div class="error-console container"></div>
<form id="download-form" class="container" method="post" action="<%= BASE_PATH %>api/v1/account/download">
<legend class="legend"><%= t('download_landing.click_to_download') %></legend>
<button type="submit"><%= t('download_landing.confirm') %></button>
</form>
<section class="container">
<h1><%= t('download_landing.download_your_account') %></h1>
<p><%= t('download_landing.download_details') %></p>
<p><%= t('download_landing.all_information_included') %></p>
<ul class="check_list">
<li><%= t('download_landing.information_included.date') %></li>
<li><%= t('download_landing.information_included.url') %></li>
<li><%= t('download_landing.information_included.body') %></li>
<li><%= t('download_landing.information_included.asset_url') %></li>
</ul>
<div class="error-console"></div>
<form id="download-form" method="post" action="<%= BASE_PATH %>api/v1/account/download">
<button type="submit"><%= t('download_landing.confirm') %></button>
</form>
</section>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
@@ -21,9 +28,9 @@
function showError(error) {
try {
let err = JSON.parse(error);
$('.error-console').text(err.message).addClass('active');
$('.error-console').text(err.message).fadeIn();
} catch (err) {
$('.error-console').text(error).addClass('active');
$('.error-console').text(error).fadeIn();
}
}
@@ -1,10 +1,18 @@
en:
download_landing:
download_your_account: "Download Your Account"
click_to_download: "Click below to download your account"
confirm: "Download"
download_your_account: "Download Your Comment History"
download_details: "Your comment history will be downloaded into a .zip file. After your comment history is unzipped you will have a comma seperated value (or .csv) file that you can easily import into your favorite spreadsheet application."
all_information_included: "For each of your comments the following information is included:"
information_included:
date: "When you wrote the comment"
url: "The permalink URL for the comment"
body: "The comment text"
asset_url: "The URL on the article or story where the comment appears"
confirm: "Download My Comment History"
email:
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
subject: "Your comments are ready for download from {0}"
download_link_ready: "Click here to download your comments from {0} as of {1}:"
download_archive: "Download Archive"
error:
DOWNLOAD_TOKEN_INVALID: "Your download link is not valid."
+50 -13
View File
@@ -6,13 +6,15 @@ body, #root {
}
.container {
max-width: 300px;
max-width: 675px;
margin: 50px auto;
}
#root form {
display: none;
padding: 15px;
padding: 15px 0;
/* max-width: 400px;
margin: 0 auto; */
}
.legend {
@@ -21,6 +23,22 @@ body, #root {
font-weight: bold;
}
section p, ul {
font-family: Source Sans Pro;
font-style: normal;
font-weight: normal;
line-height: 34px;
font-size: 24px;
letter-spacing: 0.3px;
}
h1 {
font-family: Source Sans Pro;
font-size: 48px;
font-weight: 600;
color: #000000;
}
label {
display: block;
margin-top: 10px;
@@ -44,28 +62,47 @@ input {
}
button[type="submit"] {
border-radius: 4px;
font-family: Source Sans Pro;
font-style: normal;
font-weight: 600;
line-height: normal;
font-size: 18px;
text-align: center;
color: white;
border-radius: 2px;
border: none;
display: block;
background-color: #333;
color: white;
text-align: center;
width: 100%;
padding: 10px;
margin-top: 10px;
background-color: #3498DB;
margin: 10px auto;
padding: 13px;
cursor: pointer;
}
.error-console {
display: none;
margin-top: 10px;
border-radius: 4px;
border-radius: 2px;
background-color: pink;
color: red;
border: 1px solid red;
padding: 10px;
font-size: 24px;
}
.error-console.active {
display: block;
}
ul.check_list {
list-style-type: none;
margin: 0 0 0 0.5em;
}
ul.check_list li {
text-indent: -1.4em;
}
ul.check_list li:before {
font-family: 'Material Icons';
content: '\E5CA';
color: #000;
float: left;
width: 1.4em;
}
+1 -1
View File
@@ -37,7 +37,7 @@ const tokenCheck = (verifier, error, ...whitelistedErrors) => async (
// Log out the error, slurp it and send out the predefined error to the
// error handler.
console.error(err);
return next(error);
return next(new error());
}
res.status(204).end();
+12 -12
View File
@@ -1,19 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<title>Email Verification</title>
<link rel="stylesheet" href="https://code.getmdl.io/1.2.1/material.indigo-pink.min.css">
<link rel="stylesheet" href="<%= BASE_PATH %>public/css/admin.css">
<%- include ../../partials/head %>
<title><%= t('confirm_email.email_confirmation') %></title>
<%- include ../../partials/account %>
</head>
<body class="confirm-email-page">
<div id="root">
<div class="error-console container"></div>
<form id="verify-email-form" class="container">
<legend class="legend"><%= t('confirm_email.click_to_confirm') %></legend>
<button type="submit"><%= t('confirm_email.confirm') %></button>
</form>
<section class="container">
<h1><%= t('confirm_email.email_confirmation') %></h1>
<p><%= t('confirm_email.click_to_confirm') %></p>
<div class="error-console"></div>
<form id="verify-email-form">
<button type="submit"><%= t('confirm_email.confirm') %></button>
</form>
</section>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
@@ -21,9 +21,9 @@
function showError(error) {
try {
let err = JSON.parse(error);
$('.error-console').text(err.message).addClass('active');
$('.error-console').text(err.message).fadeIn();
} catch (err) {
$('.error-console').text(error).addClass('active');
$('.error-console').text(error).fadeIn();
}
}
+22 -23
View File
@@ -1,29 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<title>Password Reset</title>
<link rel="stylesheet" href="https://code.getmdl.io/1.2.1/material.indigo-pink.min.css">
<link rel="stylesheet" href="<%= BASE_PATH %>public/css/admin.css">
<%- include ../../partials/head %>
<title><%= t('password_reset.set_new_password') %></title>
<%- include ../../partials/account %>
</head>
<body class="password-reset-page">
<body>
<div id="root">
<div class="error-console container"></div>
<form id="reset-password-form" class="container">
<legend class="legend"><%= t('password_reset.set_new_password') %></legend>
<label for="password">
<%= t('password_reset.new_password') %>
<input type="password" name="password" placeholder="<%= t('password_reset.new_password') %>" />
<p><small><%= t('password_reset.new_password_help') %></small></p>
</label>
<label for="confirm-password">
<%= t('password_reset.confirm_new_password') %>
<input type="password" name="confirm-password" placeholder="<%= t('password_reset.confirm_new_password') %>" />
</label>
<button type="submit"><%= t('password_reset.change_password') %></button>
</form>
<section class="container">
<h1><%= t('password_reset.set_new_password') %></h1>
<p><%= t('password_reset.change_password_help') %></p>
<div class="error-console"></div>
<form id="reset-password-form">
<label for="password">
<%= t('password_reset.new_password') %>
<input type="password" name="password" placeholder="<%= t('password_reset.new_password') %>" />
<p><small><%= t('password_reset.new_password_help') %></small></p>
</label>
<label for="confirm-password">
<%= t('password_reset.confirm_new_password') %>
<input type="password" name="confirm-password" placeholder="<%= t('password_reset.confirm_new_password') %>" />
</label>
<button type="submit"><%= t('password_reset.change_password') %></button>
</form>
</section>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
@@ -31,9 +30,9 @@
function showError(error) {
try {
let err = JSON.parse(error);
$('.error-console').text(err.message).addClass('active');
$('.error-console').text(err.message).fadeIn();
} catch (err) {
$('.error-console').text(error).addClass('active');
$('.error-console').text(error).fadeIn();
}
}
-2
View File
@@ -2,8 +2,6 @@
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="<%= resolve('embed/stream/default.css') %>">
<link rel="stylesheet" type="text/css" href="<%= resolve('embed/stream/bundle.css') %>">
<%- include ../partials/head %>
+6
View File
@@ -13,8 +13,14 @@
<link rel="icon" type="image/png" sizes="16x16" href="<%= STATIC_URL %>public/img/favicon-16x16.png">
<link rel="manifest" href="<%= STATIC_URL %>public/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600" rel="stylesheet">
<%_ if (locals.customCssUrl) { _%>
<link href="<%= customCssUrl %>" rel="stylesheet" type="text/css">
<%_ } _%>
<%- include data %>
<base href="<%= BASE_URL %>"/>