import { type ReactNode } from "react"; /** import { useEffect, useState, type ReactNode } from "react"; import { useUser } from "@tensamin/identity/context"; import { useStorage } from "@tensamin/storage/context"; import { Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@methanium/ui"; import { useLocation, useNavigate } from "@tanstack/react-router"; import { useDeeplinks } from "@tensamin/tauri/deeplinkHandler"; import { useMTP } from "@tensamin/mtp"; import { log, toast } from "@tensamin/shared/log"; import { Loader2 } from "lucide-react"; import { isTauri } from "@tauri-apps/api/core"; */ export default function Wrapper({ children }: { children: ReactNode }) { /** const { get } = useUser(); const { load } = useStorage(); const { send } = useMTP(); const { searchStr } = useLocation(); const navigate = useNavigate(); const [dialogOpen, setDialogOpen] = useState(false); const [loading, setLoading] = useState(false); const [identifier, setIdentifier] = useState(null); const [redirect, setRedirect] = useState(null); const [challenge, setChallenge] = useState(null); const [appPublicKey, setAppPublicKey] = useState(null); const [sessionId, setSessionId] = useState(null); const [allowChildern, setAllowChildern] = useState(false); const { deeplinks } = useDeeplinks(); const authorizeApp = async () => { if (!identifier || !redirect || !challenge || !appPublicKey) return; try { // Get Data const user = await get(await load("user_id")); const { data: { Content: appPublicKeyHash }, } = await send("LoadTxtRecord", { Path: "tauth." + identifier, }); const verifiedAppPublicKeyHash = await sha256Hex(appPublicKey); if (normalizeHash(appPublicKeyHash) !== verifiedAppPublicKeyHash) { log(1, "tauth", "red", "App public key hash mismatch", undefined, { appPublicKey, appPublicKeyHash, verifiedAppPublicKeyHash, }); throw new Error("App public key hash mismatch"); } // Get Shared Secret const sharedSecret = await getSharedSecret( await load("mtp_keyring"), user.PublicKey, appPublicKey, ).catch((err) => { log(1, "tauth", "red", "Failed to get shared secret", err, { appPublicKey, }); throw new Error("Failed to get shared secret"); }); // Solve Challenge const solvedChallenge = await decryptText(sharedSecret, challenge).catch( (err) => { log(1, "tauth", "red", "Failed to solve challenge", err, { challenge, }); throw new Error("Failed to solve challenge"); }, ); // Craft Redirect URL const finalUrl = new URL(redirect); finalUrl.searchParams.set("userId", String(await load("user_id"))); finalUrl.searchParams.set("challenge", solvedChallenge); finalUrl.searchParams.set("originalChallenge", challenge); finalUrl.searchParams.set( "sessionId", String(sessionId || new Date().getTime()), ); // Save Session await send("CreateApp", { AppPublicKey: appPublicKey, AppIdentifier: identifier, }); // Open Redirect URL if (isTauri()) { window.open(finalUrl.toString(), "_blank"); setLoading(false); setDialogOpen(false); setIdentifier(null); setRedirect(null); setChallenge(null); setAppPublicKey(null); setSessionId(null); toast("success", "App authorized successfully"); return; } else { navigate({ href: finalUrl.toString(), }); return; } } catch (err) { toast("error", "Failed to authorize app"); log(1, "tauth", "red", "Failed to authorize app", err); setLoading(false); setDialogOpen(false); setIdentifier(null); setRedirect(null); setChallenge(null); setAppPublicKey(null); setSessionId(null); } }; async function sha256Hex(value: string): Promise { const hash = await crypto.subtle.digest( "SHA-256", new TextEncoder().encode(value), ); return [...new Uint8Array(hash)] .map((byte) => byte.toString(16).padStart(2, "0")) .join(""); } function normalizeHash(value: string): string { return value .trim() .toLowerCase() .replace(/^sha256[:=]/, ""); } function hexToBase64(hex: string): string { const bytes = hex.match(/.{2}/g)?.map((byte) => parseInt(byte, 16)) ?? []; const binaryString = String.fromCharCode(...bytes); return btoa(binaryString); } useEffect(() => { const params = new URLSearchParams(searchStr); const identifier = params.get("identifier"); const redirect = params.get("redirect"); const challenge = params.get("challenge"); const appPublicKey = params.get("public_key"); const urlSessionId = params.get("sessionId"); if (!identifier || !redirect) { setAllowChildern(true); return; } load("user_id").then((userId) => { if (!challenge) { const newUrl = new URL(redirect); newUrl.searchParams.set("userId", String(userId)); newUrl.searchParams.set( "sessionId", String(urlSessionId || new Date().getTime()), ); window.location.href = newUrl.toString(); return; } if (!appPublicKey) { toast("error", "Missing app public key"); log(1, "tauth", "red", "Missing app public key"); setAllowChildern(true); return; } setAllowChildern(true); setIdentifier(identifier); setRedirect(redirect); setChallenge(hexToBase64(challenge || "")); setAppPublicKey(appPublicKey); setSessionId(urlSessionId); setDialogOpen(true); }); }, [searchStr, load]); useEffect(() => { deeplinks.forEach((link) => { if (link.startsWith("tensamin://authorize_app")) { const url = new URL(link); const identifier = url.searchParams.get("identifier"); const redirect = url.searchParams.get("redirect"); const appPublicKey = url.searchParams.get("public_key"); const urlSessionId = url.searchParams.get("sessionId"); if (identifier && redirect && appPublicKey) { setIdentifier(identifier); setRedirect(redirect); setChallenge(hexToBase64(url.searchParams.get("challenge") || "")); setAppPublicKey(appPublicKey); setSessionId(urlSessionId); setDialogOpen(true); } } }); }, [deeplinks]); return ( <> { setDialogOpen(value); if (!value) { setIdentifier(null); setRedirect(null); setChallenge(null); setAppPublicKey(null); setSessionId(null); } }} > Allow this app to access your data? This app is requesting access to your data. Please review the permissions and only grant access if you trust this app. {allowChildern && children} ); */ return children; }