acklen-keystone
Version:
Web Application Framework and Admin GUI / Content Management System built on Express.js and Mongoose
219 lines (217 loc) • 7.57 kB
JavaScript
/**
* The actual Sign In view, with the login form
*/
import assign from 'object-assign';
import classnames from 'classnames';
import React from 'react';
import Auth0Lock from 'auth0-lock';
import Auth0 from 'auth0-js';
import xhr from 'xhr';
import { Button } from '../App/elemental';
import Alert from './components/Alert';
import Brand from './components/Brand';
import { isTokenExpired } from '../utils/jwtHelper';
const clientID = Keystone.auth0ClientId;
const domain = Keystone.auth0DomainUrl;
var webAuth = new Auth0.WebAuth({
domain,
clientID,
responseType: 'token id_token',
scope: 'openid',
});
var lock = new Auth0Lock(clientID, domain, {
configurationBaseUrl: 'https://cdn.auth0.com',
auth: {
responseType: 'token',
redirectUrl: window.location.origin,
params: {
state: window.location.pathname,
},
},
allowSignUp: false,
theme: {
logo: `${Keystone.adminPath}/images/aga_full_logo.png`,
primaryColor: '#008fd4',
},
version: 'v2',
socialButtonStyle: 'small',
additionalSignUpFields: [
{
name: 'first_name',
placeholder: 'your first name',
icon: `${Keystone.adminPath}/images/user.png`,
},
{
name: 'last_name',
placeholder: 'your last name',
icon: `${Keystone.adminPath}/images/user.png`,
},
],
});
var SigninView = React.createClass({
getInitialState () {
lock.on('authenticated', this.doAuthentication);
lock.on('authorization_error', this.authorizationError);
return {
email: '',
password: '',
isAnimating: false,
isInvalid: false,
invalidMessage: '',
signedOut: window.location.search === '?signedout',
};
},
componentDidMount () {
webAuth.checkSession({
redirectUri: window.location.origin,
}, (errRenew, authResult) => {
if (authResult && authResult.accessToken) {
this.doAuthentication(authResult);
} else {
this.clearToken();
}
});
},
clearToken () {
localStorage.removeItem('id_token');
},
login () {
lock.show();
},
doAuthentication (authResult) {
lock.getProfile(authResult.accessToken, (error, profile) => {
if (error) {
this.setState({
invalidMessage: 'We\'re sorry, something went wrong when attempting to log in.',
});
} else {
var firstName = profile.first;
var lastName = profile.last;
var email = profile.email ? profile.email : profile.screen_name;
var pwd = profile.pwd || profile.user_id;
var netForumUserId = profile.user_metadata.netForumUserId;
this.authenticateKeystoneUser(email, firstName, lastName, pwd, netForumUserId, authResult.accessToken);
}
});
},
authorizationError (error) {
if (error && error.error_description) {
this.displayError(error.error_description);
} else {
this.displayError('Sorry, we are unable to login you in with this account.');
}
},
validToken () {
const token = this.getToken();
return !!token && !isTokenExpired(token);
},
getToken () {
return localStorage.getItem('id_token');
},
setToken (idToken) {
localStorage.setItem('id_token', idToken);
},
handleInputChange (e) {
// Set the new state when the input changes
const newState = {};
newState[e.target.name] = e.target.value;
this.setState(newState);
},
logout () {
localStorage.removeItem('id_token');
new Auth0Lock(clientID, domain).logout({
returnTo: window.location.origin + `${Keystone.adminPath}/signout`,
});
},
authenticateKeystoneUser (email, firstName, lastName, pwd, netForumUserId, token) {
if (!email) {
return this.displayError('Invalid credentials to sign in.');
}
xhr({
url: `${Keystone.adminPath}/api/session/signin`,
method: 'post',
json: {
email,
firstName,
lastName,
pwd,
netForumUserId,
},
headers: assign({}, Keystone.csrf.header),
}, (err, resp, body) => {
if (err || body && body.error) {
return body.error === 'invalid csrf'
? this.displayError('Something went wrong; please refresh your browser and try again.')
: this.displayError('The email and password you entered are not valid.');
} else {
if (body.user.isAdmin) {
this.setToken(token);
// Redirect to where we came from or to the default admin path
if (Keystone.redirect) {
top.location.href = Keystone.redirect;
} else {
top.location.href = this.props.from ? this.props.from : Keystone.adminPath;
}
} else {
this.displayError('You are not authorized to view this content');
}
}
});
},
/**
* Display an error message
*
* @param {String} message The message you want to show
*/
displayError (message) {
this.setState({
isAnimating: true,
isInvalid: true,
invalidMessage: message,
});
setTimeout(this.finishAnimation, 750);
},
// Finish the animation and select the email field
finishAnimation () {
// TODO isMounted was deprecated, find out if we need this guard
if (!this.isMounted()) return;
if (this.refs.email) {
this.refs.email.select();
}
this.setState({
isAnimating: false,
});
},
render () {
const boxClassname = classnames('auth-box', {
'auth-box--has-errors': this.state.isAnimating,
});
return (
<div className="auth-wrapper">
<Alert
isInvalid={this.state.isInvalid}
signedOut={this.state.signedOut}
invalidMessage={this.state.invalidMessage}
/>
<div className={boxClassname}>
<h1 className="u-hidden-visually">{this.props.brand ? this.props.brand : 'Keystone'} Sign In </h1>
<div className="auth-box__inner">
<Brand logo={this.props.logo} brand={this.props.brand} />
<div className="auth-box__col">
<div className="auth-box__brand" style={{ borderRight: 'inherit' }}>
<Button color="primary" type="button" onClick={this.login}>
Sign In
</Button>
</div>
</div>
</div>
</div>
<div className="auth-footer">
<span>Powered by </span>
<a href="http://keystonejs.com" target="_blank" title="The Node.js CMS and web application platform (new window)">KeystoneJS</a>
</div>
</div>
);
},
});
module.exports = SigninView;