From 1d3574d38909bc9aae2792d839023e296fb25791 Mon Sep 17 00:00:00 2001 From: Mark Powers Date: Thu, 23 Dec 2021 16:50:42 -0600 Subject: Add email unsubcribe link, update about me, add hello.js --- src/html/admin.html | 13 +++++++++- src/html/email-confirm.html | 23 ++++++++++++++++++ src/html/email-success.html | 2 +- src/html/email-unsubscribe.html | 23 ++++++++++++++++++ src/index.js | 8 ++++-- src/js/hello.js | 6 +++++ src/server.js | 23 +++++++++++++++--- src/templates/about.html | 54 ++++++++++++++++++++++++++++++++--------- src/templates/blog-single.html | 3 ++- src/templates/blog.html | 2 +- src/templates/bread.html | 2 +- src/templates/index.html | 1 + src/templates/projects.html | 2 +- src/templates/tags.html | 2 +- 14 files changed, 141 insertions(+), 23 deletions(-) create mode 100644 src/html/email-confirm.html create mode 100644 src/html/email-unsubscribe.html create mode 100644 src/js/hello.js diff --git a/src/html/admin.html b/src/html/admin.html index 29e4b87..d15598a 100644 --- a/src/html/admin.html +++ b/src/html/admin.html @@ -18,7 +18,7 @@ showSessionTable: false, showUrlTable: false, showLogData: false, - showEmailData: false, + showEmailData: true, }, created() { fetch(new Request('/admin/stats')).then(response => response.json()) @@ -28,6 +28,15 @@ } }); } + function delete_email(id, name){ + if (confirm(`Delete ${name}?`)) { + let path = `/admin/email/${id}` + fetch(new Request(path, { + method: 'delete', + })).then(response => response.json()) + .then(response => this.emails = response); + } + } @@ -130,10 +139,12 @@ Name Address + {{item.name}} {{item.address}} + diff --git a/src/html/email-confirm.html b/src/html/email-confirm.html new file mode 100644 index 0000000..b0ee130 --- /dev/null +++ b/src/html/email-confirm.html @@ -0,0 +1,23 @@ + + + + + Mark's Kitchen - Email + + + + + + + +
+

+ < + Unsubcribe? +

+ Click to unsubscribe! +
+ + + + diff --git a/src/html/email-success.html b/src/html/email-success.html index 65bc2e5..11350df 100644 --- a/src/html/email-success.html +++ b/src/html/email-success.html @@ -15,7 +15,7 @@ < Email -

Success, thank you!

+

Success, thank you!

diff --git a/src/html/email-unsubscribe.html b/src/html/email-unsubscribe.html new file mode 100644 index 0000000..37acf97 --- /dev/null +++ b/src/html/email-unsubscribe.html @@ -0,0 +1,23 @@ + + + + + Mark's Kitchen - Email + + + + + + + +
+

+ < + Email +

+

You are now unsubscribed!

