mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-06-02 07:59:56 -04:00
Update to support optional email register and signin
This commit is contained in:
parent
52772829ce
commit
a73d9ce39e
14 changed files with 180 additions and 16 deletions
27
lib/auth.js
27
lib/auth.js
|
@ -7,6 +7,8 @@ var GithubStrategy = require('passport-github').Strategy;
|
|||
var GitlabStrategy = require('passport-gitlab2').Strategy;
|
||||
var DropboxStrategy = require('passport-dropbox-oauth2').Strategy;
|
||||
var GoogleStrategy = require('passport-google-oauth20').Strategy;
|
||||
var LocalStrategy = require('passport-local').Strategy;
|
||||
var validator = require('validator');
|
||||
|
||||
//core
|
||||
var config = require('./config.js');
|
||||
|
@ -35,12 +37,10 @@ function callback(accessToken, refreshToken, profile, done) {
|
|||
if (user.accessToken != accessToken) {
|
||||
user.accessToken = accessToken;
|
||||
needSave = true;
|
||||
|
||||
}
|
||||
if (user.refreshToken != refreshToken) {
|
||||
user.refreshToken = refreshToken;
|
||||
needSave = true;
|
||||
|
||||
}
|
||||
if (needSave) {
|
||||
user.save().then(function () {
|
||||
|
@ -57,7 +57,7 @@ function callback(accessToken, refreshToken, profile, done) {
|
|||
}).catch(function (err) {
|
||||
logger.error('auth callback failed: ' + err);
|
||||
return done(err, null);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
//facebook
|
||||
|
@ -109,4 +109,25 @@ if (config.google) {
|
|||
clientSecret: config.google.clientSecret,
|
||||
callbackURL: config.serverurl + '/auth/google/callback'
|
||||
}, callback));
|
||||
}
|
||||
// email
|
||||
if (config.email) {
|
||||
passport.use(new LocalStrategy({
|
||||
usernameField: 'email'
|
||||
},
|
||||
function(email, password, done) {
|
||||
if (!validator.isEmail(email)) return done(null, false);
|
||||
models.User.findOne({
|
||||
where: {
|
||||
email: email
|
||||
}
|
||||
}).then(function (user) {
|
||||
if (!user) return done(null, false);
|
||||
if (!user.verifyPassword(password)) return done(null, false);
|
||||
return done(null, user);
|
||||
}).catch(function (err) {
|
||||
logger.error(err);
|
||||
return done(err);
|
||||
});
|
||||
}));
|
||||
}
|
|
@ -94,6 +94,7 @@ var google = (process.env.HMD_GOOGLE_CLIENTID && process.env.HMD_GOOGLE_CLIENTSE
|
|||
clientSecret: process.env.HMD_GOOGLE_CLIENTSECRET
|
||||
} : config.google || false;
|
||||
var imgur = process.env.HMD_IMGUR_CLIENTID || config.imgur || false;
|
||||
var email = process.env.HMD_EMAIL || config.email || false;
|
||||
|
||||
function getserverurl() {
|
||||
var url = '';
|
||||
|
@ -151,6 +152,7 @@ module.exports = {
|
|||
dropbox: dropbox,
|
||||
google: google,
|
||||
imgur: imgur,
|
||||
email: email,
|
||||
imageUploadType: imageUploadType,
|
||||
s3: s3,
|
||||
s3bucket: s3bucket
|
||||
|
|
13
lib/migrations/20161201050312-support-email-signin.js
Normal file
13
lib/migrations/20161201050312-support-email-signin.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
up: function (queryInterface, Sequelize) {
|
||||
queryInterface.addColumn('Users', 'email', Sequelize.TEXT);
|
||||
queryInterface.addColumn('Users', 'password', Sequelize.TEXT);
|
||||
},
|
||||
|
||||
down: function (queryInterface, Sequelize) {
|
||||
queryInterface.removeColumn('Users', 'email', Sequelize.TEXT);
|
||||
queryInterface.removeColumn('Users', 'password', Sequelize.TEXT);
|
||||
}
|
||||
};
|
|
@ -3,6 +3,7 @@
|
|||
// external modules
|
||||
var md5 = require("blueimp-md5");
|
||||
var Sequelize = require("sequelize");
|
||||
var scrypt = require('scrypt');
|
||||
|
||||
// core
|
||||
var logger = require("../logger.js");
|
||||
|
@ -29,8 +30,30 @@ module.exports = function (sequelize, DataTypes) {
|
|||
},
|
||||
refreshToken: {
|
||||
type: DataTypes.STRING
|
||||
},
|
||||
email: {
|
||||
type: Sequelize.TEXT,
|
||||
validate: {
|
||||
isEmail: true
|
||||
}
|
||||
},
|
||||
password: {
|
||||
type: Sequelize.TEXT,
|
||||
set: function(value) {
|
||||
var hash = scrypt.kdfSync(value, scrypt.paramsSync(0.1)).toString("hex");
|
||||
this.setDataValue('password', hash);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
instanceMethods: {
|
||||
verifyPassword: function(attempt) {
|
||||
if (scrypt.verifyKdfSync(new Buffer(this.password, "hex"), attempt)) {
|
||||
return this;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
classMethods: {
|
||||
associate: function (models) {
|
||||
User.hasMany(models.Note, {
|
||||
|
@ -42,6 +65,9 @@ module.exports = function (sequelize, DataTypes) {
|
|||
constraints: false
|
||||
});
|
||||
},
|
||||
getProfile: function (user) {
|
||||
return user.profile ? User.parseProfile(user.profile) : (user.email ? User.parseProfileByEmail(user.email) : null);
|
||||
},
|
||||
parseProfile: function (profile) {
|
||||
try {
|
||||
var profile = JSON.parse(profile);
|
||||
|
@ -81,6 +107,13 @@ module.exports = function (sequelize, DataTypes) {
|
|||
break;
|
||||
}
|
||||
return photo;
|
||||
},
|
||||
parseProfileByEmail: function (email) {
|
||||
var photoUrl = 'https://www.gravatar.com/avatar/' + md5(email);
|
||||
return {
|
||||
name: email.substring(0, email.lastIndexOf("@")),
|
||||
photo: photoUrl += '?s=96'
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -131,7 +131,7 @@ function updateNote(note, callback) {
|
|||
}
|
||||
}).then(function (user) {
|
||||
if (!user) return callback(null, null);
|
||||
note.lastchangeuserprofile = models.User.parseProfile(user.profile);
|
||||
note.lastchangeuserprofile = models.User.getProfile(user);
|
||||
return finishUpdateNote(note, _note, callback);
|
||||
}).catch(function (err) {
|
||||
logger.error(err);
|
||||
|
@ -455,10 +455,10 @@ function startConnection(socket) {
|
|||
return failConnection(404, 'note not found', socket);
|
||||
}
|
||||
var owner = note.ownerId;
|
||||
var ownerprofile = note.owner ? models.User.parseProfile(note.owner.profile) : null;
|
||||
var ownerprofile = note.owner ? models.User.getProfile(note.owner) : null;
|
||||
|
||||
var lastchangeuser = note.lastchangeuserId;
|
||||
var lastchangeuserprofile = note.lastchangeuser ? models.User.parseProfile(note.lastchangeuser.profile) : null;
|
||||
var lastchangeuserprofile = note.lastchangeuser ? models.User.getProfile(note.lastchangeuser) : null;
|
||||
|
||||
var body = LZString.decompressFromBase64(note.content);
|
||||
var createtime = note.createdAt;
|
||||
|
@ -468,7 +468,7 @@ function startConnection(socket) {
|
|||
var authors = {};
|
||||
for (var i = 0; i < note.authors.length; i++) {
|
||||
var author = note.authors[i];
|
||||
var profile = models.User.parseProfile(author.user.profile);
|
||||
var profile = models.User.getProfile(author.user);
|
||||
authors[author.userId] = {
|
||||
userid: author.userId,
|
||||
color: author.color,
|
||||
|
@ -598,7 +598,7 @@ function buildUserOutData(user) {
|
|||
function updateUserData(socket, user) {
|
||||
//retrieve user data from passport
|
||||
if (socket.request.user && socket.request.user.logged_in) {
|
||||
var profile = models.User.parseProfile(socket.request.user.profile);
|
||||
var profile = models.User.getProfile(socket.request.user);
|
||||
user.photo = profile.photo;
|
||||
user.name = profile.name;
|
||||
user.userid = socket.request.user.id;
|
||||
|
|
|
@ -66,7 +66,10 @@ function showIndex(req, res, next) {
|
|||
gitlab: config.gitlab,
|
||||
dropbox: config.dropbox,
|
||||
google: config.google,
|
||||
signin: req.isAuthenticated()
|
||||
email: config.email,
|
||||
signin: req.isAuthenticated(),
|
||||
infoMessage: req.flash('info'),
|
||||
errorMessage: req.flash('error')
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -94,7 +97,8 @@ function responseHackMD(res, note) {
|
|||
github: config.github,
|
||||
gitlab: config.gitlab,
|
||||
dropbox: config.dropbox,
|
||||
google: config.google
|
||||
google: config.google,
|
||||
email: config.email
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -202,9 +206,9 @@ function showPublishNote(req, res, next) {
|
|||
body: body,
|
||||
useCDN: config.usecdn,
|
||||
owner: note.owner ? note.owner.id : null,
|
||||
ownerprofile: note.owner ? models.User.parseProfile(note.owner.profile) : null,
|
||||
ownerprofile: note.owner ? models.User.getProfile(note.owner) : null,
|
||||
lastchangeuser: note.lastchangeuser ? note.lastchangeuser.id : null,
|
||||
lastchangeuserprofile: note.lastchangeuser ? models.User.parseProfile(note.lastchangeuser.profile) : null,
|
||||
lastchangeuserprofile: note.lastchangeuser ? models.User.getProfile(note.lastchangeuser) : null,
|
||||
robots: meta.robots || false, //default allow robots
|
||||
GA: meta.GA,
|
||||
disqus: meta.disqus
|
||||
|
@ -591,9 +595,9 @@ function showPublishSlide(req, res, next) {
|
|||
meta: JSON.stringify(obj.meta || {}),
|
||||
useCDN: config.usecdn,
|
||||
owner: note.owner ? note.owner.id : null,
|
||||
ownerprofile: note.owner ? models.User.parseProfile(note.owner.profile) : null,
|
||||
ownerprofile: note.owner ? models.User.getProfile(note.owner) : null,
|
||||
lastchangeuser: note.lastchangeuser ? note.lastchangeuser.id : null,
|
||||
lastchangeuserprofile: note.lastchangeuser ? models.User.parseProfile(note.lastchangeuser.profile) : null,
|
||||
lastchangeuserprofile: note.lastchangeuser ? models.User.getProfile(note.lastchangeuser) : null,
|
||||
robots: meta.robots || false, //default allow robots
|
||||
GA: meta.GA,
|
||||
disqus: meta.disqus
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue