mirror of
				https://github.com/karl0ss/homepage.git
				synced 2025-11-04 00:10:57 +00:00 
			
		
		
		
	Merge pull request from GHSA-24m5-7vjx-9x37
* Restrict emby endpoints and proxy segments * Dont allow path traversal in segments * Restrict qbittorrent proxy endpoints * Restrict npm proxy endpoints * Restrict flood proxy endpoints * Restrict tdarr proxy endpoints * Restrict xteve proxy endpoints * Restrict transmission proxy endpoints * disallow non-mapped endpoints this change drops all requests that have un-mapped endpoint queries allowedEndpoints is added as a method to pass proxy requests via a regex on the endpoint most widgets with custom proxies use either no endpoint, or a static one Co-Authored-By: Ben Phelps <ben@phelps.io>
This commit is contained in:
		
							parent
							
								
									8823b04291
								
							
						
					
					
						commit
						52cce0ee21
					
				@ -18,6 +18,11 @@ export default async function handler(req, res) {
 | 
				
			|||||||
    const serviceProxyHandler = widget.proxyHandler || genericProxyHandler;
 | 
					    const serviceProxyHandler = widget.proxyHandler || genericProxyHandler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (serviceProxyHandler instanceof Function) {
 | 
					    if (serviceProxyHandler instanceof Function) {
 | 
				
			||||||
 | 
					      // quick return for no endpoint services
 | 
				
			||||||
 | 
					      if (!req.query.endpoint) {
 | 
				
			||||||
 | 
					        return serviceProxyHandler(req, res);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // map opaque endpoints to their actual endpoint
 | 
					      // map opaque endpoints to their actual endpoint
 | 
				
			||||||
      if (widget?.mappings) {
 | 
					      if (widget?.mappings) {
 | 
				
			||||||
        const mapping = widget?.mappings?.[req.query.endpoint];
 | 
					        const mapping = widget?.mappings?.[req.query.endpoint];
 | 
				
			||||||
@ -38,6 +43,15 @@ export default async function handler(req, res) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (req.query.segments) {
 | 
					        if (req.query.segments) {
 | 
				
			||||||
          const segments = JSON.parse(req.query.segments);
 | 
					          const segments = JSON.parse(req.query.segments);
 | 
				
			||||||
 | 
					          for (const key in segments) {
 | 
				
			||||||
 | 
					            if (!mapping.segments.includes(key)) {
 | 
				
			||||||
 | 
					              logger.debug("Unsupported segment: %s", key);
 | 
				
			||||||
 | 
					              return res.status(403).json({ error: "Unsupported segment" });
 | 
				
			||||||
 | 
					            } else if (segments[key].includes("/")) {
 | 
				
			||||||
 | 
					              logger.debug("Unsupported segment value: %s", segments[key]);
 | 
				
			||||||
 | 
					              return res.status(403).json({ error: "Unsupported segment value" });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
          req.query.endpoint = formatApiCall(endpoint, segments);
 | 
					          req.query.endpoint = formatApiCall(endpoint, segments);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -66,7 +80,14 @@ export default async function handler(req, res) {
 | 
				
			|||||||
        return serviceProxyHandler(req, res, map);
 | 
					        return serviceProxyHandler(req, res, map);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return serviceProxyHandler(req, res);
 | 
					      if (widget.allowedEndpoints instanceof RegExp) {
 | 
				
			||||||
 | 
					        if (widget.allowedEndpoints.test(req.query.endpoint)) {
 | 
				
			||||||
 | 
					          return serviceProxyHandler(req, res);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      logger.debug("Unmapped proxy request.");
 | 
				
			||||||
 | 
					      return res.status(403).json({ error: "Unmapped proxy request." });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    logger.debug("Unknown proxy service type: %s", type);
 | 
					    logger.debug("Unknown proxy service type: %s", type);
 | 
				
			||||||
 | 
				
			|||||||
@ -8,22 +8,16 @@ export function formatApiCall(url, args) {
 | 
				
			|||||||
  return url.replace(/\/+$/, "").replace(find, replace).replace(find, replace);
 | 
					  return url.replace(/\/+$/, "").replace(find, replace).replace(find, replace);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getURLSearchParams(widget, endpoint) {
 | 
					export function getURLSearchParams(widget, endpoint) {
 | 
				
			||||||
  const params = new URLSearchParams({
 | 
					  const params = new URLSearchParams({
 | 
				
			||||||
    type: widget.type,
 | 
					    type: widget.type,
 | 
				
			||||||
    group: widget.service_group,
 | 
					    group: widget.service_group,
 | 
				
			||||||
    service: widget.service_name,
 | 
					    service: widget.service_name,
 | 
				
			||||||
    endpoint,
 | 
					 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  return params;
 | 
					  if (endpoint) {
 | 
				
			||||||
}
 | 
					    params.append("endpoint", endpoint);
 | 
				
			||||||
 | 
					 | 
				
			||||||
export function formatProxyUrlWithSegments(widget, endpoint, segments) {
 | 
					 | 
				
			||||||
  const params = getURLSearchParams(widget, endpoint);
 | 
					 | 
				
			||||||
  if (segments) {
 | 
					 | 
				
			||||||
    params.append("segments", JSON.stringify(segments));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return `/api/services/proxy?${params.toString()}`;
 | 
					  return params;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function formatProxyUrl(widget, endpoint, queryParams) {
 | 
					export function formatProxyUrl(widget, endpoint, queryParams) {
 | 
				
			||||||
@ -59,6 +53,7 @@ export function sanitizeErrorURL(errorURL) {
 | 
				
			|||||||
  const url = new URL(errorURL);
 | 
					  const url = new URL(errorURL);
 | 
				
			||||||
  ["apikey", "api_key", "token", "t", "access_token", "auth"].forEach((key) => {
 | 
					  ["apikey", "api_key", "token", "t", "access_token", "auth"].forEach((key) => {
 | 
				
			||||||
    if (url.searchParams.has(key)) url.searchParams.set(key, "***");
 | 
					    if (url.searchParams.has(key)) url.searchParams.set(key, "***");
 | 
				
			||||||
 | 
					    if (url.hash.includes(key)) url.hash = url.hash.replace(new RegExp(`${key}=[^&]+`), `${key}=***`);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  return url.toString();
 | 
					  return url.toString();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@ import { MdOutlineSmartDisplay } from "react-icons/md";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import Block from "components/services/widget/block";
 | 
					import Block from "components/services/widget/block";
 | 
				
			||||||
import Container from "components/services/widget/container";
 | 
					import Container from "components/services/widget/container";
 | 
				
			||||||
import { formatProxyUrlWithSegments } from "utils/proxy/api-helpers";
 | 
					import { getURLSearchParams } from "utils/proxy/api-helpers";
 | 
				
			||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
 | 
					import useWidgetAPI from "utils/proxy/use-widget-api";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function ticksToTime(ticks) {
 | 
					function ticksToTime(ticks) {
 | 
				
			||||||
@ -217,10 +217,14 @@ export default function Component({ service }) {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async function handlePlayCommand(session, command) {
 | 
					  async function handlePlayCommand(session, command) {
 | 
				
			||||||
    const url = formatProxyUrlWithSegments(widget, "PlayControl", {
 | 
					    const params = getURLSearchParams(widget, command);
 | 
				
			||||||
      sessionId: session.Id,
 | 
					    params.append(
 | 
				
			||||||
      command,
 | 
					      "segments",
 | 
				
			||||||
    });
 | 
					      JSON.stringify({
 | 
				
			||||||
 | 
					        sessionId: session.Id,
 | 
				
			||||||
 | 
					      }),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    const url = `/api/services/proxy?${params.toString()}`;
 | 
				
			||||||
    await fetch(url).then(() => {
 | 
					    await fetch(url).then(() => {
 | 
				
			||||||
      sessionMutate();
 | 
					      sessionMutate();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
				
			|||||||
@ -10,12 +10,16 @@ const widget = {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    Count: {
 | 
					    Count: {
 | 
				
			||||||
      endpoint: "Items/Counts",
 | 
					      endpoint: "Items/Counts",
 | 
				
			||||||
      segments: ["MovieCount", "SeriesCount", "EpisodeCount", "SongCount"],
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    PlayControl: {
 | 
					    Unpause: {
 | 
				
			||||||
      method: "POST",
 | 
					      method: "POST",
 | 
				
			||||||
      endpoint: "Sessions/{sessionId}/Playing/{command}",
 | 
					      endpoint: "Sessions/{sessionId}/Playing/Unpause",
 | 
				
			||||||
      segments: ["sessionId", "command"],
 | 
					      segments: ["sessionId"],
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    Pause: {
 | 
				
			||||||
 | 
					      method: "POST",
 | 
				
			||||||
 | 
					      endpoint: "Sessions/{sessionId}/Playing/Pause",
 | 
				
			||||||
 | 
					      segments: ["sessionId"],
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,12 @@ import floodProxyHandler from "./proxy";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const widget = {
 | 
					const widget = {
 | 
				
			||||||
  proxyHandler: floodProxyHandler,
 | 
					  proxyHandler: floodProxyHandler,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  mappings: {
 | 
				
			||||||
 | 
					    torrents: {
 | 
				
			||||||
 | 
					      endpoint: "torrents",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default widget;
 | 
					export default widget;
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@ import fritzboxProxyHandler from "./proxy";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const widget = {
 | 
					const widget = {
 | 
				
			||||||
  proxyHandler: fritzboxProxyHandler,
 | 
					  proxyHandler: fritzboxProxyHandler,
 | 
				
			||||||
 | 
					  allowedEndpoints: /status/,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default widget;
 | 
					export default widget;
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@ import gamedigProxyHandler from "./proxy";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const widget = {
 | 
					const widget = {
 | 
				
			||||||
  proxyHandler: gamedigProxyHandler,
 | 
					  proxyHandler: gamedigProxyHandler,
 | 
				
			||||||
 | 
					  allowedEndpoints: /status/,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default widget;
 | 
					export default widget;
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@ import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
 | 
				
			|||||||
const widget = {
 | 
					const widget = {
 | 
				
			||||||
  api: "{url}/api/{endpoint}",
 | 
					  api: "{url}/api/{endpoint}",
 | 
				
			||||||
  proxyHandler: credentialedProxyHandler,
 | 
					  proxyHandler: credentialedProxyHandler,
 | 
				
			||||||
 | 
					  allowedEndpoints: /\d\/quicklook|diskio|fs|gpu|system|mem|network|processlist|sensors/,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default widget;
 | 
					export default widget;
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@ import minecraftProxyHandler from "./proxy";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const widget = {
 | 
					const widget = {
 | 
				
			||||||
  proxyHandler: minecraftProxyHandler,
 | 
					  proxyHandler: minecraftProxyHandler,
 | 
				
			||||||
 | 
					  allowedEndpoints: /status/,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default widget;
 | 
					export default widget;
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@ import useWidgetAPI from "utils/proxy/use-widget-api";
 | 
				
			|||||||
export default function Component({ service }) {
 | 
					export default function Component({ service }) {
 | 
				
			||||||
  const { widget } = service;
 | 
					  const { widget } = service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const { data: infoData, error: infoError } = useWidgetAPI(widget, "nginx/proxy-hosts");
 | 
					  const { data: infoData, error: infoError } = useWidgetAPI(widget, "hosts");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (infoError) {
 | 
					  if (infoError) {
 | 
				
			||||||
    return <Container service={service} error={infoError} />;
 | 
					    return <Container service={service} error={infoError} />;
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,12 @@ import npmProxyHandler from "./proxy";
 | 
				
			|||||||
const widget = {
 | 
					const widget = {
 | 
				
			||||||
  api: "{url}/api/{endpoint}",
 | 
					  api: "{url}/api/{endpoint}",
 | 
				
			||||||
  proxyHandler: npmProxyHandler,
 | 
					  proxyHandler: npmProxyHandler,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  mappings: {
 | 
				
			||||||
 | 
					    hosts: {
 | 
				
			||||||
 | 
					      endpoint: "nginx/proxy-hosts",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default widget;
 | 
					export default widget;
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@ import jsonrpcProxyHandler from "utils/proxy/handlers/jsonrpc";
 | 
				
			|||||||
const widget = {
 | 
					const widget = {
 | 
				
			||||||
  api: "{url}/jsonrpc",
 | 
					  api: "{url}/jsonrpc",
 | 
				
			||||||
  proxyHandler: jsonrpcProxyHandler,
 | 
					  proxyHandler: jsonrpcProxyHandler,
 | 
				
			||||||
 | 
					  allowedEndpoints: /status/,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default widget;
 | 
					export default widget;
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ export default function Component({ service }) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  const { widget } = service;
 | 
					  const { widget } = service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const { data: torrentData, error: torrentError } = useWidgetAPI(widget, "torrents/info");
 | 
					  const { data: torrentData, error: torrentError } = useWidgetAPI(widget, "torrents");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (torrentError) {
 | 
					  if (torrentError) {
 | 
				
			||||||
    return <Container service={service} error={torrentError} />;
 | 
					    return <Container service={service} error={torrentError} />;
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,12 @@ import qbittorrentProxyHandler from "./proxy";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const widget = {
 | 
					const widget = {
 | 
				
			||||||
  proxyHandler: qbittorrentProxyHandler,
 | 
					  proxyHandler: qbittorrentProxyHandler,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  mappings: {
 | 
				
			||||||
 | 
					    torrents: {
 | 
				
			||||||
 | 
					      endpoint: "torrents/info",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default widget;
 | 
					export default widget;
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@ import qnapProxyHandler from "./proxy";
 | 
				
			|||||||
const widget = {
 | 
					const widget = {
 | 
				
			||||||
  api: "{url}",
 | 
					  api: "{url}",
 | 
				
			||||||
  proxyHandler: qnapProxyHandler,
 | 
					  proxyHandler: qnapProxyHandler,
 | 
				
			||||||
 | 
					  allowedEndpoints: /status/,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default widget;
 | 
					export default widget;
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@ import genericProxyHandler from "utils/proxy/handlers/generic";
 | 
				
			|||||||
const widget = {
 | 
					const widget = {
 | 
				
			||||||
  api: "{url}/?stats=true",
 | 
					  api: "{url}/?stats=true",
 | 
				
			||||||
  proxyHandler: genericProxyHandler,
 | 
					  proxyHandler: genericProxyHandler,
 | 
				
			||||||
 | 
					  allowedEndpoints: /overview/,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default widget;
 | 
					export default widget;
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,7 @@ const proxyName = "tdarrProxyHandler";
 | 
				
			|||||||
const logger = createLogger(proxyName);
 | 
					const logger = createLogger(proxyName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default async function tdarrProxyHandler(req, res) {
 | 
					export default async function tdarrProxyHandler(req, res) {
 | 
				
			||||||
  const { group, service, endpoint } = req.query;
 | 
					  const { group, service } = req.query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!group || !service) {
 | 
					  if (!group || !service) {
 | 
				
			||||||
    logger.debug("Invalid or missing service '%s' or group '%s'", service, group);
 | 
					    logger.debug("Invalid or missing service '%s' or group '%s'", service, group);
 | 
				
			||||||
@ -22,7 +22,7 @@ export default async function tdarrProxyHandler(req, res) {
 | 
				
			|||||||
    return res.status(400).json({ error: "Invalid proxy service type" });
 | 
					    return res.status(400).json({ error: "Invalid proxy service type" });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
 | 
					  const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint: undefined, ...widget }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const [status, contentType, data] = await httpProxy(url, {
 | 
					  const [status, contentType, data] = await httpProxy(url, {
 | 
				
			||||||
    method: "POST",
 | 
					    method: "POST",
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@ const headerCacheKey = `${proxyName}__headers`;
 | 
				
			|||||||
const logger = createLogger(proxyName);
 | 
					const logger = createLogger(proxyName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default async function transmissionProxyHandler(req, res) {
 | 
					export default async function transmissionProxyHandler(req, res) {
 | 
				
			||||||
  const { group, service, endpoint } = req.query;
 | 
					  const { group, service } = req.query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!group || !service) {
 | 
					  if (!group || !service) {
 | 
				
			||||||
    logger.debug("Invalid or missing service '%s' or group '%s'", service, group);
 | 
					    logger.debug("Invalid or missing service '%s' or group '%s'", service, group);
 | 
				
			||||||
@ -35,7 +35,7 @@ export default async function transmissionProxyHandler(req, res) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  const api = `${widget.url}${widget.rpcUrl || widgets[widget.type].rpcUrl}rpc`;
 | 
					  const api = `${widget.url}${widget.rpcUrl || widgets[widget.type].rpcUrl}rpc`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const url = new URL(formatApiCall(api, { endpoint, ...widget }));
 | 
					  const url = new URL(formatApiCall(api, { endpoint: undefined, ...widget }));
 | 
				
			||||||
  const csrfHeaderName = "x-transmission-session-id";
 | 
					  const csrfHeaderName = "x-transmission-session-id";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const method = "POST";
 | 
					  const method = "POST";
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@ import urbackupProxyHandler from "./proxy";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const widget = {
 | 
					const widget = {
 | 
				
			||||||
  proxyHandler: urbackupProxyHandler,
 | 
					  proxyHandler: urbackupProxyHandler,
 | 
				
			||||||
 | 
					  allowedEndpoints: /status/,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default widget;
 | 
					export default widget;
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ export default function Component({ service }) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  const { widget } = service;
 | 
					  const { widget } = service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const { data: xteveData, error: xteveError } = useWidgetAPI(widget, "api");
 | 
					  const { data: xteveData, error: xteveError } = useWidgetAPI(widget);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (xteveError) {
 | 
					  if (xteveError) {
 | 
				
			||||||
    return <Container service={service} error={xteveError} />;
 | 
					    return <Container service={service} error={xteveError} />;
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@ import getServiceWidget from "utils/config/service-helpers";
 | 
				
			|||||||
const logger = createLogger("xteveProxyHandler");
 | 
					const logger = createLogger("xteveProxyHandler");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default async function xteveProxyHandler(req, res) {
 | 
					export default async function xteveProxyHandler(req, res) {
 | 
				
			||||||
  const { group, service, endpoint } = req.query;
 | 
					  const { group, service } = req.query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!group || !service) {
 | 
					  if (!group || !service) {
 | 
				
			||||||
    return res.status(400).json({ error: "Invalid proxy service type" });
 | 
					    return res.status(400).json({ error: "Invalid proxy service type" });
 | 
				
			||||||
@ -19,7 +19,7 @@ export default async function xteveProxyHandler(req, res) {
 | 
				
			|||||||
    return res.status(403).json({ error: "Service does not support API calls" });
 | 
					    return res.status(403).json({ error: "Service does not support API calls" });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const url = formatApiCall(api, { endpoint, ...widget });
 | 
					  const url = formatApiCall(api, { endpoint: "api/", ...widget });
 | 
				
			||||||
  const method = "POST";
 | 
					  const method = "POST";
 | 
				
			||||||
  const payload = { cmd: "status" };
 | 
					  const payload = { cmd: "status" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,12 +3,6 @@ import xteveProxyHandler from "./proxy";
 | 
				
			|||||||
const widget = {
 | 
					const widget = {
 | 
				
			||||||
  api: "{url}/{endpoint}",
 | 
					  api: "{url}/{endpoint}",
 | 
				
			||||||
  proxyHandler: xteveProxyHandler,
 | 
					  proxyHandler: xteveProxyHandler,
 | 
				
			||||||
 | 
					 | 
				
			||||||
  mappings: {
 | 
					 | 
				
			||||||
    api: {
 | 
					 | 
				
			||||||
      endpoint: "api/",
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default widget;
 | 
					export default widget;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user