From 4ba0bb2f896259e3083d7f567cdde3d031540835 Mon Sep 17 00:00:00 2001 From: Stuart Taylor Date: Thu, 12 Apr 2018 16:06:40 +0100 Subject: [PATCH] Initial sign in flow --- packages/learn/src/auth/index.js | 120 ------------------ packages/learn/src/components/Header/index.js | 7 +- packages/learn/src/pages/sign-in.js | 64 ++++++++++ packages/learn/src/redux/app/index.js | 16 ++- packages/learn/src/redux/app/sign-in-epic.js | 31 +++++ packages/learn/src/redux/store.js | 9 +- 6 files changed, 120 insertions(+), 127 deletions(-) delete mode 100644 packages/learn/src/auth/index.js create mode 100644 packages/learn/src/pages/sign-in.js create mode 100644 packages/learn/src/redux/app/sign-in-epic.js diff --git a/packages/learn/src/auth/index.js b/packages/learn/src/auth/index.js deleted file mode 100644 index f82eea395a..0000000000 --- a/packages/learn/src/auth/index.js +++ /dev/null @@ -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; -// } -// } diff --git a/packages/learn/src/components/Header/index.js b/packages/learn/src/components/Header/index.js index 5692bc54ef..2fbf03d13e 100644 --- a/packages/learn/src/components/Header/index.js +++ b/packages/learn/src/components/Header/index.js @@ -21,13 +21,14 @@ function Header() { > Logo - freeCodeCamp | Learn to code + + + ); } diff --git a/packages/learn/src/pages/sign-in.js b/packages/learn/src/pages/sign-in.js new file mode 100644 index 0000000000..725c33c57b --- /dev/null +++ b/packages/learn/src/pages/sign-in.js @@ -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 ( +
+

Start coding

+
+ + +
+
+ ); + } +} +SignInPage.displayName = 'SignInPage'; +SignInPage.propTypes = propTypes; + +export default connect(mapStateToProps, mapDispatchToProps)(SignInPage); diff --git a/packages/learn/src/redux/app/index.js b/packages/learn/src/redux/app/index.js index c8afdfb28e..ec84ae5bea 100644 --- a/packages/learn/src/redux/app/index.js +++ b/packages/learn/src/redux/app/index.js @@ -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); diff --git a/packages/learn/src/redux/app/sign-in-epic.js b/packages/learn/src/redux/app/sign-in-epic.js new file mode 100644 index 0000000000..f6eb121f48 --- /dev/null +++ b/packages/learn/src/redux/app/sign-in-epic.js @@ -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); + }) + ); + }) + ); +} diff --git a/packages/learn/src/redux/store.js b/packages/learn/src/redux/store.js index 5b6b2933d1..cd50379a5b 100644 --- a/packages/learn/src/redux/store.js +++ b/packages/learn/src/redux/store.js @@ -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: {