From 698cd6a2024dfa6b46af3c1349d9ac2b32495a09 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Thu, 27 Sep 2018 15:26:37 -0700 Subject: [PATCH] Login and account creation working Signed-off-by: James Ketrenos --- frontend/src/ketr-photos/ketr-photos.html | 88 +++++++++++++++++++---- server/routes/users.js | 65 +++++++++++++++-- server/scanner.js | 5 +- 3 files changed, 137 insertions(+), 21 deletions(-) diff --git a/frontend/src/ketr-photos/ketr-photos.html b/frontend/src/ketr-photos/ketr-photos.html index 34b5552..93bac98 100755 --- a/frontend/src/ketr-photos/ketr-photos.html +++ b/frontend/src/ketr-photos/ketr-photos.html @@ -377,7 +377,11 @@ Unfortunately, I haven't built this part of the site yet... send me an email (james @ ketrenos.com) and I'll create an account for you. - close + + + + +
create
@@ -399,6 +403,14 @@ type: String, value: "" }, + name: { + type: String, + value: "" + }, + mail: { + type: String, + value: "" + }, years: { type: Array, value: [] @@ -462,19 +474,23 @@ return !username || username == "" || !password || password == ""; }, + disableCreate: function(username, name, mail, password) { + return !username || username == "" || + !password || password == "" || + !name || name == "" || + !mail || mail == ""; + }, + enterCheck: function(event) { if (event.key == 'Enter') { - if (event.currentTarget.id == "username") { - event.preventDefault(); - this.async(function() { - this.$.password._focusableElement.focus(); - }, 100); - return; - } - - if (event.currentTarget.id == "password") { - event.preventDefault(); - this.login(); + var next = event.currentTarget.nextElementSibling; + event.preventDefault(); + if (next.tagName.toLowerCase() == "paper-button") { + next.click(); + } else { + this.async(function(next) { + next._focusableElement.focus(); + }.bind(this, next), 100); return; } } @@ -516,6 +532,7 @@ this.loading = false; this.password = ""; var user; + if (error) { this.user = null; this.$.toast.text = error; @@ -543,6 +560,53 @@ }.bind(this), null, "POST", { u: this.username, p: this.password }); }, + create: function(event) { + if (this.loading) { + return; + } + this.loading = true; + this.loggingIn = true; + this.user = null; + window.fetch("api/v1/users/create", function(error, xhr) { + this.loggingIn = false; + this.loading = false; + this.password = ""; + var user; + + this.$.requestAccess.close(); + + if (error) { + this.user = null; + this.$.toast.text = error; + this.$.toast.setAttribute("error", true); + this.$.toast.updateStyles(); + this.$.toast.show(); + console.error("Invalid login information."); + return; + } + + try { + user = JSON.parse(xhr.responseText); + } catch(___) { + this.$.toast.text = "Unable to load/parse user information."; + this.$.toast.setAttribute("error", true); + this.$.toast.updateStyles(); + this.$.toast.show(); + console.error("Unable to parse user information"); + return; + } + + if (user && user.username) { + this.user = user; + } + }.bind(this), null, "POST", { + u: this.username, + p: this.password, + n: this.name, + m: this.mail + }); + }, + logout: function(event) { window.fetch("api/v1/users/logout", function(error, xhr) { this.user = null; diff --git a/server/routes/users.js b/server/routes/users.js index 03be8ec..18fb306 100755 --- a/server/routes/users.js +++ b/server/routes/users.js @@ -2,7 +2,8 @@ const express = require("express"), config = require("config"), - LdapAuth = require("ldapauth-fork"); + LdapAuth = require("ldapauth-fork"), + crypto = require("crypto"); const router = express.Router(); @@ -29,7 +30,7 @@ router.get("/", function(req, res/*, next*/) { function ldapPromise(username, password) { if (!ldap) { - throw "LDAP not being used"; + return Promise.reject("LDAP not being used"); } return new Promise(function(resolve, reject) { ldap.authenticate(username, password, function(error, user) { @@ -41,6 +42,51 @@ function ldapPromise(username, password) { }); } +router.post("/create", function(req, res) { + let username = req.query.u || req.body.u || "", + password = req.query.p || req.body.p || "", + name = req.query.n || req.body.n || username, + mail = req.query.m || req.body.m; + + if (!username || !password || !mail || !name) { + return res.status(400).send("Missing user id, name, password, and/or email"); + } + + let query = "SELECT * FROM users WHERE uid=:username"; + return userDB.sequelize.query(query, { + replacements: { + username: username + }, + type: userDB.Sequelize.QueryTypes.SELECT + }).then(function(results) { + if (results.length != 0) { + return res.status(400).send("Username already exists."); + } + + return userDB.sequelize.query("INSERT INTO users " + + "(uid,displayName,password,mail,memberSince,authenticated) " + + "VALUES(:username,:name,:password,:mail,CURRENT_TIMESTAMP,0)", { + replacements: { + username: username, + name: name, + password: crypto.createHash('sha256').update(password).digest('base64'), + mail: mail + } + }).then(function(results) { +/* + req.session.user = { + name: name, + mail: mail, + username: username, + }; + return res.status(200).send(req.session.user); +*/ + req.session.user = {}; + return res.status(401).send("Account has not been authenticated."); + }); + }); +}); + router.post("/login", function(req, res) { let username = req.query.u || req.body.u || "", password = req.query.p || req.body.p || ""; @@ -51,23 +97,24 @@ router.post("/login", function(req, res) { return res.status(400).send("Missing username and/or password"); } - /* We use LDAP as the primary authenticator; if the user is not - * found there, we look them up in the site-specific user database */ + /* We use LDAP as the primary authenticator; if the user is not + * found there, we look them up in the site-specific user database */ return ldapPromise(username, password).then(function(user) { return user; }).catch(function() { - let query = "SELECT * FROM users WHERE uid=:username"; + console.log("User not found in LDAP. Looking up in DB."); + let query = "SELECT * FROM users WHERE uid=:username AND password=:password"; return userDB.sequelize.query(query, { replacements: { username: username, + password: crypto.createHash('sha256').update(password).digest('base64') }, type: userDB.Sequelize.QueryTypes.SELECT }).then(function(users) { if (users.length != 1) { return null; } - return users[0]; }); }).then(function(user) { @@ -77,6 +124,12 @@ router.post("/login", function(req, res) { return res.status(401).send("Invalid login credentials"); } + if (!user.authenticated) { + console.log(username + " not authenticated."); + req.session.user = {}; + return res.status(401).send("Account has not been authenticated."); + } + console.log("Logging in as " + user.displayName); req.session.user = { diff --git a/server/scanner.js b/server/scanner.js index a4a3a74..14e9ee3 100755 --- a/server/scanner.js +++ b/server/scanner.js @@ -246,8 +246,6 @@ function processBlock(items) { created = asset.stats.ctime, albumId = asset.album.id; - console.log(picturesPath, path, file); - let tmp = Promise.resolve(file); /* If this is a Nikon RAW file, convert it to JPG and move to /raw dir */ if (rawExtension.exec(file)) { @@ -401,7 +399,7 @@ function scanDir(parent, path) { allAssetCount: 0, allAlbumCount: 0 }, albums = [ album ], assets = []; - + return new Promise(function(resolve, reject) { fs.readdir(path, function(error, files) { if (error) { @@ -496,6 +494,7 @@ function findOrCreateDBAlbum(album) { if (!album.parent) { console.warn("Creating top level album: " + picturesPath); } + console.log("album: " + album.path); return photoDB.sequelize.query("INSERT INTO albums (path,parentId,name) VALUES(:path,:parentId,:name)", { replacements: album }).spread(function(results, metadata) {