diff --git a/assets/styles/gargoyle.scss b/assets/styles/gargoyle.scss
index 763186f..79d402e 100644
--- a/assets/styles/gargoyle.scss
+++ b/assets/styles/gargoyle.scss
@@ -19,6 +19,12 @@ a{
}
}
+header{
+ h1{
+ text-align: center;
+ }
+}
+
.button.button-primary,
button.button-primary,
input[type="button"].button-primary,
@@ -56,6 +62,7 @@ input[type="submit"].button-primary{
}
.nav-bar-right{
float: right;
+ margin-right: 35px;
}
ul{
diff --git a/index.js b/index.js
index 08b71fd..22a63c4 100644
--- a/index.js
+++ b/index.js
@@ -42,6 +42,10 @@ app.use(express.urlencoded({
extended: true,
}));
+// load middleware
+const userSessionMiddleware = require('./src/middleware/user-session');
+app.use(userSessionMiddleware.userSession);
+
// load the template engine
app.set('view engine', 'twig');
@@ -50,12 +54,18 @@ app.use(express.static('public'));
// load route handlers
const homeRoutes = require('./src/routes/home');
+const authRoutes = require('./src/routes/auth');
const itemRoutes = require('./src/routes/item');
const licenseRoutes = require('./src/routes/license');
const searchRoutes = require('./src/routes/search');
// register route handlers
app.get('/', homeRoutes.getIndex);
+app.get('/auth/register', authRoutes.getRegister);
+app.post('/auth/register', authRoutes.postRegister);
+app.get('/auth/login', authRoutes.getLogin);
+app.post('/auth/login', authRoutes.postLogin);
+app.get('/auth/logout', authRoutes.getLogout);
app.get('/item/add', itemRoutes.getAdd);
app.post('/item/add', itemRoutes.postAdd);
app.get('/item/:id', itemRoutes.getItem);
diff --git a/migrations/0003_add_users_table.js b/migrations/0003_add_users_table.js
new file mode 100644
index 0000000..8e378c0
--- /dev/null
+++ b/migrations/0003_add_users_table.js
@@ -0,0 +1,44 @@
+module.exports = {
+ up: (queryInterface, Sequelize) => {
+ return queryInterface.createTable('users', {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ primaryKey: true,
+ type: Sequelize.INTEGER
+ },
+ username: {
+ type: Sequelize.DataTypes.STRING,
+ allowNull: false,
+ unique: true,
+ },
+ email: {
+ type: Sequelize.DataTypes.STRING,
+ allowNull: false,
+ unique: true,
+ },
+ password: {
+ type: Sequelize.DataTypes.STRING,
+ allowNull: false,
+ },
+ salt: {
+ type: Sequelize.DataTypes.STRING,
+ allowNull: false,
+ },
+ firstName: {
+ type: Sequelize.DataTypes.STRING,
+ allowNull: true,
+ },
+ lastName: {
+ type: Sequelize.DataTypes.STRING,
+ allowNull: true,
+ },
+ createdAt: Sequelize.DataTypes.DATE,
+ updatedAt: Sequelize.DataTypes.DATE,
+ });
+ },
+
+ down: (queryInterface, Sequelize) => {
+ return queryInterface.dropTable('users');
+ }
+};
diff --git a/src/middleware/user-session.js b/src/middleware/user-session.js
new file mode 100644
index 0000000..386c17a
--- /dev/null
+++ b/src/middleware/user-session.js
@@ -0,0 +1,18 @@
+const db = require('../models');
+const User = db.users;
+
+// checks if a session user ID is set, and if so grab the user's info
+exports.userSession = async function(req, res, next) {
+ if ('user' in req.session) {
+ const user = await User.findAll({
+ where: {
+ id: req.session.user,
+ },
+ });
+
+ // pass user info to views
+ res.locals.user = user[0];
+ }
+
+ next();
+};
diff --git a/src/models/index.js b/src/models/index.js
index c5736ea..937fcfb 100644
--- a/src/models/index.js
+++ b/src/models/index.js
@@ -10,6 +10,7 @@ db.sequelize = sequelize;
db.items = require('./item.js')(sequelize, Sequelize);
db.licenses = require('./license.js')(sequelize, Sequelize);
+db.users = require('./user.js')(sequelize, Sequelize);
module.exports = db;
diff --git a/src/models/user.js b/src/models/user.js
new file mode 100644
index 0000000..a69a2e3
--- /dev/null
+++ b/src/models/user.js
@@ -0,0 +1,39 @@
+module.exports = (sequelize, Sequelize) => {
+ const User = sequelize.define('user', {
+
+ username: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ unique: true,
+ },
+
+ email: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ unique: true,
+ },
+
+ password: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ },
+
+ salt: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ },
+
+ firstName: {
+ type: Sequelize.STRING,
+ allowNull: true,
+ },
+
+ lastName: {
+ type: Sequelize.STRING,
+ allowNull: true,
+ },
+
+ });
+
+ return User;
+};
diff --git a/src/routes/auth.js b/src/routes/auth.js
new file mode 100644
index 0000000..f192972
--- /dev/null
+++ b/src/routes/auth.js
@@ -0,0 +1,58 @@
+const db = require('../models');
+const User = db.users;
+const crypto = require('crypto');
+
+// GET - /auth/login
+exports.getLogin = async function(req, res) {
+ res.render('auth/login.twig');
+};
+
+// POST - /auth/login
+exports.postLogin = async function(req, res) {
+ const user = await User.findAll({
+ where: {
+ username: req.body.login_username,
+ },
+ });
+
+ const attemptedKey = crypto.pbkdf2Sync(req.body.login_password, user[0].salt, 10000, 64, 'sha512');
+ const attemptedHash = attemptedKey.toString('hex');
+
+ if (attemptedHash == user[0].password) {
+ req.session.user = user[0].id;
+ res.redirect('/');
+ } else {
+ res.redirect('/auth/login');
+ }
+}
+
+// GET - /auth/register
+exports.getRegister = async function(req, res) {
+ res.render('auth/register.twig');
+};
+
+// POST - /auth/register
+exports.postRegister = async function(req, res) {
+ const passwordSalt = crypto.randomBytes(32).toString('base64');
+ const passwordKey = crypto.pbkdf2Sync(req.body.register_password, passwordSalt, 10000, 64, 'sha512');
+ const passwordHash = passwordKey.toString('hex');
+
+ const user = await User.create({
+ username: req.body.register_username,
+ password: passwordHash,
+ salt: passwordSalt,
+ email: req.body.register_email,
+ firstName: req.body.register_first_name,
+ lastName: req.body.register_last_name,
+ });
+
+ res.redirect('/');
+};
+
+// GET - /auth/logout
+exports.getLogout = async function(req, res) {
+ // destroy the user's session
+ req.session.destroy();
+
+ res.redirect('/');
+}
diff --git a/views/auth/login.twig b/views/auth/login.twig
new file mode 100644
index 0000000..aab7874
--- /dev/null
+++ b/views/auth/login.twig
@@ -0,0 +1,40 @@
+{% extends 'layout.twig' %}
+
+{% block title %}Home{% endblock %}
+
+{% block content %}
+
+
+ . .Login to your account.
+ Register for a new account.
+