login feature removal
This commit is contained in:
parent
613449a82c
commit
101dc0504d
|
@ -1,2 +1,3 @@
|
||||||
# Nothing interesting here
|
# Kana Quiz 2
|
||||||
Early alpha of Kana Quiz remade with React.js and Auth0
|
Kana Quiz remade with React.js.
|
||||||
|
See live at http://simplemedia.org/kana/
|
||||||
|
|
|
@ -37,10 +37,9 @@
|
||||||
"webpack-dev-server": "^1.14.1"
|
"webpack-dev-server": "^1.14.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"auth0-lock": "^10.0.0",
|
|
||||||
"jwt-decode": "^2.1.0",
|
|
||||||
"postcss": "^5.1.0",
|
"postcss": "^5.1.0",
|
||||||
"react": "^15.2.1",
|
"react": "^15.2.1",
|
||||||
|
"react-addons-css-transition-group": "^15.3.0",
|
||||||
"react-dom": "^15.2.1",
|
"react-dom": "^15.2.1",
|
||||||
"react-toggle-switch": "^2.1.2"
|
"react-toggle-switch": "^2.1.2"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +1,21 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import AuthService from '../../utils/AuthService'
|
|
||||||
import './App.scss';
|
import './App.scss';
|
||||||
import Navbar from '../Navbar/Navbar';
|
import Navbar from '../Navbar/Navbar';
|
||||||
import GameContainer from '../GameContainer/GameContainer';
|
import GameContainer from '../GameContainer/GameContainer';
|
||||||
import { removeHash } from '../../data/helperFuncs';
|
import { removeHash } from '../../data/helperFuncs';
|
||||||
|
|
||||||
const options = {};
|
const options = {};
|
||||||
const auth = new AuthService(__AUTH0_CLIENT_ID__, __AUTH0_DOMAIN__, options);
|
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
isAuthenticated: this.isAuthenticated(),
|
|
||||||
gameState: 'chooseCharacters'
|
gameState: 'chooseCharacters'
|
||||||
}
|
}
|
||||||
auth.on('profile_updated', (newProfile) => {
|
|
||||||
this.setState({isAuthenticated: this.isAuthenticated()});
|
|
||||||
})
|
|
||||||
this.logout = this.logout.bind(this);
|
|
||||||
this.getNickName = this.getNickName.bind(this);
|
|
||||||
this.startGame = this.startGame.bind(this);
|
this.startGame = this.startGame.bind(this);
|
||||||
this.endGame = this.endGame.bind(this);
|
this.endGame = this.endGame.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
isAuthenticated() {
|
|
||||||
removeHash();
|
|
||||||
return auth.loggedIn() && auth.getProfile() && auth.getProfile().hasOwnProperty('user_id');
|
|
||||||
}
|
|
||||||
|
|
||||||
getNickName() {
|
|
||||||
return auth.loggedIn() && auth.getProfile() && auth.getProfile().hasOwnProperty('nickname')?auth.getProfile().nickname:'';
|
|
||||||
}
|
|
||||||
|
|
||||||
startGame() {
|
startGame() {
|
||||||
this.setState({gameState: 'game'});
|
this.setState({gameState: 'game'});
|
||||||
}
|
}
|
||||||
|
@ -41,34 +24,22 @@ class App extends Component {
|
||||||
this.setState({gameState: 'chooseCharacters'});
|
this.setState({gameState: 'chooseCharacters'});
|
||||||
}
|
}
|
||||||
|
|
||||||
logout() {
|
|
||||||
auth.logout();
|
|
||||||
this.setState({isAuthenticated: this.isAuthenticated()});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let loginButton = !this.state.isAuthenticated ?
|
|
||||||
<p className="login-button"><a href="javascript:;" onClick={auth.login.bind(this)}>Log in to save your progress!</a></p> : '';
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Navbar isAuthenticated={this.state.isAuthenticated}
|
<Navbar
|
||||||
handleLogin={auth.login.bind(this)}
|
|
||||||
handleLogout={this.logout}
|
|
||||||
gameState={this.state.gameState}
|
gameState={this.state.gameState}
|
||||||
handleEndGame={this.endGame}
|
handleEndGame={this.endGame}
|
||||||
/>
|
/>
|
||||||
<div className="outercontainer">
|
<div className="outercontainer">
|
||||||
<div className="container game">
|
<div className="container game">
|
||||||
<GameContainer
|
<GameContainer
|
||||||
isAuthenticated={this.state.isAuthenticated}
|
|
||||||
nickName={this.getNickName()}
|
|
||||||
gameState={this.state.gameState}
|
gameState={this.state.gameState}
|
||||||
handleStartGame={this.startGame}
|
handleStartGame={this.startGame}
|
||||||
handleEndGame={this.endGame}
|
handleEndGame={this.endGame}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="row text-center">{loginButton}</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,6 @@ class CharacterGroup extends Component {
|
||||||
<span className={this.props.selected ?
|
<span className={this.props.selected ?
|
||||||
'glyphicon glyphicon-small glyphicon-check' :
|
'glyphicon glyphicon-small glyphicon-check' :
|
||||||
'glyphicon glyphicon-small glyphicon-unchecked'}></span> {this.state.shownChars}
|
'glyphicon glyphicon-small glyphicon-unchecked'}></span> {this.state.shownChars}
|
||||||
<span className="pull-right success-percent">0 %</span>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ class ChooseCharacters extends Component {
|
||||||
<div className="col-xs-12">
|
<div className="col-xs-12">
|
||||||
<div className="panel panel-default">
|
<div className="panel panel-default">
|
||||||
<div className="panel-body welcome">
|
<div className="panel-body welcome">
|
||||||
<h4>Welcome to Kana Quiz{this.props.isAuthenticated && this.props.nickName !== '' && typeof this.props.nickName !== 'undefined'?', '+this.props.nickName:''}!</h4>
|
<h4>Welcome to Kana Quiz!</h4>
|
||||||
<p>Please choose the groups of characters that you'd like to be studying.</p>
|
<p>Please choose the groups of characters that you'd like to be studying.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -105,7 +105,7 @@ class ChooseCharacters extends Component {
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-sm-6">
|
<div className="col-sm-6">
|
||||||
<div className="panel panel-default">
|
<div className="panel panel-default">
|
||||||
<div className="panel-heading">Hiragana · ひらがな<span className="pull-right">Progress</span></div>
|
<div className="panel-heading">Hiragana · ひらがな</div>
|
||||||
<div className="panel-body selection-areas">
|
<div className="panel-body selection-areas">
|
||||||
{this.showGroupRows('hiragana')}
|
{this.showGroupRows('hiragana')}
|
||||||
</div>
|
</div>
|
||||||
|
@ -116,7 +116,7 @@ class ChooseCharacters extends Component {
|
||||||
</div>
|
</div>
|
||||||
<div className="col-sm-6">
|
<div className="col-sm-6">
|
||||||
<div className="panel panel-default">
|
<div className="panel panel-default">
|
||||||
<div className="panel-heading">Katakana · カタカナ<span className="pull-right">Progress</span></div>
|
<div className="panel-heading">Katakana · カタカナ</div>
|
||||||
<div className="panel-body selection-areas">
|
<div className="panel-body selection-areas">
|
||||||
{this.showGroupRows('katakana')}
|
{this.showGroupRows('katakana')}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -40,8 +40,6 @@ class GameContainer extends Component {
|
||||||
{ this.props.gameState==='chooseCharacters' ?
|
{ this.props.gameState==='chooseCharacters' ?
|
||||||
<ChooseCharacters selectedGroups={this.state.decidedGroups}
|
<ChooseCharacters selectedGroups={this.state.decidedGroups}
|
||||||
handleStartGame={this.startGame}
|
handleStartGame={this.startGame}
|
||||||
isAuthenticated={this.props.isAuthenticated}
|
|
||||||
nickName={this.props.nickName}
|
|
||||||
stage={this.state.stage}
|
stage={this.state.stage}
|
||||||
isLocked={this.state.isLocked}
|
isLocked={this.state.isLocked}
|
||||||
lockStage={this.lockStage}
|
lockStage={this.lockStage}
|
||||||
|
|
|
@ -12,9 +12,6 @@ class Navbar extends Component {
|
||||||
case 'game':
|
case 'game':
|
||||||
leftLink = <li id="nav-choosecharacters"><a href="javascript:;" onClick={this.props.handleEndGame}><span className="glyphicon glyphicon-small glyphicon-arrow-left"></span> Back to menu</a></li>
|
leftLink = <li id="nav-choosecharacters"><a href="javascript:;" onClick={this.props.handleEndGame}><span className="glyphicon glyphicon-small glyphicon-arrow-left"></span> Back to menu</a></li>
|
||||||
}
|
}
|
||||||
let profileButton = this.props.isAuthenticated ?
|
|
||||||
<a href="javascript:;" onClick={this.props.handleLogout}><span className="glyphicon glyphicon-small glyphicon-log-out"></span> Log out</a> :
|
|
||||||
<a href="javascript:;" onClick={this.props.handleLogin}><span className="glyphicon glyphicon-small glyphicon-log-in"></span> Log in</a>;
|
|
||||||
return (
|
return (
|
||||||
<nav className="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
<nav className="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||||
<div className="container">
|
<div className="container">
|
||||||
|
@ -22,20 +19,11 @@ class Navbar extends Component {
|
||||||
<ul className="nav navbar-nav">
|
<ul className="nav navbar-nav">
|
||||||
{leftLink}
|
{leftLink}
|
||||||
</ul>
|
</ul>
|
||||||
<ul className="nav navbar-nav navbar-right">
|
|
||||||
<li id="nav-profile">{profileButton}</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// <li id="nav-settings"><a href="#"><span className="glyphicon glyphicon-small glyphicon-cog"></span><span className="hidden-nano"> Settings</span></a></li>
|
|
||||||
|
|
||||||
// <div>{this.props.profile.hasOwnProperty('user_id')?this.props.profile.name+' is logged in':'not logged in'}</div>
|
|
||||||
// <ul className="nav navbar-nav">
|
|
||||||
// <li id="nav-about"><a href="#menu">< Back to menu</a></li>
|
|
||||||
// </ul>
|
|
||||||
|
|
||||||
export default Navbar;
|
export default Navbar;
|
|
@ -1,75 +0,0 @@
|
||||||
import { EventEmitter } from 'events'
|
|
||||||
import { isTokenExpired } from './jwtHelper'
|
|
||||||
import Auth0Lock from 'auth0-lock'
|
|
||||||
|
|
||||||
export default class AuthService extends EventEmitter {
|
|
||||||
constructor(clientId, domain, options) {
|
|
||||||
super()
|
|
||||||
// Configure Auth0
|
|
||||||
this.lock = new Auth0Lock(clientId, domain, options)
|
|
||||||
// Add callback for lock `authenticated` event
|
|
||||||
this.lock.on('authenticated', this._doAuthentication.bind(this))
|
|
||||||
// Add callback for lock `authorization_error` event
|
|
||||||
this.lock.on('authorization_error', this._authorizationError.bind(this))
|
|
||||||
// binds login functions to keep this context
|
|
||||||
this.login = this.login.bind(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
_doAuthentication(authResult){
|
|
||||||
// Saves the user token
|
|
||||||
this.setToken(authResult.idToken)
|
|
||||||
// Async loads the user profile data
|
|
||||||
this.lock.getProfile(authResult.idToken, (error, profile) => {
|
|
||||||
if (error) {
|
|
||||||
console.log('Error loading the Profile', error)
|
|
||||||
} else {
|
|
||||||
this.setProfile(profile)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
_authorizationError(error){
|
|
||||||
// Unexpected authentication error
|
|
||||||
console.log('Authentication Error', error)
|
|
||||||
}
|
|
||||||
|
|
||||||
login() {
|
|
||||||
// Call the show method to display the widget.
|
|
||||||
this.lock.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
loggedIn(){
|
|
||||||
// Checks if there is a saved token and it's still valid
|
|
||||||
const token = this.getToken()
|
|
||||||
return !!token && !isTokenExpired(token)
|
|
||||||
}
|
|
||||||
|
|
||||||
setProfile(profile){
|
|
||||||
// Saves profile data to localStorage
|
|
||||||
localStorage.setItem('profile', JSON.stringify(profile))
|
|
||||||
// Triggers profile_updated event to update the UI
|
|
||||||
this.emit('profile_updated', profile)
|
|
||||||
}
|
|
||||||
|
|
||||||
getProfile(){
|
|
||||||
// Retrieves the profile data from localStorage
|
|
||||||
const profile = localStorage.getItem('profile')
|
|
||||||
return profile ? JSON.parse(localStorage.profile) : {}
|
|
||||||
}
|
|
||||||
|
|
||||||
setToken(idToken){
|
|
||||||
// Saves user token to localStorage
|
|
||||||
localStorage.setItem('id_token', idToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
getToken(){
|
|
||||||
// Retrieves the user token from localStorage
|
|
||||||
return localStorage.getItem('id_token')
|
|
||||||
}
|
|
||||||
|
|
||||||
logout(){
|
|
||||||
// Clear user token and profile data from localStorage
|
|
||||||
localStorage.removeItem('id_token');
|
|
||||||
localStorage.removeItem('profile');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
import decode from 'jwt-decode';
|
|
||||||
|
|
||||||
export function getTokenExpirationDate(token){
|
|
||||||
const decoded = decode(token)
|
|
||||||
if(!decoded.exp) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const date = new Date(0) // The 0 here is the key, which sets the date to the epoch
|
|
||||||
date.setUTCSeconds(decoded.exp)
|
|
||||||
return date
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isTokenExpired(token){
|
|
||||||
const date = getTokenExpirationDate(token)
|
|
||||||
const offsetSeconds = 60*60*24*7
|
|
||||||
if (date === null) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return !(date.valueOf() > (new Date().valueOf() + (offsetSeconds * 1000)))
|
|
||||||
}
|
|
Loading…
Reference in a new issue