From b97d625c930d34bed1c6e3eba038cf710c2b99f3 Mon Sep 17 00:00:00 2001 From: technowhizz <7688823+technowhizz@users.noreply.github.com> Date: Sun, 17 Mar 2024 00:49:38 +0000 Subject: [PATCH] Fix Jackett widget when using password (#3097) Fixes the error that occurs as seen in (#437, #1799 and #2794) which occurs due to the way password authentication works in Jackett. We now make a login request to Jackett to get the cookie and then use that cookie to make the actual request to the Jackett API. --- docs/widgets/services/jackett.md | 3 ++- src/utils/proxy/handlers/credentialed.js | 10 ++++++++++ src/utils/proxy/http.js | 2 +- src/utils/proxy/jackett.js | 22 ++++++++++++++++++++++ src/widgets/jackett/widget.js | 5 +++-- 5 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 src/utils/proxy/jackett.js diff --git a/docs/widgets/services/jackett.md b/docs/widgets/services/jackett.md index 22e089a4..a8c9d897 100644 --- a/docs/widgets/services/jackett.md +++ b/docs/widgets/services/jackett.md @@ -5,7 +5,7 @@ description: Jackett Widget Configuration Learn more about [Jackett](https://github.com/Jackett/Jackett). -Jackett must not have any authentication for the widget to work. +If Jackett has an admin password set, you must set the `password` field for the widget to work. Allowed fields: `["configured", "errored"]`. @@ -14,4 +14,5 @@ widget: type: jackett url: http://jackett.host.or.ip key: jackettapikey + password: JackettAdminPassword ``` diff --git a/src/utils/proxy/handlers/credentialed.js b/src/utils/proxy/handlers/credentialed.js index de2111b1..9960e1cc 100644 --- a/src/utils/proxy/handlers/credentialed.js +++ b/src/utils/proxy/handlers/credentialed.js @@ -4,6 +4,7 @@ import validateWidgetData from "utils/proxy/validate-widget-data"; import { httpProxy } from "utils/proxy/http"; import createLogger from "utils/logger"; import widgets from "widgets/widgets"; +import { fetchJackettCookie } from "utils/proxy/jackett"; const logger = createLogger("credentialedProxyHandler"); @@ -69,6 +70,15 @@ export default async function credentialedProxyHandler(req, res, map) { headers.Authorization = `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`; } else if (widget.type === "plantit") { headers.Key = `${widget.key}`; + } else if (widget.type === "jackett") { + if (widget.password) { + const jackettCookie = await fetchJackettCookie(widget, widgets[widget.type].loginURL); + if (jackettCookie) { + headers.Cookie = jackettCookie; + } else { + return res.status(500).json({ error: "Failed to authenticate with Jackett" }); + } + } } else { headers["X-API-Key"] = `${widget.key}`; } diff --git a/src/utils/proxy/http.js b/src/utils/proxy/http.js index ff34ce0d..8a9ce380 100644 --- a/src/utils/proxy/http.js +++ b/src/utils/proxy/http.js @@ -103,7 +103,7 @@ export async function httpProxy(url, params = {}) { try { const [status, contentType, data, responseHeaders] = await request; - return [status, contentType, data, responseHeaders]; + return [status, contentType, data, responseHeaders, params]; } catch (err) { logger.error( "Error calling %s//%s%s%s...", diff --git a/src/utils/proxy/jackett.js b/src/utils/proxy/jackett.js new file mode 100644 index 00000000..3d02a564 --- /dev/null +++ b/src/utils/proxy/jackett.js @@ -0,0 +1,22 @@ +import { httpProxy } from "utils/proxy/http"; +import { formatApiCall } from "utils/proxy/api-helpers"; + +export async function fetchJackettCookie(widget, loginURL) { + const url = new URL(formatApiCall(loginURL, widget)); + const loginData = `password=${encodeURIComponent(widget.password)}`; + const [status, , , , params] = await httpProxy(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: loginData, + }); + + if (status === 200 && params && params.headers && params.headers.Cookie) { + const cookieValue = params.headers.Cookie; + return cookieValue; + } else { + logger.error("Failed to fetch Jackett cookie, status: %d", status); + return null; + } +} diff --git a/src/widgets/jackett/widget.js b/src/widgets/jackett/widget.js index 9d2a9b5c..d2677b49 100644 --- a/src/widgets/jackett/widget.js +++ b/src/widgets/jackett/widget.js @@ -1,8 +1,9 @@ -import genericProxyHandler from "utils/proxy/handlers/generic"; +import credentialedProxyHandler from "utils/proxy/handlers/credentialed"; const widget = { api: "{url}/api/v2.0/{endpoint}?apikey={key}&configured=true", - proxyHandler: genericProxyHandler, + proxyHandler: credentialedProxyHandler, + loginURL: "{url}/UI/Dashboard", mappings: { indexers: {