Fix #5: Support LDAP and DB, and pull from DB every access instead of caching in 'sessions'

Signed-off-by: James Ketrenos <james_git@ketrenos.com>
This commit is contained in:
James Ketr 2018-10-04 17:19:04 -07:00
parent 8f8a6887a0
commit 568db0ad54
2 changed files with 117 additions and 50 deletions

View File

@ -161,13 +161,7 @@ app.use(basePath, function(req, res, next) {
html: hb.compile(templates.html)(user) html: hb.compile(templates.html)(user)
}; };
req.session.user = { req.session.userId = user.id;
name: user.displayName,
mail: user.mail,
username: user.uid,
authenticated: user.authenticated,
mailVerified: user.mailVerified
};
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
let attempts = 10; let attempts = 10;
@ -217,25 +211,59 @@ app.use(function(err, req, res, next) {
/* Everything below here requires a successful authentication */ /* Everything below here requires a successful authentication */
app.use(basePath, function(req, res, next) { app.use(basePath, function(req, res, next) {
if (!req.session || !req.session.user || !req.session.user.username) { if (!req.session || !req.session.userId) {
return res.status(401).send("Unauthorized"); return res.status(401).send("Unauthorized");
} }
if (config.has("restrictions")) { if (req.session.userId == "LDAP") {
if (req.session.ldapUser) {
req.user = req.session.ldapUser;
return next();
}
req.session.userId = null;
req.session.ldapUser = null;
return res.status(401).send("Invalid LDAP session");
}
let query = "SELECT uid AS username,displayName,mailVerified,authenticated,memberSince AS name,mail " +
"FROM users WHERE id=:id";
return userDB.sequelize.query(query, {
replacements: {
id: req.session.userId
},
type: userDB.Sequelize.QueryTypes.SELECT,
raw: true
}).then(function(results) {
if (results.length != 1) {
return res.status(401).send("Invalid account");
}
req.user = results[0];
if (!req.user.authenticated) {
return res.status(401).send("Accout not authenticated.");
}
if (!req.user.mailVerified) {
return res.status(401).send("Account mail not verified.");
}
if (!config.has("restrictions")) {
return next();
}
let allowed = config.get("restrictions"); let allowed = config.get("restrictions");
if (!Array.isArray(allowed)) { if (!Array.isArray(allowed)) {
allowed = [ allowed ]; allowed = [ allowed ];
} }
for (let i = 0; i < allowed.length; i++) { for (let i = 0; i < allowed.length; i++) {
if (allowed[i] == req.session.user.username) { if (allowed[i] == req.user.username) {
return next(); return next();
} }
} }
console.log("Unauthorized (logged in) access by user: " + req.session.user.username); console.log("Unauthorized (logged in) access by user: " + req.user.username);
return res.status(401).send("Unauthorized"); return res.status(401).send("Unauthorized");
} });
return next();
}); });
app.use(basePath, express.static(picturesPath, { index: false })); app.use(basePath, express.static(picturesPath, { index: false }));

View File

@ -29,12 +29,11 @@ require("../db/users").then(function(db) {
}); });
router.get("/", function(req, res/*, next*/) { router.get("/", function(req, res/*, next*/) {
console.log("/users"); console.log("/users/");
return getSessionUser(req).then(function(user) {
if (req.session.user) { req.user = user;
return res.status(200).send(req.session.user); return res.status(200).send(req.user);
} });
return res.status(200).send({});
}); });
const templates = { const templates = {
@ -79,6 +78,8 @@ function ldapPromise(username, password) {
} }
router.post("/create", function(req, res) { router.post("/create", function(req, res) {
console.log("/users/create");
let who = req.query.w || req.body.w || "", let who = req.query.w || req.body.w || "",
password = req.query.p || req.body.p || "", password = req.query.p || req.body.p || "",
name = req.query.n || req.body.n || "", name = req.query.n || req.body.n || "",
@ -93,7 +94,8 @@ router.post("/create", function(req, res) {
replacements: { replacements: {
username: mail username: mail
}, },
type: userDB.Sequelize.QueryTypes.SELECT type: userDB.Sequelize.QueryTypes.SELECT,
raw: true
}).then(function(results) { }).then(function(results) {
if (results.length != 0) { if (results.length != 0) {
return res.status(400).send("Email address already used."); return res.status(400).send("Email address already used.");
@ -125,12 +127,15 @@ router.post("/create", function(req, res) {
notes: who notes: who
} }
}).spread(function(results, metadata) { }).spread(function(results, metadata) {
req.session.userId = metadata.lastID;
return userDB.sequelize.query("INSERT INTO authentications " + return userDB.sequelize.query("INSERT INTO authentications " +
"(userId,issued,key,type) VALUES " + "(userId,issued,key,type) VALUES " +
"(:userId,CURRENT_TIMESTAMP,:key,'account-setup')", { "(:userId,CURRENT_TIMESTAMP,:key,'account-setup')", {
replacements: { replacements: {
key: secret, key: secret,
userId: metadata.lastID userId: req.session.userId
} }
}).catch(function(error) { }).catch(function(error) {
console.log(error); console.log(error);
@ -176,19 +181,43 @@ router.post("/create", function(req, res) {
send(envelope); send(envelope);
}); });
}).then(function() { }).then(function() {
req.session.user = { return getSessionUser(req).then(function(user) {
name: name, return res.status(200).send(user);
mail: mail, });
username: mail,
authenticated: false,
mailVerified: false
};
return res.status(200).send(req.session.user);
}); });
}); });
}); });
const getSessionUser = function(req) {
if (!req.session.userId) {
return Promise.resolve({});
}
if (req.session.userId == "LDAP") {
return Promise.resolve(req.session.ldapUser);
}
let query = "SELECT " +
"uid AS username,displayName,mailVerified,authenticated,memberSince AS name,mail " +
"FROM users WHERE id=:id";
return userDB.sequelize.query(query, {
replacements: {
id: req.session.userId
},
type: userDB.Sequelize.QueryTypes.SELECT,
raw: true
}).then(function(results) {
if (results.length != 1) {
return {};
}
return results[0];
});
}
router.post("/login", function(req, res) { router.post("/login", function(req, res) {
console.log("/users/login");
let username = req.query.u || req.body.u || "", let username = req.query.u || req.body.u || "",
password = req.query.p || req.body.p || ""; password = req.query.p || req.body.p || "";
@ -199,15 +228,23 @@ router.post("/login", function(req, res) {
} }
/* We use LDAP as the primary authenticator; if the user is not /* We use LDAP as the primary authenticator; if the user is not
* found there, we look them up in the site-specific user database */ * found there, we look the user up in the site-specific user database */
return ldapPromise(username, password).then(function(user) { return ldapPromise(username, password).then(function(user) {
user.name = user.displayName;
user.username = user.uid;
user.id = "LDAP";
user.mail = user.mail;
user.authenticated = 1; user.authenticated = 1;
user.mailVerified = 1; user.mailVerified = 1;
req.session.userId = "LDAP";
req.session.ldapUser = user;
return user; return user;
}).catch(function() { }).catch(function() {
console.log("User not found in LDAP. Looking up in DB."); console.log("User not found in LDAP. Looking up in DB.");
let query = "SELECT * FROM users WHERE uid=:username AND password=:password"; let query = "SELECT " +
"id,mailVerified,authenticated,uid AS username,displayName AS name,mail " +
"FROM users WHERE uid=:username AND password=:password";
return userDB.sequelize.query(query, { return userDB.sequelize.query(query, {
replacements: { replacements: {
username: username, username: username,
@ -218,40 +255,42 @@ router.post("/login", function(req, res) {
if (users.length != 1) { if (users.length != 1) {
return null; return null;
} }
return users[0]; let user = users[0];
req.session.userId = user.id;
return user;
}); });
}).then(function(user) { }).then(function(user) {
if (!user) { if (!user) {
console.log(username + " not found (or invalid password.)"); console.log(username + " not found (or invalid password.)");
req.session.user = {}; req.session.userId = null;
return res.status(401).send("Invalid login credentials"); return res.status(401).send("Invalid login credentials");
} }
req.session.user = { let message = "Logged in as " + user.name + " (" + user.id + ")";
name: user.displayName,
mail: user.mail,
username: user.uid,
authenticated: user.authenticated,
mailVerified: user.mailVerified
};
if (!user.mailVerified) { if (!user.mailVerified) {
console.log("Logged in as " + user.displayName + ", who is not verified email."); console.log(message + ", who is not verified email.");
} else if (!user.authenticated) { } else if (!user.authenticated) {
console.log("Logged in as " + user.displayName + ", who is not authenticated."); console.log(message + ", who is not authenticated.");
} else { } else {
console.log("Logging in as " + user.displayName); console.log(message);
} }
return res.status(200).send(req.session.user); delete user.id;
return res.status(200).send(user);
}); });
}); });
router.get("/logout", function(req, res) { router.get("/logout", function(req, res) {
if (req.session && req.session.user) { console.log("/users/logout");
req.session.user = {};
if (req.session && req.session.userId) {
if (req.session.userId == "LDAP") {
req.session.ldapUser = null;
} }
res.status(200).send(req.session.user); req.session.userId = null;
}
res.status(200).send({});
}); });
module.exports = router; module.exports = router;