chahinebrini 77edd67cbe fix(magic): explicit imports + staging defaults + sheet height
- backend/api/magic/register: explicit import of MAGIC_DEVICE_LIMIT
  and createAdGuardClient (Nitro auto-import was missing them
  → ReferenceError → HTTP 500 on /api/magic/register)
- mac-app: default backendBaseUrl falls back to staging.rebreak.org
  (app.rebreak.org serves wrong TLS cert)
- native MagicSheet: fallback download/dmg URLs point to staging
- native settings: Magic sheet capped at detents=[0.85] so AppHeader
  stays visible
- bundles all in-flight Magic feature work (pair create/redeem,
  device endpoints, schema, adguard utils, mac-app, locales)
2026-06-03 08:25:02 +02:00

119 lines
3.3 KiB
TypeScript

/**
* AdGuard Home API Client für RebreakMagic DNS-over-HTTPS Client-Provisioning.
* Docs: https://github.com/AdguardTeam/AdGuardHome/tree/master/openapi
*/
export interface AdGuardClientOptions {
use_global_settings?: boolean;
filtering_enabled?: boolean;
parental_enabled?: boolean;
safebrowsing_enabled?: boolean;
safesearch_enabled?: boolean;
blocked_services?: string[];
upstreams?: string[];
tags?: string[];
}
interface AdGuardClientPayload {
name: string;
ids: string[];
use_global_settings?: boolean;
filtering_enabled?: boolean;
parental_enabled?: boolean;
safebrowsing_enabled?: boolean;
safesearch_enabled?: boolean;
blocked_services?: string[];
upstreams?: string[];
tags?: string[];
}
/**
* Erstellt einen AdGuard Persistent Client mit gegebener Client-ID (DNS-Token).
* AdGuard nutzt die Client-ID im DoH-URL-Path: /dns-query/{clientId}
*
* @param name - Interner Client-Name (z.B. "magic_<deviceId>")
* @param clientId - DNS-Token (wird in DoH URL embedded)
* @param options - Filtering/Blocking-Optionen
*/
export async function createAdGuardClient(
name: string,
clientId: string,
options: AdGuardClientOptions = {},
): Promise<void> {
const config = useRuntimeConfig();
const baseUrl = config.adguardBaseUrl || "https://dns.rebreak.org";
const user = config.adguardUser;
const password = config.adguardPassword;
if (!user || !password) {
throw createError({
statusCode: 500,
message: "ADGUARD_USER and ADGUARD_PASSWORD required for Magic features",
});
}
const payload: AdGuardClientPayload = {
name,
ids: [clientId],
...options,
};
const authHeader = `Basic ${Buffer.from(`${user}:${password}`).toString("base64")}`;
try {
const response = await $fetch(`${baseUrl}/control/clients/add`, {
method: "POST",
headers: {
Authorization: authHeader,
"Content-Type": "application/json",
},
body: payload,
});
return response as void;
} catch (err: any) {
console.error("[AdGuard] Client creation failed:", err);
throw createError({
statusCode: 502,
message: `AdGuard API error: ${err.message || "unknown"}`,
});
}
}
/**
* Löscht einen AdGuard Persistent Client.
* @param name - Interner Client-Name (z.B. "magic_<deviceId>")
*/
export async function deleteAdGuardClient(name: string): Promise<void> {
const config = useRuntimeConfig();
const baseUrl = config.adguardBaseUrl || "https://dns.rebreak.org";
const user = config.adguardUser;
const password = config.adguardPassword;
if (!user || !password) {
throw createError({
statusCode: 500,
message: "ADGUARD_USER and ADGUARD_PASSWORD required for Magic features",
});
}
const authHeader = `Basic ${Buffer.from(`${user}:${password}`).toString("base64")}`;
try {
const response = await $fetch(`${baseUrl}/control/clients/delete`, {
method: "POST",
headers: {
Authorization: authHeader,
"Content-Type": "application/json",
},
body: { name },
});
return response as void;
} catch (err: any) {
console.error("[AdGuard] Client deletion failed:", err);
throw createError({
statusCode: 502,
message: `AdGuard API error: ${err.message || "unknown"}`,
});
}
}