Search for existing user account using Github emails (#337)

* Tries to match user account from list of emails in Github API

Requests the 'user:email' scope from Github which returns the private
emails associated with the user's account.

* Centres GitHub button in layout
This commit is contained in:
Andrew Nicolaou 2017-04-13 18:04:10 +02:00 committed by Cassie Tarakajian
parent 4f531c14f4
commit 7be45ce875
4 changed files with 42 additions and 9 deletions

View file

@ -7,6 +7,7 @@ import axios from 'axios';
import { updateSettings } from '../actions';
import AccountForm from '../components/AccountForm';
import { validateSettings } from '../../../utils/reduxFormUtils';
import GithubButton from '../components/GithubButton';
const exitUrl = require('../../../images/exit.svg');
const logoUrl = require('../../../images/p5js-logo.svg');
@ -41,8 +42,8 @@ class AccountView extends React.Component {
<div className="form-container__content">
<h2 className="form-container__title">My Account</h2>
<AccountForm {...this.props} />
{/* <h2 className="form-container__divider">Or</h2>
<GithubButton buttonText="Login with Github" /> */}
<h2 className="form-container__divider">Or</h2>
<GithubButton buttonText="Login with Github" />
</div>
</div>
);

View file

@ -5,7 +5,8 @@ import InlineSVG from 'react-inlinesvg';
import { validateAndLoginUser } from '../actions';
import LoginForm from '../components/LoginForm';
import { validateLogin } from '../../../utils/reduxFormUtils';
// import GithubButton from '../components/GithubButton';
import GithubButton from '../components/GithubButton';
const exitUrl = require('../../../images/exit.svg');
const logoUrl = require('../../../images/p5js-logo.svg');
@ -39,8 +40,8 @@ class LoginView extends React.Component {
<div className="form-container__content">
<h2 className="form-container__title">Log In</h2>
<LoginForm {...this.props} />
{/* <h2 className="form-container__divider">Or</h2>
<GithubButton buttonText="Login with Github" /> */}
<h2 className="form-container__divider">Or</h2>
<GithubButton buttonText="Login with Github" />
<p className="form__navigation-options">
Don&apos;t have an account?&nbsp;
<Link className="form__signup-button" to="/signup">Sign Up</Link>

View file

@ -18,6 +18,7 @@
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.form-container__title {

View file

@ -1,5 +1,6 @@
import User from '../models/user';
const lodash = require('lodash');
const passport = require('passport');
const GitHubStrategy = require('passport-github').Strategy;
const LocalStrategy = require('passport-local').Strategy;
@ -33,6 +34,28 @@ passport.use(new LocalStrategy({ usernameField: 'email' }, (email, password, don
.catch(err => done(null, false, { msg: err }));
}));
/*
Input:
[
{ value: 'email@example.com', primary: false, verified: true },
{ value: 'unverified@example.com', primary: false, verified: false }
]
Output:
['email@example.com']
*/
const getVerifiedEmails = githubEmails => (
(githubEmails || [])
.filter(item => item.verified === true)
.map(item => item.value)
);
const getPrimaryEmail = githubEmails => (
(
lodash.find(githubEmails, { primary: true }) || {}
).value
);
/**
* Sign in with GitHub.
*/
@ -40,16 +63,23 @@ passport.use(new GitHubStrategy({
clientID: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
callbackURL: '/auth/github/callback',
passReqToCallback: true
passReqToCallback: true,
scope: ['user:email'],
}, (req, accessToken, refreshToken, profile, done) => {
User.findOne({ github: profile.id }, (findByGithubErr, existingUser) => {
if (existingUser) {
done(null, existingUser);
return;
}
User.findOne({ email: profile._json.email }, (findByEmailErr, existingEmailUser) => {
const emails = getVerifiedEmails(profile.emails);
const primaryEmail = getPrimaryEmail(profile.emails);
User.findOne({
email: { $in: emails },
}, (findByEmailErr, existingEmailUser) => {
if (existingEmailUser) {
existingEmailUser.email = existingEmailUser.email || profile._json.email;
existingEmailUser.email = existingEmailUser.email || primaryEmail;
existingEmailUser.github = profile.id;
existingEmailUser.username = existingEmailUser.username || profile.username;
existingEmailUser.tokens.push({ kind: 'github', accessToken });
@ -57,7 +87,7 @@ passport.use(new GitHubStrategy({
existingEmailUser.save(saveErr => done(null, existingEmailUser));
} else {
const user = new User();
user.email = profile._json.email;
user.email = primaryEmail;
user.github = profile.id;
user.username = profile.username;
user.tokens.push({ kind: 'github', accessToken });