From 98de002e14b07304b1518bd9e8eac5d5f47d761f Mon Sep 17 00:00:00 2001 From: Enstrayed <48845980+Enstrayed@users.noreply.github.com> Date: Sun, 31 Mar 2024 12:52:26 -0700 Subject: [PATCH 1/5] god why --- routes/etyd.js | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/routes/etyd.js b/routes/etyd.js index 5ace98a..8c011ec 100644 --- a/routes/etyd.js +++ b/routes/etyd.js @@ -31,24 +31,26 @@ app.post("/etydwrite", (rreq,rres) => { switch(rreq.body.action) { case "set": // Write to db - if (rreq.body.random == true) { - let workingTarget = makeRandomHex() - - db.get(`/${workingTarget}`).then(dbres => { - if (dbres != null) { - let workingTarget = makeRandomHex() - - db.get(`/${workingTarget}`).then(dbres => { - if (dbres != null) { - // well fuck + let workingTarget = makeRandomHex() // Make a random URL + db.get(`/${workingTarget}`).then(dbres => { // Check if it exists + if (dbres != null) { // If it does + let workingTarget = makeRandomHex() // Make a new one + db.get(`/${workingTarget}`).then(dbres => { // Check if *that* exists + if (dbres != null) { // If it does + // Then everything is dumb and pointless so just give up + console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION set returned 409 (Two attempts to find an open key failed)`) rres.sendStatus(409) - + } else { // if it doesnt then set the stupid key I hate this code so much why did I do this serverside this is so dumb + console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION set returned 200 KEY:${rreq.get("Authorization")} TARGET: ${workingTarget}`) + db.set(`/${workingTarget}`,rreq.body.value) + rres.send(`https://etyd.cc/${workingTarget}`) } }) } else { + console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION set returned 200 KEY:${rreq.get("Authorization")} TARGET: ${workingTarget}`) db.set(`/${workingTarget}`,rreq.body.value) rres.send(`https://etyd.cc/${workingTarget}`) } @@ -71,12 +73,18 @@ app.post("/etydwrite", (rreq,rres) => { case "delete": - db.get(`/${rreq.body.target}`).then(dbres => { + let workingTarget = rreq.body.target.replace("https://etyd.cc/","") // Sanitize input + if (workingTarget.startsWith("/")) { + workingTarget = workingTarget.slice(1) + } + + db.get(`/${workingTarget}`).then(dbres => { if (dbres == null) { //if key doesnt exist then log and return 400 - console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION delete returned 400 KEY:${rreq.get("Authorization")}`) - rres.sendStatus(400) + console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION delete returned 404 KEY:${rreq.get("Authorization")} TARGET: ${workingTarget}`) + rres.sendStatus(404) } else { - db.del(`/${rreq.body.target}`) + console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION delete returned 200 KEY:${rreq.get("Authorization")} TARGET: ${workingTarget}`) + db.del(`/${workingTarget}`) rres.sendStatus(200) } }) @@ -84,6 +92,7 @@ app.post("/etydwrite", (rreq,rres) => { default: + console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION default returned 400 KEY:${rreq.get("Authorization")}`) rres.sendStatus(400) // request json didnt include a valid action break; } From 3b96e07d13a6e3d94f2a417cd1c02a2851d86281 Mon Sep 17 00:00:00 2001 From: Enstrayed <48845980+Enstrayed@users.noreply.github.com> Date: Tue, 9 Apr 2024 15:02:16 -0700 Subject: [PATCH 2/5] working changes --- .gitignore | 3 +- Caddyfile | 21 ++++ etydFrontend/_static/etyd.js | 61 ++++++++++ etydFrontend/_static/index.css | 22 ++++ etydFrontend/index.html | 75 +++++++++++++ package-lock.json | 33 +++++- package.json | 6 +- routes/etyd.js | 198 ++++++++++++++++----------------- 8 files changed, 317 insertions(+), 102 deletions(-) create mode 100644 Caddyfile create mode 100644 etydFrontend/_static/etyd.js create mode 100644 etydFrontend/_static/index.css create mode 100644 etydFrontend/index.html diff --git a/.gitignore b/.gitignore index cf7c602..29b0255 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules/ -config.json \ No newline at end of file +config.json +bun.lockb \ No newline at end of file diff --git a/Caddyfile b/Caddyfile new file mode 100644 index 0000000..eb42a99 --- /dev/null +++ b/Caddyfile @@ -0,0 +1,21 @@ +:8082 { + reverse_proxy localhost:8081 +} + +:8083 { + @staticpaths { + path / + path /_static* + path /favicon.ico + } + + handle @staticpaths { + root ./etydFrontend + file_server + } + + handle /* { + rewrite * /etyd{uri} + reverse_proxy localhost:8081 + } +} \ No newline at end of file diff --git a/etydFrontend/_static/etyd.js b/etydFrontend/_static/etyd.js new file mode 100644 index 0000000..5879b9d --- /dev/null +++ b/etydFrontend/_static/etyd.js @@ -0,0 +1,61 @@ +//Firefox check +window.onload = function() { + document.getElementById('resultfeed').value = "hii :3" + if (navigator.userAgent.includes("Firefox")) { + document.getElementById('resultfeed').value += `\nClipboard functionality does not work on Firefox.` + document.getElementById('clipboard1').disabled = true + document.getElementById('clipboard2').disabled = true + } +} + +function makeRandomHex(amount) { + const characters = "1234567890abcdef" + let counter = 0 + let result = "" + while (counter < amount) { + result += characters.charAt(Math.floor(Math.random() * characters.length)) + counter += 1 + } + return result +} + +function randomUrlTick() { + if (document.getElementById("randomizationtoggle").checked == true) { + document.getElementById("targetfield").disabled = true + document.getElementById("targetfield").value = makeRandomHex(6) + } else { + document.getElementById("targetfield").disabled = false + document.getElementById("targetfield").value = null + } +} + +function buttonCopyResult() { + navigator.clipboard.writeText(`${document.location.href}${document.getElementById("urlfield").value}`) +} + +function buttonFillFromClipboard() { + navigator.clipboard.readText().then(res => { + document.getElementById("valuefield").value = res; + }) +} + +function postData() { + fetch("http://nrdesktop:8081/etydwrite", { + method: "POST", + mode: "cors", + headers: { + "Authorization": document.getElementById("authfield").value + }, + body: JSON.stringify({ + "target": document.getElementById("targetfield").value, + "value": document.getElementById("valuefield").value, + "action": document.getElementById("actiondropdown").value, + "random": document.getElementById("randomizationtoggle").checked + }) + }).then(response => { + document.getElementById("resultfeed").value += `\n${response.status} ${response.body}` + }).catch(error => { + document.getElementById("resultfeed").value += `\nError: ${error}` + }) +} + diff --git a/etydFrontend/_static/index.css b/etydFrontend/_static/index.css new file mode 100644 index 0000000..cf34de1 --- /dev/null +++ b/etydFrontend/_static/index.css @@ -0,0 +1,22 @@ +body { + font-family: Arial, Helvetica, sans-serif; +} + +.flexbox { + display: flex; + flex-wrap: wrap; +} + +.marginright1em { + margin-right: 1em; +} + +.resultfeed { + height: 100%; +} + +@media (max-width: 700px) { + .resultfeed { + min-height: 20vh; + } +} \ No newline at end of file diff --git a/etydFrontend/index.html b/etydFrontend/index.html new file mode 100644 index 0000000..d210c0d --- /dev/null +++ b/etydFrontend/index.html @@ -0,0 +1,75 @@ + +
+ + + + +
+ 1. Enter your API Key in the 'Authorization' field
+ 2. Enter the shortened URL you want to act upon under the 'URL' field
+ 3. Enter the URL that the user will be redirected to under the 'Value' field
+ 4. Change 'Action' depending if you want to create or delete a URL
+ 5. Press 'POST Data' to submit the form to the server
+
+ 400: Bad Request - You will see this if you try and delete a non-existent URL
+ 401: Unauthorized - Did you enter your API key?
+ 405: Method Not Allowed - You will see this if you try a request with no arguments
+ 409: Conflict - The entered URL already exists, tick 'Random' and try again
+ 500: Internal Server Error - If this happens something has gone very wrong
+ 502: Bad Gateway - If you see this the backend is down/unreachable by Caddy
+
400: Bad Request - You will see this if you try and delete a non-existent URL
401: Unauthorized - Did you enter your API key?
- 405: Method Not Allowed - You will see this if you try a request with no arguments
409: Conflict - The entered URL already exists, tick 'Random' and try again
500: Internal Server Error - If this happens something has gone very wrong
502: Bad Gateway - If you see this the backend is down/unreachable by Caddy
diff --git a/routes/etyd.js b/routes/etyd.js
index 34fc166..ca39d10 100644
--- a/routes/etyd.js
+++ b/routes/etyd.js
@@ -1,4 +1,5 @@
-const { app, db, globalConfig } = require("../index.js") // Get globals from index
+const { app, globalConfig } = require("../index.js") // Get globals from index
+const { checkAuthorization } = require("../liberals/authorization.js")
app.get("/etyd*", (rreq,rres) => {
fetch(`http://${globalConfig.couchdb.host}/etyd${rreq.path.replace("/etyd","")}`, {
@@ -25,119 +26,111 @@ app.get("/etyd*", (rreq,rres) => {
})
app.delete("/etyd*", (rreq,rres) => {
-
- fetch(`http://${globalConfig.couchdb.host}/apiauthkeys/${globalConfig.etyd.authKeysDoc}`, {
- headers: {
- "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`
- }
- }).then(dbRes => dbRes.json()).then(dbRes => {
- if (dbRes.status == 404) { // If document containing cider auth keys does not exist
- console.log(`ERROR: Could not find apiauthkeys/${globalConfig.etyd.authKeysDoc}`)
- rres.sendStatus(500) // Refuse request
- } else {
- if (rreq.get("Authorization") == null) { // If authorization header is not supplied
- rres.sendStatus(400) // then return bad request (would return 500 otherwise)
- } else {
- if (dbRes["content"][rreq.get("Authorization").split("_")[0]] === rreq.get("Authorization").split("_")[1]) {
+ if (rreq.get("Authorization") === undefined) {
+ rres.sendStatus(400)
+ } else {
+ checkAuthorization(globalConfig.etyd.authKeysDoc,rreq.get("Authorization")).then(authRes => {
+ if (authRes === false) {
+ console.log(`${rreq.get("cf-connecting-ip")} DELETE ${rreq.path} returned 401`) // Log unauthorized requests
+ rres.sendStatus(401)
+ } else if (authRes === true) { // Authorization successful
- fetch(`http://${globalConfig.couchdb.host}/etyd${rreq.path.replace("/etyd", "")}`, {
- headers: {
- "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`
- }
- }).then(dbRes => {
-
- if (dbRes.status == 404) {
- rres.sendStatus(404)
- } else {
- dbRes.json().then(dbRes => {
-
- fetch(`http://${globalConfig.couchdb.host}/etyd${rreq.path.replace("/etyd", "")}`, {
- method: "DELETE",
- headers: {
- "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`,
- "If-Match": dbRes["_rev"]
- }
- }).then(fetchRes => {
- if (fetchRes.status == 200) {
- console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 200 KEY: ${rreq.get("Authorization")}`)
- rres.sendStatus(200)
- }
- }).catch(fetchError => {
- rres.sendStatus(500)
- console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 500: ${fetchError}`)
- })
-
+ fetch(`http://${globalConfig.couchdb.host}/etyd${rreq.path.replace("/etyd", "")}`, {
+ headers: {
+ "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`
+ }
+ }).then(dbRes => {
+
+ if (dbRes.status == 404) {
+ rres.sendStatus(404)
+ } else {
+ dbRes.json().then(dbRes => {
+
+ fetch(`http://${globalConfig.couchdb.host}/etyd${rreq.path.replace("/etyd", "")}`, {
+ method: "DELETE",
+ headers: {
+ "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`,
+ "If-Match": dbRes["_rev"] // Using the If-Match header is easiest for deleting entries in couchdb
+ }
+ }).then(fetchRes => {
+ if (fetchRes.status == 200) {
+ console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 200 KEY: ${rreq.get("Authorization")}`)
+ rres.sendStatus(200)
+ }
+ }).catch(fetchError => {
+ console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 500: ${fetchError}`)
+ rres.sendStatus(500)
})
- }
-
- }).catch(fetchError => {
- rres.sendStatus(500)
- console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 500: ${fetchError}`)
- })
-
- } else {
- console.log(`${rreq.get("cf-connecting-ip")} DELETE ${rreq.path} returned 401`) // log ip of unauthorized requests
- rres.sendStatus(401) // received auth key was not in database
- }
+
+ })
+ }
+
+ }).catch(fetchError => {
+ console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 500: ${fetchError}`)
+ rres.sendStatus(500)
+ })
+
}
- }
- }).catch(fetchError => {
- rres.sendStatus(500)
- console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 500: ${fetchError}`)
- })
+ })
+ }
})
-// app.post("/etyd*", (rreq,rres) => {
+app.post("/etyd*", (rreq,rres) => {
+
+ if (rreq.get("Authorization") === undefined) {
+ rres.sendStatus(400)
+ } else {
+ checkAuthorization(globalConfig.etyd.authKeysDoc,rreq.get("Authorization")).then(authRes => {
+ if (authRes === false) {
+ console.log(`${rreq.get("cf-connecting-ip")} POST ${rreq.path} returned 401`) // Log unauthorized requests
+ rres.sendStatus(401)
+ } else if (authRes === true) { // Authorization successful
+
+ if (rreq.body["url"] == undefined) {
+ console.log(`${rreq.get("cf-connecting-ip")} POST ${rreq.path} returned 400 KEY: ${rreq.get("Authorization")}`)
+ rres.sendStatus(400)
+ } else {
+ fetch(`http://${globalConfig.couchdb.host}/etyd${rreq.path.replace("/etyd", "")}`, {
+ headers: {
+ "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`
+ },
+ method: "PUT",
+ body: JSON.stringify({
+ "content": {
+ "url": rreq.body["url"]
+ }
+ })
+ }).then(dbRes => {
-// fetch(`http://${globalConfig.couchdb.host}/apiauthkeys/${globalConfig.etyd.authKeysDoc}`, {
-// headers: {
-// "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`
-// }
-// }).then(dbRes => dbRes.json()).then(dbRes => {
+ switch(dbRes.status) {
+ case 409:
+ console.log(`${rreq.get("cf-connecting-ip")} POST ${rreq.path} returned 409 KEY: ${rreq.get("Authorization")}`)
+ rres.sendStatus(409)
+ break;
-// if (dbRes.status == 404) { // If document containing cider auth keys does not exist
-// console.log(`ERROR: Could not find apiauthkeys/${globalConfig.etyd.authKeysDoc}`)
-// rres.sendStatus(500) // Refuse request
-// } else {
-// if (rreq.get("Authorization") == null) { // If authorization header is not supplied
-// rres.sendStatus(400) // then return bad request (would return 500 otherwise)
-// } else {
-// if (dbRes["content"][rreq.get("Authorization").split("_")[0]] === rreq.get("Authorization").split("_")[1]) {
+ case 201:
+ console.log(`${rreq.get("cf-connecting-ip")} POST ${rreq.path} returned 200 KEY: ${rreq.get("Authorization")}`)
+ rres.status(200).send(rreq.path.replace("/etyd", ""))
+ break;
-// fetch(`http://${globalConfig.couchdb.host}/etyd${rreq.path.replace("/etyd", "")}`, {
-// headers: {
-// "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`
-// }
-// }).then(dbRes => {
+ default:
+ console.log(`ERROR: CouchDB PUT did not return expected code: ${dbRes.status}`)
+ break;
+ }
-// if (dbRes.status !== 404) {
-// console.log(`${rres.get("cf-connecting-ip")} POST ${rreq.path} returned 409 KEY: ${rreq.get("Authorization")}`)
-// rres.sendStatus(409)
-// } else {
-
+ }).catch(fetchError => {
+ console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 500: ${fetchError}`)
+ rres.sendStatus(500)
+ })
+ }
+ }
+ })
+ }
-// }
-
-// }).catch(fetchError => {
-// rres.sendStatus(500)
-// console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 500: ${fetchError}`)
-// })
-
-// } else {
-// console.log(`${rreq.get("cf-connecting-ip")} DELETE ${rreq.path} returned 401`) // log ip of unauthorized requests
-// rres.sendStatus(401) // received auth key was not in database
-// }
-// }
-// }
-// }).catch(fetchError => {
-// rres.sendStatus(500)
-// console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 500: ${fetchError}`)
-// })
-
-// })
+})
module.exports = {app} // export routes to be imported by index for execution
\ No newline at end of file
diff --git a/routes/mailjet.js b/routes/mailjet.js
index 1ef3cc1..b26e9d5 100644
--- a/routes/mailjet.js
+++ b/routes/mailjet.js
@@ -7,7 +7,7 @@ app.post("/sendemail", (rreq,rres) => {
if (authRes === false) { // If the supplied authorization is invalid or an error occured
console.log(`${rreq.get("cf-connecting-ip")} POST /sendemail returned 401`) // Log the request
- rres.sendStatus(401) // Return 401 Unauthorized
+ rres.sendStatus(401)
} else if (authRes === true) { // If the authorization was valid, continue function