+
+ + + + diff --git a/src/index.js b/src/index.js index c2ad0c1..a7dff9b 100644 --- a/src/index.js +++ b/src/index.js @@ -87,7 +87,8 @@ function setUpModels(){ }), "emails": database.define('email', { address: Sequelize.STRING, - name: Sequelize.STRING + name: Sequelize.STRING, + code: Sequelize.STRING, }), "wordsquares": database.define('wordsquare', { words: Sequelize.STRING, @@ -99,7 +100,10 @@ function setUpModels(){ name: {type:Sequelize.STRING, primaryKey: true}, turn: Sequelize.STRING, userside: Sequelize.STRING - }) + }), + "hellos": database.define('hellos', { + page: { type: Sequelize.TEXT, allowNull: false}, + }), } models.pictures.belongsTo(models.posts); models.tags.belongsTo(models.posts); diff --git a/src/js/hello.js b/src/js/hello.js new file mode 100644 index 0000000..ab67810 --- /dev/null +++ b/src/js/hello.js @@ -0,0 +1,6 @@ +// Just says hello to the server. No personal information is stored, this +// just tells me when someone real (or a bot running JS) visits my site. +function hello(){ + fetch(`/hello/${encodeURIComponent(location.pathname)}`) +} +window.onload = hello diff --git a/src/server.js b/src/server.js index e680266..b2b8d25 100644 --- a/src/server.js +++ b/src/server.js @@ -220,6 +220,7 @@ function setUpRoutes(models, jwtFunctions, database, templates) { server.get('/login', cache('5 minutes'), (req, res) => res.sendFile(__dirname + "/html/login.html")) server.get('/email', cache('5 minutes'), (req, res) => res.sendFile(__dirname + "/html/email.html")) server.get('/email-success', cache('5 minutes'), (req, res) => res.sendFile(__dirname + "/html/email-success.html")) + server.get('/email-unsubscribe', cache('5 minutes'), (req, res) => res.sendFile(__dirname + "/html/email-unsubscribe.html")) server.get('/feed', cache('5 minutes'), (req, res) => res.sendFile(__dirname + "/html/feed.html")); server.get('/essay', cache('5 minutes'), (req, res) => res.sendFile(__dirname + "/html/essay.html")); server.get('/word-square', cache('5 minutes'), (req, res) => res.sendFile(__dirname + "/html/word-square.html")); @@ -228,6 +229,10 @@ function setUpRoutes(models, jwtFunctions, database, templates) { server.get('/zines', cache('5 minutes'), (req, res) => res.sendFile(__dirname + "/public/zines.html")); server.use('/static', express.static(__dirname + '/public')) + server.get('/hello/:path', async (req, res) => { + await models.hellos.create({page: req.params.path}) + res.status(200).send() + }) server.get('/misc', cache('5 minutes'), async (req, res) => { let body = templates["misc"](); res.status(200).send(body) @@ -272,7 +277,7 @@ function setUpRoutes(models, jwtFunctions, database, templates) { try { var sessionResult = await database.query("SELECT session, count(id) as c FROM requests GROUP BY session HAVING c > 1", { type: database.QueryTypes.SELECT }) var total = await database.query("select count(distinct session) as t FROM requests", { type: database.QueryTypes.SELECT }) - var urlResult = await database.query("SELECT method, url, count(id) as c FROM requests GROUP BY method, url", { type: database.QueryTypes.SELECT }) + var urlResult = await database.query("SELECT method, url, count(id) as c FROM requests GROUP BY method, url ORDER BY c DESC", { type: database.QueryTypes.SELECT }) let urls = (await get_routes(models)).map(obj => obj.route) urlResult = urlResult.filter(obj => { return urls.includes(obj.url) }) var logResult = await database.query("SELECT createdAt, session, method, url FROM requests order by createdAt desc limit 15", { type: database.QueryTypes.SELECT }) @@ -334,6 +339,11 @@ function setUpRoutes(models, jwtFunctions, database, templates) { res.status(400).send(e.message); } }) + server.delete('/admin/email/:id', async (req, res, next) => { + await models.emails.destroy({ where: { id: req.params.id } }); + var emails = await models.emails.findAll(); + res.status(200).send(emails); + }) server.post('/login', async (req, res, next) => { const user = await models.users.findOne({ where: { username: req.body.username} }) const hash = hashWithSalt(req.body.password, user.salt) @@ -351,12 +361,20 @@ function setUpRoutes(models, jwtFunctions, database, templates) { const name = req.body.name; const email = req.body.email; if (name && email) { - models.emails.create({"name": name, "address": email}) + const code = crypto.randomBytes(40).toString('hex').slice(0, 40) + models.emails.create({"name": name, "address": email, "code": code}) res.redirect('/email-success'); } else { console.debug("Error with email submission") } }) + server.get('/email/unsubscribe/:code/check', async (req, res, next) => { + res.sendFile(__dirname + "/html/email-confirm.html") + }) + server.get('/email/unsubscribe/:code/confirm', async (req, res, next) => { + await models.emails.destroy({ where: {"code": req.params.code}}) + res.redirect('/email-unsubscribe'); + }) server.post('/wordsquares', async (req, res, next) => { const words = req.body.words; const name = req.body.name; @@ -384,7 +402,6 @@ function setUpRoutes(models, jwtFunctions, database, templates) { res.status(200).send(game); }) - server.get('/favicon.ico', cache('5 minutes'), (req, res) => res.sendFile(__dirname + "/icon/favicon.ico")) server.get('/favicon.svg', cache('5 minutes'), (req, res) => res.sendFile(__dirname + "/icon/favicon.svg")) server.get('/css/:id', cache('5 minutes'), (req, res) => { diff --git a/src/templates/about.html b/src/templates/about.html index 800a47a..703e78b 100644 --- a/src/templates/about.html +++ b/src/templates/about.html @@ -2,7 +2,7 @@ - Mark's Kitchen - About + Mark's Kitchen — About {{> header}} @@ -29,20 +29,21 @@
Software engineer at Chameleon Cloud
Location
-
Chicagoland
+
Chicagoland. Previously, Madison and West Michigan
Almae Matres
Hope College, UW-Madison
Source Code
- Gitweb - or - GitHub +
Social
-
markp
+
markp@fosstodon
Hobbies
@@ -50,14 +51,45 @@ chess, cooking, disc golf
-
Operating System
-
Regolith Linux
+
Operating System
+
+ Regolith Linux — I like how little fuss Ubuntu is, it runs any I + want without too much hassle. Regolith is great for people like me, + who are also want to try/use i3 in an environment they are + comfortable with. +
-
Editor
-
vim
+
Editor
+
+ Vim — I stick mostly to defaults. I like that pretty much on any + system, it'll have this editor that I am used to, and Vim is + very powerful with enough practice. +
-
Pets
+
Pets
One very fluffy black cat, one shorthair kitten
+ +
Erdos Number
+
3 — Myself ↔ Charles A. Cusack ↔ Charles J. Colbourn ↔ Paul Erdos
+ +
Articles
+
+

