aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Powers <markppowers0@gmail.com>2019-02-02 10:51:10 -0500
committerMark Powers <markppowers0@gmail.com>2019-02-02 10:51:10 -0500
commitc21eba4246be5c9831705a86592b45c70648c167 (patch)
tree0e4470f574ab77287a1ad40f196b1643dd0b1c7d
parentd1162d1bd12cbb3eae9889768adbbb293852c066 (diff)
Add admin panel
-rw-r--r--package-lock.json99
-rw-r--r--package.json2
-rw-r--r--src/html/admin.html2
-rw-r--r--src/html/bread.html2
-rw-r--r--src/html/index.html2
-rw-r--r--src/html/login.html25
-rw-r--r--src/index.js28
-rw-r--r--src/server.js58
8 files changed, 199 insertions, 19 deletions
diff --git a/package-lock.json b/package-lock.json
index 2fe6214..17a85b3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -107,6 +107,11 @@
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.1.3.tgz",
"integrity": "sha512-rDFIzgXcof0jDyjNosjv4Sno77X4KuPeFxG2XZZv1/Kc8DRVGVADdoQyyOVDwPqL36DDmtCQbrpMCqvpPLJQ0w=="
},
+ "buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
+ },
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
@@ -203,6 +208,15 @@
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
},
+ "cookie-parser": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.3.tgz",
+ "integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=",
+ "requires": {
+ "cookie": "0.3.1",
+ "cookie-signature": "1.0.6"
+ }
+ },
"cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
@@ -272,6 +286,14 @@
"safer-buffer": "^2.1.0"
}
},
+ "ecdsa-sig-formatter": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz",
+ "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=",
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -512,6 +534,29 @@
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
+ "jsonwebtoken": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.4.0.tgz",
+ "integrity": "sha512-coyXjRTCy0pw5WYBpMvWOMN+Kjaik2MwTUIq9cna/W7NpO9E+iYbumZONAz3hcr+tXFJECoQVrtmIoC3Oz0gvg==",
+ "requires": {
+ "jws": "^3.1.5",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
+ "ms": "^2.1.1"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+ }
+ }
+ },
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -523,11 +568,65 @@
"verror": "1.10.0"
}
},
+ "jwa": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.2.0.tgz",
+ "integrity": "sha512-Grku9ZST5NNQ3hqNUodSkDfEBqAmGA1R8yiyPHOnLzEKI0GaCQC/XhFmsheXYuXzFQJdILbh+lYBiliqG5R/Vg==",
+ "requires": {
+ "buffer-equal-constant-time": "1.0.1",
+ "ecdsa-sig-formatter": "1.0.10",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "jws": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.1.tgz",
+ "integrity": "sha512-bGA2omSrFUkd72dhh05bIAN832znP4wOU3lfuXtRBuGTbsmNmDXMQg28f0Vsxaxgk4myF5YkKQpz6qeRpMgX9g==",
+ "requires": {
+ "jwa": "^1.2.0",
+ "safe-buffer": "^5.0.1"
+ }
+ },
"lodash": {
"version": "4.17.11",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
},
+ "lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
+ },
+ "lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
+ },
+ "lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
+ },
+ "lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
+ },
+ "lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
+ },
+ "lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
+ },
+ "lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
+ },
"long": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
diff --git a/package.json b/package.json
index 716b581..ae9a975 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,9 @@
"dependencies": {
"body-parser": "^1.18.3",
"bootstrap": "^4.1.3",
+ "cookie-parser": "^1.4.3",
"express": "^4.16.4",
+ "jsonwebtoken": "^8.4.0",
"multer": "^1.4.1",
"mysql2": "^1.6.4",
"request": "^2.88.0",
diff --git a/src/html/admin.html b/src/html/admin.html
index 7c87ba6..d0d2e81 100644
--- a/src/html/admin.html
+++ b/src/html/admin.html
@@ -27,7 +27,7 @@
<option value="index">Index</option>
</select>
</div>
- <input type="submit">
+ <input type="submit" value="Submit">
</form>
</div>
</div>
diff --git a/src/html/bread.html b/src/html/bread.html
index e6eeb47..1ce1478 100644
--- a/src/html/bread.html
+++ b/src/html/bread.html
@@ -18,7 +18,7 @@
},
created() {
fetch(new Request('/posts/bread')).then(response => response.json())
- .then(response => this.posts = response.data);
+ .then(response => this.posts = response);
}
});
}
diff --git a/src/html/index.html b/src/html/index.html
index c7e398b..01f6e4e 100644
--- a/src/html/index.html
+++ b/src/html/index.html
@@ -19,7 +19,7 @@
},
created() {
fetch(new Request('/posts/index')).then(response => response.json())
- .then(response => this.posts = response.data);
+ .then(response => this.posts = response);
}
});
}
diff --git a/src/html/login.html b/src/html/login.html
new file mode 100644
index 0000000..53a2d06
--- /dev/null
+++ b/src/html/login.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html lang="en">
+
+<head>
+ <title>Mark's Kitchen - Login</title>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+ <link rel="stylesheet" type="text/css" href="/css/bootstrap.css">
+ <link rel="stylesheet" type="text/css" href="/css/styles.css">
+</head>
+
+<body>
+ <div>
+ <h1>Login</h1>
+ <div class="form">
+ <form action="/login" method="post" enctype="application/x-www-form-urlencoded">
+ <input type="text" placeholder="Enter Username" name="username" required>
+ <input type="password" placeholder="Enter Password" name="password" required>
+ <input type="submit">
+ </form>
+ </div>
+ </div>
+</body>
+
+</html> \ No newline at end of file
diff --git a/src/index.js b/src/index.js
index b47824a..925a166 100644
--- a/src/index.js
+++ b/src/index.js
@@ -2,8 +2,21 @@ const server = require('./server');
const Sequelize = require('sequelize');
const fs = require('fs');
const path = require('path');
+const jwt = require('jsonwebtoken');
-const dbCreds = JSON.parse(fs.readFileSync(path.join(__dirname, 'config.json'))).database;
+const config = JSON.parse(fs.readFileSync(path.join(__dirname, 'config.json')));
+
+const dbCreds = config.database;
+const secret = config.jwt_secret;
+
+const jwtFunctions = {
+ sign: function(message) {
+ return jwt.sign({ value: message }, secret);
+ },
+ verify: function(token) {
+ return jwt.verify(token, secret).value;
+ }
+}
const database = new Sequelize(dbCreds.database, dbCreds.user, dbCreds.password, {
logging(str) {
@@ -43,7 +56,16 @@ function setUpModels(){
},}),
"pictures": database.define('pictures', {
source: { type: Sequelize.TEXT, allowNull: false},
- })
+ }),
+ "users": database.define('user', {
+ username: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ },
+ password: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ },})
}
models.pictures.belongsTo(models.posts);
return models;
@@ -52,6 +74,6 @@ function setUpModels(){
const models = setUpModels();
sync();
-server.setUpRoutes(models);
+server.setUpRoutes(models, jwtFunctions);
server.listen();
diff --git a/src/server.js b/src/server.js
index 4cf76d1..c6630e8 100644
--- a/src/server.js
+++ b/src/server.js
@@ -1,6 +1,8 @@
const express = require('express');
const bodyParser = require('body-parser');
+const cookieParser = require('cookie-parser');
const request = require('request');
+const crypto = require('crypto');
const multer = require('multer');
var storage = multer.diskStorage({
@@ -8,13 +10,10 @@ var storage = multer.diskStorage({
cb(null, 'src/uploads/')
},
filename: function (req, file, cb) {
- console.log(file);
var ext = "";
if(file.originalname.includes(".")){
ext = "." + file.originalname.split(".")[1];
- console.log(ext);
}
- console.log(ext);
return cb(null, 'img-' + Date.now()+ext)
}
})
@@ -24,21 +23,46 @@ const port = 80;
const server = express();
// server.use(bodyParser.json());
+server.use(cookieParser())
server.use(bodyParser.urlencoded({ extended: true }));
+// Route logging
server.use(function (req, res, next) {
console.debug("express:", req.method, req.originalUrl);
next()
})
-
function listen(){
server.listen(port, () => console.info(`Listening on port ${port}!`));
}
-function setUpRoutes(models){
+function setUpRoutes(models, jwtFunctions){
+ // Authentication routine
+ server.use(function(req, res, next) {
+ if(req.path.startsWith("/admin")){
+ let cookie = req.cookies.authorization
+ if (!cookie) {
+ res.redirect('/login');
+ }
+ try {
+ const decryptedUserId = jwtFunctions.verify(cookie);
+ models.users.findOne({where: {username: decryptedUserId}}).then((user, error) => {
+ if (user) {
+ res.locals.user = user.get({ plain: true });
+ } else {
+ res.redirect('/login');
+ }
+ });
+ } catch (e){
+ res.status(400).send(e.message);
+ }
+ }
+ next();
+ })
+
server.get('/', (req, res) => res.sendFile(__dirname + "/html/index.html"))
server.get('/index', (req, res) => res.sendFile(__dirname + "/html/index.html"))
server.get('/admin', (req, res) => res.sendFile(__dirname + "/html/admin.html"));
+ server.get('/login', (req, res) => res.sendFile(__dirname + "/html/login.html"))
server.get('/bread', (req, res) => res.sendFile(__dirname + "/html/bread.html"));
server.get('/essay', (req, res) => res.sendFile(__dirname + "/html/essay.html"));
server.get('/snake', (req, res) => res.sendFile(__dirname + "/html/snake.html"));
@@ -55,16 +79,15 @@ function setUpRoutes(models){
const images = await models.pictures.findAll({ attributes: ["source"], where: { postId: post.id }}).map(x => x.source);
post.images = images;
}
- res.status(200).send({ success: true, data: posts });
+ res.status(200).send(posts);
next();
} catch (e) {
- res.status(400).send({ success: false, error: e.message });
+ res.status(400).send(e.message);
}
})
server.post('/posts', upload.array('images'), async (req, res, next) => {
try {
console.log(req.body);
-
const type = req.body.type
const newPost = await models.posts.create(req.body);
req.files.forEach(async (file) => {
@@ -75,8 +98,21 @@ function setUpRoutes(models){
res.redirect(`/${type}`);
next();
} catch (e) {
- res.status(400).send({ success: false, error: e.message });
+ res.status(400).send(e.message);
+ }
+ })
+ server.post('/login', async (req, res, next) => {
+ console.log(req.body);
+ const hash = crypto.createHash("sha512").update(req.body.password, "binary").digest("base64");
+ console.log(hash);
+ const user = await models.users.findOne({where: { username: req.body.username, password: hash }})
+ if(user){
+ const token = jwtFunctions.sign(user.username);
+ res.redirect('/admin');
+ } else {
+ res.redirect('/login');
}
+ next();
})
@@ -84,10 +120,6 @@ function setUpRoutes(models){
server.get('/css/:id', (req, res) => {
res.sendFile(__dirname + "/css/"+req.params.id);
});
- server.get('/photo/:id', (req, res) => {
- // res.setHeater("Content-Type", "image")
- res.sendFile(__dirname + "/photo/"+req.params.id);
- });
server.get('/uploads/:id', (req, res) => {
res.sendFile(__dirname + "/uploads/"+req.params.id);
});