diff --git a/client/coral-framework/actions/auth.js b/client/coral-framework/actions/auth.js index b78f32b2d..03ab61c76 100644 --- a/client/coral-framework/actions/auth.js +++ b/client/coral-framework/actions/auth.js @@ -9,7 +9,7 @@ import translations from './../translations'; import I18n from '../../coral-framework/modules/i18n/i18n'; // Dialog Actions -export const showSignInDialog = () => dispatch => { +export const showSignInDialog = () => (dispatch) => { const signInPopUp = window.open( '/embed/stream/login', 'Login', @@ -32,7 +32,7 @@ export const showSignInDialog = () => dispatch => { dispatch({type: actions.SHOW_SIGNIN_DIALOG}); }; -export const hideSignInDialog = () => dispatch => { +export const hideSignInDialog = () => (dispatch) => { dispatch({type: actions.HIDE_SIGNIN_DIALOG}); window.close(); }; @@ -51,7 +51,7 @@ const createUsernameSuccess = () => ({ type: actions.CREATE_USERNAME_SUCCESS }); -const createUsernameFailure = error => ({ +const createUsernameFailure = (error) => ({ type: actions.CREATE_USERNAME_FAILURE, error }); @@ -61,7 +61,7 @@ export const updateUsername = ({username}) => ({ username }); -export const createUsername = (userId, formData) => dispatch => { +export const createUsername = (userId, formData) => (dispatch) => { dispatch(createUsernameRequest()); coralApi('/account/username', {method: 'PUT', body: formData}) .then(() => { @@ -69,26 +69,26 @@ export const createUsername = (userId, formData) => dispatch => { dispatch(hideCreateUsernameDialog()); dispatch(updateUsername(formData)); }) - .catch(error => { + .catch((error) => { dispatch(createUsernameFailure(lang.t(`error.${error.translation_key}`))); }); }; -export const changeView = view => dispatch => { +export const changeView = (view) => (dispatch) => { dispatch({ type: actions.CHANGE_VIEW, view }); switch (view) { - case 'SIGNUP': - window.resizeTo(500, 800); - break; - case 'FORGOT': - window.resizeTo(500, 400); - break; - default: - window.resizeTo(500, 550); + case 'SIGNUP': + window.resizeTo(500, 800); + break; + case 'FORGOT': + window.resizeTo(500, 400); + break; + default: + window.resizeTo(500, 550); } }; @@ -102,7 +102,7 @@ const signInRequest = () => ({ type: actions.FETCH_SIGNIN_REQUEST }); -const signInFailure = error => ({ +const signInFailure = (error) => ({ type: actions.FETCH_SIGNIN_FAILURE, error }); @@ -111,7 +111,7 @@ const signInFailure = error => ({ // AUTH TOKEN //============================================================================== -export const handleAuthToken = token => dispatch => { +export const handleAuthToken = (token) => (dispatch) => { Storage.setItem('exp', jwtDecode(token).exp); Storage.setItem('token', token); dispatch({type: 'HANDLE_AUTH_TOKEN'}); @@ -121,20 +121,22 @@ export const handleAuthToken = token => dispatch => { // SIGN IN //============================================================================== -export const fetchSignIn = formData => dispatch => { +export const fetchSignIn = (formData) => (dispatch) => { dispatch(signInRequest()); return coralApi('/auth/local', {method: 'POST', body: formData}) .then(({token}) => { dispatch(handleAuthToken(token)); dispatch(hideSignInDialog()); }) - .catch(error => { + .catch((error) => { if (error.metadata) { + // 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)) ); } else { + // invalid credentials dispatch(signInFailure(lang.t('error.emailPasswordError'))); } @@ -149,17 +151,17 @@ const signInFacebookRequest = () => ({ type: actions.FETCH_SIGNIN_FACEBOOK_REQUEST }); -const signInFacebookSuccess = user => ({ +const signInFacebookSuccess = (user) => ({ type: actions.FETCH_SIGNIN_FACEBOOK_SUCCESS, user }); -const signInFacebookFailure = error => ({ +const signInFacebookFailure = (error) => ({ type: actions.FETCH_SIGNIN_FACEBOOK_FAILURE, error }); -export const fetchSignInFacebook = () => dispatch => { +export const fetchSignInFacebook = () => (dispatch) => { dispatch(signInFacebookRequest()); window.open( `${base}/auth/facebook`, @@ -176,7 +178,7 @@ const signUpFacebookRequest = () => ({ type: actions.FETCH_SIGNUP_FACEBOOK_REQUEST }); -export const fetchSignUpFacebook = () => dispatch => { +export const fetchSignUpFacebook = () => (dispatch) => { dispatch(signUpFacebookRequest()); window.open( `${base}/auth/facebook`, @@ -185,17 +187,14 @@ export const fetchSignUpFacebook = () => dispatch => { ); }; -export const facebookCallback = (err, data) => dispatch => { - console.log('asd') - debugger +export const facebookCallback = (err, data) => (dispatch) => { if (err) { dispatch(signInFacebookFailure(err)); return; } try { - const user = JSON.parse(data); - console.log(user); - dispatch(signInFacebookSuccess(user)); + dispatch(handleAuthToken(data.token)); + dispatch(signInFacebookSuccess(data.user)); dispatch(hideSignInDialog()); dispatch(showCreateUsernameDialog()); dispatch(hideSignInDialog()); @@ -210,10 +209,10 @@ export const facebookCallback = (err, data) => dispatch => { //============================================================================== const signUpRequest = () => ({type: actions.FETCH_SIGNUP_REQUEST}); -const signUpSuccess = user => ({type: actions.FETCH_SIGNUP_SUCCESS, user}); -const signUpFailure = error => ({type: actions.FETCH_SIGNUP_FAILURE, error}); +const signUpSuccess = (user) => ({type: actions.FETCH_SIGNUP_SUCCESS, user}); +const signUpFailure = (error) => ({type: actions.FETCH_SIGNUP_FAILURE, error}); -export const fetchSignUp = (formData, redirectUri) => dispatch => { +export const fetchSignUp = (formData, redirectUri) => (dispatch) => { dispatch(signUpRequest()); coralApi('/users', { @@ -224,7 +223,7 @@ export const fetchSignUp = (formData, redirectUri) => dispatch => { .then(({user}) => { dispatch(signUpSuccess(user)); }) - .catch(error => { + .catch((error) => { let errorMessage = lang.t(`error.${error.message}`); // if there is no translation defined, just show the error string @@ -251,7 +250,7 @@ const forgotPasswordFailure = () => ({ type: actions.FETCH_FORGOT_PASSWORD_FAILURE }); -export const fetchForgotPassword = email => dispatch => { +export const fetchForgotPassword = (email) => (dispatch) => { dispatch(forgotPasswordRequest(email)); const redirectUri = pym.parentUrl || location.href; coralApi('/account/password/reset', { @@ -259,14 +258,14 @@ export const fetchForgotPassword = email => dispatch => { body: {email, loc: redirectUri} }) .then(() => dispatch(forgotPasswordSuccess())) - .catch(error => dispatch(forgotPasswordFailure(error))); + .catch((error) => dispatch(forgotPasswordFailure(error))); }; //============================================================================== // LOGOUT //============================================================================== -export const logout = () => dispatch => { +export const logout = () => (dispatch) => { return coralApi('/auth', {method: 'DELETE'}).then(() => { dispatch({type: actions.LOGOUT}); Storage.removeItem('token'); @@ -278,7 +277,7 @@ export const logout = () => dispatch => { //============================================================================== const checkLoginRequest = () => ({type: actions.CHECK_LOGIN_REQUEST}); -const checkLoginFailure = error => ({type: actions.CHECK_LOGIN_FAILURE, error}); +const checkLoginFailure = (error) => ({type: actions.CHECK_LOGIN_FAILURE, error}); const checkLoginSuccess = (user, isAdmin) => ({ type: actions.CHECK_LOGIN_SUCCESS, @@ -286,26 +285,26 @@ const checkLoginSuccess = (user, isAdmin) => ({ isAdmin }); -export const checkLogin = () => dispatch => { +export const checkLogin = () => (dispatch) => { dispatch(checkLoginRequest()); coralApi('/auth') - .then(result => { + .then((result) => { if (!result.user) { Storage.removeItem('token'); throw new Error('Not logged in'); } - const isAdmin = !!result.user.roles.filter(i => i === 'ADMIN').length; + const isAdmin = !!result.user.roles.filter((i) => i === 'ADMIN').length; dispatch(checkLoginSuccess(result.user, isAdmin)); }) - .catch(error => { + .catch((error) => { console.error(error); dispatch(checkLoginFailure(`${error.translation_key}`)); }); }; export const validForm = () => ({type: actions.VALID_FORM}); -export const invalidForm = error => ({type: actions.INVALID_FORM, error}); +export const invalidForm = (error) => ({type: actions.INVALID_FORM, error}); //============================================================================== // VERIFY EMAIL @@ -323,7 +322,7 @@ const verifyEmailFailure = () => ({ type: actions.VERIFY_EMAIL_FAILURE }); -export const requestConfirmEmail = (email, redirectUri) => dispatch => { +export const requestConfirmEmail = (email, redirectUri) => (dispatch) => { dispatch(verifyEmailRequest()); return coralApi('/users/resend-verify', { method: 'POST', @@ -333,7 +332,8 @@ export const requestConfirmEmail = (email, redirectUri) => dispatch => { .then(() => { dispatch(verifyEmailSuccess()); }) - .catch(err => { + .catch((err) => { + // email might have already been verifyed dispatch(verifyEmailFailure(err)); }); diff --git a/client/coral-framework/helpers/storage.js b/client/coral-framework/helpers/storage.js index d6bb280c2..ec83c3fb3 100644 --- a/client/coral-framework/helpers/storage.js +++ b/client/coral-framework/helpers/storage.js @@ -86,8 +86,7 @@ export function clear() { } } -// Enable this to debug WEB Storage events -window.addEventListener('storage', function(e) { - const msg = `${e.key} " was changed in page ${e.url} from ${e.oldValue} to ${e.newValue}`; - console.log(msg); -}); +// window.addEventListener('storage', function(e) { +// const msg = `${e.key} " was changed in page ${e.url} from ${e.oldValue} to ${e.newValue}`; +// console.log(msg); +// }); diff --git a/client/coral-sign-in/containers/SignInContainer.js b/client/coral-sign-in/containers/SignInContainer.js index d2095b527..de1d2086e 100644 --- a/client/coral-sign-in/containers/SignInContainer.js +++ b/client/coral-sign-in/containers/SignInContainer.js @@ -39,24 +39,26 @@ class SignInContainer extends Component { constructor(props) { super(props); this.state = this.initialState; + this.addError = this.addError.bind(this); + this.handleAuth = this.handleAuth.bind(this); + this.handleSignUp = this.handleSignUp.bind(this); + this.handleSignIn = this.handleSignIn.bind(this); this.handleChange = this.handleChange.bind(this); this.handleChangeEmail = this.handleChangeEmail.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 () { + componentWillMount() { this.props.checkLogin(); } componentDidMount() { - window.authCallback = this.props.facebookCallback; + window.addEventListener('storage', this.handleAuth); + const {formData} = this.state; const errors = Object.keys(formData).reduce((map, prop) => { map[prop] = lang.t('signIn.requiredField'); @@ -65,17 +67,36 @@ class SignInContainer extends Component { this.setState({errors}); } + componentWillUnmount() { + window.removeEventListener('storage', this.handleAuth); + } + + handleAuth(e) { + + // Listening to FB changes + // FB localStorage key is 'auth' + const authCallback = this.props.facebookCallback; + + if (e.key === 'auth') { + const {err, data} = JSON.parse(e.newValue); + authCallback(err, data); + } + } + handleChange(e) { const {name, value} = e.target; - this.setState((state) => ({ - ...state, - formData: { - ...state.formData, - [name]: value + this.setState( + (state) => ({ + ...state, + formData: { + ...state.formData, + [name]: value + } + }), + () => { + this.validation(name, value); } - }), () => { - this.validation(name, value); - }); + ); } handleChangeEmail(e) { @@ -85,7 +106,11 @@ class SignInContainer extends Component { handleResendVerification(e) { e.preventDefault(); - this.props.requestConfirmEmail(this.state.emailToBeResent, pym.parentUrl || location.href) + this.props + .requestConfirmEmail( + this.state.emailToBeResent, + pym.parentUrl || location.href + ) .then(() => { setTimeout(() => { @@ -110,12 +135,15 @@ class SignInContainer extends Component { if (!value.length) { addError(name, lang.t('signIn.requiredField')); - } else if (name === 'confirmPassword' && formData.confirmPassword !== formData.password) { + } else if ( + name === 'confirmPassword' && + formData.confirmPassword !== formData.password + ) { addError('confirmPassword', lang.t('signIn.passwordsDontMatch')); } else if (!validate[name](value)) { addError(name, errorMsj[name]); } else { - const { [name]: prop, ...errors } = this.state.errors; // eslint-disable-line + const {[name]: prop, ...errors} = this.state.errors; // eslint-disable-line // Removes Error this.setState((state) => ({...state, errors})); } @@ -181,14 +209,12 @@ const mapDispatchToProps = (dispatch) => ({ fetchSignInFacebook: () => dispatch(fetchSignInFacebook()), fetchSignUpFacebook: () => dispatch(fetchSignUpFacebook()), fetchForgotPassword: (formData) => dispatch(fetchForgotPassword(formData)), - requestConfirmEmail: (email, url) => dispatch(requestConfirmEmail(email, url)), + requestConfirmEmail: (email, url) => + dispatch(requestConfirmEmail(email, url)), changeView: (view) => dispatch(changeView(view)), handleClose: () => dispatch(hideSignInDialog()), invalidForm: (error) => dispatch(invalidForm(error)), validForm: () => dispatch(validForm()) }); -export default connect( - mapStateToProps, - mapDispatchToProps -)(SignInContainer); +export default connect(mapStateToProps, mapDispatchToProps)(SignInContainer);