diff --git a/liberals/auth.js b/liberals/auth.js index 0db2b29..066316c 100644 --- a/liberals/auth.js +++ b/liberals/auth.js @@ -19,25 +19,36 @@ 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 + * Checks for tokens provided in request and validates them against the sessions table including the desired scope + * @param {object} request Express request object * @param {string} scope Desired scope for action - * @typedef {Object} Object containing the result and the username of the token owner + * @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 * @property {number} ownerId Database ID of the token owner */ -async function checkTokenNew(token,scope) { - return await db`select s.*, u.username from sessions s join users u on s.owner = u.id where s.token = ${token}`.then(response => { - if (response.length === 0) { - return { result: false, owner: response[0]?.username, ownerId: response[0]?.owner} - } else if (response[0]?.scopes.split(",").includes(scope)) { - return { result: true, owner: response[0]?.username, ownerId: response[0]?.owner} - } else { - return { result: false, owner: response[0]?.username, ownerId: response[0]?.owner} - } - }) +async function checkTokenNew(request, scope) { + + if (!request.cookies["APIToken"] && !request.get("Authorization")) { + return { result: false, owner: "", ownerId: "" } + } else { + return await db`select s.*, u.username from sessions s join users u on s.owner = u.id where s.token = ${request.get("Authorization") ?? request.cookies["APIToken"]}`.then(response => { + if (response.length === 0) { + return { result: false, owner: response[0]?.username, ownerId: response[0]?.owner } + } else if (response[0]?.scopes.split(",").includes(scope)) { + return { result: true, owner: response[0]?.username, ownerId: response[0]?.owner } + } else { + return { result: false, owner: response[0]?.username, ownerId: response[0]?.owner } + } + }).catch(dbErr => { + return { result: false, owner: "", ownerId: "" } + }) + } + + + + } export {checkToken, checkTokenNew} \ No newline at end of file diff --git a/routes/auth.js b/routes/auth.js index d99beae..7178d09 100644 --- a/routes/auth.js +++ b/routes/auth.js @@ -1,4 +1,4 @@ -// import { app, db, globalConfig } from "../index.js" // Get globals from index +import { app, db, globalConfig } from "../index.js" // Get globals from index import { checkTokenNew } from "../liberals/auth.js" import { logRequest } from "../liberals/logging.js" import { randomStringBase62, getHumanReadableUserAgent } from "../liberals/misc.js" diff --git a/routes/debug.js b/routes/debug.js deleted file mode 100644 index c5c350e..0000000 --- a/routes/debug.js +++ /dev/null @@ -1,19 +0,0 @@ -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) - } - }) -}) - -app.get("/api/debugurl", (rreq,rres) => { - rres.send(`${rreq.protocol}://${rreq.get("Host")}`) -}) - -export { app } \ No newline at end of file diff --git a/routes/email.js b/routes/email.js index 3d916ca..9058096 100644 --- a/routes/email.js +++ b/routes/email.js @@ -14,7 +14,7 @@ const transporter = nodemailer.createTransport({ }) app.post("/api/sendemail", (rreq,rres) => { - checkTokenNew(rreq.get("Authorization"),"email").then(authRes => { + checkTokenNew(rreq,"email").then(authRes => { if (authRes.result === false) { rres.sendStatus(401) } else if (authRes.result === true) { diff --git a/routes/etyd.js b/routes/etyd.js index 653a4ea..dbd3cf1 100644 --- a/routes/etyd.js +++ b/routes/etyd.js @@ -1,5 +1,5 @@ import { app, db, globalConfig } from "../index.js" // Get globals from index -import { checkToken } from "../liberals/auth.js" +import { checkToken, checkTokenNew } from "../liberals/auth.js" import { logRequest } from "../liberals/logging.js" app.get("/api/etyd*", (rreq,rres) => { @@ -18,105 +18,55 @@ app.get("/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 - - 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 => { - - 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) + checkTokenNew(rreq,"etyd").then(authRes => { + if (authRes.result === false) { + rres.sendStatus(401) // Token not provided or invalid for this action + } else { + db`delete from etyd where url = ${rreq.path.replace("/api/etyd/","")} and owner = ${authRes.ownerId}`.then(dbRes => { + if (dbRes.count === 1) { + rres.sendStatus(200) + } else if (dbRes.count === 0) { + rres.sendStatus(400) + } else { + logRequest(rres, rreq, 500, `Something bad happened during delete from database`) rres.sendStatus(500) - }) - - } - }) - } + } + }).catch(dbErr => { + logRequest(rres, rreq, 500, dbErr) + rres.sendStatus(500) + }) + } + }) }) 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.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; - - 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; - } - - }).catch(fetchError => { - logRequest(rres,rreq,500,fetchError) + checkTokenNew(rreq,"etyd").then(authRes => { + if (authRes.result === false) { + rres.sendStatus(401) // Token not provided or invalid for this action + } else { + if (!rreq.body["url"]) { // Assumption that if the url key isnt present in the body then the request is malformed + rres.sendStatus(400) + } else { + db`insert into etyd (url,content,owner) values (${rreq.path.replace("/api/etyd/","")},${rreq.body["url"]},${authRes.ownerId})`.then(dbRes => { + if (dbRes.count === 1) { + rres.sendStatus(201) + } else { + logRequest(rres,rreq,500,`Database insert did not return expected count but did not error out`) rres.sendStatus(500) - }) - } - + } + }).catch(dbErr => { + if (dbErr.code == "23505") { // Unique constraint violation, entry already exists + rres.sendStatus(409) + } else { + logRequest(rres,rreq,500,dbErr) + rres.sendStatus(500) + } + }) } - }) - } + } + }) })