river-of-ebooks/config/protocols.js

167 lines
5.0 KiB
JavaScript
Raw Normal View History

2018-11-02 00:21:36 +00:00
// Passport protocol configurations
2018-11-07 20:06:36 +00:00
const crypto = require('crypto')
const base64URL = require('base64url')
2018-11-02 00:21:36 +00:00
module.exports.protocols = {
local: {
/**
* Validate a login request
*
* Looks up a user using the supplied identifier (email or username) and then
* attempts to find a local Passport associated with the user. If a Passport is
* found, its password is checked against the password supplied in the form.
*
* @param {Object} req
* @param {string} identifier
* @param {string} password
* @param {Function} next
*/
login: async function (req, identifier, password, next) {
if (!validateEmail(identifier)) {
2018-11-07 20:06:36 +00:00
return next(new Error('invalid email address'), false)
2018-11-02 00:21:36 +00:00
}
try {
const user = await User.findOne({
email: identifier
2018-11-07 20:06:36 +00:00
})
2018-11-12 22:12:16 +00:00
if (!user) throw new Error('an account with that email was not found')
2018-11-02 00:21:36 +00:00
const passport = await Passport.findOne({
protocol: 'local',
user: user.id
2018-11-07 20:06:36 +00:00
})
2018-11-02 00:21:36 +00:00
if (passport) {
2018-11-07 20:06:36 +00:00
const res = await Passport.validatePassword(password, passport)
2018-11-12 22:12:16 +00:00
if (!res) throw new Error('incorrect password')
2018-11-07 20:06:36 +00:00
return next(null, user)
2018-11-02 00:21:36 +00:00
} else {
2018-11-07 20:06:36 +00:00
throw new Error('that account does not have password login enabled')
2018-11-02 00:21:36 +00:00
}
} catch (e) {
2018-11-07 20:06:36 +00:00
return next(e, false)
2018-11-02 00:21:36 +00:00
}
},
register: async function (user, next) {
try {
2018-11-07 20:06:36 +00:00
const token = generateToken()
const password = user.password
2018-11-12 22:12:16 +00:00
if (!password.length) throw new Error('password cannot be blank')
2018-11-07 20:06:36 +00:00
delete user.password
2018-11-02 00:21:36 +00:00
2018-11-07 20:06:36 +00:00
const newUser = await User.create(user).fetch()
2018-11-02 00:21:36 +00:00
try {
await Passport.create({
protocol: 'local',
password,
user: newUser.id,
2018-11-19 20:34:13 +00:00
accesstoken: token
2018-11-07 20:06:36 +00:00
})
return next(null, token)
2018-11-02 00:21:36 +00:00
} catch (e) {
2018-11-07 20:06:36 +00:00
await User.destroy(newUser.id)
throw e
2018-11-02 00:21:36 +00:00
}
} catch (e) {
2018-11-07 20:06:36 +00:00
return next(e)
2018-11-02 00:21:36 +00:00
}
},
update: async function (user, next) {
2019-02-04 21:08:45 +00:00
try {
const dbUser = await User.findOne({
id: user.id
})
if (!dbUser) throw new Error('An account with that id was not found.')
2019-02-04 21:08:45 +00:00
const passport = await Passport.findOne({
protocol: 'local',
user: user.id
})
if (!user.currentPassword && passport) throw new Error('Please enter your current password.')
2019-02-04 21:08:45 +00:00
if (passport) {
const res = await Passport.validatePassword(user.currentPassword, passport)
if (!res) throw new Error('incorrect password')
const otherUser = await User.findOne({ email: user.email })
if (otherUser && otherUser.id !== dbUser.id) throw new Error('There is already an account with that email.')
2019-02-04 21:08:45 +00:00
await User.update({ id: user.id }, {
email: user.email
})
if (user.password && user.password.length) {
await Passport.update({ id: passport.id }, {
password: user.password
})
}
} else { // no password yet, add one
const otherUser = await User.findOne({ email: user.email })
if (otherUser && otherUser.id !== dbUser.id) throw new Error('There is already an account with that email.')
2019-02-04 21:08:45 +00:00
await User.update({ id: user.id }, {
email: user.email
})
if (user.password && user.password.length) {
const token = generateToken()
await Passport.create({
protocol: 'local',
password: user.password,
user: dbUser.id,
accesstoken: token
})
}
}
delete dbUser.password
next(null, dbUser)
} catch (e) {
return next(e)
}
2018-11-02 00:21:36 +00:00
},
connect: async function (req, res, next) {
try {
2018-11-07 20:06:36 +00:00
const user = req.user
const password = req.param('password')
2018-11-02 00:21:36 +00:00
const pass = await Passport.findOne({
protocol: 'local',
user: user.id
2018-11-07 20:06:36 +00:00
})
2018-11-02 00:21:36 +00:00
if (!pass) {
await Passport.create({
protocol: 'local',
password,
user: user.id
2018-11-07 20:06:36 +00:00
})
2018-11-02 00:21:36 +00:00
} else {
2018-11-07 20:06:36 +00:00
return next(null, user)
2018-11-02 00:21:36 +00:00
}
} catch (e) {
2018-11-07 20:06:36 +00:00
return next(e)
2018-11-02 00:21:36 +00:00
}
}
},
oauth2: {
login: async function (req, accessToken, refreshToken, profile, next) {
try {
const passportHelper = await sails.helpers.passport()
await passportHelper.connect(req, {
tokens: {
accessToken,
refreshToken
},
identifier: profile.id,
protocol: 'oauth2'
}, profile, next)
} catch (e) {
return next(e, false)
}
}
2018-11-02 00:21:36 +00:00
}
2018-11-07 20:06:36 +00:00
}
2018-11-02 00:21:36 +00:00
const EMAIL_REGEX = /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i
2018-11-02 00:21:36 +00:00
function validateEmail (email) {
2018-11-07 20:06:36 +00:00
return EMAIL_REGEX.test(email)
2018-11-02 00:21:36 +00:00
}
function generateToken () {
2018-11-07 20:06:36 +00:00
return base64URL(crypto.randomBytes(48))
2018-11-02 00:21:36 +00:00
}