diff --git a/client/coral-admin/src/components/ui/Header.css b/client/coral-admin/src/components/ui/Header.css index e30cb46d7..eba94d892 100644 --- a/client/coral-admin/src/components/ui/Header.css +++ b/client/coral-admin/src/components/ui/Header.css @@ -74,8 +74,12 @@ background-color: transparent; transition: background-color 200ms; + &:hover { + background-color: #232323; + } + &.active { - background-color: #232323; + background-color: #232323; } } diff --git a/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js b/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js index a6d3527c7..61352b921 100644 --- a/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js +++ b/client/coral-admin/src/containers/ModerationQueue/ModerationContainer.js @@ -163,6 +163,7 @@ class ModerationContainer extends Component { activeTab={activeTab} singleView={moderation.singleView} selectedIndex={this.state.selectedIndex} + bannedWords={settings.wordlist.banned} suspectWords={settings.wordlist.suspect} showBanUserDialog={props.showBanUserDialog} acceptComment={props.acceptComment} diff --git a/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js b/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js index b90b59f81..79b4ce7e4 100644 --- a/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js +++ b/client/coral-admin/src/containers/ModerationQueue/ModerationQueue.js @@ -24,6 +24,7 @@ const ModerationQueue = ({comments, selectedIndex, commentCount, singleView, loa commentType={activeTab} selected={i === selectedIndex} suspectWords={props.suspectWords} + bannedWords={props.bannedWords} actions={actionsMap[status]} showBanUserDialog={props.showBanUserDialog} acceptComment={props.acceptComment} @@ -47,6 +48,7 @@ const ModerationQueue = ({comments, selectedIndex, commentCount, singleView, loa }; ModerationQueue.propTypes = { + bannedWords: PropTypes.arrayOf(PropTypes.string).isRequired, suspectWords: PropTypes.arrayOf(PropTypes.string).isRequired, currentAsset: PropTypes.object, showBanUserDialog: PropTypes.func.isRequired, diff --git a/client/coral-admin/src/containers/ModerationQueue/components/Comment.js b/client/coral-admin/src/containers/ModerationQueue/components/Comment.js index f68bab2b7..a2bbbf092 100644 --- a/client/coral-admin/src/containers/ModerationQueue/components/Comment.js +++ b/client/coral-admin/src/containers/ModerationQueue/components/Comment.js @@ -19,6 +19,7 @@ const lang = new I18n(translations); const Comment = ({actions = [], ...props}) => { const links = linkify.getMatches(props.comment.body); + const linkText = links ? links.map(link => link.raw) : []; const actionSummaries = props.comment.action_summaries; return (
  • @@ -49,9 +50,9 @@ const Comment = ({actions = [], ...props}) => {

    - - - +

    {links ? Contains Link : null} @@ -77,6 +78,7 @@ Comment.propTypes = { acceptComment: PropTypes.func.isRequired, rejectComment: PropTypes.func.isRequired, suspectWords: PropTypes.arrayOf(PropTypes.string).isRequired, + bannedWords: PropTypes.arrayOf(PropTypes.string).isRequired, currentAsset: PropTypes.object, comment: PropTypes.shape({ body: PropTypes.string.isRequired, @@ -92,9 +94,4 @@ Comment.propTypes = { }) }; -const linkStyles = { - backgroundColor: 'rgb(255, 219, 135)', - padding: '1px 2px' -}; - export default Comment; diff --git a/client/coral-admin/src/containers/ModerationQueue/components/ModerationMenu.js b/client/coral-admin/src/containers/ModerationQueue/components/ModerationMenu.js index b8160e21b..e428f6a52 100644 --- a/client/coral-admin/src/containers/ModerationQueue/components/ModerationMenu.js +++ b/client/coral-admin/src/containers/ModerationQueue/components/ModerationMenu.js @@ -1,35 +1,53 @@ -import React, {PropTypes} from 'react'; +import React, { PropTypes } from 'react'; import CommentCount from './CommentCount'; import styles from './styles.css'; -import {SelectField, Option} from 'react-mdl-selectfield'; +import { SelectField, Option } from 'react-mdl-selectfield'; import I18n from 'coral-framework/modules/i18n/i18n'; import translations from 'coral-admin/src/translations.json'; -import {Link} from 'react-router'; +import { Link } from 'react-router'; const lang = new I18n(translations); -const ModerationMenu = ({asset, premodCount, rejectedCount, flaggedCount, selectSort, sort}) => { - const premodPath = asset ? `/admin/moderate/premod/${asset.id}` : '/admin/moderate/premod'; - const rejectPath = asset ? `/admin/moderate/rejected/${asset.id}` : '/admin/moderate/rejected'; - const flagPath = asset ? `/admin/moderate/flagged/${asset.id}` : '/admin/moderate/flagged'; +const ModerationMenu = ( + { asset, premodCount, rejectedCount, flaggedCount, selectSort, sort } +) => { + const premodPath = asset + ? `/admin/moderate/premod/${asset.id}` + : '/admin/moderate/premod'; + const rejectPath = asset + ? `/admin/moderate/rejected/${asset.id}` + : '/admin/moderate/rejected'; + const flagPath = asset + ? `/admin/moderate/flagged/${asset.id}` + : '/admin/moderate/flagged'; + return ( -
    +
    -
    +
    - + {lang.t('modqueue.premod')} - - {lang.t('modqueue.rejected')} - - + {lang.t('modqueue.flagged')} + + {lang.t('modqueue.rejected')} +
    selectSort(sort)}> diff --git a/client/coral-admin/src/containers/ModerationQueue/components/styles.css b/client/coral-admin/src/containers/ModerationQueue/components/styles.css index 9576045de..51086dfd4 100644 --- a/client/coral-admin/src/containers/ModerationQueue/components/styles.css +++ b/client/coral-admin/src/containers/ModerationQueue/components/styles.css @@ -170,7 +170,7 @@ span { border-bottom: 1px solid #e0e0e0; font-size: 18px; width: 100%; - max-width: 660px; + max-width: 700px; min-width: 400px; margin: 0 auto; position: relative; @@ -192,7 +192,7 @@ span { } &.selected { - max-width: 670px; + max-width: 720px; max-height: 410px; } @@ -216,10 +216,12 @@ span { justify-content: space-between; .author { - font-weight: 600; + font-weight: 300; min-width: 230px; display: flex; align-items: center; + color: #262626; + font-size: 16px; } } @@ -242,10 +244,11 @@ span { } .created { - color: #666; - font-size: 13px; + color: #262626; + font-size: 14px; margin-left: 15px; line-height: 1px; + font-weight: 300; } .actionButton { @@ -260,6 +263,7 @@ span { max-width: 500px; word-wrap: break-word; font-weight: 300; + font-size: 16px; } .flagged { diff --git a/client/coral-embed-stream/src/Comment.css b/client/coral-embed-stream/src/Comment.css index 6966d82ab..01022ae66 100644 --- a/client/coral-embed-stream/src/Comment.css +++ b/client/coral-embed-stream/src/Comment.css @@ -1,9 +1,10 @@ .Reply { position: relative; + margin-bottom: 15px; } .Comment { - + margin-bottom: 15px; } .pendingComment { diff --git a/client/coral-embed-stream/src/Embed.js b/client/coral-embed-stream/src/Embed.js index 4722a44b1..a3d2a24a9 100644 --- a/client/coral-embed-stream/src/Embed.js +++ b/client/coral-embed-stream/src/Embed.js @@ -121,7 +121,7 @@ class Embed extends Component {
    - {lang.t('profile')} + {lang.t('MY_COMMENTS')} Configure Stream {loggedIn && this.props.logout().then(refetch)} changeTab={this.changeTab}/>} @@ -160,7 +160,6 @@ class Embed extends Component { charCount={asset.settings.charCountEnable && asset.settings.charCount} /> : null } -
    :

    {asset.settings.closedMessage}

    @@ -170,6 +169,7 @@ class Embed extends Component { refetch={refetch} offset={signInOffset}/>} {loggedIn && user && } + {loggedIn && } { highlightedComment && { - this.initialState = false; - loadMoreComments(assetId, comments, loadMore, parentId); - }}> - {topLevel ? lang.t('viewMoreComments') : this.replyCountFormat(replyCount)} - + ?
    + +
    : null; } } diff --git a/client/coral-embed-stream/style/default.css b/client/coral-embed-stream/style/default.css index 629efd29f..4c427543e 100644 --- a/client/coral-embed-stream/style/default.css +++ b/client/coral-embed-stream/style/default.css @@ -212,6 +212,7 @@ hr { .coral-plugin-commentcontent-text { margin-bottom: 7px; + font-size: 16px; } .coral-plugin-author-name-text { @@ -417,8 +418,11 @@ button.comment__action-button[disabled], /* Load More */ -button.coral-load-more { - width: 100%; +.coral-load-more { + text-align: center; +} + +.coral-load-more button { text-align: center; color: #FFF; background-color: #2376D8; @@ -427,9 +431,10 @@ button.coral-load-more { border-radius: 2px; line-height: 1em; text-transform: capitalize; + display: inline-block; } -button.coral-load-more:hover { +.coral-load-more:hover button { background-color: #4399FF; } diff --git a/client/coral-embed/src/index.js b/client/coral-embed/src/index.js index 21b159e8c..8ebd403b8 100644 --- a/client/coral-embed/src/index.js +++ b/client/coral-embed/src/index.js @@ -167,7 +167,16 @@ Talk.render = function (el, opts) { el.id = `_${Math.random()}`; } - let asset_url = opts.asset_url || window.location.href.split('#')[0]; + let asset_url = opts.asset_url; + if (!asset_url) { + try { + asset_url = document.querySelector('link[rel="canonical"]').href; + } catch (e) { + console.warn('This page does not include a canonical link tag. Talk has inferred this asset_url from the window object. Query params have been stripped, which may cause a single thread to be present across multiple pages.'); + asset_url = window.location.origin + window.location.pathname; + } + } + let comment = window.location.hash.slice(1); let query = { diff --git a/client/coral-framework/actions/asset.js b/client/coral-framework/actions/asset.js index 02e72ea98..609525986 100644 --- a/client/coral-framework/actions/asset.js +++ b/client/coral-framework/actions/asset.js @@ -2,7 +2,7 @@ import * as actions from '../constants/asset'; import coralApi from '../helpers/response'; import {addNotification} from '../actions/notification'; -import I18n from 'coral-framework/modules/i18n/i18n'; +import I18n from '../../coral-framework/modules/i18n/i18n'; import translations from './../translations'; const lang = new I18n(translations); diff --git a/client/coral-framework/actions/auth.js b/client/coral-framework/actions/auth.js index 9dedaa2f2..01174cf05 100644 --- a/client/coral-framework/actions/auth.js +++ b/client/coral-framework/actions/auth.js @@ -1,8 +1,9 @@ -import I18n from 'coral-framework/modules/i18n/i18n'; +import I18n from '../../coral-framework/modules/i18n/i18n'; import translations from './../translations'; const lang = new I18n(translations); import * as actions from '../constants/auth'; import coralApi, {base} from '../helpers/response'; +import {pym} from 'coral-framework'; // Dialog Actions export const showSignInDialog = (offset = 0) => ({type: actions.SHOW_SIGNIN_DIALOG, offset}); @@ -135,7 +136,8 @@ const forgotPassowordFailure = () => ({type: actions.FETCH_FORGOT_PASSWORD_FAILU export const fetchForgotPassword = email => (dispatch) => { dispatch(forgotPassowordRequest(email)); - coralApi('/account/password/reset', {method: 'POST', body: {email}}) + const redirectUri = pym.parentUrl || location.href; + coralApi('/account/password/reset', {method: 'POST', body: {email, loc: redirectUri}}) .then(() => dispatch(forgotPassowordSuccess())) .catch(error => dispatch(forgotPassowordFailure(error))); }; diff --git a/client/coral-framework/actions/notification.js b/client/coral-framework/actions/notification.js index f2cc053ec..cb1aee5dd 100644 --- a/client/coral-framework/actions/notification.js +++ b/client/coral-framework/actions/notification.js @@ -1,4 +1,4 @@ -import {pym} from 'coral-framework'; +import {pym} from '../../coral-framework'; export const addNotification = (notifType, text) => { pym.sendMessage('coral-alert', `${notifType}|${text}`); diff --git a/client/coral-framework/translations.json b/client/coral-framework/translations.json index b327a7097..c6070e61a 100644 --- a/client/coral-framework/translations.json +++ b/client/coral-framework/translations.json @@ -1,5 +1,6 @@ { "en": { + "MY_COMMENTS": "My Comments", "profile": "Profile", "successUpdateSettings": "The changes you have made have been applied to the comment stream on this article", "successNameUpdate": "Your username has been updated", @@ -15,7 +16,7 @@ "viewReply": "view reply", "viewAllRepliesInitial": "view all {0} replies", "viewAllReplies": "view {0} replies", - "newCount": "View {0} more {1}", + "newCount": "View {0} new {1}", "comment": "comment", "comments": "comments", "error": { @@ -40,13 +41,14 @@ } }, "es": { + "MY_COMMENTS": "Mis Comentarios", "profile": "Perfil", "successUpdateSettings": "La configuración de este articulo fue actualizada", "successBioUpdate": "Tu bio fue actualizada", "contentNotAvailable": "El contenido no se encuentra disponible", "bannedAccountMsg": "Tu cuenta se encuentra suspendida. Esto significa que no puedes dar Like, Marcar o escribir commentarios.", "editNameMsg": "", - "viewMoreComments": "Var commentarios más", + "viewMoreComments": "Ver commentarios más", "viewReply": "ver respuesta", "viewAllRepliesInitial": "ver todas las {0} respuestas", "viewAllReplies": "ver {0} respuestas", diff --git a/client/coral-plugin-history/Comment.css b/client/coral-plugin-history/Comment.css index f54b0ad29..2c0dee094 100644 --- a/client/coral-plugin-history/Comment.css +++ b/client/coral-plugin-history/Comment.css @@ -1,16 +1,74 @@ +@custom-media --big-viewport (min-width: 780px); + .myComment { border-bottom: 1px solid lightgrey; + display: flex; + align-items: baseline; + justify-content: space-between; } .myComment:last-child { - border-bottom: none; + border-bottom: solid 1px #EBEBEB; } .assetURL { font-size: 16px; color: black; + text-decoration: none; + font-weight: bold; } .commentBody { } + +.sidebar { + ul { + min-width: 136px; + } + + li { + margin-bottom: 10px; + + &:nth-child(1) { + color: #5394D7; + } + + &:nth-child(2) { + color: #909090; + } + + + i { + margin-right: 5px; + font-size: 15px; + vertical-align: bottom; + } + + a:hover { + cursor: pointer; + } + } +} + +@custom-media --mobile-viewport (max-width: 480px); + +@media (--mobile-viewport) { + .myComment { + flex-direction: column; + } + + .sidebar ul { + display: flex; + li { + margin-right: 20px; + } + } +} + +.pubdate { + display: inline-block; + font-size: inherit; + margin: inherit; + color: inherit; +} diff --git a/client/coral-plugin-history/Comment.js b/client/coral-plugin-history/Comment.js index 00dcc40c7..707939536 100644 --- a/client/coral-plugin-history/Comment.js +++ b/client/coral-plugin-history/Comment.js @@ -1,13 +1,42 @@ -import React, {PropTypes} from 'react'; +import React, { PropTypes } from 'react'; +import { Icon } from '../coral-ui'; import styles from './Comment.css'; +import PubDate from '../coral-plugin-pubdate/PubDate'; +import Content from '../coral-plugin-commentcontent/CommentContent'; const Comment = props => { return ( ); }; diff --git a/client/coral-ui/components/TabBar.css b/client/coral-ui/components/TabBar.css index 33a4c6d8b..b5d44d570 100644 --- a/client/coral-ui/components/TabBar.css +++ b/client/coral-ui/components/TabBar.css @@ -19,7 +19,7 @@ } .base li:hover { - background: #f3f3f3; + background: #d5d5d5; cursor: pointer; } diff --git a/routes/admin/index.js b/routes/admin/index.js index d250ea32a..1a9769591 100644 --- a/routes/admin/index.js +++ b/routes/admin/index.js @@ -12,7 +12,7 @@ router.get('/password-reset', (req, res) => { // TODO: store the redirect uri in the token or something fancy. // admins and regular users should probably be redirected to different places. - res.render('admin/password-reset', {redirectUri: process.env.TALK_ROOT_URL}); + res.render('admin/password-reset'); }); router.get('*', (req, res) => { diff --git a/routes/api/account/index.js b/routes/api/account/index.js index 44b4b3953..e1c73d638 100644 --- a/routes/api/account/index.js +++ b/routes/api/account/index.js @@ -41,14 +41,14 @@ router.post('/email/verify', (req, res, next) => { * if it does, create a JWT and send an email */ router.post('/password/reset', (req, res, next) => { - const {email} = req.body; + const {email, loc} = req.body; if (!email) { return next('you must submit an email when requesting a password.'); } UsersService - .createPasswordResetToken(email) + .createPasswordResetToken(email, loc) .then((token) => { // Check to see if the token isn't defined. @@ -101,11 +101,11 @@ router.put('/password/reset', (req, res, next) => { UsersService .verifyPasswordResetToken(token) - .then((user) => { - return UsersService.changePassword(user.id, password); + .then(([user, loc]) => { + return Promise.all([UsersService.changePassword(user.id, password), loc]); }) - .then(() => { - res.status(204).end(); + .then(([ , loc]) => { + res.json({redirect: loc}); }) .catch(() => { next(authorization.ErrNotAuthorized); diff --git a/services/users.js b/services/users.js index 6c309977f..1332ff7f0 100644 --- a/services/users.js +++ b/services/users.js @@ -1,4 +1,5 @@ const bcrypt = require('bcrypt'); +const url = require('url'); const jwt = require('jsonwebtoken'); const Wordlist = require('./wordlist'); @@ -16,6 +17,7 @@ const USER_ROLES = require('../models/user').USER_ROLES; const RECAPTCHA_WINDOW_SECONDS = 60 * 10; // 10 minutes. const RECAPTCHA_INCORRECT_TRIGGER = 5; // after 3 incorrect attempts, recaptcha will be required. +const SettingsService = require('./settings'); const ActionsService = require('./actions'); const MailerService = require('./mailer'); @@ -520,15 +522,18 @@ module.exports = class UsersService { * Creates a JWT from a user email. Only works for local accounts. * @param {String} email of the local user */ - static createPasswordResetToken(email) { + static createPasswordResetToken(email, loc) { if (!email || typeof email !== 'string') { return Promise.reject('email is required when creating a JWT for resetting passord'); } email = email.toLowerCase(); - return UserModel.findOne({profiles: {$elemMatch: {id: email}}}) - .then((user) => { + return Promise.all([ + UserModel.findOne({profiles: {$elemMatch: {id: email}}}), + SettingsService.retrieve() + ]) + .then(([user, settings]) => { if (!user) { // Since we don't want to reveal that the email does/doesn't exist @@ -537,9 +542,21 @@ module.exports = class UsersService { return; } + let redirectDomain; + try { + redirectDomain = url.parse(loc).hostname; + } catch (e) { + return Promise.reject('redirect location is invalid'); + } + + if (settings.domains.whitelist.indexOf(redirectDomain) === -1) { + return Promise.reject('redirect location is not on the list of acceptable domains'); + } + const payload = { jti: uuid.v4(), email, + loc, userId: user.id, version: user.__v }; @@ -584,7 +601,9 @@ module.exports = class UsersService { }) // TODO: add search by __v as well - .then((decoded) => UsersService.findById(decoded.userId)); + .then((decoded) => { + return Promise.all([UsersService.findById(decoded.userId), decoded.loc]); + }); } /** diff --git a/test/client/coral-plugin-history/Comment.spec.js b/test/client/coral-plugin-history/Comment.spec.js deleted file mode 100644 index 6d69d54cd..000000000 --- a/test/client/coral-plugin-history/Comment.spec.js +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react'; -import {shallow, mount} from 'enzyme'; -import {expect} from 'chai'; -import Comment from '../../../client/coral-plugin-history/Comment'; - -describe('coral-plugin-history/Comment', () => { - let render; - const comment = {body: 'this is a comment', id: '123'}; - const asset = {url: 'https://google.com'}; - - beforeEach(() => { - render = shallow({}}/>); - }); - - it('should render the provided comment body', () => { - const wrapper = mount({}}/>); - expect(wrapper.find('.myCommentBody')).to.have.length(1); - expect(wrapper.find('.myCommentBody').text()).to.equal('this is a comment'); - }); - - it('should render the asset url as a link', () => { - const wrapper = mount({}}/>); - expect(wrapper.find('.myCommentAnchor')).to.have.length(1); - expect(wrapper.find('.myCommentAnchor').text()).to.equal('https://google.com'); - }); - - it('should render the comment with styles', () => { - expect(render.props().style).to.be.defined; - }); -}); diff --git a/test/client/coral-plugin-history/CommentHistory.spec.js b/test/client/coral-plugin-history/CommentHistory.spec.js deleted file mode 100644 index 671a50137..000000000 --- a/test/client/coral-plugin-history/CommentHistory.spec.js +++ /dev/null @@ -1,39 +0,0 @@ -import React from 'react'; -import {shallow, mount} from 'enzyme'; -import {expect} from 'chai'; -import CommentHistory from '../../../client/coral-plugin-history/CommentHistory'; - -describe('coral-plugin-history/CommentHistory', () => { - let render; - const comments = [{body: 'a comment or something', 'status_history':[{'type':'premod', 'created_at':'2016-12-09T01:40:53.327Z', 'assigned_by':null}, {'created_at':'2016-12-09T22:52:44.888Z', 'type':'accepted', 'assigned_by':'92256159-1164-4f66-9970-c7f23de7e461'}], 'asset_id':'96fddf96-7c83-4008-80ad-50091997d006', 'created_at':'2016-12-09T01:40:53.360Z', 'author_id':'92256159-1164-4f66-9970-c7f23de7e461', 'status':'accepted', '__v':0, 'updated_at':'2016-12-09T22:52:44.893Z', 'id':'3962c2ea-4ec4-42e4-b9bd-c571ff30f56b'}, {'body':'another comment', 'status_history':[{'type':'premod', 'created_at':'2016-12-09T22:53:43.148Z', 'assigned_by':null}], 'asset_id':'96fddf96-7c83-4008-80ad-50091997d006', 'created_at':'2016-12-09T22:53:43.158Z', 'author_id':'92256159-1164-4f66-9970-c7f23de7e461', 'status':'premod', '__v':0, 'updated_at':'2016-12-09T22:53:43.158Z', 'id':'b51e27af-bcfd-4932-91be-e3f01a4802e6'}, {'body':'can I comment?', 'status_history':[{'type':'premod', 'created_at':'2016-12-13T23:23:47.123Z', 'assigned_by':null}, {'created_at':'2016-12-13T23:23:58.487Z', 'type':'accepted', 'assigned_by':'92256159-1164-4f66-9970-c7f23de7e461'}], 'asset_id':'cef81015-1b53-4d70-b9af-6eca680f22fc', 'created_at':'2016-12-13T23:23:47.131Z', 'author_id':'92256159-1164-4f66-9970-c7f23de7e461', 'status':'accepted', '__v':0, 'updated_at':'2016-12-13T23:23:58.493Z', 'id':'dc9d7be1-b911-4dc3-8e1e-400e8b8d110e'}, {'body':'pre-mod comment', 'status_history':[{'type':'premod', 'created_at':'2016-12-08T21:34:56.994Z', 'assigned_by':null}, {'created_at':'2016-12-08T21:38:04.961Z', 'type':'rejected', 'assigned_by':'92256159-1164-4f66-9970-c7f23de7e461'}], 'asset_id':'96fddf96-7c83-4008-80ad-50091997d006', 'created_at':'2016-12-08T21:34:56.997Z', 'author_id':'92256159-1164-4f66-9970-c7f23de7e461', 'status':'rejected', '__v':0, 'updated_at':'2016-12-08T21:38:04.965Z', 'id':'6f02af16-a8f8-4ead-80ea-0d48824eb74d'}, {'body':'a flagged commetn', 'status_history':[{'type':'premod', 'created_at':'2016-12-08T21:38:26.342Z', 'assigned_by':null}, {'created_at':'2016-12-09T23:47:27.009Z', 'type':'accepted', 'assigned_by':'92256159-1164-4f66-9970-c7f23de7e461'}], 'asset_id':'96fddf96-7c83-4008-80ad-50091997d006', 'created_at':'2016-12-08T21:38:26.344Z', 'author_id':'92256159-1164-4f66-9970-c7f23de7e461', 'status':'accepted', '__v':0, 'updated_at':'2016-12-09T23:47:27.018Z', 'id':'784c5f91-36b9-4bda-b4ca-a114cef2c9f0'}, {'body':'a post mod comment', 'status_history':[{'type':'premod', 'created_at':'2016-12-08T22:19:05.870Z', 'assigned_by':null}, {'created_at':'2016-12-09T23:26:41.427Z', 'type':'accepted', 'assigned_by':'92256159-1164-4f66-9970-c7f23de7e461'}], 'asset_id':'96fddf96-7c83-4008-80ad-50091997d006', 'created_at':'2016-12-08T22:19:05.874Z', 'author_id':'92256159-1164-4f66-9970-c7f23de7e461', 'status':'accepted', '__v':0, 'updated_at':'2016-12-09T23:26:41.450Z', 'id':'e8b86039-f850-4e53-bd9d-f8c9186a9637'}, {'body':'an actual post-mod comment here', 'status_history':[], 'asset_id':'96fddf96-7c83-4008-80ad-50091997d006', 'created_at':'2016-12-08T22:20:11.147Z', 'author_id':'92256159-1164-4f66-9970-c7f23de7e461', 'status':null, '__v':0, 'updated_at':'2016-12-08T22:20:11.147Z', 'id':'cff1a318-50c6-431e-9a63-de7a7b7136bf'}]; - const asset = { - 'settings': null, - 'created_at':'2016-12-06T21:36:09.302Z', - 'url':'localhost:3000/', - 'scraped':null, - 'status':'open', - 'updated_at':'2016-12-08T02:11:15.943Z', - '_id':'58472f499e775a38f23d5da0', - 'type':'article', - 'closedMessage':null, - 'id':'7302e637-f884-47c0-9723-02cc10a18617', - 'closedAt':null - }; - - comments.forEach((comment) => { - comment.asset = asset; - }); - - beforeEach(() => { - render = shallow({}}/>); - }); - - it('should render Comments as children when given comments and assets', () => { - const wrapper = mount({}}/>); - expect(wrapper.find('.commentHistory__list').children()).to.have.length(7); - }); - - it('should render with styles', () => { - expect(render.props().style).to.be.defined; - }); -}); diff --git a/views/admin/password-reset.ejs b/views/admin/password-reset.ejs index 06b9d2a86..4b25d1279 100644 --- a/views/admin/password-reset.ejs +++ b/views/admin/password-reset.ejs @@ -126,7 +126,7 @@ }, data: JSON.stringify({password: password, token: location.hash.replace('#', '')}) }).then(function (success) { - location.href = '<%= redirectUri %>'; + location.href = success.redirect; }).catch(function (error) { showError(error.responseText); }); diff --git a/views/article.ejs b/views/article.ejs index 3869262ff..5f90cdf4d 100644 --- a/views/article.ejs +++ b/views/article.ejs @@ -27,7 +27,7 @@ diff --git a/yarn.lock b/yarn.lock index 25171f74d..ef0b4fa82 100644 --- a/yarn.lock +++ b/yarn.lock @@ -49,7 +49,7 @@ "@types/express-serve-static-core" "*" "@types/mime" "*" -abab@^1.0.0: +abab@^1.0.0, abab@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d" @@ -76,7 +76,7 @@ acorn-globals@^1.0.4: dependencies: acorn "^2.1.0" -acorn-globals@^3.0.0: +acorn-globals@^3.0.0, acorn-globals@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf" dependencies: @@ -2022,11 +2022,11 @@ csso@~2.3.1: clap "^1.0.9" source-map "^0.5.3" -cssom@0.3.x, "cssom@>= 0.3.0 < 0.4.0": +cssom@0.3.x, "cssom@>= 0.3.0 < 0.4.0", "cssom@>= 0.3.2 < 0.4.0": version "0.3.2" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.2.tgz#b8036170c79f07a90ff2f16e22284027a243848b" -"cssstyle@>= 0.2.29 < 0.3.0", "cssstyle@>= 0.2.36 < 0.3.0": +"cssstyle@>= 0.2.29 < 0.3.0", "cssstyle@>= 0.2.37 < 0.3.0": version "0.2.37" resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-0.2.37.tgz#541097234cb2513c83ceed3acddc27ff27987d54" dependencies: @@ -3635,7 +3635,7 @@ iconv-lite@0.4.13: version "0.4.13" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" -iconv-lite@0.4.15, iconv-lite@^0.4.13, iconv-lite@^0.4.5, iconv-lite@~0.4.13: +iconv-lite@0.4.15, iconv-lite@^0.4.5, iconv-lite@~0.4.13: version "0.4.15" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" @@ -4188,6 +4188,10 @@ jsbn@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.0.tgz#650987da0dd74f4ebf5a11377a2aa2d273e97dfd" +jsdom-global@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/jsdom-global/-/jsdom-global-2.1.1.tgz#47d46fe77f6167baf5d34431d3bb59fc41b0915a" + jsdom@^7.0.2: version "7.2.2" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-7.2.2.tgz#40b402770c2bda23469096bee91ab675e3b1fc6e" @@ -4208,30 +4212,29 @@ jsdom@^7.0.2: whatwg-url-compat "~0.6.5" xml-name-validator ">= 2.0.1 < 3.0.0" -jsdom@^9.8.3: - version "9.9.1" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.9.1.tgz#84f3972ad394ab963233af8725211bce4d01bfd5" +jsdom@^9.12.0: + version "9.12.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.12.0.tgz#e8c546fffcb06c00d4833ca84410fed7f8a097d4" dependencies: - abab "^1.0.0" - acorn "^2.4.0" - acorn-globals "^1.0.4" + abab "^1.0.3" + acorn "^4.0.4" + acorn-globals "^3.1.0" array-equal "^1.0.0" content-type-parser "^1.0.1" - cssom ">= 0.3.0 < 0.4.0" - cssstyle ">= 0.2.36 < 0.3.0" + cssom ">= 0.3.2 < 0.4.0" + cssstyle ">= 0.2.37 < 0.3.0" escodegen "^1.6.1" html-encoding-sniffer "^1.0.1" - iconv-lite "^0.4.13" nwmatcher ">= 1.3.9 < 2.0.0" parse5 "^1.5.1" - request "^2.55.0" - sax "^1.1.4" - symbol-tree ">= 3.1.0 < 4.0.0" - tough-cookie "^2.3.1" - webidl-conversions "^3.0.1" + request "^2.79.0" + sax "^1.2.1" + symbol-tree "^3.2.1" + tough-cookie "^2.3.2" + webidl-conversions "^4.0.0" whatwg-encoding "^1.0.1" - whatwg-url "^4.1.0" - xml-name-validator ">= 2.0.1 < 3.0.0" + whatwg-url "^4.3.0" + xml-name-validator "^2.0.1" jsesc@^1.3.0: version "1.3.0" @@ -6919,7 +6922,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.1.4, sax@^1.2.1, sax@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" @@ -7401,7 +7404,7 @@ symbol-observable@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" -"symbol-tree@>= 3.1.0 < 4.0.0": +"symbol-tree@>= 3.1.0 < 4.0.0", symbol-tree@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.1.tgz#8549dd1d01fa9f893c18cc9ab0b106b4d9b168cb" @@ -7565,7 +7568,7 @@ touch@1.0.0: dependencies: nopt "~1.0.10" -tough-cookie@^2.0.0, tough-cookie@^2.2.0, tough-cookie@^2.3.1, tough-cookie@~2.3.0: +tough-cookie@^2.0.0, tough-cookie@^2.2.0, tough-cookie@^2.3.2, tough-cookie@~2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" dependencies: @@ -7801,10 +7804,14 @@ webidl-conversions@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-2.0.1.tgz#3bf8258f7d318c7443c36f2e169402a1a6703506" -webidl-conversions@^3.0.0, webidl-conversions@^3.0.1: +webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" +webidl-conversions@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.1.tgz#8015a17ab83e7e1b311638486ace81da6ce206a0" + webpack-sources@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.1.4.tgz#ccc2c817e08e5fa393239412690bb481821393cd" @@ -7853,9 +7860,9 @@ whatwg-url-compat@~0.6.5: dependencies: tr46 "~0.0.1" -whatwg-url@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.3.0.tgz#92aaee21f4f2a642074357d70ef8500a7cbb171a" +whatwg-url@^4.3.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.6.0.tgz#ef98da442273be04cf9632e176f257d2395a1ae4" dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0" @@ -7956,7 +7963,7 @@ xdg-basedir@^2.0.0: dependencies: os-homedir "^1.0.0" -"xml-name-validator@>= 2.0.1 < 3.0.0": +"xml-name-validator@>= 2.0.1 < 3.0.0", xml-name-validator@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635"