+ Cusack, Charles A., Aaron Green, Airat Bekmetjev, and Mark Powers. + "Graph pebbling algorithms and Lemke graphs." + Discrete Applied Mathematics 262 (2019): 72-82. +

+

+ Cusack, Charles A., Airat Bekmetjev, and Mark Powers. + "Two-pebbling and odd-two-pebbling are not equivalent." + Discrete Mathematics 342, no. 3 (2019): 777-783. +

+

+ Cusack, Charles A., Mark Powers, and Airat Bekmetjev. + "Doppelgangers and Lemke graphs." + Discrete Mathematics 341, no. 10 (2018): 2686-2693. +

+
diff --git a/src/templates/blog-single.html b/src/templates/blog-single.html index 3dd0520..201caaa 100644 --- a/src/templates/blog-single.html +++ b/src/templates/blog-single.html @@ -2,10 +2,11 @@ - Mark's Kitchen - Blog + Mark's Kitchen — Blog {{> header}} + diff --git a/src/templates/blog.html b/src/templates/blog.html index 85c9d2e..ceb9f17 100644 --- a/src/templates/blog.html +++ b/src/templates/blog.html @@ -2,7 +2,7 @@ - Mark's Kitchen - Blog + Mark's Kitchen — Blog {{> header}} diff --git a/src/templates/bread.html b/src/templates/bread.html index 9f1d4b6..f0683e2 100644 --- a/src/templates/bread.html +++ b/src/templates/bread.html @@ -1,7 +1,7 @@ - Mark's Kitchen - Bread + Mark's Kitchen — Bread {{> header}} diff --git a/src/templates/index.html b/src/templates/index.html index 6ba3d5a..c321ce9 100644 --- a/src/templates/index.html +++ b/src/templates/index.html @@ -6,6 +6,7 @@ {{> header}} + diff --git a/src/templates/projects.html b/src/templates/projects.html index 3554e4d..e29de36 100644 --- a/src/templates/projects.html +++ b/src/templates/projects.html @@ -2,7 +2,7 @@ - Mark's Kitchen - Projects + Mark's Kitchen — Projects {{> header}} diff --git a/src/templates/tags.html b/src/templates/tags.html index 9b87eba..184263f 100644 --- a/src/templates/tags.html +++ b/src/templates/tags.html @@ -2,7 +2,7 @@ - Mark's Kitchen - Tags + Mark's Kitchen — Tags -- cgit v1.2.3