diff --git a/admin/admin.js b/admin/admin.js
index 5e4b7c7..4a95c8b 100644
--- a/admin/admin.js
+++ b/admin/admin.js
@@ -48,6 +48,10 @@ module.exports=
{
page = "./posts.js";
}
+ else if(filename.includes("/users"))
+ {
+ page = "./users.js";
+ }
require(page).main(postData, templateContext).then(function(template)
{
@@ -61,7 +65,8 @@ module.exports=
}
else
{
- require("./login/login.js").main(request, clientAddress, templateContext).then(function()
+ require("./login/login.js").main(request, clientAddress, templateContext)
+ .then(function()
{
resolve();
}).catch(function(err)
diff --git a/admin/users.js b/admin/users.js
new file mode 100644
index 0000000..b0d1c4c
--- /dev/null
+++ b/admin/users.js
@@ -0,0 +1,175 @@
+/**
+ * File which deals with adding and removing downloads from
+ * the admin section of the website.
+ *
+ * @author Jeffery Russell 6-30-18
+ */
+
+/** Whiskers template file */
+const TEMPLATE_FILE = "admin/adminUsers.html";
+
+
+const includes = require('../includes/includes.js');
+
+//updates db
+const sql = require('../utils/sql');
+
+//parses post data
+const qs = require('querystring');
+
+
+/**
+ * Processes post requests from the addDownload form
+ *
+ * @param postData
+ * @returns {*|Promise}
+ */
+const addUserPostData = function(postData)
+{
+ return new Promise(function(resolve, reject)
+ {
+ const post = qs.parse(postData);
+ if(post.add_user)
+ {
+ sql.addUser(post.add_user_name, post.add_user_password)
+ .then(function()
+ {
+ resolve();
+ }).catch(function(error)
+ {
+ reject(error);
+ })
+ }
+ else
+ {
+ resolve();
+ }
+ });
+};
+
+
+/**
+ * Removes a download if requested by the
+ * post data from an admin.
+ */
+const removeUserPost = function(postData)
+{
+ return new Promise(function(resolve, reject)
+ {
+ const post = qs.parse(postData);
+ console.log(post);
+ if(post.delete_user)
+ {
+ console.log("Removing user: " + post.delete_user);
+ sql.removeUser(post.delete_user).then(function()
+ {
+ resolve();
+ }).catch(function(err)
+ {
+ reject(err);
+ });
+ }
+ else
+ {
+ resolve();
+ }
+ });
+};
+
+
+/**
+ * Processes post data to determine if the user requested that
+ * a user be updated in the database.
+ */
+const editUserPost = function(postData, templateContext)
+{
+ return new Promise(function(resolve, reject)
+ {
+ const post = qs.parse(postData);
+ if(post.edit_user)
+ {
+ sql.getUserByID(post.edit_user).then(function(user)
+ {
+ if(user.length == 1)
+ {
+ templateContext.edit_user = post.edit_user;
+ templateContext.user_name = user[0].user_name;
+ resolve();
+ }
+ else
+ {
+ resolve();
+ }
+ }).catch(function(err)
+ {
+ reject(err);
+ });
+ }
+ else if(post.edit_user_2)
+ {
+ sql.updateUser(post.edit_user_2, post.edit_user_name, post.edit_user_password)
+ .then(function()
+ {
+ resolve();
+ })
+ }
+ else
+ {
+ resolve();
+ }
+ });
+};
+
+
+/**
+ * Fetches the download items in the database so that
+ * the template engine can use it to display them in
+ * a table.
+ *
+ * @param templateContext-- context item used by whiskers
+ * @returns {Promise}
+ */
+const getUserInformation = function(templateContext)
+{
+ return new Promise(function(resolve, reject)
+ {
+ sql.getAllUsers().then(function(users)
+ {
+ templateContext.users = users;
+ resolve();
+ }).catch(function(error)
+ {
+ reject(error);
+ });
+ });
+};
+
+
+module.exports=
+ {
+ /** Fetches context information for the template and handles
+ * post data for the downloads.
+ *
+ * @param postData posted by user
+ * @param templateContext json object used as the template context
+ * @returns {Promise} renders the template used for this page
+ */
+ main: function(postData, templateContext)
+ {
+ return new Promise(function(resolve, reject)
+ {
+ Promise.all([includes.fetchTemplate(TEMPLATE_FILE),
+ addUserPostData(postData),
+ removeUserPost(postData),
+ editUserPost(postData, templateContext),
+ getUserInformation(templateContext)]).then(function(template)
+ {
+ resolve(template[0]);
+ }).catch(function(error)
+ {
+ console.log("error in add downloads.js");
+ reject(error);
+ });
+ });
+ }
+ };
\ No newline at end of file
diff --git a/includes/html/adminHeader.html b/includes/html/adminHeader.html
index a47e45b..6076443 100644
--- a/includes/html/adminHeader.html
+++ b/includes/html/adminHeader.html
@@ -58,7 +58,7 @@
-
diff --git a/templates/admin/adminUsers.html b/templates/admin/adminUsers.html
new file mode 100644
index 0000000..7c7b826
--- /dev/null
+++ b/templates/admin/adminUsers.html
@@ -0,0 +1,95 @@
+
+{if edit_user}
+
+{/if}
+
+
+
+
+
+
+
Users
+
+
+
+
+ User ID |
+ User Name |
+ Edit |
+ Delete |
+
+
+
+
+ {for user in users}
+
+
+ {user.user_id}
+ |
+
+ {user.user_name}
+ |
+
+
+ |
+
+
+ |
+
+ {/for}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/utils/sql.js b/utils/sql.js
index 6e48364..805dab6 100644
--- a/utils/sql.js
+++ b/utils/sql.js
@@ -56,6 +56,60 @@ const fetch = function(sqlStatement)
};
+/**
+ * Function used to use insert statements into the database
+ *
+ * Don't worry, the input gets sanitized
+ *
+ * @param sqlStatement
+ * @return the id of the new record - if there is one
+ */
+const insert = function(sqlStatement)
+{
+ return new Promise(function(resolve, reject)
+ {
+ con.query(sanitizer.sanitize(sqlStatement), function (err, result)
+ {
+ if (err)
+ {
+ console.log(err);
+ reject();
+ }
+ resolve(result.insertId);
+ });
+ })
+};
+
+
+/**
+ * Helper function to generate a hashed password
+ * from a given plain text password.
+ *
+ * This uses 64 bits of entropy as the random salt
+ * and uses sha256 hashing method to hash the password
+ * combined with the salt.
+ *
+ * @param password
+ * @returns {Object pass: hashedPassword, salt: salt used to hash}
+ */
+const createHashedPassword = function(password)
+{
+ const randBuff = crypto.randomBytes(64);
+
+ const salt = crypto.createHash('sha256').update(randBuff).digest('hex');
+
+ const hashPass = crypto.createHash('sha256')
+ .update(password + salt)
+ .digest('hex');
+
+ var hashPassObject = new Object();
+ hashPassObject.pass = hashPass;
+ hashPassObject.salt = salt;
+
+ return hashPassObject;
+};
+
+
/**
* Helper function which fetches the category url for all the
* posts returned in the posts table and appends them to the
@@ -95,30 +149,6 @@ const fetchWithCategoryInformation = function(sqlPosts)
module.exports=
{
- /**
- * Function used to use insert statements into the database
- *
- * Don't worry, the input gets sanitized
- *
- * @param sqlStatement
- * @return the id of the new record - if there is one
- */
- insert : function(sqlStatement)
- {
- return new Promise(function(resolve, reject)
- {
- con.query(sanitizer.sanitize(sqlStatement), function (err, result)
- {
- if (err)
- {
- console.log(err);
- reject();
- }
- resolve(result.insertId);
- });
- })
- },
-
/**
* function which fetches the sql info on a post based on it's sql id
* @param id
@@ -187,7 +217,7 @@ module.exports=
*/
getCategories : function()
{
- var q = "select * from categories";
+ const q = "select * from categories";
return fetch(q);
},
@@ -343,6 +373,59 @@ module.exports=
return fetch("select * from posts order by published desc");
},
+ getAllUsers: function()
+ {
+ return fetch("select * from users");
+ },
+
+ getUserByID: function(userID)
+ {
+ const cleanID = sanitizer.sanitize(userID);
+
+ const q = "select * from users where user_id='" + cleanID + "'";
+
+ return fetch(q);
+ },
+
+
+
+ removeUser: function(user_id)
+ {
+ const cleanID = sanitizer.sanitize(user_id);
+
+ return insert("delete from users where user_id='" + cleanID + "'");
+ },
+
+ addUser: function(username, password)
+ {
+ const cleanName = sanitizer.sanitize(username);
+ const cleanPassword = sanitizer.sanitize(password);
+ const hashedPassword = createHashedPassword(cleanPassword);
+
+ const q = "insert into users(user_name, password, salt) values('" + cleanName + "'," +
+ "'" + hashedPassword.pass + "','" + hashedPassword.salt + "')";
+
+
+ return insert(q);
+ },
+
+
+ updateUser: function(userID, username, password)
+ {
+ const cleanID = sanitizer.sanitize(userID);
+ const cleanName = sanitizer.sanitize(username);
+ const cleanPassword = sanitizer.sanitize(password);
+ const hashedPassword = createHashedPassword(cleanPassword);
+
+ const q = "update users " +
+ "set user_name='" + cleanName + "'" +
+ ",password='" + hashedPassword.pass + "'" +
+ ",salt='" + hashedPassword.salt + "'" +
+ " where user_id='" + cleanID + "'";
+
+ return insert(q);
+ },
+
/**
* Fetches the sql category information based on it's id
@@ -397,7 +480,7 @@ module.exports=
(sqlRow[0].download_count + 1) + "' where download_id='" +
sqlRow[0].download_id + "'";
console.log(q);
- module.exports.insert(q).then(function(r)
+ insert(q).then(function(r)
{
resolve(sqlRow);
}).catch(function(err)
@@ -436,7 +519,7 @@ module.exports=
const q = "insert into downloads (name, file, download_count) " +
"values('" + name + "', '" + file + "', '0')";
- return module.exports.insert(q);
+ return insert(q);
},
@@ -448,7 +531,7 @@ module.exports=
{
const q = "delete from downloads where download_id='" + id + "'";
- return module.exports.insert(q);
+ return insert(q);
},
@@ -478,7 +561,7 @@ module.exports=
console.log(q);
- return module.exports.insert(q);
+ return insert(q);
},
@@ -551,6 +634,6 @@ module.exports=
const q = "insert into traffic_log (url, ip, date) values " +
"('" + page + "', '" + ip + "', now())";
- module.exports.insert(q);
+ insert(q);
}
};
\ No newline at end of file
diff --git a/utils/utils.js b/utils/utils.js
index f32ee38..376bc89 100644
--- a/utils/utils.js
+++ b/utils/utils.js
@@ -149,29 +149,5 @@ module.exports=
print404: function()
{
return this.include("includes/html/404.html");
- },
-
-
- /**
- * Displays 404 error to user
- *
- * @param result
- * @returns {*}
- */
- printWrongHost: function()
- {
- return this.include("includes/html/incorrectHost.html");
- },
-
-
- /**
- * Displays a ban message to the user
- *
- * @param result
- * @returns {*}
- */
- printBannedPage: function()
- {
- return this.include("includes/html/banHammer.html");
}
};
\ No newline at end of file