aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Powers <mark@marks.kitchen>2021-12-23 16:50:42 -0600
committerMark Powers <mark@marks.kitchen>2021-12-23 16:50:42 -0600
commit1d3574d38909bc9aae2792d839023e296fb25791 (patch)
treec409fbff38083b85356498f636714e6ec74f95e4
parent85a103d6a02a50ce28cbb44c2e693000d9b7388d (diff)
Add email unsubcribe link, update about me, add hello.js
-rw-r--r--src/html/admin.html13
-rw-r--r--src/html/email-confirm.html23
-rw-r--r--src/html/email-success.html2
-rw-r--r--src/html/email-unsubscribe.html23
-rw-r--r--src/index.js8
-rw-r--r--src/js/hello.js6
-rw-r--r--src/server.js23
-rw-r--r--src/templates/about.html54
-rw-r--r--src/templates/blog-single.html3
-rw-r--r--src/templates/blog.html2
-rw-r--r--src/templates/bread.html2
-rw-r--r--src/templates/index.html1
-rw-r--r--src/templates/projects.html2
-rw-r--r--src/templates/tags.html2
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">&lt;</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">&lt;</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">&lt;</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 &#8212; 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 &#8212; 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 &#8212; 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 &#8212; Myself &#8596; Charles A. Cusack &#8596; Charles J. Colbourn &#8596; 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 &#8212; 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 &#8212; 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 &#8212; 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 &#8212; 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 &#8212; 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">