From 4c0f140e9edfd28b71587152ae8ea9b0777ec8a0 Mon Sep 17 00:00:00 2001 From: Enstrayed <48845980+Enstrayed@users.noreply.github.com> Date: Thu, 17 Apr 2025 22:41:08 -0700 Subject: [PATCH] working changes --- liberals/auth.js | 13 ++++ routes/debug.js | 15 ++++ routes/etyd.js | 197 +++++++++++++++++++++++------------------------ todo.md | 5 ++ 4 files changed, 128 insertions(+), 102 deletions(-) create mode 100644 routes/debug.js create mode 100644 todo.md diff --git a/liberals/auth.js b/liberals/auth.js index e7ac0ca..eb60dc8 100644 --- a/liberals/auth.js +++ b/liberals/auth.js @@ -18,4 +18,17 @@ async function checkToken(token,scope) { }) } +/** + * New function to check if a token exists in the sessions table (authentication) and if it has the desired scope (authorization) + * @param {string} token Token as received by client + * @param {string} scope Desired scope for action + * @typedef {Object} Object containing the result and the username of the token owner + * @property {boolean} result Boolean result of if the check passed + * @property {string} owner Username of the token owner + */ + +async function checkTokenNew(token,scope) { + +} + export {checkToken} \ No newline at end of file diff --git a/routes/debug.js b/routes/debug.js new file mode 100644 index 0000000..c155ad5 --- /dev/null +++ b/routes/debug.js @@ -0,0 +1,15 @@ +import { app, globalConfig } from "../index.js" // Get globals from index +import { checkToken } from "../liberals/auth.js" +import { logRequest } from "../liberals/logging.js" + +app.get("/api/debugtokencheck", (rreq,rres) => { + checkToken(rreq.get("Authorization"),"etyd").then(authRes => { + if (authRes) { + rres.sendStatus(200) + } else { + rres.sendStatus(401) + } + }) +}) + +export { app } \ No newline at end of file diff --git a/routes/etyd.js b/routes/etyd.js index f185745..653a4ea 100644 --- a/routes/etyd.js +++ b/routes/etyd.js @@ -1,130 +1,123 @@ -import { app, globalConfig } from "../index.js" // Get globals from index +import { app, db, globalConfig } from "../index.js" // Get globals from index import { checkToken } from "../liberals/auth.js" import { logRequest } from "../liberals/logging.js" app.get("/api/etyd*", (rreq,rres) => { - fetch(`${process.env.API_DBHOST}/etyd${rreq.path.replace("/api/etyd","")}`,{ - headers: { "Authorization": `Basic ${btoa(process.env.API_DBCRED)}`} - }).then(dbRes => { - if (dbRes.status == 404) { - rres.sendStatus(404) + let userRequest = rreq.path.replace("/api/etyd/","") + db`select content from etyd where url = ${userRequest}`.then(response => { + if (response.length == 0) { + rres.status(404).send(`etyd.cc: URL "${userRequest}" was not found`) } else { - dbRes.json().then(dbRes => { - try { - rres.redirect(dbRes.content.url) // Node will crash if the Database entry is malformed - } catch (responseError) { - logRequest(rres,rreq,500,responseError) - rres.sendStatus(500) - } - }) + rres.redirect(response[0].content) } - }).catch(fetchError => { - logRequest(rres,rreq,500,fetchError) - rres.sendStatus(500) + }).catch(dbError => { + logRequest(rres,rreq,500,dbError) + rres.status(500).send(`etyd.cc: An internal error occured`) }) }) -// app.delete("/api/etyd*", (rreq,rres) => { +app.delete("/api/etyd*", (rreq,rres) => { -// if (rreq.get("Authorization") === undefined) { -// rres.sendStatus(400) -// } else { -// checkToken(rreq.get("Authorization"),"etyd").then(authRes => { -// if (authRes === false) { -// rres.sendStatus(401) -// } else if (authRes === true) { // Authorization successful + if (rreq.get("Authorization") === undefined) { + rres.sendStatus(400) + } else { + checkToken(rreq.get("Authorization"),"etyd").then(authRes => { + if (authRes === false) { + rres.sendStatus(401) + } else if (authRes === true) { // Authorization successful -// fetch(`${process.env.API_DBHOST}/etyd${rreq.path.replace("/api/etyd", "")}`,{ -// headers: { "Authorization": `Basic ${btoa(process.env.API_DBCRED)}`} -// }).then(dbRes => { + fetch(`${process.env.API_DBHOST}/etyd${rreq.path.replace("/api/etyd", "")}`,{ + headers: { "Authorization": `Basic ${btoa(process.env.API_DBCRED)}`} + }).then(dbRes => { -// if (dbRes.status == 404) { -// rres.sendStatus(404) // Entry does not exist -// } else { -// dbRes.json().then(dbRes => { + if (dbRes.status == 404) { + rres.sendStatus(404) // Entry does not exist + } else { + dbRes.json().then(dbRes => { -// fetch(`${process.env.API_DBHOST}/etyd${rreq.path.replace("/api/etyd", ""),{ -// headers: { "Authorization": `Basic ${btoa(process.env.API_DBCRED)}`} -// }}`, { -// method: "DELETE", -// headers: { -// "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")}`) -// logRequest(rres,rreq,200) -// rres.sendStatus(200) -// } -// }).catch(fetchError => { -// // console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 500: ${fetchError}`) -// logRequest(rres,rreq,500,fetchError) -// rres.sendStatus(500) -// }) + fetch(`${process.env.API_DBHOST}/etyd${rreq.path.replace("/api/etyd", "")}`,{ + headers: { "Authorization": `Basic ${btoa(process.env.API_DBCRED)}`}, + method: "DELETE", + headers: { + "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")}`) + logRequest(rres,rreq,200) + rres.sendStatus(200) + } else { + rres.send(`Received status ${fetchRes.status}`) + } + }).catch(fetchError => { + // console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 500: ${fetchError}`) + logRequest(rres,rreq,500,fetchError) + rres.sendStatus(500) + }) -// }) -// } + }) + } -// }).catch(fetchError => { -// logRequest(rres,rreq,500,fetchError) -// rres.sendStatus(500) -// }) + }).catch(fetchError => { + logRequest(rres,rreq,500,fetchError) + rres.sendStatus(500) + }) -// } -// }) -// } + } + }) + } -// }) +}) -// app.post("/api/etyd*", (rreq,rres) => { +app.post("/api/etyd*", (rreq,rres) => { -// if (rreq.get("Authorization") === undefined) { -// rres.sendStatus(400) -// } else { -// checkToken(rreq.get("Authorization"),"etyd").then(authRes => { -// if (authRes === false) { -// rres.sendStatus(401) -// } else if (authRes === true) { // Authorization successful + if (rreq.get("Authorization") === undefined) { + rres.sendStatus(400) + } else { + checkToken(rreq.get("Authorization"),"etyd").then(authRes => { + if (authRes === false) { + rres.sendStatus(401) + } else if (authRes === true) { // Authorization successful -// if (rreq.body["url"] == undefined) { -// rres.sendStatus(400) -// } else { -// fetch(`${process.env.API_DBHOST}/etyd${rreq.path.replace("/api/etyd", ""),{ -// headers: { "Authorization": `Basic ${btoa(process.env.API_DBCRED)}`} -// }}`, { -// method: "PUT", -// body: JSON.stringify({ -// "content": { -// "url": rreq.body["url"] -// } -// }) -// }).then(dbRes => { + if (rreq.body["url"] == undefined) { + rres.sendStatus(400) + } else { + fetch(`${process.env.API_DBHOST}/etyd${rreq.path.replace("/api/etyd", "")}`,{ + headers: { "Authorization": `Basic ${btoa(process.env.API_DBCRED)}`}, + method: "PUT", + body: JSON.stringify({ + "content": { + "url": rreq.body["url"] + } + }) + }).then(dbRes => { -// switch(dbRes.status) { -// case 409: -// rres.sendStatus(409) -// break; + switch(dbRes.status) { + case 409: + rres.sendStatus(409) + break; -// case 201: -// rres.status(200).send(rreq.path.replace("/api/etyd", "")) -// break; + case 201: + rres.status(200).send(rreq.path.replace("/api/etyd", "")) + break; -// default: -// logRequest(rres,rreq,500,`CouchDB PUT did not return expected code: ${dbRes.status} ${dbRes.statusText}`) -// rres.sendStatus(500) -// break; -// } + default: + logRequest(rres,rreq,500,`CouchDB PUT did not return expected code: ${dbRes.status} ${dbRes.statusText}`) + rres.sendStatus(500) + break; + } -// }).catch(fetchError => { -// logRequest(rres,rreq,500,fetchError) -// rres.sendStatus(500) -// }) -// } + }).catch(fetchError => { + logRequest(rres,rreq,500,fetchError) + rres.sendStatus(500) + }) + } -// } -// }) -// } + } + }) + } -// }) +}) export {app} // export routes to be imported by index for execution \ No newline at end of file diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..71f8b01 --- /dev/null +++ b/todo.md @@ -0,0 +1,5 @@ +- [ ] GET /api/whoami - Returns owner of token and what scopes it has +- [ ] GET /api/login - OIDC login redirect to ECLS +- [ ] GET /api/callback - Creates new token that is intended to be local to browser; e.g. can be used in turn to make longer lasting more specific tokens +- [ ] POST /api/token - Allows owner to create a new token with customized scopes, comments & expiration date +- [ ] DELETE /api/token - Invalidate a token \ No newline at end of file