Inital user auth commit
This commit is contained in:
committed by
Mrugesh Mohapatra
parent
6dd6b44848
commit
c4108aca5d
@ -9,7 +9,7 @@ module.exports = {
|
||||
siteUrl: 'https://learn.freecodecamp.org'
|
||||
},
|
||||
proxy: {
|
||||
prefix: '/',
|
||||
prefix: '/api',
|
||||
url: 'http://localhost:3000'
|
||||
},
|
||||
plugins: [
|
||||
|
@ -69,7 +69,13 @@ exports.createPages = ({ graphql, boundActionCreators }) => {
|
||||
|
||||
// Create challenge pages.
|
||||
result.data.allChallengeNode.edges.forEach((edge, index, thisArray) => {
|
||||
const { fields: { slug }, required = [], template, challengeType, id } = edge.node;
|
||||
const {
|
||||
fields: { slug },
|
||||
required = [],
|
||||
template,
|
||||
challengeType,
|
||||
id
|
||||
} = edge.node;
|
||||
const next = thisArray[index + 1];
|
||||
const nextChallengePath = next ? next.node.fields.slug : '/';
|
||||
createPage({
|
||||
|
@ -5,6 +5,7 @@
|
||||
"author": "Kyle Mathews <mathews.kyle@gmail.com>",
|
||||
"dependencies": {
|
||||
"adler32": "^0.1.7",
|
||||
"auth0-js": "^9.4.2",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-jest": "^22.4.3",
|
||||
"babel-standalone": "^6.26.0",
|
||||
|
120
packages/learn/src/auth/index.js
Normal file
120
packages/learn/src/auth/index.js
Normal file
@ -0,0 +1,120 @@
|
||||
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;
|
||||
}
|
||||
}
|
@ -1,32 +1,99 @@
|
||||
import React from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import Link from 'gatsby-link';
|
||||
|
||||
const Header = () => (
|
||||
<div
|
||||
style={{
|
||||
background: '#006400',
|
||||
marginBottom: '1.45rem'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
margin: '0 auto',
|
||||
maxWidth: 960
|
||||
}}
|
||||
>
|
||||
<h1 style={{ margin: 0 }}>
|
||||
<Link
|
||||
import Auth from '../../auth';
|
||||
|
||||
const auth = new Auth();
|
||||
|
||||
class Header extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
authenticated: false
|
||||
};
|
||||
}
|
||||
|
||||
login() {
|
||||
auth.login();
|
||||
|
||||
this.setState({
|
||||
authenticated: auth.isAuthenticated()
|
||||
});
|
||||
}
|
||||
|
||||
logout() {
|
||||
auth.logout();
|
||||
|
||||
this.setState({
|
||||
authenticated: auth.isAuthenticated()
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// this.setState({
|
||||
// authenticated: auth.isAuthenticated()
|
||||
// });
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
background: '#006400',
|
||||
marginBottom: '0.45rem'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: 'white',
|
||||
textDecoration: 'none'
|
||||
margin: '0 auto',
|
||||
maxWidth: 960
|
||||
}}
|
||||
to='/'
|
||||
>
|
||||
Gatsby
|
||||
</Link>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
<h1 style={{ margin: 0 }}>
|
||||
<Link
|
||||
style={{
|
||||
color: 'white',
|
||||
textDecoration: 'none'
|
||||
}}
|
||||
to='/'
|
||||
>
|
||||
freeCodeCamp
|
||||
</Link>
|
||||
</h1>
|
||||
{this.state.authenticated ? (
|
||||
<span>
|
||||
<a
|
||||
href='#'
|
||||
onClick={this.logout.bind(this)}
|
||||
style={{
|
||||
boxShadow: 'none',
|
||||
lineHeight: '37px',
|
||||
color: '#fff'
|
||||
}}
|
||||
>
|
||||
Log Out
|
||||
{auth.getUserName() && <span> ({auth.getUserName()})</span>}
|
||||
</a>
|
||||
</span>
|
||||
) : (
|
||||
<span>
|
||||
<a
|
||||
href='#'
|
||||
onClick={this.login.bind(this)}
|
||||
style={{
|
||||
boxShadow: 'none',
|
||||
lineHeight: '37px',
|
||||
color: '#fff'
|
||||
}}
|
||||
>
|
||||
Log In
|
||||
</a>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Header;
|
||||
|
12
packages/learn/src/pages/callback.js
Normal file
12
packages/learn/src/pages/callback.js
Normal file
@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import Auth from '../auth';
|
||||
|
||||
function AuthCallBack() {
|
||||
const auth = new Auth();
|
||||
auth.handleAuthentication();
|
||||
return <h2>One moment please...</h2>;
|
||||
}
|
||||
|
||||
AuthCallBack.displayName = 'AuthCallBack';
|
||||
|
||||
export default AuthCallBack;
|
28
packages/learn/src/redux/app/index.js
Normal file
28
packages/learn/src/redux/app/index.js
Normal file
@ -0,0 +1,28 @@
|
||||
import { createAction, handleActions } from 'redux-actions';
|
||||
|
||||
import { createTypes } from '../../../utils/stateManagment';
|
||||
|
||||
const ns = 'app';
|
||||
|
||||
export const types = createTypes(
|
||||
['fetchUser', 'fetchUserComplete', 'fetchUserError'],
|
||||
ns
|
||||
);
|
||||
|
||||
const initialState = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
export const fetchUser = createAction(types.fetchUser);
|
||||
export const fetchUserComplete = createAction(types.fetchUserComplete);
|
||||
export const fecthUserError = createAction(types.fetchUserError);
|
||||
|
||||
export const reducer = handleActions(
|
||||
{
|
||||
[types.fetchUserComplete]: (state, { payload }) => ({
|
||||
...state,
|
||||
user: payload
|
||||
})
|
||||
},
|
||||
initialState
|
||||
);
|
@ -6,16 +6,19 @@ 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 map } from '../components/Map/redux';
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
app,
|
||||
challenge,
|
||||
map,
|
||||
router
|
||||
});
|
||||
|
||||
const rootEpic = combineEpics(...epics);
|
||||
|
||||
const epicMiddleware = createEpicMiddleware(rootEpic, {
|
||||
dependencies: {
|
||||
window: typeof window !== 'undefined' ? window : {},
|
||||
|
@ -519,6 +519,17 @@ atob@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.0.tgz#ab2b150e51d7b122b9efc8d7340c06b6c41076bc"
|
||||
|
||||
auth0-js@^9.4.2:
|
||||
version "9.4.2"
|
||||
resolved "https://registry.yarnpkg.com/auth0-js/-/auth0-js-9.4.2.tgz#44363933266781fb9447ce09503c6f783b86a474"
|
||||
dependencies:
|
||||
base64-js "^1.2.0"
|
||||
idtoken-verifier "^1.2.0"
|
||||
qs "^6.4.0"
|
||||
superagent "^3.8.2"
|
||||
url-join "^1.1.0"
|
||||
winchan "^0.2.0"
|
||||
|
||||
autoprefixer@^6.0.2, autoprefixer@^6.3.1:
|
||||
version "6.7.7"
|
||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014"
|
||||
@ -1436,7 +1447,7 @@ base64-arraybuffer@0.1.5:
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
|
||||
|
||||
base64-js@^1.0.2:
|
||||
base64-js@^1.0.2, base64-js@^1.2.0:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.3.tgz#fb13668233d9614cf5fb4bce95a9ba4096cdf801"
|
||||
|
||||
@ -2211,7 +2222,7 @@ component-emitter@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.0.tgz#ccd113a86388d06482d03de3fc7df98526ba8efe"
|
||||
|
||||
component-emitter@1.2.1, component-emitter@^1.2.1:
|
||||
component-emitter@1.2.1, component-emitter@^1.2.0, component-emitter@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
|
||||
|
||||
@ -2307,6 +2318,10 @@ cookie@0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
|
||||
|
||||
cookiejar@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.1.tgz#41ad57b1b555951ec171412a81942b1e8200d34a"
|
||||
|
||||
copy-concurrently@^1.0.0:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
|
||||
@ -2459,6 +2474,10 @@ crypto-browserify@^3.11.0:
|
||||
randombytes "^2.0.0"
|
||||
randomfill "^1.0.3"
|
||||
|
||||
crypto-js@^3.1.9-1:
|
||||
version "3.1.9-1"
|
||||
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.9-1.tgz#fda19e761fc077e01ffbfdc6e9fdfc59e8806cd8"
|
||||
|
||||
crypto-random-string@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
|
||||
@ -3822,6 +3841,14 @@ forever-agent@~0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
||||
|
||||
form-data@^2.3.1, form-data@~2.3.1:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099"
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "1.0.6"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
form-data@~2.1.1:
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
|
||||
@ -3830,13 +3857,9 @@ form-data@~2.1.1:
|
||||
combined-stream "^1.0.5"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
form-data@~2.3.1:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099"
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "1.0.6"
|
||||
mime-types "^2.1.12"
|
||||
formidable@^1.1.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.1.tgz#70fb7ca0290ee6ff961090415f4b3df3d2082659"
|
||||
|
||||
forwarded@~0.1.2:
|
||||
version "0.1.2"
|
||||
@ -4748,6 +4771,16 @@ icss-replace-symbols@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
|
||||
|
||||
idtoken-verifier@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/idtoken-verifier/-/idtoken-verifier-1.2.0.tgz#4654f1f07ab7a803fc9b1b8b36057e2a87ad8b09"
|
||||
dependencies:
|
||||
base64-js "^1.2.0"
|
||||
crypto-js "^3.1.9-1"
|
||||
jsbn "^0.1.0"
|
||||
superagent "^3.8.2"
|
||||
url-join "^1.1.0"
|
||||
|
||||
ieee754@^1.1.4:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.11.tgz#c16384ffe00f5b7835824e67b6f2bd44a5229455"
|
||||
@ -5626,7 +5659,7 @@ jsan@^3.1.5, jsan@^3.1.9:
|
||||
version "3.1.9"
|
||||
resolved "https://registry.yarnpkg.com/jsan/-/jsan-3.1.9.tgz#2705676c1058f0a7d9ac266ad036a5769cfa7c96"
|
||||
|
||||
jsbn@~0.1.0:
|
||||
jsbn@^0.1.0, jsbn@~0.1.0:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
|
||||
|
||||
@ -6203,7 +6236,7 @@ merge@^1.1.3, merge@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da"
|
||||
|
||||
methods@~1.1.2:
|
||||
methods@^1.1.1, methods@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
|
||||
@ -6283,7 +6316,7 @@ mime@1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
|
||||
|
||||
mime@^1.3.6, mime@^1.5.0:
|
||||
mime@^1.3.6, mime@^1.4.1, mime@^1.5.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
|
||||
@ -7879,7 +7912,7 @@ q@^1.1.2:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
||||
|
||||
qs@6.5.1, qs@~6.5.1:
|
||||
qs@6.5.1, qs@^6.4.0, qs@^6.5.1, qs@~6.5.1:
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
|
||||
|
||||
@ -9534,6 +9567,21 @@ style-loader@^0.13.0:
|
||||
dependencies:
|
||||
loader-utils "^1.0.2"
|
||||
|
||||
superagent@^3.8.2:
|
||||
version "3.8.2"
|
||||
resolved "https://registry.yarnpkg.com/superagent/-/superagent-3.8.2.tgz#e4a11b9d047f7d3efeb3bbe536d9ec0021d16403"
|
||||
dependencies:
|
||||
component-emitter "^1.2.0"
|
||||
cookiejar "^2.1.0"
|
||||
debug "^3.1.0"
|
||||
extend "^3.0.0"
|
||||
form-data "^2.3.1"
|
||||
formidable "^1.1.1"
|
||||
methods "^1.1.1"
|
||||
mime "^1.4.1"
|
||||
qs "^6.5.1"
|
||||
readable-stream "^2.0.5"
|
||||
|
||||
supports-color@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
|
||||
@ -10026,6 +10074,10 @@ urix@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
|
||||
|
||||
url-join@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/url-join/-/url-join-1.1.0.tgz#741c6c2f4596c4830d6718460920d0c92202dc78"
|
||||
|
||||
url-loader@^0.5.7:
|
||||
version "0.5.9"
|
||||
resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-0.5.9.tgz#cc8fea82c7b906e7777019250869e569e995c295"
|
||||
@ -10389,6 +10441,10 @@ widest-line@^2.0.0:
|
||||
dependencies:
|
||||
string-width "^2.1.1"
|
||||
|
||||
winchan@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/winchan/-/winchan-0.2.0.tgz#3863028e7f974b0da1412f28417ba424972abd94"
|
||||
|
||||
window-size@0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
|
||||
|
Reference in New Issue
Block a user