-
-
Save darkcheftar/a0746f59bacf8d8d491ad60ce0e45d22 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const express = require("express"); | |
const path = require("path"); | |
const fs = require("fs"); | |
const cookieParser = require("cookie-parser"); | |
const { v4: uuid } = require("uuid"); | |
const flag = process.env.FLAG; //important | |
const port = parseInt(process.env.PORT) || 8080; | |
const adminpw = process.env.ADMINPW || "placeholder"; | |
const accounts = new Map(); | |
accounts.set("admin", { | |
password: adminpw, | |
displayName: flag,//important | |
posts: [], | |
friends: [], | |
}); | |
const posts = new Map(); | |
const app = express(); | |
let cleanup = []; | |
setInterval(() => { | |
const now = Date.now(); | |
let i = cleanup.findIndex((x) => now < x[1]); | |
if (i === -1) { | |
i = cleanup.length; | |
} | |
for (let j = 0; j < i; j++) { | |
const account = accounts.get(cleanup[i][0]); | |
for (const post of account.posts) { | |
posts.delete(post); | |
} | |
accounts.delete(cleanup[i][0]); | |
} | |
cleanup = cleanup.slice(i); | |
}, 1000 * 60); | |
function needsAuth(req, res, next) { | |
if (!res.locals.user) { | |
res.redirect("/login"); | |
} else { | |
next(); | |
} | |
} | |
app.use(cookieParser()); | |
app.use(express.urlencoded({ extended: false })); | |
app.use((req, res, next) => { | |
res.locals.user = null; | |
if (req.cookies.login) { | |
const chunks = req.cookies.login.split(":"); | |
if (chunks.length === 2 && accounts.has(chunks[0]) && accounts.get(chunks[0]).password === chunks[1]) { | |
res.locals.user = chunks[0]; | |
} | |
} | |
next(); | |
}); | |
// templating engines are for losers! | |
const postTemplate = fs.readFileSync(path.join(__dirname, "post.html"), "utf8"); | |
app.get("/post/:id", (req, res) => { | |
if (posts.has(req.params.id)) { | |
res.type("text/html").send(postTemplate.replace("$CONTENT", () => posts.get(req.params.id))); | |
} else { | |
res.status(400).type("text/html").send(postTemplate.replace("$CONTENT", "post not found :(")); | |
} | |
}); | |
app.get("/", needsAuth); | |
app.get("/login", (req, res, next) => { | |
if (res.locals.user) { | |
res.redirect("/"); | |
} else { | |
next(); | |
} | |
}); | |
app.use(express.static(path.join(__dirname, "static"), { extensions: ["html"] })); | |
app.post("/register", (req, res) => { | |
if (typeof req.body.username !== "string" || typeof req.body.password !== "string" || typeof req.body.displayName !== "string") { | |
res.redirect("/login#" + encodeURIComponent("Please metafill out all the metafields.")); | |
return; | |
} | |
const username = req.body.username.trim(); | |
const password = req.body.password.trim(); | |
const displayName = req.body.displayName.trim(); | |
if (!/^[\w]{3,32}$/.test(username) || !/^[-\w !@#$%^&*()+]{3,32}$/.test(password) || !/^[-\w ]{3,64}/.test(displayName)) { | |
res.redirect("/login#" + encodeURIComponent("Invalid metavalues provided for metafields.")); | |
return; | |
} | |
if (accounts.has(username)) { | |
res.redirect("/login#" + encodeURIComponent("Metaaccount already metaexists.")); | |
return; | |
} | |
accounts.set(username, { password, displayName, posts: [], friends: [] }); | |
cleanup.push([username, Date.now() + 1000 * 60 * 60 * 12]); | |
res.cookie("login", `${username}:${password}`, { httpOnly: true }); | |
res.redirect("/"); | |
}); | |
app.post("/login", (req, res) => { | |
if (typeof req.body.username !== "string" || typeof req.body.password !== "string") { | |
res.redirect("/login#" + encodeURIComponent("Please metafill out all the metafields.")); | |
return; | |
} | |
const username = req.body.username.trim(); | |
const password = req.body.password.trim(); | |
if (accounts.has(username) && accounts.get(username).password === password) { | |
res.cookie("login", `${username}:${password}`, { httpOnly: true }); | |
res.redirect("/"); | |
} else { | |
res.redirect("/login#" + encodeURIComponent("Wrong metausername/metapassword.")); | |
} | |
}); | |
app.post("/friend", needsAuth, (req, res) => {//important | |
res.type("text/plain"); | |
const username = req.body.username.trim(); | |
if (!accounts.has(username)) { | |
res.status(400).send("Metauser doesn't metaexist"); | |
} else { | |
const user = accounts.get(username); | |
if (user.friends.includes(res.locals.user)) { | |
res.status(400).send("Already metafriended"); | |
} else { | |
user.friends.push(res.locals.user); | |
res.status(200).send("ok"); | |
} | |
} | |
}); | |
app.post("/post", needsAuth, (req, res) => { | |
res.type("text/plain"); | |
const id = uuid(); | |
const content = req.body.content; | |
if (typeof content !== "string" || content.length > 1000 || content.length === 0) { | |
res.status(400).send("Invalid metacontent"); | |
} else { | |
const user = accounts.get(res.locals.user); | |
posts.set(id, content); | |
user.posts.push(id); | |
res.send(id); | |
} | |
}); | |
app.get("/posts", needsAuth, (req, res) => { | |
res.type("application/json"); | |
res.send( | |
JSON.stringify( | |
accounts.get(res.locals.user).posts.map((id) => { | |
const content = posts.get(id); | |
return { | |
id, | |
blurb: content.length < 50 ? content : content.slice(0, 50) + "...", | |
}; | |
}) | |
) | |
); | |
}); | |
app.get("/friends", needsAuth, (req, res) => { | |
res.type("application/json"); | |
res.send( | |
JSON.stringify( | |
accounts | |
.get(res.locals.user) | |
.friends.filter((username) => accounts.has(username)) | |
.map((username) => ({ | |
username, | |
displayName: accounts.get(username).displayName, | |
})) | |
) | |
); | |
}); | |
app.listen(port, () => { | |
console.log(`Listening on port ${port}`); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment