195 lines
5.6 KiB
TypeScript

import { ref, computed } from "vue";
import { useTauri, type IphoneDeviceState, type DesktopProtectionState, type MagicDeviceInfo } from "~/composables/useTauri";
import { useIphoneDevice, useMagicDevices, useMagicSession } from "~/composables/useMagicState";
export interface ProtectionStatus {
overall: "protected" | "partial" | "unprotected" | "unknown";
label: string;
message: string;
iosConnected: boolean;
iosProtected: boolean;
desktopProtected: boolean;
anyBackendDevice: boolean;
}
function normalizeHostname(value: string): string {
return (value.toLowerCase().split(".")[0] ?? "").replace(/[^a-z0-9]/g, "");
}
export function useProtectionStatus() {
const {
detectIphoneState,
getDesktopProtectionStatus,
getMagicDevices,
getMagicStatus,
getHostname,
} = useTauri();
const iphone = useIphoneDevice();
const devices = useMagicDevices();
const session = useMagicSession();
const desktopProtection = ref<DesktopProtectionState | null>(null);
const localHostname = ref<string | null>(null);
const loading = ref(false);
const lastError = ref<string | null>(null);
const lastUpdated = ref<Date | null>(null);
const iosConnected = computed(() => !!iphone.value);
const iosProtected = computed(() => {
if (!iphone.value) return false;
const hasEnrollment = iphone.value.installedProfileIDs?.includes("org.rebreak.mdm.enrollment");
const hasLock = iphone.value.installedProfileIDs?.includes("org.rebreak.protection.contentfilter.sideload");
return iphone.value.isSupervised && hasEnrollment && hasLock;
});
const currentBackendDevice = computed<MagicDeviceInfo | null>(() => {
if (!session.value) return null;
const hardwareId = session.value.hardwareId;
const deviceId = session.value.deviceId;
return (
devices.value.find((d) => {
if (hardwareId && d.hardwareId) return d.hardwareId === hardwareId;
return d.deviceId === deviceId;
}) ?? null
);
});
const desktopProtected = computed(() => !!desktopProtection.value?.active || !!currentBackendDevice.value);
const anyBackendDevice = computed(() => devices.value.length > 0);
const status = computed<ProtectionStatus>(() => {
const ios = iosConnected.value;
const iosOk = iosProtected.value;
const desktopOk = desktopProtected.value;
const backendOk = anyBackendDevice.value;
if (!ios && !desktopOk && !backendOk) {
return {
overall: "unprotected",
label: "Kein Schutz aktiv",
message: "Verbinde ein iPhone oder aktiviere den Desktop-Schutz.",
iosConnected: false,
iosProtected: false,
desktopProtected: false,
anyBackendDevice: false,
};
}
if (ios && !iosOk) {
return {
overall: "partial",
label: "iOS-Schutz unvollständig",
message: "Supervision oder Schutz-Profile fehlen. Führe das Setup fort.",
iosConnected: true,
iosProtected: false,
desktopProtected: desktopOk,
anyBackendDevice: backendOk,
};
}
if (iosOk && desktopOk) {
return {
overall: "protected",
label: "Vollständig geschützt",
message: "iPhone und Desktop sind aktiv geschützt.",
iosConnected: true,
iosProtected: true,
desktopProtected: true,
anyBackendDevice: backendOk,
};
}
if (iosOk || desktopOk || backendOk) {
return {
overall: "partial",
label: "Teilweise geschützt",
message: iosOk
? "iPhone geschützt. Desktop-Schutz ist optional."
: desktopOk
? "Desktop geschützt. iPhone noch nicht verbunden."
: "Ein registriertes Gerät vorhanden, aber keine lokale Schutzkontrolle.",
iosConnected: ios,
iosProtected: iosOk,
desktopProtected: desktopOk,
anyBackendDevice: backendOk,
};
}
return {
overall: "unknown",
label: "Status unbekannt",
message: "Schutzstatus konnte nicht ermittelt werden.",
iosConnected: false,
iosProtected: false,
desktopProtected: false,
anyBackendDevice: false,
};
});
async function refreshIphone() {
try {
const state = await detectIphoneState();
iphone.value = state;
} catch (e: any) {
// Bei Fehler nicht crashen — Gerät ist einfach nicht verbunden
iphone.value = null;
}
}
async function refreshDesktop() {
try {
desktopProtection.value = await getDesktopProtectionStatus();
} catch (e: any) {
lastError.value = e?.message ?? "Desktop-Schutzstatus konnte nicht geladen werden";
}
}
async function refreshBackendDevices() {
try {
devices.value = await getMagicDevices();
if (session.value?.dnsToken) {
await getMagicStatus(session.value.dnsToken);
}
} catch (e: any) {
lastError.value = e?.message ?? "Geräte konnten nicht geladen werden";
}
}
async function refresh() {
loading.value = true;
lastError.value = null;
await Promise.all([
refreshIphone(),
refreshDesktop(),
refreshBackendDevices(),
refreshHostname(),
]);
lastUpdated.value = new Date();
loading.value = false;
}
async function refreshHostname() {
try {
localHostname.value = await getHostname();
} catch (e: any) {
localHostname.value = null;
}
}
return {
status,
iphone: computed(() => iphone.value),
desktopProtection,
localHostname,
loading,
lastError,
lastUpdated,
iosConnected,
iosProtected,
desktopProtected,
anyBackendDevice,
refresh,
refreshIphone,
refreshBackendDevices,
};
}