summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorWu Cheng-Han2016-12-02 01:58:14 +0800
committerWu Cheng-Han2016-12-02 01:58:14 +0800
commita73d9ce39e2107b2a9628003f05900d4a641bee5 (patch)
tree15778b1a6e3322bfe6e6c7a68f2c6e31f4c34844 /lib
parent52772829ce8ccc7eac1fe1df9ace65d90ef36a2c (diff)
Update to support optional email register and signin
Diffstat (limited to 'lib')
-rw-r--r--lib/auth.js27
-rw-r--r--lib/config.js2
-rw-r--r--lib/migrations/20161201050312-support-email-signin.js13
-rw-r--r--lib/models/user.js33
-rw-r--r--lib/realtime.js10
-rwxr-xr-xlib/response.js16
6 files changed, 87 insertions, 14 deletions
diff --git a/lib/auth.js b/lib/auth.js
index 76a962f5..f167cede 100644
--- a/lib/auth.js
+++ b/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);
+ });
+ }));
} \ No newline at end of file
diff --git a/lib/config.js b/lib/config.js
index a906dfa4..669fcaa8 100644
--- a/lib/config.js
+++ b/lib/config.js
@@ -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
diff --git a/lib/migrations/20161201050312-support-email-signin.js b/lib/migrations/20161201050312-support-email-signin.js
new file mode 100644
index 00000000..bdea7c8c
--- /dev/null
+++ b/lib/migrations/20161201050312-support-email-signin.js
@@ -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);
+ }
+};
diff --git a/lib/models/user.js b/lib/models/user.js
index 7272f688..aaf344de 100644
--- a/lib/models/user.js
+++ b/lib/models/user.js
@@ -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'
+ };
}
}
});
diff --git a/lib/realtime.js b/lib/realtime.js
index b50e05b2..73f831f4 100644
--- a/lib/realtime.js
+++ b/lib/realtime.js
@@ -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;
diff --git a/lib/response.js b/lib/response.js
index 0004f824..aae39851 100755
--- a/lib/response.js
+++ b/lib/response.js
@@ -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