editing user redirects to user's page and began to implment ATOM

This commit is contained in:
2025-07-30 00:43:21 +01:00
parent 39eba8fcda
commit 0c43c7315c
12 changed files with 106 additions and 43 deletions

View File

@@ -32,7 +32,6 @@ Read the [configuation guide](docs/CONFIG.md) for configuration help (in config.
* probably insecure as hell
# Planned features/todo list
* edit user (could be on instead of the delete_account page)
* user specific RSS feeds
* atom
* federation (looks tricky)
@@ -41,6 +40,8 @@ Read the [configuation guide](docs/CONFIG.md) for configuration help (in config.
* inline comments and docs
* clean up code a bit
* comment pages?
* /postID and /userID pages
* site index
TODO (not finished)
# EJS variable names

View File

@@ -10,13 +10,13 @@
"enable_hitcount": true,
"charset": "UTF-8",
"root_path": "/home/deadvey/code/web/blogger-webroot/",
"delete_account_url": "/delete_account",
"edit_account_base_url": "/edit_account",
"new_post_url": "/post",
"signup_url": "/signup",
"edit_post_base_url": "/edit",
"default_comenter_username": "Anon",
"rss": true,
"rss_url": "/rss",
"atom": true,
"date_format": "yyyy-MM-dd",
"time_zone": "+0000",
"string": {
@@ -24,7 +24,7 @@
"signups_unavailable": "Sorry, this server does not allow signups",
"user_exists": "Sorry, this user already exists, try a different username",
"user_doesnt_exist": "Sorry, this user does not exist",
"delete_account_confirmation": "I agree that my account and all of my posts will be permanently deleted instantly",
"delete_account_confirmation": "Delete my account - (I agree that my account and all of my posts will be permanently deleted instantly)",
"incorrect_password": "Incorrect Password",
"rss_disabled": "Sorry, RSS is disabled",
"attribution": "Powered by blogger-nodejs: <a href='https://git.javalsai.tuxcord.net/deadvey/blogger-nodejs'>Source Code</a>, <a href='https://git.javalsai.tuxcord.net/deadvey/blogger-nodejs/raw/branch/master/LICENSE'>license (WTFPL)</a>"

View File

@@ -10,13 +10,13 @@
"enable_hitcount": true,
"charset": "UTF-8",
"root_path": "/path/to/blogger-webroot",
"delete_account_url": "/delete_account",
"edit_account_base_url": "/edit_account",
"new_post_url": "/post",
"signup_url": "/signup",
"edit_post_base_url": "/edit",
"default_comenter_username": "Anon",
"rss": true,
"rss_url": "/rss",
"atom": true,
"date_format": "yyyy-MM-dd",
"time_zone": "+0000",
"string": {

View File

@@ -25,6 +25,13 @@ export function unix_time_to_rss_date(unix_time) {
let formatted_date = format(date, "EEE, dd MMM yyyy HH:mm:ss")
return `${formatted_date} ${config.time_zone}`
}
// And again with atom's date format
export function unix_time_to_atom_date(unix_time) {
const { fromUnixTime, format, getUnixTime } = require("date-fns") // A date utility library
let date = fromUnixTime(unix_time)
let formatted_date = format(date, "yyyy-MM-dd\\THH:mm:ss\\Z")
return `${formatted_date}`
}
// This function accepts a list of strings eg ["string1","string2,"string3"] (any length)
// then returns a string of them each pointing to a seperate url
// eg "<a href="/tag/string1">string1</a>, <a href="/tag/string2">string2</a>, <a href="/tag/string3">string3</a>"

View File

@@ -61,7 +61,7 @@ app.set('views', '../views')
////////////////////// SYNDICATION ////////////////////////
// RSS protocol gets
app.get(config.rss_url, (req,res) => {
app.get("/rss", (req,res) => {
if (config.rss == false) {
res.render("partials/message", {
message: config.string.rss_disabled,
@@ -70,7 +70,25 @@ app.get(config.rss_url, (req,res) => {
}
else {
res.setHeader('content-type', 'application/rss+xml');
res.render("syndication/rss", {
res.render("syndication/global_rss", {
config,
posts,
converter,
func,
})
};
});
// ATOM protocol gets
app.get("/atom", (req,res) => {
if (config.rss == false) {
res.render("partials/message", {
message: config.string.rss_disabled,
config: config,
})
}
else {
res.setHeader('content-type', 'application/rss+xml');
res.render("syndication/global_atom", {
config,
posts,
converter,
@@ -183,8 +201,9 @@ app.get(config.signup_url, (req,res) => {
console.log("Error, invalid value for allow_signup (bool)")
}
}); // /signup
app.get(config.delete_account_url, (req,res) => {
res.render("forms/delete_account", { config });
app.get(`${config.edit_account_base_url}/:user_id`, (req,res) => {
const userID = parseInt(req.params.user_id);
res.render("forms/edit_account", { config, user: users[userID], userID });
}); // /delete_account
app.get(`${config.edit_post_base_url}/:post_id`, (req,res) => {
const post_id = req.params.post_id
@@ -295,16 +314,21 @@ app.post("/submit_signup", (req,res) => {
console.log("Error, invalid value for allow_signup (bool)")
}
}); // /submit_signup
app.post("/submit_delete_account", (req,res) => {
app.post("/submit_edit_user", (req,res) => {
// Get the form info
const password = crypto.createHash("sha512").update(req.body.password).digest("hex");
const username = func.escape_input(req.body.username)
// get the userID
const userID = func.get_userID(username)
const userID = func.escape_input(req.body.userID)
const description = func.escape_input(req.body.description)
const prettyname = func.escape_input(req.body.prettyname)
const delete_bool = req.body.delete
if (userID >= 0) { // The user exists
if (password == users[userID]['hash']) { // password matches
console.log(username, "(userID:", userID, ") is trying deleting their account")
console.log(userID, " (userID) is modifying their account")
users[userID]["prettyname"] = prettyname;
users[userID]["description"] = description;
if (delete_bool == true) {
// Delete the user
users[userID] = {"deleted": true}
// Delete all their posts
@@ -314,11 +338,12 @@ app.post("/submit_delete_account", (req,res) => {
comments.comments[postid] = {"deleted": true} // the comments for this post should also be deleted
}
};
}
// Write these changes
fs.writeFileSync(`../data/users.json`, `${JSON.stringify(users)}`, 'utf-8');
fs.writeFileSync(`../data/posts.json`, `${JSON.stringify(posts)}`, 'utf-8');
fs.writeFileSync(`../data/comments.json`, `${JSON.stringify(comments)}`, 'utf-8');
res.redirect(301,"/")
res.redirect(301,`/user/${users[userID]["username"]}`)
}
else { // password does not match
res.render("partials/message", {
@@ -335,7 +360,7 @@ app.post("/submit_delete_account", (req,res) => {
})
}
}); // /submit_delete_account
app.post("/submit_edit", (req,res) => {
app.post("/submit_edit_post", (req,res) => {
const password = crypto.createHash('sha512').update(req.body.password).digest('hex');
const postID = req.body.postID
const userID = req.body.userID
@@ -356,7 +381,7 @@ app.post("/submit_edit", (req,res) => {
console.log("Deleting post!")
posts[postID] = {"deleted": true}
comments.comments[postID] = {"deleted": true}
fs.writeFileSync(`../data/comments.json`, `${JSON.stringify(comments.comments)}\nexport const counter = ${comments.counter}`, 'utf-8');
fs.writeFileSync(`../data/comments.json`, `${JSON.stringify(comments)}`, 'utf-8');
}
fs.writeFileSync(`../data/posts.json`, `${JSON.stringify(posts)}`, 'utf-8');
res.redirect(302, "/");

View File

@@ -1,14 +0,0 @@
<!DOCTYPE html>
<html lang="<%= config.language %>
<head>
<%- include("../partials/head") %>
</head>
<body>
<form action="/submit_delete_account" method="POST">
<input placeholder="username" required name="username"><br/>
<input placeholder="password" type="password" required id="password" name="password"><br/>
<label><%- config.string.delete_account_confirmation %>: </label><input type="checkbox" name="agreement" required><br/>
<input type="submit" value="Submit"><br/>
</form>
</body>
</html>

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="<%= config.language %>
<head>
<%- include("../partials/head") %>
</head>
<body>
<form action="/submit_edit_user" method="POST">
<input name="userID" type="hidden" value="<%= userID %>">
<input placeholder="<%= user.prettyname %>'s password" type="password" required id="password" name="password"><br/>
<input placeholder="Pretty Name" name="prettyname" value="<%= user.prettyname %>"><br/>
<textarea placeholder="Description" name="description"><%= user.description %></textarea><br/>
<label><%- config.string.delete_account_confirmation %>: </label><input type="checkbox" name="agreement"><br/>
<input type="submit" value="Submit"><br/>
</form>
</body>
</html>

View File

@@ -4,7 +4,7 @@
<%- include("../partials/head") %>
</head>
<body>
<form action="/submit_edit" method="POST" onsubmit="sha512password()">
<form action="/submit_edit_post" method="POST" onsubmit="sha512password()">
<input name="userID" type="hidden" value="<%= post['userID'] %>">
<input name="postID" type="hidden" value="<%= post_id %>">
<input placeholder="<%= user['prettyname'] %>'s password" type="password" required id="password" name="password"><br/>

View File

@@ -7,7 +7,6 @@
<a href="<%= config.rss_url %>">RSS Feed</a><br/>
<a href="<%= config.new_post_url %>">New post</a><br/>
<a href="<%= config.signup_url %>">Sign Up</a><br/>
<a href="<%= config.delete_account_url %>">Delete Account</a><br/>
<% if (config.enable_hitcount == true) { %>
Hitcount: <%= hitcount %>
<% } %>

View File

@@ -2,4 +2,5 @@
<%= user.prettyname %>'s posts
</h1>
<p><%- converter.makeHtml(user.description) %></p>
<a href="<%= config.edit_account_base_url %>/<%= userID %>">edit account</a>
<%- config.seperator %>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="<%= config.charset %>" ?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><%= config.site_name %></title>
<link><%= config.site_url %></title>
<description><%= config.site_description %></description>
<updated><%= new Date() %></updated>
<id><%= config.site_url %></id>
</feed>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="<%= config.charset %>" ?>
<rss version="2.0">
<channel>
<title><%= config.site_name %></title>
<link><%= config.site_url %></title>
<description><%= config.site_description %></description>
<% for (let postID = posts.length-1; postID >= 0; postID--) { %>
<item>
<title><%= posts[postID]["title"] %></title>
<link><%= config.site_url %>/post/<%= postID %></link>
<description><![CDATA[<%= converter.makeHtml(posts[postID]["content"]) %>]]></description>
<guid isPermaLink="true"><%= config.site_url %>/post/<%= postID %></guid>
<pubDate><%= func.unix_time_to_rss_date(posts[postID]['pubdate']) %></pubDate>
<% for (let tag_index = 0; tag_index < posts[postID]['tags'].length; tag_index++) { %>
<category><![CDATA[<%= posts[postID]['tags'][tag_index] %>]]></category>
<% } %>
</item>
<% } %>
</channel>
</rss>