Initial sign in flow

This commit is contained in:
Stuart Taylor
2018-04-12 16:06:40 +01:00
committed by Mrugesh Mohapatra
parent 653d2bc454
commit 4ba0bb2f89
6 changed files with 120 additions and 127 deletions

View File

@ -1,120 +0,0 @@
// import auth0 from 'auth0-js';
// import { navigateTo } from 'gatsby-link';
// import { ajax$ } from '../templates/Challenges/utils/ajax-stream';
// const AUTH0_DOMAIN = 'freecodecamp.auth0.com';
// const AUTH0_CLIENT_ID = 'vF70CJZyPKbZR4y0avecXXLkfyMNnyKn';
// export default class Auth {
// constructor() {
// this.login = this.login.bind(this);
// this.logout = this.logout.bind(this);
// this.handleAuthentication = this.handleAuthentication.bind(this);
// this.isAuthenticated = this.isAuthenticated.bind(this);
// this.sessionEmail = '';
// }
// auth0 = new auth0.WebAuth({
// domain: AUTH0_DOMAIN,
// clientID: AUTH0_CLIENT_ID,
// redirectUri: 'http://localhost:8000/callback',
// audience: `https://${AUTH0_DOMAIN}/api/v2/`,
// responseType: 'token id_token',
// scope: 'openid profile email'
// });
// login() {
// this.auth0.authorize();
// }
// logout() {
// localStorage.removeItem('access_token');
// localStorage.removeItem('id_token');
// localStorage.removeItem('expires_at');
// localStorage.removeItem('user');
// }
// handleAuthentication() {
// if (typeof window !== 'undefined') {
// this.auth0.parseHash((err, authResult) => {
// if (authResult && authResult.accessToken && authResult.idToken) {
// this.setSession(authResult);
// } else if (err) {
// console.error(err);
// }
// // Return to the homepage after authentication.
// navigateTo('/');
// });
// }
// }
// isAuthenticated() {
// const expiresAt = JSON.parse(localStorage.getItem('expires_at'));
// const isAuth = new Date().getTime() < expiresAt;
// // isAuth && this.getFCCUser();
// return isAuth;
// }
// setSession(authResult) {
// const expiresAt = JSON.stringify(
// authResult.expiresIn * 9000 + new Date().getTime()
// );
// localStorage.setItem('access_token', authResult.accessToken);
// localStorage.setItem('id_token', authResult.idToken);
// localStorage.setItem('expires_at', expiresAt);
// this.auth0.client.userInfo(authResult.accessToken, (err, user) => {
// if (err) {
// console.error(err);
// }
// localStorage.setItem('user', JSON.stringify(user));
// });
// }
// getFCCUser() {
// const token = localStorage.getItem('access_token');
// if (!token) {
// console.warn('no token found');
// }
// const { email } = JSON.parse(localStorage.getItem('user'));
// const headers = {
// Authorization: `Bearer ${token}`
// };
// const body = { email };
// ajax$({
// url: '/api/auth/auth0/login',
// headers,
// body
// }).subscribe(
// resp => {
// console.info('YES');
// console.log(resp);
// },
// err => {
// console.warn('NO?');
// console.log(err.message);
// },
// () => {
// console.log('done');
// }
// );
// }
// getUser() {
// if (localStorage.getItem('user')) {
// return JSON.parse(localStorage.getItem('user'));
// }
// return null;
// }
// getUserName() {
// if (this.getUser()) {
// return this.getUser().name;
// }
// return null;
// }
// }

View File

@ -21,13 +21,14 @@ function Header() {
>
<img
alt='Logo - freeCodeCamp | Learn to code'
src={
'https://s3.amazonaws.com/freecodecamp/freecodecamp_logo.svg'
}
src={'https://s3.amazonaws.com/freecodecamp/freecodecamp_logo.svg'}
title='freeCodeCamp | Learn to code'
/>
</Link>
</div>
<Link to='/sign-in'>
<button>Sign In</button>
</Link>
</header>
);
}

View File

@ -0,0 +1,64 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { signIn } from '../redux/app';
const mapStateToProps = () => ({});
const mapDispatchToProps = dispatch =>
bindActionCreators(
{
signIn
},
dispatch
);
const propTypes = {
signIn: PropTypes.func.isRequired
};
class SignInPage extends PureComponent {
constructor(...props) {
super(...props);
this.state = {
userEmail: ''
};
}
handleEmailChange = e => {
e.persist();
return this.setState(state => ({ ...state, userEmail: e.target.value }));
};
handleSubmit = e => {
e.preventDefault();
const { userEmail } = this.state;
this.props.signIn(userEmail);
};
render() {
const { userEmail } = this.state;
console.log(window.location.origin);
return (
<div id='sigin-view'>
<h2>Start coding</h2>
<form onSubmit={this.handleSubmit}>
<input
name='userEmail'
onChange={this.handleEmailChange}
type='email'
value={userEmail}
/>
<button type='submit'>Submit</button>
</form>
</div>
);
}
}
SignInPage.displayName = 'SignInPage';
SignInPage.propTypes = propTypes;
export default connect(mapStateToProps, mapDispatchToProps)(SignInPage);

View File

@ -1,11 +1,21 @@
import { createAction, handleActions } from 'redux-actions';
import { createTypes } from '../../../utils/stateManagment';
import signInEpic from './sign-in-epic';
const ns = 'app';
export const epics = [signInEpic];
export const types = createTypes(
['fetchUser', 'fetchUserComplete', 'fetchUserError'],
[
'fetchUser',
'fetchUserComplete',
'fetchUserError',
'signIn',
'signInComplete',
'signInError'
],
ns
);
@ -13,6 +23,10 @@ const initialState = {
user: {}
};
export const signIn = createAction(types.signIn);
export const signInComplete = createAction(types.signInComplete);
export const signInError = createAction(types.signInError);
export const fetchUser = createAction(types.fetchUser);
export const fetchUserComplete = createAction(types.fetchUserComplete);
export const fecthUserError = createAction(types.fetchUserError);

View File

@ -0,0 +1,31 @@
import { ajax } from 'rxjs/observable/dom/ajax';
import { map } from 'rxjs/operators/map';
import { catchError } from 'rxjs/operators/catchError';
import { switchMap } from 'rxjs/operators/switchMap';
import { ofType } from 'redux-observable';
import { types, signInComplete, signInError } from './';
export default function signInEpic(action$, _, { window }) {
return action$.pipe(
ofType(types.signIn),
switchMap(({ payload }) => {
const request = {
url: 'http://localhost:3000/passwordless-auth',
method: 'POST',
body: { email: payload, returnTo: window.location.origin }
};
return ajax(request).pipe(
map(resp => {
console.log('RES', resp);
return signInComplete();
}),
catchError(e => {
console.warn(e);
return signInError(e);
})
);
})
);
}

View File

@ -6,8 +6,11 @@ import {
import { combineEpics, createEpicMiddleware } from 'redux-observable';
import { routerReducer as router, routerMiddleware } from 'react-router-redux';
import { reducer as app } from './app';
import { reducer as challenge, epics } from '../templates/Challenges/redux';
import { reducer as app, epics as appEpics } from './app';
import {
reducer as challenge,
epics as challengeEpics
} from '../templates/Challenges/redux';
import { reducer as map } from '../components/Map/redux';
const rootReducer = combineReducers({
@ -17,7 +20,7 @@ const rootReducer = combineReducers({
router
});
const rootEpic = combineEpics(...epics);
const rootEpic = combineEpics(...appEpics, ...challengeEpics);
const epicMiddleware = createEpicMiddleware(rootEpic, {
dependencies: {