From 22b3f5890ee75ab2d989af5c8192852621b6648c Mon Sep 17 00:00:00 2001 From: Bouncey Date: Thu, 30 Aug 2018 15:36:26 +0100 Subject: [PATCH] fix(email-change): Complete the update and confirm email flow --- server/boot/authentication.js | 2 +- src/pages/update-email.css | 3 + src/pages/update-email.js | 141 +++++++++++++++++++++++++++++++++ src/redux/update-email-saga.js | 23 ++++++ src/utils/ajax.js | 7 +- static/_redirects | 8 +- 6 files changed, 172 insertions(+), 12 deletions(-) create mode 100644 src/pages/update-email.css create mode 100644 src/pages/update-email.js create mode 100644 src/redux/update-email-saga.js diff --git a/server/boot/authentication.js b/server/boot/authentication.js index 6363fe48e0..d72b4652d7 100644 --- a/server/boot/authentication.js +++ b/server/boot/authentication.js @@ -152,7 +152,7 @@ module.exports = function enableAuthentication(app) { 'success', 'Success! You have signed in to your account. Happy Coding!' ); - return res.redirect(homeLocation); + return res.redirectWithFlash(`${homeLocation}/welcome`); }) .subscribe(() => {}, next) ); diff --git a/src/pages/update-email.css b/src/pages/update-email.css new file mode 100644 index 0000000000..b41b65704c --- /dev/null +++ b/src/pages/update-email.css @@ -0,0 +1,3 @@ +.control-label.email-label { + text-align: left; +} \ No newline at end of file diff --git a/src/pages/update-email.js b/src/pages/update-email.js new file mode 100644 index 0000000000..12b5b0c077 --- /dev/null +++ b/src/pages/update-email.js @@ -0,0 +1,141 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { Link } from 'gatsby'; +import { bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { + Form, + FormGroup, + FormControl, + ControlLabel, + Grid, + Row, + Col, + Button +} from 'react-bootstrap'; + +import Layout from '../components/Layout'; +import { Spacer } from '../components/helpers'; +import './update-email.css'; +import { userSelector, updateMyEmail } from '../redux'; +import { isString } from 'lodash'; +import isEmail from 'validator/lib/isEmail'; + +const propTypes = { + isNewEmail: PropTypes.bool, + updateMyEmail: PropTypes.func.isRequired +}; + +const mapStateToProps = createSelector( + userSelector, + ({ email, emailVerified }) => ({ + isNewEmail: !email || emailVerified + }) +); + +const mapDispatchToProps = dispatch => + bindActionCreators({ updateMyEmail }, dispatch); + +const maybeEmailRE = /[\w\.\+]*?@\w*?\.\w+?/; + +class UpdateEmail extends Component { + constructor(props) { + super(props); + + this.state = { + emailValue: '' + }; + + // this.createSubmitHandler = this.createSubmitHandler.bind(this); + this.onChange = this.onChange.bind(this); + } + + createSubmitHandler(fn) { + return e => { + e.preventDefault(); + return fn(this.state.emailValue); + }; + } + + onChange(e) { + const change = e.target.value; + if (!isString(change)) { + return null; + } + return this.setState({ + emailValue: change + }); + } + + getEmailValidationState() { + const { emailValue } = this.state; + if (maybeEmailRE.test(emailValue)) { + return isEmail(emailValue) ? 'success' : 'error'; + } + return null; + } + + render() { + const { isNewEmail, updateMyEmail } = this.props; + return ( + + +

Update your email address here:

+ + + + +
+ + + Email + + + + + + +
+

+ Sign out +

+
+ +
+
+
+ ); + } +} + +UpdateEmail.displayName = 'Update-Email'; +UpdateEmail.propTypes = propTypes; + +export default connect( + mapStateToProps, + mapDispatchToProps +)(UpdateEmail); diff --git a/src/redux/update-email-saga.js b/src/redux/update-email-saga.js new file mode 100644 index 0000000000..e59ef7988d --- /dev/null +++ b/src/redux/update-email-saga.js @@ -0,0 +1,23 @@ +import { call, put, takeEvery } from 'redux-saga/effects'; + +import { updateMyEmailComplete, updateMyEmailError } from './'; +import { createFlashMessage } from '../components/Flash/redux'; + +import { putUserUpdateEmail } from '../utils/ajax'; + +function* updateMyEmailSaga({ payload: newEmail }) { + try { + const { data: response } = yield call(putUserUpdateEmail, newEmail); + + yield put(updateMyEmailComplete()); + yield put(createFlashMessage(response)); + } catch (e) { + yield put(updateMyEmailError(e)); + } +} + +export function createUpdateMyEmailSaga(types) { + return [ + takeEvery(types.updateMyEmail, updateMyEmailSaga) + ]; +} diff --git a/src/utils/ajax.js b/src/utils/ajax.js index 554b124a7c..587888de60 100644 --- a/src/utils/ajax.js +++ b/src/utils/ajax.js @@ -14,13 +14,8 @@ function put(path, body) { return axios.put(`${base}${path}`, body); } -function sniff(things) { - console.log(things); - return things; -} - export function getSessionUser() { - return get('/user/get-session-user').then(sniff); + return get('/user/get-session-user'); } export function putUserAcceptsTerms(quincyEmails) { diff --git a/static/_redirects b/static/_redirects index 0508902bf9..9c76ea9fb0 100644 --- a/static/_redirects +++ b/static/_redirects @@ -1,9 +1,7 @@ - -# signin redirects +# auth redirects /signup /signin 301 /email-signin /signin 301 /login /signin 301 /deprecated-signin /signin 301 - -# signout redirects -/logout /signout 301 \ No newline at end of file +/logout /signout 301 +/passwordless-change /confirm-email 301 \ No newline at end of file