From 5a8defb478538b54d89d749057f6b7a82b0a5175 Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Mon, 5 Sep 2022 20:14:14 +0300 Subject: [PATCH 1/5] allow weather apis to use hidden api keys --- .../widgets/openweathermap/weather.jsx | 4 +-- src/components/widgets/weather/weather.jsx | 5 ++-- src/pages/api/widgets/openweathermap.js | 25 ++++++++++++++++--- src/pages/api/widgets/weather.js | 25 ++++++++++++++++--- src/skeleton/settings.yaml | 3 +++ src/utils/config.js | 11 ++++++++ 6 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 src/skeleton/settings.yaml diff --git a/src/components/widgets/openweathermap/weather.jsx b/src/components/widgets/openweathermap/weather.jsx index 63b7b0816..a2074353f 100644 --- a/src/components/widgets/openweathermap/weather.jsx +++ b/src/components/widgets/openweathermap/weather.jsx @@ -4,9 +4,7 @@ import { BiError } from "react-icons/bi"; import Icon from "./icon"; export default function OpenWeatherMap({ options }) { - const { data, error } = useSWR( - `/api/widgets/openweathermap?lat=${options.latitude}&lon=${options.longitude}&apiKey=${options.apiKey}&duration=${options.cache}&units=${options.units}` - ); + const { data, error } = useSWR(`/api/widgets/openweathermap?${new URLSearchParams(options).toString()}`); if (error || data?.cod == 401) { return ( diff --git a/src/components/widgets/weather/weather.jsx b/src/components/widgets/weather/weather.jsx index 6fc365f0f..87d03786d 100644 --- a/src/components/widgets/weather/weather.jsx +++ b/src/components/widgets/weather/weather.jsx @@ -4,9 +4,8 @@ import { BiError } from "react-icons/bi"; import Icon from "./icon"; export default function WeatherApi({ options }) { - const { data, error } = useSWR( - `/api/widgets/weather?lat=${options.latitude}&lon=${options.longitude}&apiKey=${options.apiKey}&duration=${options.cache}` - ); + console.log(options); + const { data, error } = useSWR(`/api/widgets/weather?${new URLSearchParams(options).toString()}`); if (error) { return ( diff --git a/src/pages/api/widgets/openweathermap.js b/src/pages/api/widgets/openweathermap.js index 07dc91399..5a6877256 100644 --- a/src/pages/api/widgets/openweathermap.js +++ b/src/pages/api/widgets/openweathermap.js @@ -1,9 +1,28 @@ import cachedFetch from "utils/cached-fetch"; +import { getSettings } from "utils/config"; export default async function handler(req, res) { - const { lat, lon, apiKey, duration, units } = req.query; + const { latitude, longitude, units, provider, cache } = req.query; + let { apiKey } = req.query; - const api_url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${apiKey}&units=${units}`; + if (!apiKey && !provider) { + return res.status(400).json({ error: "Missing API key or provider" }); + } - res.send(await cachedFetch(api_url, duration)); + if (!apiKey && provider !== "openweathermap") { + return res.status(400).json({ error: "Invalid provider for endpoint" }); + } + + if (!apiKey && provider) { + const settings = await getSettings(); + apiKey = settings?.providers?.openweathermap; + } + + if (!apiKey) { + return res.status(400).json({ error: "Missing API key" }); + } + + const api_url = `https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${apiKey}&units=${units}`; + + res.send(await cachedFetch(api_url, cache)); } diff --git a/src/pages/api/widgets/weather.js b/src/pages/api/widgets/weather.js index 5d1af4b04..a7da10938 100644 --- a/src/pages/api/widgets/weather.js +++ b/src/pages/api/widgets/weather.js @@ -1,9 +1,28 @@ import cachedFetch from "utils/cached-fetch"; +import { getSettings } from "utils/config"; export default async function handler(req, res) { - const { lat, lon, apiKey, duration } = req.query; + const { latitude, longitude, provider, cache } = req.query; + let { apiKey } = req.query; - const api_url = `http://api.weatherapi.com/v1/current.json?q=${lat},${lon}&key=${apiKey}`; + if (!apiKey && !provider) { + return res.status(400).json({ error: "Missing API key or provider" }); + } - res.send(await cachedFetch(api_url, duration)); + if (!apiKey && provider !== "weatherapi") { + return res.status(400).json({ error: "Invalid provider for endpoint" }); + } + + if (!apiKey && provider) { + const settings = await getSettings(); + apiKey = settings?.providers?.weatherapi; + } + + if (!apiKey) { + return res.status(400).json({ error: "Missing API key" }); + } + + const api_url = `http://api.weatherapi.com/v1/current.json?q=${latitude},${longitude}&key=${apiKey}`; + + res.send(await cachedFetch(api_url, cache)); } diff --git a/src/skeleton/settings.yaml b/src/skeleton/settings.yaml new file mode 100644 index 000000000..5efd0e25e --- /dev/null +++ b/src/skeleton/settings.yaml @@ -0,0 +1,3 @@ +providers: + openweathermap: openweathermapapikey + weatherapi: weatherapiapikey diff --git a/src/utils/config.js b/src/utils/config.js index 758393ce1..d00f3818f 100644 --- a/src/utils/config.js +++ b/src/utils/config.js @@ -1,5 +1,8 @@ import { join } from "path"; import { existsSync, copyFile } from "fs"; +import { promises as fs } from "fs"; +import path from "path"; +import yaml from "js-yaml"; export default function checkAndCopyConfig(config) { const configYaml = join(process.cwd(), "config", config); @@ -14,3 +17,11 @@ export default function checkAndCopyConfig(config) { }); } } + +export async function getSettings() { + checkAndCopyConfig("settings.yaml"); + + const settingsYaml = path.join(process.cwd(), "config", "settings.yaml"); + const fileContents = await fs.readFile(settingsYaml, "utf8"); + return yaml.load(fileContents); +} From 6061d9ec65c8e06053dd75054fbc6d87097ecd2e Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Mon, 5 Sep 2022 20:19:08 +0300 Subject: [PATCH 2/5] cleanup imports --- src/utils/config.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/utils/config.js b/src/utils/config.js index d00f3818f..40d4b66aa 100644 --- a/src/utils/config.js +++ b/src/utils/config.js @@ -1,7 +1,5 @@ -import { join } from "path"; -import { existsSync, copyFile } from "fs"; -import { promises as fs } from "fs"; -import path from "path"; +import { join, path } from "path"; +import { existsSync, copyFile, promises as fs } from "fs"; import yaml from "js-yaml"; export default function checkAndCopyConfig(config) { From cf3939592490d266e87b9ec27d5a692ba2b3d210 Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Mon, 5 Sep 2022 20:20:34 +0300 Subject: [PATCH 3/5] add documentation link --- src/skeleton/settings.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/skeleton/settings.yaml b/src/skeleton/settings.yaml index 5efd0e25e..c9f13888d 100644 --- a/src/skeleton/settings.yaml +++ b/src/skeleton/settings.yaml @@ -1,3 +1,6 @@ +# For configuration options and examples, please see: +# https://github.com/benphelps/homepage/wiki/Settings + providers: openweathermap: openweathermapapikey weatherapi: weatherapiapikey From 939f5d7c20430580ca55259dca5c72120d15537b Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Tue, 6 Sep 2022 08:39:25 +0300 Subject: [PATCH 4/5] fix path.join import --- src/utils/config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/config.js b/src/utils/config.js index 40d4b66aa..5fa3fa7f9 100644 --- a/src/utils/config.js +++ b/src/utils/config.js @@ -1,4 +1,4 @@ -import { join, path } from "path"; +import { join } from "path"; import { existsSync, copyFile, promises as fs } from "fs"; import yaml from "js-yaml"; @@ -19,7 +19,7 @@ export default function checkAndCopyConfig(config) { export async function getSettings() { checkAndCopyConfig("settings.yaml"); - const settingsYaml = path.join(process.cwd(), "config", "settings.yaml"); + const settingsYaml = join(process.cwd(), "config", "settings.yaml"); const fileContents = await fs.readFile(settingsYaml, "utf8"); return yaml.load(fileContents); } From 837305775807cadcd9c6e88e61ba97a347056a32 Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Tue, 6 Sep 2022 09:13:48 +0300 Subject: [PATCH 5/5] add simple healthcheck endpoint --- src/pages/api/healthcheck.js | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/pages/api/healthcheck.js diff --git a/src/pages/api/healthcheck.js b/src/pages/api/healthcheck.js new file mode 100644 index 000000000..a5ffc66a3 --- /dev/null +++ b/src/pages/api/healthcheck.js @@ -0,0 +1,3 @@ +export default function handler(req, res) { + res.send("up"); +}