+12








fcd7c979df
Co-authored-by: Artur <145776561+arturict@users.noreply.github.com> Co-authored-by: arturict <arturict@users.noreply.github.com> Co-authored-by: Thomas <thomas@ajnart.fr> Co-authored-by: Afonso Jorge Ramos <afonsojorgeramos@gmail.com> Co-authored-by: Danura30082 <danura30082+github@gmail.com> Co-authored-by: Kushie <122986913+kushiemoon-dev@users.noreply.github.com> Co-authored-by: ajnart <thomas@ajnart.fr> Co-authored-by: ajnart <thomas@ajnart.dev> Co-authored-by: chenjun <chenjun@foxmail.com> Co-authored-by: Wikibear <wikibear@users.noreply.github.com> Co-authored-by: Bergasha <bergasha@gmail.com> Co-authored-by: leafyelin <43306196+leafyelin@users.noreply.github.com> Co-authored-by: Lucas Araujo <lucas.lra@gmail.com> Co-authored-by: GreenMonito <86085570+GreenMonito@users.noreply.github.com> Co-authored-by: Nerdy-Technician <roffo@nerdy-technician.social> Co-authored-by: Jun <34545896+jcstrong@users.noreply.github.com> Co-authored-by: Edmond Abraham <54119952+gitedmond@users.noreply.github.com> Co-authored-by: thrawnx <tight.bulb9384@fastmail.com> Co-authored-by: Chris <58918656+nordada@users.noreply.github.com> Co-authored-by: yi111 <153097222+Yi-111-a@users.noreply.github.com> Co-authored-by: Yanis <naamaneyanis@gmail.com> Co-authored-by: Wikibear <me@sej.de> Co-authored-by: alessiottavo <93441886+alessiottavo@users.noreply.github.com>
75 lines
2.9 KiB
TypeScript
75 lines
2.9 KiB
TypeScript
import { Buffer } from "node:buffer";
|
|
|
|
import type {
|
|
IntegrationHttpAuthDefinition,
|
|
IntegrationHttpBodyAuth,
|
|
IntegrationSecretKind,
|
|
} from "@homarr/definitions";
|
|
|
|
import type { IntegrationInput } from "./base/integration";
|
|
|
|
/** Server-only credentials supplied by the integration's native adapter. */
|
|
export interface IntegrationHttpAuthentication {
|
|
headers: Record<string, string>;
|
|
query?: Record<string, string>;
|
|
body?: IntegrationHttpBodyAuth;
|
|
redactValues?: string[];
|
|
}
|
|
|
|
function secret(input: IntegrationInput, kind: IntegrationSecretKind) {
|
|
const value = input.decryptedSecrets.find((entry) => entry.kind === kind)?.value;
|
|
if (!value) throw new Error(`Integration credential ${kind} is missing`);
|
|
return value;
|
|
}
|
|
|
|
export function apiKeyAuth(input: IntegrationInput): IntegrationHttpAuthentication {
|
|
return { headers: { "X-API-Key": secret(input, "apiKey") } };
|
|
}
|
|
|
|
export function resolveDeclaredHttpAuthentication(
|
|
input: IntegrationInput,
|
|
definition: IntegrationHttpAuthDefinition,
|
|
): IntegrationHttpAuthentication {
|
|
if (definition.type === "modes") {
|
|
const savedKinds = new Set(input.decryptedSecrets.map(({ kind }) => kind));
|
|
const mode = definition.modes.find(
|
|
({ when }) => when.length === savedKinds.size && when.every((kind) => savedKinds.has(kind)),
|
|
);
|
|
if (!mode) throw new Error("Saved credentials do not support generic HTTP requests");
|
|
return resolveDeclaredHttpAuthentication(input, mode.auth);
|
|
}
|
|
switch (definition.type) {
|
|
case "none":
|
|
return { headers: {} };
|
|
case "bearer":
|
|
return { headers: { Authorization: `Bearer ${secret(input, definition.secretKind ?? "apiKey")}` } };
|
|
case "apiKeyHeader":
|
|
return {
|
|
headers: { [definition.name]: `${definition.prefix ?? ""}${secret(input, definition.secretKind ?? "apiKey")}` },
|
|
};
|
|
case "apiKeyQuery":
|
|
return { headers: {}, query: { [definition.name]: secret(input, definition.secretKind ?? "apiKey") } };
|
|
case "basic":
|
|
if (definition.username !== undefined) {
|
|
const credentials = Buffer.from(
|
|
`${definition.username}:${secret(input, definition.passwordKind ?? "password")}`,
|
|
).toString("base64");
|
|
return { headers: { Authorization: `Basic ${credentials}` }, redactValues: [credentials] };
|
|
}
|
|
return basicAuth(definition.usernameKind, definition.passwordKind)(input);
|
|
case "adapter":
|
|
throw new Error("This integration requires adapter-owned HTTP authentication");
|
|
}
|
|
}
|
|
|
|
export const basicAuth =
|
|
(
|
|
username: IntegrationSecretKind = "username",
|
|
password: IntegrationSecretKind = "password",
|
|
headers: Record<string, string> = {},
|
|
) =>
|
|
(input: IntegrationInput): IntegrationHttpAuthentication => {
|
|
const credentials = Buffer.from(`${secret(input, username)}:${secret(input, password)}`).toString("base64");
|
|
return { headers: { ...headers, Authorization: `Basic ${credentials}` }, redactValues: [credentials] };
|
|
};
|