Added new note type

Better authentication
This commit is contained in:
Martin Donnelly 2020-03-21 21:22:12 +00:00
parent 9e172ef598
commit a4ebf90586
20 changed files with 1355 additions and 56 deletions

File diff suppressed because one or more lines are too long

2
dist/index.html vendored
View File

@ -1 +1 @@
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><title>Menus</title><link href=/css/app.65ce66e5.css rel=preload as=style><link href=/js/app.a4f9d1d7.js rel=preload as=script><link href=/js/chunk-vendors.979cbe79.js rel=preload as=script><link href=/css/app.65ce66e5.css rel=stylesheet></head><body><noscript><strong>We're sorry but vue_menu doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.979cbe79.js></script><script src=/js/app.a4f9d1d7.js></script></body></html>
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><title>Menus</title><link href=/css/app.5fa0b293.css rel=preload as=style><link href=/js/app.53dc46ec.js rel=preload as=script><link href=/js/chunk-vendors.979cbe79.js rel=preload as=script><link href=/css/app.5fa0b293.css rel=stylesheet></head><body><noscript><strong>We're sorry but vue_menu doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.979cbe79.js></script><script src=/js/app.53dc46ec.js></script></body></html>

2
dist/js/app.53dc46ec.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/js/app.53dc46ec.js.map vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -30,7 +30,8 @@ body {
top: 50%;
left: 50%;
margin: -150px 0 0 -150px;
width:300px;
min-width: 300px;
width:0.5vw;
height:300px;
}
.login h1 { color: #fff; text-shadow: 0 0 10px rgba(0,0,0,0.3); letter-spacing:1px; text-align:center; }
@ -42,7 +43,7 @@ input {
border: none;
outline: none;
padding: 10px;
font-size: 13px;
font-size: 1rem;
color: #fff;
text-shadow: 1px 1px 1px rgba(0,0,0,0.3);
border: 1px solid rgba(0,0,0,0.3);

View File

@ -2,6 +2,8 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv=X-UA-Compatible content="IE=edge">
<meta name=viewport content="width=device-width,initial-scale=1">
<title>Login</title>
<link href="/css/login.css" rel="stylesheet" type="text/css"/>
</head>

BIN
menu.db

Binary file not shown.

1119
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@
"backbone": "^1.4.0",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"dateformat": "^3.0.3",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"express-session": "^1.17.0",
@ -21,10 +22,16 @@
"lodash": "^4.17.15",
"markdown": "^0.5.0",
"minibus": "^3.1.0",
"node-cron": "^2.0.3",
"nosql": "^6.1.0",
"pug": "^2.0.4",
"schema-check": "0.0.7",
"short-hash": "^1.0.0",
"sqlite3": "^4.1.1"
"smtp-email-sender": "^1.0.0",
"sqlite3": "^4.1.1",
"tape": "^4.13.2",
"tape-promise": "^4.0.0",
"ultrases": "^0.1.3"
},
"devDependencies": {
"browserify": "^16.5.0",

10
pug/email.jade Normal file
View File

@ -0,0 +1,10 @@
html(lang="en")
head
meta(charset='utf-8')
title
Suggestions
body
h1 Suggestions for !{ts}
ol
each item in suggestions
li: a(href=item.url)= item.name

10
pug/email.pug Normal file
View File

@ -0,0 +1,10 @@
html(lang="en")
head
meta(charset='utf-8')
title
Suggestions
body
h1 Suggestions for !{ts}
ol
each item in suggestions
li: a(href=item.url)= item.name

View File

@ -1,3 +1,4 @@
require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const session = require('express-session');
@ -7,6 +8,9 @@ const cors = require('cors');
const db = require('./server/lib/loginmanager');
const doJob = require('./server/lib/job');
const checkAuth = require('./server/middle/checkAuth');
// create express app
const app = express();
require('dotenv').config();
@ -24,12 +28,17 @@ app.use(session({
'saveUninitialized': true
}));
app.get('/', function(request, response) {
if (request.session.loggedin !== true)
response.sendFile(path.join(`${__dirname }/server/static/login.html`));
else
response.redirect('/recipes.html');
app.get('/', (request, response) => {
if (request.session.auth)
response.redirect('/menu');
else
response.sendFile(path.join(`${__dirname}/server/static/login.html`));
});
app.get('/menu', checkAuth, (req, res) => {
res.sendFile(path.join(`${__dirname }/dist/index.html`));
});
app.use(express.static(path.join(__dirname, sitePath)));
// parse requests of content-type - application/x-www-form-urlencoded
@ -38,7 +47,7 @@ app.use(bodyParser.urlencoded({ 'extended': true }));
// parse requests of content-type - application/json
app.use(bodyParser.json());
app.post('/auth', function(request, response) {
app.post('/auth', (request, response) => {
const username = request.body.u;
const password = request.body.p;
@ -47,12 +56,12 @@ app.post('/auth', function(request, response) {
db.getOne(username, password)
.then((data) => {
if (!data)
response.send('Incorrect Username and/or Password!');
// response.send('Incorrect Username and/or Password!');
response.redirect('/');
else {
request.session.loggedin = true;
request.session.username = username;
response.redirect('/recipes.html');
request.session.auth = 'jhgkjgkjhgkjhgjkhgjkhgfhghfjgfjhgf';
response.redirect('/menu');
}
})
.catch((err) => {
@ -75,3 +84,8 @@ require('./server/routes/view.routes')(app);
app.listen(serverPort, () => {
console.log(`Server is listening on port ${serverPort}`);
});
((() => {
console.log('Menuizer started');
// doJob();
})());

39
server/lib/FoodObj.js Normal file
View File

@ -0,0 +1,39 @@
class FoodObj {
constructor(limit) {
this.limit = limit;
this.store = [];
this.types = [0, 0, 0, 0, 0, 0, 0];
}
get () {
return this.store;
}
getFirstFive() {
return (this.store.slice(0, 5));
}
getFirstFiveIDs() {
const outVal = this.store.slice(0, 5).map((item) => {
return item._id;
});
return (outVal);
}
add(item) {
// console.log('>>', item);
item.url = `https://menu.silvrtree.co.uk/view/${item.short}`;
if (this.types[item.meat] < this.limit) {
this.store.push(item);
this.types[item.meat]++;
}
}
count() {
return (this.store.slice(0, 5).length);
}
}
module.exports = FoodObj;

View File

@ -106,3 +106,50 @@ exports.updateOne = (data) => {
});
});
};
exports.getRandom = (timestamp) => {
const sql = 'SELECT _id, short, hash, name, meat, mealtype FROM menu where mealtype =1 and lastused<? order by RANDOM()';
const sqlTimestamp = ~~(timestamp / 1000);
return new Promise((resolve, reject) => {
db.all(sql, [sqlTimestamp], (err, rows) => {
if (err)
reject(err);
if (!err) {
const outgoing = [...rows];
resolve(outgoing) ;
}
});
});
};
exports.updateTimestamps = (newTimestamp, items) => {
const sqlTimestamp = ~~(newTimestamp / 1000);
console.log('>> items', items);
const sql = 'UPDATE menu SET lastused = $lastused WHERE _id = $in';
return new Promise((resolve, reject) => {
db.serialize(() => {
const stmt = db.prepare(sql);
items.forEach((item) => {
console.log(item);
const newData = { '$lastused':sqlTimestamp, '$in':item };
stmt.run(newData);
});
stmt.finalize((err) => {
if (err)
reject(err);
resolve({ 'msg':'Row updateds' });
});
});
});
};

61
server/lib/job.js Normal file
View File

@ -0,0 +1,61 @@
const dbmanager = require('./dbmanager');
const FoodObj = require('./FoodObj');
const pug = require('pug');
const dateFormat = require('dateformat');
const email = require('smtp-email-sender')({
'host': 'mail.caliban.io',
'port': '465',
'auth': {
'user': 'aida@caliban.io',
'pass': 'WaF#E+5am7.)\\csD',
'type': 'LOGIN' // PLAIN, LOGIN, MD5 etc...
},
'secure': 'secure'
});
function sendSMTP(data, newPath) {
const now = new Date();
const html = pug.renderFile(`${newPath}/` + 'pug/email.pug', data);
email({
'from': 'Aida <aida@caliban.io>',
'to': 'Aida <aida@caliban.io>',
// 'bcc': 'Martin <martind2000@gmail.com>, Jessica <ing.arvid@gmail.com>',
'bcc': 'Martin <martind2000@gmail.com>',
'subject': `Suggestions 🍽️ - ${dateFormat(now, 'dddd, mmmm dS, yyyy')}`,
'html': html
});
}
function pugTest(data, newpath) {
console.log(pug.renderFile(`${newpath}/` + 'pug/email.pug', data));
}
async function doJob() {
console.log('Doing job...');
const now = new Date();
const currentTS = ~~(now.getTime() / 86400000) * 86400000;
const pastTS = currentTS - (86400000 * 28);
const fo = new FoodObj(2);
await dbmanager.getRandom(pastTS).then((r) => {
// console.log(r);
for(const item of r)
fo.add(item);
});
if (fo.count() === 5) {
sendSMTP({ 'suggestions':fo.getFirstFive() }, './');
await dbmanager.updateTimestamps(currentTS, fo.getFirstFiveIDs()).then((r) => {
console.log(r);
});
} else {
console.log(`Not enough items, only got ${fo.count()}`);
}
}
module.exports = doJob;

View File

@ -0,0 +1,15 @@
function checkAuth(req, res, next) {
if (!req.session.auth)
// res.send('You are not authorized to view this page');
res.redirect('/');
else {
res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
next();
}
}
module.exports = checkAuth;
// https://stackoverflow.com/questions/7990890/how-to-implement-login-auth-in-node-js
// look aT JWT BIT AT BOTTOM

View File

@ -2,6 +2,8 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv=X-UA-Compatible content="IE=edge">
<meta name=viewport content="width=device-width,initial-scale=1">
<title>Login</title>
<style>
@import url(https://fonts.googleapis.com/css?family=Open+Sans);
@ -32,12 +34,13 @@
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3E1D6D', endColorstr='#092756',GradientType=1 );
}
.login {
position: absolute;
top: 50%;
left: 50%;
margin: -150px 0 0 -150px;
width:300px;
height:300px;
position: absolute;
top: 50%;
left: 50%;
margin: -150px 0 0 -150px;
min-width: 300px;
width:300px;
height:300px;
}
.login h1 { color: #fff; text-shadow: 0 0 10px rgba(0,0,0,0.3); letter-spacing:1px; text-align:center; }

35
tests/db.js Normal file
View File

@ -0,0 +1,35 @@
const tape = require('tape');
const _test = require('tape-promise').default; // <---- notice 'default'
const test = _test(tape); // decorate tape
const dbmanager = require('../server/lib/dbmanager');
const FoodObj = require('../server/lib/FoodObj');
test('DB tests', async function(t) {
const now = new Date();
const currentTS = ~~(now.getTime() / 86400000) * 86400000;
const pastTS = currentTS - (86400000 * 28);
console.log(currentTS);
const fo = new FoodObj(2);
await dbmanager.getRandom(pastTS).then((r) => {
// console.log(r);
for(const item of r)
fo.add(item);
console.log(fo.getFirstFive());
console.log(fo.getFirstFiveIDs());
});
await dbmanager.updateTimestamps(currentTS, fo.getFirstFiveIDs()).then((r) => {
console.log(r);
});
t.end();
});
// 1209600000