const Raven = require('raven')
const GithubStrategy = require('passport-github2').Strategy
const axios = require('axios');
const models = require('../../../db/models').models
const config = require('../../../../config')
const secrets = config.SECRETS
const debug = require('debug')('oauth:strategies:github')
const { generateReferralCode } = require('../../../utils/referral')
/**
* Authenticate _users_ using their Github Accounts
*/
module.exports = new GithubStrategy({
clientID: secrets.GITHUB_CONSUMER_KEY,
clientSecret: secrets.GITHUB_CONSUMER_SECRET,
callbackURL: config.SERVER_URL + config.GITHUB_CALLBACK,
passReqToCallback: true,
}, async function (req, token, tokenSecret, profile, cb) {
let profileJson = profile._json
console.log(profileJson);
try{
const config = {method:'get',headers:{'Authorization':`Bearer ${token}`}};
const result = await axios.get('https://api.github.com/user/emails',config);
let emailArr = result.data;
let primaryGithubEmail = emailArr.filter((email)=>{return email.primary;});
profileJson.email = primaryGithubEmail[0].email;
}catch(error){
console.log(error);
}
console.log('======== profile after request ============');
console.log(profileJson);
console.log('====================');
let oldUser = req.user
Raven.setContext({ extra: { file: 'githubstrategy' } })
try {
if (oldUser) {
debug('User exists, is connecting Github account')
/*
This means an already logged in users is trying to
connect Github to his account. Let us see if there
are any connections to his Github already
*/
const ghaccount = await models.UserGithub.findOne({ where: { id: profileJson.id } })
if (ghaccount) {
throw new Error('Your Github account is already linked with codingblocks account Id: ' + ghaccount.get('userId'))
} else {
await models.UserGithub.upsert({
id: profileJson.id,
token: token,
tokenSecret: tokenSecret,
username: profileJson.login,
userId: oldUser.id
})
const user = await models.User.findById(oldUser.id)
if (user) {
return cb(null, user.get())
} else {
return cb(null, false, { message: "Could not retrieve existing Github linked account" })
}
}
} else {
/*
This means either -
a. This is a new signup via Github
b. Someone is trying to login via Github
*/
let userGithub = await models.UserGithub.findOne({
include: [models.User],
where: { id: profileJson.id }
})
/*
If userGithub exists then
Case (a): login
*/
if (!userGithub) {
/*
If there is any user with verified email equal to the email comming from github strategy , then create a new entry in userGithub table and login that user
*/
const userWithVerifiedEmail = await models.User.findOne({
where: {
verifiedemail: profileJson.email
}
})
if (userWithVerifiedEmail) {
userGithub = await models.UserGithub.create({
id: profileJson.id,
token: token,
tokenSecret: tokenSecret,
username: profileJson.login,
userId: userWithVerifiedEmail.get('id'),
})
return cb(null, userWithVerifiedEmail.get());
}
/*
Case (b): New Signup
First ensure there aren't already users with the same email
id that comes from Github
*/
let existingUsers = [];
if (profileJson.email) {
existingUsers = await models.User.findAll({
include: [{
model: models.UserGithub,
attributes: ['id'],
required: false
}],
where: {
email: profileJson.email,
'$usergithub.id$': { $eq: null }
}
})
}
if (existingUsers && existingUsers.length > 0) {
let oldIds = existingUsers.map(eu => eu.id).join(',')
return cb(null, false, {
message: `
Your email id "${profileJson.email}" is already used in the following Coding Blocks Account(s):
[ ${oldIds} ]
Please log into your old account and connect Github in it instead.
Use 'Forgot Password' option if you do not remember password of old account`
})
}
/* Check if users with same username exist. Modify username accordingly */
const existCount = await models.User.count({ where: { username: profileJson.login } })
userGithub = await models.UserGithub.create({
id: profileJson.id,
token: token,
tokenSecret: tokenSecret,
username: profileJson.login,
user: {
username: existCount === 0 ? profileJson.login : profileJson.login + "-gh",
firstname: profileJson.name ? profileJson.name.split(' ')[0] : profileJson.login,
email: profileJson.email,
referralCode: generateReferralCode(profileJson.email).toUpperCase(),
photo: profileJson.avatar_url,
verifiedemail: profileJson.email,
marketing_meta: req.session.marketingMeta
}
}, {
include: [models.User],
})
req.visitor.event({
ea: 'successful',
ec: 'signup',
el: 'github'
}).send()
req.session.isNewSignup = true
if (!userGithub) {
return cb(null, false, { message: 'Authentication Failed' })
}
}
return cb(null, userGithub.user.get())
}
} catch (err) {
Raven.captureException(err)
cb(null, false, { message: err.message })
}
})
当我在我的系统上本地运行此代码时,它工作正常,但是一旦我将代码发送到登台和生产,我就会收到错误
{ Error: Request failed with status code 404
0|oneauth | at createError (/home/codingblocks/servers/khaate/node_modules/axios/lib/core/createError.js:16:15)
0|oneauth | at settle (/home/codingblocks/servers/khaate/node_modules/axios/lib/core/settle.js:17:12)
0|oneauth | at IncomingMessage.handleStreamEnd (/home/codingblocks/servers/khaate/node_modules/axios/lib/adapters/http.js:236:11)
0|oneauth | at IncomingMessage.emit (events.js:203:15)
0|oneauth | at IncomingMessage.EventEmitter.emit (domain.js:466:23)
0|oneauth | at IncomingMessage.wrapped (/home/codingblocks/servers/khaate/node_modules/newrelic/lib/transaction/tracer/index.js:188:22)
...............
我无法理解为什么会出现此错误并且我也无法获取用户电子邮件,但在本地此代码工作正常,我能够获取与用户的 github 关联的所有电子邮件。