diff --git a/src/widgets/npm/component.jsx b/src/widgets/npm/component.jsx index b35e27c85..92aef0359 100644 --- a/src/widgets/npm/component.jsx +++ b/src/widgets/npm/component.jsx @@ -11,7 +11,7 @@ export default function Component({ service }) { const { data: infoData, error: infoError } = useWidgetAPI(widget, "nginx/proxy-hosts"); - if (infoError) { + if (infoError || infoData?.error) { return ; } diff --git a/src/widgets/npm/proxy.js b/src/widgets/npm/proxy.js index eed43b571..ff15db62b 100644 --- a/src/widgets/npm/proxy.js +++ b/src/widgets/npm/proxy.js @@ -1,6 +1,33 @@ +import cache from "memory-cache"; + import getServiceWidget from "utils/config/service-helpers"; import { formatApiCall } from "utils/proxy/api-helpers"; +import { httpProxy } from "utils/proxy/http"; import widgets from "widgets/widgets"; +import createLogger from "utils/logger"; + +const proxyName = "npmProxyHandler"; +const tokenCacheKey = `${proxyName}__token`; +const logger = createLogger(proxyName); + +async function login(loginUrl, username, password) { + const authResponse = await httpProxy(loginUrl, { + method: "POST", + body: JSON.stringify({ identity: username, secret: password }), + headers: { + "Content-Type": "application/json", + }, + }); + + const status = authResponse[0]; + const data = JSON.parse(Buffer.from(authResponse[2]).toString()); + + if (status === 200) { + cache.put(tokenCacheKey, data.token); + } + + return [status, data.token ?? data]; +} export default async function npmProxyHandler(req, res) { const { group, service, endpoint } = req.query; @@ -14,27 +41,54 @@ export default async function npmProxyHandler(req, res) { if (widget) { const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget })); - const loginUrl = `${widget.url}/api/tokens`; - const body = { identity: widget.username, secret: widget.password }; - const authResponse = await fetch(loginUrl, { - method: "POST", - body: JSON.stringify(body), - headers: { - "Content-Type": "application/json", - }, - }).then((response) => response.json()); + let status; + let contentType; + let data; + + let token = cache.get(tokenCacheKey); + if (!token) { + [status, token] = await login(loginUrl, widget.username, widget.password); + if (status !== 200) { + logger.debug(`HTTTP ${status} logging into npm api: ${data}`); + return res.status(status).send(data); + } + } - const apiResponse = await fetch(url, { + [status, contentType, data] = await httpProxy(url, { method: "GET", headers: { "Content-Type": "application/json", - Authorization: `Bearer ${authResponse.token}`, + Authorization: `Bearer ${token}`, }, - }).then((response) => response.json()); + }); + + if (status === 403) { + logger.debug(`HTTTP ${status} retrieving data from npm api, logging in and trying again.`); + cache.del(tokenCacheKey); + [status, token] = await login(loginUrl, widget.username, widget.password); + + if (status !== 200) { + logger.debug(`HTTTP ${status} logging into npm api: ${data}`); + return res.status(status).send(data); + } + + // eslint-disable-next-line no-unused-vars + [status, contentType, data] = await httpProxy(url, { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, + }); + } + + if (status !== 200) { + return res.status(status).send(data); + } - return res.send(apiResponse); + return res.send(data); } }