diff options
author | Mark Powers <mark@marks.kitchen> | 2021-12-23 16:50:42 -0600 |
---|---|---|
committer | Mark Powers <mark@marks.kitchen> | 2021-12-23 16:50:42 -0600 |
commit | 1d3574d38909bc9aae2792d839023e296fb25791 (patch) | |
tree | c409fbff38083b85356498f636714e6ec74f95e4 | |
parent | 85a103d6a02a50ce28cbb44c2e693000d9b7388d (diff) |
Add email unsubcribe link, update about me, add hello.js
-rw-r--r-- | src/html/admin.html | 13 | ||||
-rw-r--r-- | src/html/email-confirm.html | 23 | ||||
-rw-r--r-- | src/html/email-success.html | 2 | ||||
-rw-r--r-- | src/html/email-unsubscribe.html | 23 | ||||
-rw-r--r-- | src/index.js | 8 | ||||
-rw-r--r-- | src/js/hello.js | 6 | ||||
-rw-r--r-- | src/server.js | 23 | ||||
-rw-r--r-- | src/templates/about.html | 54 | ||||
-rw-r--r-- | src/templates/blog-single.html | 3 | ||||
-rw-r--r-- | src/templates/blog.html | 2 | ||||
-rw-r--r-- | src/templates/bread.html | 2 | ||||
-rw-r--r-- | src/templates/index.html | 1 | ||||
-rw-r--r-- | src/templates/projects.html | 2 | ||||
-rw-r--r-- | src/templates/tags.html | 2 |
14 files changed, 141 insertions, 23 deletions
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); + } + } </script> </head> @@ -130,10 +139,12 @@ <tr> <th>Name</th> <th>Address</th> + <th></th> </tr> <tr v-for="item in emails"> <td>{{item.name}}</td> <td>{{item.address}}</td> + <td><button v-on:click="delete_email(item.id, item.name)">X</button></td> </tr> </table> </div> 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 @@ +<!doctype html> +<html lang="en"> + +<head> + <title>Mark's Kitchen - Email</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/styles.css"> + <meta name="description" content="Email unsubscrube"> +</head> + +<body> + <div> + <h1> + <a class="navigation" href="/" title="marks.kitchen"><</a> + Unsubcribe? + </h1> + <a href="confirm">Click to unsubscribe!</a> + </div> + </div> +</body> + +</html> 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 @@ <a class="navigation" href="/" title="marks.kitchen"><</a> Email </h1> - <h2 id="status" v-if='show'>Success, thank you!</h2> + <h2 id="status">Success, thank you!</h2> </div> </div> </body> 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 @@ +<!doctype html> +<html lang="en"> + +<head> + <title>Mark's Kitchen - Email</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/styles.css"> + <meta name="description" content="Email unsubscrube"> +</head> + +<body> + <div> + <h1> + <a class="navigation" href="/" title="marks.kitchen"><</a> + Email + </h1> + <h2 id="status">You are now unsubscribed!</h2> + </div> + </div> +</body> + +</html> 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 @@ <html lang="en"> <head> - <title>Mark's Kitchen - About</title> + <title>Mark's Kitchen — About</title> <link rel="stylesheet" type="text/css" href="/css/styles.css"> <meta name="description" content="About Mark"> {{> header}} @@ -29,20 +29,21 @@ <dd>Software engineer at <a href="https://www.chameleoncloud.org/">Chameleon Cloud</a></dd> <dt>Location</dt> - <dd>Chicagoland</dd> + <dd>Chicagoland. Previously, Madison and West Michigan</dd> <dt>Almae Matres</dt> <dd>Hope College, UW-Madison</dd> <dt>Source Code</dt> <dd> - <a href="https://git.marks.kitchen/">Gitweb</a> - or - <a href="https://github.com/Mark-Powers/">GitHub</a> + <ul> + <li><a href="https://git.marks.kitchen/">Gitweb</a></li> + <li><a href="https://github.com/Mark-Powers/">GitHub</a></li> + </ul> </dd> <dt>Social</dt> - <dd><a href="https://fosstodon.org/@markp">markp</a></dd> + <dd><a href="https://fosstodon.org/@markp">markp@fosstodon</a></dd> <dt>Hobbies</dt> <dd> @@ -50,14 +51,45 @@ chess, cooking, disc golf </dd> - <dt>Operating System<dt> - <dd>Regolith Linux</dd> + <dt>Operating System</dt> + <dd> + 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. + </dd> - <dt>Editor<dt> - <dd>vim</dd> + <dt>Editor</dt> + <dd> + 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. + </dd> - <dt>Pets<dt> + <dt>Pets</dt> <dd>One very fluffy black cat, one shorthair kitten</dd> + + <dt>Erdos Number</dt> + <dd>3 — Myself ↔ Charles A. Cusack ↔ Charles J. Colbourn ↔ Paul Erdos</dd> + + <dt>Articles</dt> + <dd> + <p> + Cusack, Charles A., Aaron Green, Airat Bekmetjev, and Mark Powers. + "Graph pebbling algorithms and Lemke graphs." + Discrete Applied Mathematics 262 (2019): 72-82. + </p> + <p> + 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. + </p> + <p> + Cusack, Charles A., Mark Powers, and Airat Bekmetjev. + "Doppelgangers and Lemke graphs." + Discrete Mathematics 341, no. 10 (2018): 2686-2693. + </p> + </dd> </dl> </div> </body> 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 @@ <html lang="en"> <head> - <title>Mark's Kitchen - Blog</title> + <title>Mark's Kitchen — Blog</title> <link rel="stylesheet" type="text/css" href="/css/styles.css"> <meta name="description" content="A post from {{date}}"> {{> header}} + <script src="/js/hello.js"></script> </head> <body> 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 @@ <html lang="en"> <head> - <title>Mark's Kitchen - Blog</title> + <title>Mark's Kitchen — Blog</title> <link rel="stylesheet" type="text/css" href="/css/styles.css"> <meta name="description" content="Mark's blog feed"> {{> 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 @@ <!doctype html> <html lang="en"> <head> - <title>Mark's Kitchen - Bread</title> + <title>Mark's Kitchen — Bread</title> <meta name="description" content="Mark's bread feed"> {{> header}} <link rel="stylesheet" type="text/css" href="/css/styles.css"> 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 @@ <link rel="stylesheet" type="text/css" href="/css/styles.css"> <link rel="alternate" type="application/rss+xml" title="RSS Feed for marks.kitchen" href="/feed.xml" /> {{> header}} + <script src="/js/hello.js"></script> </head> <body> 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 @@ <html lang="en"> <head> - <title>Mark's Kitchen - Projects</title> + <title>Mark's Kitchen — Projects</title> <link rel="stylesheet" type="text/css" href="/css/styles.css"> <meta name="description" content="A list of Mark's 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 @@ <html lang="en"> <head> - <title>Mark's Kitchen - Tags</title> + <title>Mark's Kitchen — Tags</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/styles.css"> |