remove confirm and replace with verify

This commit is contained in:
Riley Davis
2017-02-02 14:59:45 -07:00
parent 03c240054a
commit a0cf467f1b
12 changed files with 200 additions and 180 deletions
+1 -1
View File
@@ -130,7 +130,7 @@ class Embed extends Component {
</div>
: <p>{asset.settings.closedMessage}</p>
}
{!loggedIn && <SignInContainer offset={signInOffset}/>}
{!loggedIn && <SignInContainer requireEmailConfirmation={asset.settings.requireEmailConfirmation} offset={signInOffset}/>}
<Stream
refetch={refetch}
addNotification={this.props.addNotification}
+9 -11
View File
@@ -21,7 +21,6 @@ export const cleanState = () => ({type: actions.CLEAN_STATE});
const signInRequest = () => ({type: actions.FETCH_SIGNIN_REQUEST});
const signInSuccess = (user, isAdmin) => ({type: actions.FETCH_SIGNIN_SUCCESS, user, isAdmin});
const signInFailure = error => ({type: actions.FETCH_SIGNIN_FAILURE, error});
const emailConfirmError = () => ({type: actions.EMAIL_CONFIRM_ERROR});
export const fetchSignIn = (formData) => (dispatch) => {
dispatch(signInRequest());
@@ -36,7 +35,6 @@ export const fetchSignIn = (formData) => (dispatch) => {
// the user might not have a valid email. prompt the user user re-request the confirmation email
dispatch(signInFailure(lang.t('error.emailNotVerified', error.metadata)));
dispatch(emailConfirmError());
} else {
// invalid credentials
@@ -150,20 +148,20 @@ export const checkLogin = () => dispatch => {
});
};
const confirmEmailRequest = () => ({type: actions.CONFIRM_EMAIL_REQUEST});
const confirmEmailSuccess = () => ({type: actions.CONFIRM_EMAIL_SUCCESS});
const confirmEmailFailure = () => ({type: actions.CONFIRM_EMAIL_FAILURE});
const verifyEmailRequest = () => ({type: actions.VERIFY_EMAIL_REQUEST});
const verifyEmailSuccess = () => ({type: actions.VERIFY_EMAIL_SUCCESS});
const verifyEmailFailure = () => ({type: actions.VERIFY_EMAIL_FAILURE});
export const requestConfirmEmail = email => dispatch => {
dispatch(confirmEmailRequest());
return coralApi('/users/resend-confirm', {method: 'POST', body: {email}})
dispatch(verifyEmailRequest());
return coralApi('/users/resend-verify', {method: 'POST', body: {email}})
.then(() => {
dispatch(confirmEmailSuccess());
dispatch(verifyEmailSuccess());
})
.catch(err => {
console.log('failed to send email confirmation', err);
console.log('failed to send email verification', err);
// email might have already been confirmed
dispatch(confirmEmailFailure());
// email might have already been verifyed
dispatch(verifyEmailFailure());
});
};
+3 -4
View File
@@ -33,7 +33,6 @@ export const CHECK_LOGIN_FAILURE = 'CHECK_LOGIN_FAILURE';
export const CHECK_CSRF_TOKEN = 'CHECK_CSRF_TOKEN';
export const EMAIL_CONFIRM_ERROR = 'EMAIL_CONFIRM_ERROR';
export const CONFIRM_EMAIL_REQUEST = 'CONFIRM_EMAIL_REQUEST';
export const CONFIRM_EMAIL_SUCCESS = 'CONFIRM_EMAIL_SUCCESS';
export const CONFIRM_EMAIL_FAILURE = 'CONFIRM_EMAIL_FAILURE';
export const VERIFY_EMAIL_REQUEST = 'VERIFY_EMAIL_REQUEST';
export const VERIFY_EMAIL_SUCCESS = 'VERIFY_EMAIL_SUCCESS';
export const VERIFY_EMAIL_FAILURE = 'VERIFY_EMAIL_FAILURE';
+14 -14
View File
@@ -11,9 +11,9 @@ const initialState = Map({
error: '',
passwordRequestSuccess: null,
passwordRequestFailure: null,
emailConfirmationFailure: false,
emailConfirmationLoading: false,
emailConfirmationSuccess: false,
emailVerificationFailure: false,
emailVerificationLoading: false,
emailVerificationSuccess: false,
successSignUp: false
});
@@ -36,9 +36,9 @@ export default function auth (state = initialState, action) {
error: '',
passwordRequestFailure: null,
passwordRequestSuccess: null,
emailConfirmationFailure: false,
emailConfirmationSuccess: false,
emailConfirmationLoading: false,
emailVerificationFailure: false,
emailVerificationSuccess: false,
emailVerificationLoading: false,
successSignUp: false
}));
case actions.CHANGE_VIEW :
@@ -107,16 +107,16 @@ export default function auth (state = initialState, action) {
return state
.set('passwordRequestFailure', 'There was an error sending your password reset email. Please try again soon!')
.set('passwordRequestSuccess', null);
case actions.EMAIL_CONFIRM_ERROR:
case actions.VERIFY_EMAIL_FAILURE:
return state
.set('emailConfirmationFailure', true)
.set('emailConfirmationLoading', false);
case actions.CONFIRM_EMAIL_REQUEST:
return state.set('emailConfirmationLoading', true);
case actions.CONFIRM_EMAIL_SUCCESS:
.set('emailVerificationFailure', true)
.set('emailVerificationLoading', false);
case actions.VERIFY_EMAIL_REQUEST:
return state.set('emailVerificationLoading', true);
case actions.VERIFY_EMAIL_SUCCESS:
return state
.set('emailConfirmationSuccess', true)
.set('emailConfirmationLoading', false);
.set('emailVerificationSuccess', true)
.set('emailVerificationLoading', false);
default :
return state;
}
@@ -17,12 +17,7 @@ const SignDialog = ({open, view, handleClose, offset, ...props}) => (
}}>
<span className={styles.close} onClick={handleClose}>×</span>
{view === 'SIGNIN' && <SignInContent {...props} />}
{
view === 'SIGNUP' && <SignUpContent
emailConfirmationLoading={props.emailConfirmationLoading}
emailConfirmationSuccess={props.emailConfirmationSuccess}
{...props} />
}
{view === 'SIGNUP' && <SignUpContent {...props} />}
{view === 'FORGOT' && <ForgotContent {...props} />}
</Dialog>
);
@@ -10,9 +10,9 @@ const SignInContent = ({
handleChange,
handleChangeEmail,
emailToBeResent,
handleResendConfirmation,
emailConfirmationLoading,
emailConfirmationSuccess,
handleResendVerification,
emailVerificationLoading,
emailVerificationSuccess,
formData,
...props
}) => {
@@ -21,24 +21,14 @@ const SignInContent = ({
<div>
<div className={styles.header}>
<h1>
{props.auth.emailConfirmationFailure ? lang.t('signIn.emailConfirmCTA') : lang.t('signIn.signIn')}
</h1>
</div>
<div className={styles.socialConnections}>
<Button cStyle="facebook" onClick={props.fetchSignInFacebook} full>
{lang.t('signIn.facebookSignIn')}
</Button>
</div>
<div className={styles.separator}>
<h1>
{lang.t('signIn.or')}
{props.auth.emailVerificationFailure ? lang.t('signIn.emailVerifyCTA') : lang.t('signIn.signIn')}
</h1>
</div>
{ props.auth.error && <Alert>{props.auth.error}</Alert> }
{
props.auth.emailConfirmationFailure
? <form onSubmit={handleResendConfirmation}>
<p>{lang.t('signIn.requestNewConfirmEmail')}</p>
props.auth.emailVerificationFailure
? <form onSubmit={handleResendVerification}>
<p>{lang.t('signIn.requestNewVerifyEmail')}</p>
<FormField
id="confirm-email"
type="email"
@@ -46,35 +36,47 @@ const SignInContent = ({
value={emailToBeResent}
onChange={handleChangeEmail} />
<Button id='resendConfirmEmail' type='submit' cStyle='black' full>Send Email</Button>
{emailConfirmationLoading && <Spinner />}
{emailConfirmationSuccess && <Success />}
{emailVerificationLoading && <Spinner />}
{emailVerificationSuccess && <Success />}
</form>
: <form onSubmit={props.handleSignIn}>
<FormField
id="email"
type="email"
label={lang.t('signIn.email')}
value={formData.email}
onChange={handleChange}
/>
<FormField
id="password"
type="password"
label={lang.t('signIn.password')}
value={formData.password}
onChange={handleChange}
/>
<div className={styles.action}>
{
!props.auth.isLoading ?
<Button id='coralLogInButton' type="submit" cStyle="black" className={styles.signInButton} full>
{lang.t('signIn.signIn')}
</Button>
:
<Spinner />
}
: <div>
<div className={styles.socialConnections}>
<Button cStyle="facebook" onClick={props.fetchSignInFacebook} full>
{lang.t('signIn.facebookSignIn')}
</Button>
</div>
</form>
<div className={styles.separator}>
<h1>
{lang.t('signIn.or')}
</h1>
</div>
<form onSubmit={props.handleSignIn}>
<FormField
id="email"
type="email"
label={lang.t('signIn.email')}
value={formData.email}
onChange={handleChange}
/>
<FormField
id="password"
type="password"
label={lang.t('signIn.password')}
value={formData.password}
onChange={handleChange}
/>
<div className={styles.action}>
{
!props.auth.isLoading ?
<Button id='coralLogInButton' type="submit" cStyle="black" className={styles.signInButton} full>
{lang.t('signIn.signIn')}
</Button>
:
<Spinner />
}
</div>
</form>
</div>
}
<div className={styles.footer}>
<span><a onClick={() => props.changeView('FORGOT')}>{lang.t('signIn.forgotYourPass')}</a></span>
@@ -90,9 +92,9 @@ const SignInContent = ({
};
SignInContent.propTypes = {
emailConfirmationLoading: PropTypes.bool.isRequired,
emailConfirmationSuccess: PropTypes.bool.isRequired,
handleResendConfirmation: PropTypes.func.isRequired,
emailVerificationLoading: PropTypes.bool.isRequired,
emailVerificationSuccess: PropTypes.bool.isRequired,
handleResendVerification: PropTypes.func.isRequired,
handleChangeEmail: PropTypes.func.isRequired,
emailToBeResent: PropTypes.string.isRequired
};
@@ -1,4 +1,4 @@
import React from 'react';
import React, {PropTypes} from 'react';
import Alert from './Alert';
import {Button, FormField, Spinner, Success} from 'coral-ui';
import styles from './styles.css';
@@ -6,83 +6,101 @@ import I18n from 'coral-framework/modules/i18n/i18n';
import translations from '../translations';
const lang = new I18n(translations);
const SignUpContent = ({handleChange, formData, ...props}) => (
<div>
<div className={styles.header}>
<h1>
{lang.t('signIn.signUp')}
</h1>
</div>
<div className={styles.socialConnections}>
<Button cStyle="facebook" onClick={props.fetchSignInFacebook} full>
{lang.t('signIn.facebookSignUp')}
</Button>
</div>
<div className={styles.separator}>
<h1>
{lang.t('signIn.or')}
</h1>
</div>
{ props.auth.error && <Alert>{props.auth.error}</Alert> }
<form onSubmit={props.handleSignUp}>
<FormField
id="email"
type="email"
label={lang.t('signIn.email')}
value={formData.email}
showErrors={props.showErrors}
errorMsg={props.errors.email}
onChange={handleChange}
/>
<FormField
id="displayName"
type="text"
label={lang.t('signIn.displayName')}
value={formData.displayName}
showErrors={props.showErrors}
errorMsg={props.errors.displayName}
onChange={handleChange}
/>
<FormField
id="password"
type="password"
label={lang.t('signIn.password')}
value={formData.password}
showErrors={props.showErrors}
errorMsg={props.errors.password}
onChange={handleChange}
minLength="8"
/>
{ props.errors.password && <span className={styles.hint}> Password must be at least 8 characters. </span> }
<FormField
id="confirmPassword"
type="password"
label={lang.t('signIn.confirmPassword')}
value={formData.confirmPassword}
showErrors={props.showErrors}
errorMsg={props.errors.confirmPassword}
onChange={handleChange}
minLength="8"
/>
<div className={styles.action}>
{ !props.auth.isLoading && !props.auth.successSignUp && (
<Button type="submit" cStyle="black" id='coralSignUpButton' className={styles.signInButton} full>
{lang.t('signIn.signUp')}
</Button>
)}
{ props.auth.isLoading && <Spinner /> }
{ !props.auth.isLoading && props.auth.successSignUp && <Success /> }
const SignUpContent = ({handleChange, formData, emailVerificationEnabled, ...props}) => {
const beforeSignup = !props.auth.isLoading && !props.auth.successSignUp;
const successfulSignup = !props.auth.isLoading && props.auth.successSignUp;
return (
<div>
<div className={styles.header}>
<h1>
{lang.t('signIn.signUp')}
</h1>
</div>
<div className={styles.socialConnections}>
<Button cStyle="facebook" onClick={props.fetchSignInFacebook} full>
{lang.t('signIn.facebookSignUp')}
</Button>
</div>
<div className={styles.separator}>
<h1>
{lang.t('signIn.or')}
</h1>
</div>
{ props.auth.error && <Alert>{props.auth.error}</Alert> }
{ beforeSignup &&
<form onSubmit={props.handleSignUp}>
<FormField
id="email"
type="email"
label={lang.t('signIn.email')}
value={formData.email}
showErrors={props.showErrors}
errorMsg={props.errors.email}
onChange={handleChange}
/>
<FormField
id="displayName"
type="text"
label={lang.t('signIn.displayName')}
value={formData.displayName}
showErrors={props.showErrors}
errorMsg={props.errors.displayName}
onChange={handleChange}
/>
<FormField
id="password"
type="password"
label={lang.t('signIn.password')}
value={formData.password}
showErrors={props.showErrors}
errorMsg={props.errors.password}
onChange={handleChange}
minLength="8"
/>
{ props.errors.password && <span className={styles.hint}> Password must be at least 8 characters. </span> }
<FormField
id="confirmPassword"
type="password"
label={lang.t('signIn.confirmPassword')}
value={formData.confirmPassword}
showErrors={props.showErrors}
errorMsg={props.errors.confirmPassword}
onChange={handleChange}
minLength="8"
/>
<div className={styles.action}>
<Button type="submit" cStyle="black" id='coralSignUpButton' className={styles.signInButton} full>
{lang.t('signIn.signUp')}
</Button>
{ props.auth.isLoading && <Spinner /> }
</div>
</form>
}
{
successfulSignup &&
<div>
<Success />
{
emailVerificationEnabled &&
<p>{lang.t('signIn.verifyEmail')}</p>
}
</div>
}
<div className={styles.footer}>
<span>
{lang.t('signIn.alreadyHaveAnAccount')}
<a onClick={() => props.changeView('SIGNIN')}>
{lang.t('signIn.signIn')}
</a>
</span>
</div>
</form>
<div className={styles.footer}>
<span>
{lang.t('signIn.alreadyHaveAnAccount')}
<a onClick={() => props.changeView('SIGNIN')}>
{lang.t('signIn.signIn')}
</a>
</span>
</div>
</div>
);
);
};
SignUpContent.propTypes = {
emailVerificationEnabled: PropTypes.bool.isRequired
};
export default SignUpContent;
@@ -1,4 +1,4 @@
import React, {Component} from 'react';
import React, {Component, PropTypes} from 'react';
import {connect} from 'react-redux';
import SignDialog from '../components/SignDialog';
import Button from 'coral-ui/components/Button';
@@ -41,12 +41,16 @@ class SignInContainer extends Component {
this.state = this.initialState;
this.handleChange = this.handleChange.bind(this);
this.handleChangeEmail = this.handleChangeEmail.bind(this);
this.handleResendConfirmation = this.handleResendConfirmation.bind(this);
this.handleResendVerification = this.handleResendVerification.bind(this);
this.handleSignUp = this.handleSignUp.bind(this);
this.handleSignIn = this.handleSignIn.bind(this);
this.addError = this.addError.bind(this);
}
static propTypes = {
requireEmailConfirmation: PropTypes.bool.isRequired
}
componentWillMount () {
this.props.checkLogin();
}
@@ -79,7 +83,7 @@ class SignInContainer extends Component {
this.setState({emailToBeResent: value});
}
handleResendConfirmation(e) {
handleResendVerification(e) {
e.preventDefault();
this.props.requestConfirmEmail(this.state.emailToBeResent)
.then(() => {
@@ -145,8 +149,9 @@ class SignInContainer extends Component {
}
render() {
const {auth, showSignInDialog, noButton, offset} = this.props;
const {emailConfirmationLoading, emailConfirmationSuccess} = auth;
const {auth, showSignInDialog, noButton, offset, requireEmailConfirmation} = this.props;
const {emailVerificationLoading, emailVerificationSuccess} = auth;
return (
<div>
{!noButton && <Button id='coralSignInButton' onClick={showSignInDialog} full>
@@ -156,8 +161,9 @@ class SignInContainer extends Component {
open={auth.showSignInDialog}
view={auth.view}
offset={offset}
emailConfirmationLoading={emailConfirmationLoading}
emailConfirmationSuccess={emailConfirmationSuccess}
emailVerificationEnabled={requireEmailConfirmation}
emailVerificationLoading={emailVerificationLoading}
emailVerificationSuccess={emailVerificationSuccess}
{...this}
{...this.state}
{...this.props}
+6 -4
View File
@@ -1,8 +1,9 @@
export default {
en: {
'signIn': {
emailConfirmCTA: 'Please verify your email address.',
requestNewConfirmEmail: 'Request another email:',
emailVerifyCTA: 'Please verify your email address.',
requestNewVerifyEmail: 'Request another email:',
verifyEmail: 'Thank you for creating an account! We sent an email to the address you provided to verify your account. You must verify your account before engaging with the community.',
notYou: 'Not you?',
loggedInAs: 'Logged in as',
facebookSignIn: 'Sign in with Facebook',
@@ -30,8 +31,9 @@ export default {
},
es: {
'signIn': {
emailConfirmCTA: 'Por favor verifique su correo electronico.',
requestNewConfirmEmail: 'Enviar otro correo:',
emailVerifyCTA: 'Por favor verifique su correo electronico.',
requestNewVerifyEmail: 'Enviar otro correo:',
verifyEmail: '',
notYou: 'No eres tu?',
loggedInAs: 'Entraste como',
facebookSignIn: 'Entrar con Facebook',
+1 -1
View File
@@ -16,7 +16,7 @@ router.get('/', authorization.needed(), (req, res, next) => {
// POST /email/confirm takes the password confirmation token available as a
// payload parameter and if it verifies, it updates the confirmed_at date on the
// local profile.
router.post('/email/confirm', (req, res, next) => {
router.post('/email/verify', (req, res, next) => {
const {
token
+1 -1
View File
@@ -178,7 +178,7 @@ router.post('/:user_id/actions', authorization.needed(), (req, res, next) => {
});
// trigger an email confirmation re-send by a new user
router.post('/resend-confirm', (req, res, next) => {
router.post('/resend-verify', (req, res, next) => {
const {email} = req.body;
const redirectUri = req.header('Referer');
+7 -7
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<title>Confirm Email</title>
<title>Email Verification</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="https://code.getmdl.io/1.2.1/material.indigo-pink.min.css">
@@ -43,14 +43,14 @@
<div id="root">
<div class="coral-card-wide mdl-card mdl-shadow--2dp">
<div class="mdl-card__title">
<h2 class="mdl-card__title-text">Confirm Email Address</h2>
<h2 class="mdl-card__title-text">Verify Email Address</h2>
</div>
<div class="mdl-card__supporting-text">
Click the button below to confirm your new user account.
Click the button below to verify the email on your new user account.
</div>
<div class="mdl-card__actions mdl-card--border">
<a class="mdl-button mdl-button--colored mdl-js-button mdl-js-ripple-effect" id="confirm-email">
Confirm
<a class="mdl-button mdl-button--colored mdl-js-button mdl-js-ripple-effect" id="verify-email">
Verify
</a>
<div style="display: none" id="p2" class="mdl-progress mdl-js-progress mdl-progress__indeterminate"></div>
</div>
@@ -71,7 +71,7 @@
$('.error-console').removeClass('active');
$.ajax({
url: '/api/v1/account/email/confirm',
url: '/api/v1/account/email/verify',
contentType: 'application/json',
method: 'POST',
headers: {
@@ -85,7 +85,7 @@
});
}
$('#confirm-email').on('click', handleClick);
$('#verify-email').on('click', handleClick);
});
</script>
</body>