(wip): migrate ttp to mtp
(feat): migrate tauth to mtp (qol): update todo (qol): add direnv
This commit is contained in:
parent
8e831fd993
commit
ee5955fc75
8 changed files with 97 additions and 38 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
use flake
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
||||||
node_modules
|
node_modules
|
||||||
releases
|
releases
|
||||||
.fallow/
|
.fallow
|
||||||
|
.direnv
|
||||||
|
|
|
||||||
4
bun.lock
4
bun.lock
|
|
@ -347,7 +347,7 @@
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"@tensamin/ui": "https://git.methanium.net/tensamin/ui/releases/download/latest/tensamin-ui.tgz",
|
"@tensamin/ui": "https://git.methanium.net/tensamin/ui/releases/download/latest/tensamin-ui.tgz",
|
||||||
"mtp": "https://git.methanium.net/methanium/mtp/releases/download/0.1.0-dev-8ae8377/mtp-0.1.0.tgz",
|
"mtp": "https://git.methanium.net/methanium/mtp/releases/download/0.1.0-dev-c3fbeb2/mtp-0.1.0.tgz",
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@babel/code-frame": ["@babel/code-frame@7.29.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw=="],
|
"@babel/code-frame": ["@babel/code-frame@7.29.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw=="],
|
||||||
|
|
@ -1540,7 +1540,7 @@
|
||||||
|
|
||||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||||
|
|
||||||
"mtp": ["mtp@https://git.methanium.net/methanium/mtp/releases/download/0.1.0-dev-8ae8377/mtp-0.1.0.tgz", {}, "sha512-W0l7Jc+1XI8BdrmRP9rlY/di6kZ5a/srv4mQvzwyJd+Tfg7BWZ9IUYUXIPze6ayx9dLY1f9Y71OgbhjstMzYjA=="],
|
"mtp": ["mtp@https://git.methanium.net/methanium/mtp/releases/download/0.1.0-dev-c3fbeb2/mtp-0.1.0.tgz", {}, "sha512-j/RGQY9/3NXzZptXbY44Kv7YnGr38CQQOehRAzPPFvnEVj+kxCwzVLgSImT765+vfgl2L+bkAE9aI2PWwOBTow=="],
|
||||||
|
|
||||||
"nanoid": ["nanoid@3.3.15", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA=="],
|
"nanoid": ["nanoid@3.3.15", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA=="],
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
commonDeps = [pkgs.wasm-pack pkgs.lld];
|
commonDeps = [rustToolchain pkgs.wasm-pack pkgs.lld];
|
||||||
in rec {
|
in rec {
|
||||||
default = electron;
|
default = electron;
|
||||||
|
|
||||||
|
|
@ -256,7 +256,6 @@
|
||||||
buildInputs = with pkgs;
|
buildInputs = with pkgs;
|
||||||
[
|
[
|
||||||
jdk17
|
jdk17
|
||||||
rustToolchain
|
|
||||||
gradle
|
gradle
|
||||||
bun
|
bun
|
||||||
nodejs
|
nodejs
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"@tensamin/ui": "https://git.methanium.net/tensamin/ui/releases/download/latest/tensamin-ui.tgz",
|
"@tensamin/ui": "https://git.methanium.net/tensamin/ui/releases/download/latest/tensamin-ui.tgz",
|
||||||
"mtp": "https://git.methanium.net/methanium/mtp/releases/download/0.1.0-dev-8ae8377/mtp-0.1.0.tgz"
|
"mtp": "https://git.methanium.net/methanium/mtp/releases/download/0.1.0-dev-c3fbeb2/mtp-0.1.0.tgz"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tensamin/ui": "*",
|
"@tensamin/ui": "*",
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import {
|
||||||
} from "react";
|
} from "react";
|
||||||
import { isTauri } from "@tauri-apps/api/core";
|
import { isTauri } from "@tauri-apps/api/core";
|
||||||
import { onResume } from "tauri-plugin-app-events-api";
|
import { onResume } from "tauri-plugin-app-events-api";
|
||||||
import { MTPClient } from "mtp";
|
import { ConnectionState, MTPClient } from "mtp";
|
||||||
import type { z } from "zod";
|
import type { z } from "zod";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|
@ -31,12 +31,6 @@ import {
|
||||||
RETRY_INTERVAL,
|
RETRY_INTERVAL,
|
||||||
} from "./values";
|
} from "./values";
|
||||||
|
|
||||||
const READY_STATE = {
|
|
||||||
CLOSED: 0,
|
|
||||||
CONNECTING: 1,
|
|
||||||
OPEN: 2,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
const PUSH_TYPES = [
|
const PUSH_TYPES = [
|
||||||
"message_live",
|
"message_live",
|
||||||
"message_state",
|
"message_state",
|
||||||
|
|
@ -153,6 +147,7 @@ function mapDataKeys(value: unknown, mapKey: (key: string) => string): unknown {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Zod schema validation
|
||||||
function validateResponse<T extends keyof Schemas & string>(
|
function validateResponse<T extends keyof Schemas & string>(
|
||||||
type: T,
|
type: T,
|
||||||
message: { id?: number; type: string; data: unknown },
|
message: { id?: number; type: string; data: unknown },
|
||||||
|
|
@ -189,8 +184,9 @@ export function Provider(props: {
|
||||||
}) {
|
}) {
|
||||||
const { load } = useStorage();
|
const { load } = useStorage();
|
||||||
|
|
||||||
const [readyState, setReadyState] = useState<number>(READY_STATE.CLOSED);
|
const [readyState, setReadyState] = useState<number>(
|
||||||
const [connected, setConnected] = useState<boolean>(false);
|
ConnectionState.Disconnected,
|
||||||
|
);
|
||||||
const [identified, setIdentified] = useState<boolean>(false);
|
const [identified, setIdentified] = useState<boolean>(false);
|
||||||
const [identifying, setIdentifying] = useState<boolean>(false);
|
const [identifying, setIdentifying] = useState<boolean>(false);
|
||||||
|
|
||||||
|
|
@ -208,11 +204,15 @@ export function Provider(props: {
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const connected = readyState === ConnectionState.Connected;
|
||||||
|
|
||||||
|
// MTP url
|
||||||
const [mtpUrl, setMtpUrl] = useState<string | null>(null);
|
const [mtpUrl, setMtpUrl] = useState<string | null>(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
load("mtp_url").then(setMtpUrl);
|
load("mtp_url").then(setMtpUrl);
|
||||||
}, [load]);
|
}, [load]);
|
||||||
|
|
||||||
|
// Validation override functions
|
||||||
const send: BoundSendFn = useMemo(
|
const send: BoundSendFn = useMemo(
|
||||||
() => async (type, data, options) => {
|
() => async (type, data, options) => {
|
||||||
const client = clientRef.current;
|
const client = clientRef.current;
|
||||||
|
|
@ -259,6 +259,7 @@ export function Provider(props: {
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// No Iota check
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!connected) return;
|
if (!connected) return;
|
||||||
|
|
||||||
|
|
@ -272,6 +273,7 @@ export function Provider(props: {
|
||||||
});
|
});
|
||||||
}, [connected, subscribe]);
|
}, [connected, subscribe]);
|
||||||
|
|
||||||
|
// Custom Pings
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!connected || !identified) {
|
if (!connected || !identified) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -297,11 +299,9 @@ export function Provider(props: {
|
||||||
};
|
};
|
||||||
}, [connected, identified, send]);
|
}, [connected, identified, send]);
|
||||||
|
|
||||||
|
// Reconnect stuff
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!mtpUrl) {
|
if (!mtpUrl) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
const url = mtpUrl;
|
|
||||||
|
|
||||||
let attempts = 0;
|
let attempts = 0;
|
||||||
let reconnectTimer: ReturnType<typeof setTimeout> | null = null;
|
let reconnectTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
|
@ -358,17 +358,28 @@ export function Provider(props: {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setReadyState(READY_STATE.CONNECTING);
|
|
||||||
setConnected(false);
|
|
||||||
setIdentified(false);
|
setIdentified(false);
|
||||||
setIdentifying(false);
|
setIdentifying(false);
|
||||||
|
|
||||||
await MTPClient.init();
|
await MTPClient.init();
|
||||||
const client = await MTPClient.create({
|
const client = await MTPClient.create({
|
||||||
url,
|
url: mtpUrl ?? "",
|
||||||
|
descriptor: "client",
|
||||||
pings: true,
|
pings: true,
|
||||||
logger: (event) => {
|
logger: (event) => {
|
||||||
log(2, "mtp", event.type === "state" ? "cyan" : "blue", event.type === "state" ? event.data : event.type, event);
|
if (event.type === "state") {
|
||||||
|
setReadyState(
|
||||||
|
clientRef.current?.state ?? ConnectionState.Disconnected,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
log(
|
||||||
|
2,
|
||||||
|
"mtp",
|
||||||
|
event.type === "state" ? "cyan" : "blue",
|
||||||
|
event.type === "state" ? event.data : event.type,
|
||||||
|
event,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -378,6 +389,7 @@ export function Provider(props: {
|
||||||
}
|
}
|
||||||
|
|
||||||
clientRef.current = client;
|
clientRef.current = client;
|
||||||
|
setReadyState(client.state);
|
||||||
await client.connect();
|
await client.connect();
|
||||||
|
|
||||||
if (disposed) {
|
if (disposed) {
|
||||||
|
|
@ -401,8 +413,7 @@ export function Provider(props: {
|
||||||
|
|
||||||
clearReconnectTimer();
|
clearReconnectTimer();
|
||||||
scheduleReconnectReset();
|
scheduleReconnectReset();
|
||||||
setReadyState(READY_STATE.OPEN);
|
setReadyState(client.state);
|
||||||
setConnected(true);
|
|
||||||
setIdentifying(true);
|
setIdentifying(true);
|
||||||
setError("");
|
setError("");
|
||||||
setErrorDescription("");
|
setErrorDescription("");
|
||||||
|
|
@ -425,8 +436,7 @@ export function Provider(props: {
|
||||||
clientRef.current?.disconnect();
|
clientRef.current?.disconnect();
|
||||||
clientRef.current = null;
|
clientRef.current = null;
|
||||||
clearReconnectResetTimer();
|
clearReconnectResetTimer();
|
||||||
setReadyState(READY_STATE.CLOSED);
|
setReadyState(ConnectionState.Disconnected);
|
||||||
setConnected(false);
|
|
||||||
setIdentified(false);
|
setIdentified(false);
|
||||||
setIdentifying(false);
|
setIdentifying(false);
|
||||||
log(
|
log(
|
||||||
|
|
@ -475,16 +485,16 @@ export function Provider(props: {
|
||||||
|
|
||||||
clientRef.current?.disconnect();
|
clientRef.current?.disconnect();
|
||||||
clientRef.current = null;
|
clientRef.current = null;
|
||||||
setReadyState(READY_STATE.CLOSED);
|
setReadyState(ConnectionState.Disconnected);
|
||||||
setConnected(false);
|
|
||||||
setIdentified(false);
|
setIdentified(false);
|
||||||
setIdentifying(false);
|
setIdentifying(false);
|
||||||
};
|
};
|
||||||
}, [mtpUrl, props.blockConnection]);
|
}, [mtpUrl, props.blockConnection]);
|
||||||
|
|
||||||
|
// Loading bar
|
||||||
const progress = useMemo(() => {
|
const progress = useMemo(() => {
|
||||||
if (!mtpUrl) return 10;
|
if (!mtpUrl) return 10;
|
||||||
if (readyState === READY_STATE.CONNECTING) return 30;
|
if (readyState === ConnectionState.Connecting) return 30;
|
||||||
if (!connected) return 45;
|
if (!connected) return 45;
|
||||||
if (identifying) return 75;
|
if (identifying) return 75;
|
||||||
if (!identified) return 90;
|
if (!identified) return 90;
|
||||||
|
|
@ -493,7 +503,7 @@ export function Provider(props: {
|
||||||
|
|
||||||
const loadingTitle = useMemo(() => {
|
const loadingTitle = useMemo(() => {
|
||||||
if (!mtpUrl) return "Looking up configuration";
|
if (!mtpUrl) return "Looking up configuration";
|
||||||
if (readyState === READY_STATE.CONNECTING || !connected)
|
if (readyState === ConnectionState.Connecting || !connected)
|
||||||
return "Connecting to Tensamin";
|
return "Connecting to Tensamin";
|
||||||
if (identifying || !identified) return "Identifying secure session";
|
if (identifying || !identified) return "Identifying secure session";
|
||||||
return "Loading";
|
return "Loading";
|
||||||
|
|
@ -501,13 +511,14 @@ export function Provider(props: {
|
||||||
|
|
||||||
const loadingDescription = useMemo(() => {
|
const loadingDescription = useMemo(() => {
|
||||||
if (!mtpUrl) return "Loading connection details";
|
if (!mtpUrl) return "Loading connection details";
|
||||||
if (readyState === READY_STATE.CONNECTING || !connected) {
|
if (readyState === ConnectionState.Connecting || !connected) {
|
||||||
return "Establishing transport channel";
|
return "Establishing transport channel";
|
||||||
}
|
}
|
||||||
if (identifying || !identified) return "Waiting for authenticated session";
|
if (identifying || !identified) return "Waiting for authenticated session";
|
||||||
return undefined;
|
return undefined;
|
||||||
}, [connected, identified, identifying, readyState, mtpUrl]);
|
}, [connected, identified, identifying, readyState, mtpUrl]);
|
||||||
|
|
||||||
|
// Return
|
||||||
if (error !== "" && errorDescription !== "") {
|
if (error !== "" && errorDescription !== "") {
|
||||||
return <ErrorScreen error={error} description={errorDescription} />;
|
return <ErrorScreen error={error} description={errorDescription} />;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import {
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from "@tensamin/ui";
|
} from "@tensamin/ui";
|
||||||
import { useLocation } from "@tanstack/react-router";
|
import { useLocation, useNavigate } from "@tanstack/react-router";
|
||||||
import { useDeeplinks } from "@tensamin/tauri/deeplinkHandler";
|
import { useDeeplinks } from "@tensamin/tauri/deeplinkHandler";
|
||||||
import { useMTP } from "@tensamin/mtp";
|
import { useMTP } from "@tensamin/mtp";
|
||||||
import { log, toast } from "@tensamin/shared/log";
|
import { log, toast } from "@tensamin/shared/log";
|
||||||
|
|
@ -25,28 +25,40 @@ export default function Wrapper({ children }: { children: ReactNode }) {
|
||||||
const { send } = useMTP();
|
const { send } = useMTP();
|
||||||
const { getSharedSecret } = useCrypto();
|
const { getSharedSecret } = useCrypto();
|
||||||
const { searchStr } = useLocation();
|
const { searchStr } = useLocation();
|
||||||
|
const navigate = useNavigate();
|
||||||
const [dialogOpen, setDialogOpen] = useState(false);
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const [identifier, setIdentifier] = useState<string | null>(null);
|
const [identifier, setIdentifier] = useState<string | null>(null);
|
||||||
const [redirect, setRedirect] = useState<string | null>(null);
|
const [redirect, setRedirect] = useState<string | null>(null);
|
||||||
const [challenge, setChallenge] = useState<string | null>(null);
|
const [challenge, setChallenge] = useState<string | null>(null);
|
||||||
|
const [appPublicKey, setAppPublicKey] = useState<string | null>(null);
|
||||||
const [allowChildern, setAllowChildern] = useState(false);
|
const [allowChildern, setAllowChildern] = useState(false);
|
||||||
|
|
||||||
const { deeplinks } = useDeeplinks();
|
const { deeplinks } = useDeeplinks();
|
||||||
|
|
||||||
const authorizeApp = async () => {
|
const authorizeApp = async () => {
|
||||||
if (!identifier || !redirect || !challenge) return;
|
if (!identifier || !redirect || !challenge || !appPublicKey) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Get Data
|
// Get Data
|
||||||
const user = await get(await load("user_id"));
|
const user = await get(await load("user_id"));
|
||||||
const {
|
const {
|
||||||
data: { content: appPublicKey },
|
data: { content: appPublicKeyHash },
|
||||||
} = await send("load_txt_record", {
|
} = await send("load_txt_record", {
|
||||||
path: "tauth." + identifier,
|
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
|
// Get Shared Secret
|
||||||
const sharedSecret = await getSharedSecret(
|
const sharedSecret = await getSharedSecret(
|
||||||
await load("private_key"),
|
await load("private_key"),
|
||||||
|
|
@ -75,7 +87,7 @@ export default function Wrapper({ children }: { children: ReactNode }) {
|
||||||
finalUrl.searchParams.set("challenge", solvedChallenge);
|
finalUrl.searchParams.set("challenge", solvedChallenge);
|
||||||
finalUrl.searchParams.set("originalChallenge", challenge);
|
finalUrl.searchParams.set("originalChallenge", challenge);
|
||||||
|
|
||||||
const session = Date.now();
|
const session = new Date().getTime();
|
||||||
finalUrl.searchParams.set("sessionId", String(session));
|
finalUrl.searchParams.set("sessionId", String(session));
|
||||||
|
|
||||||
// Save Session
|
// Save Session
|
||||||
|
|
@ -92,11 +104,14 @@ export default function Wrapper({ children }: { children: ReactNode }) {
|
||||||
setIdentifier(null);
|
setIdentifier(null);
|
||||||
setRedirect(null);
|
setRedirect(null);
|
||||||
setChallenge(null);
|
setChallenge(null);
|
||||||
|
setAppPublicKey(null);
|
||||||
|
|
||||||
toast("success", "App authorized successfully");
|
toast("success", "App authorized successfully");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
window.location.href = finalUrl.toString();
|
navigate({
|
||||||
|
to: finalUrl.toString(),
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -108,9 +123,27 @@ export default function Wrapper({ children }: { children: ReactNode }) {
|
||||||
setIdentifier(null);
|
setIdentifier(null);
|
||||||
setRedirect(null);
|
setRedirect(null);
|
||||||
setChallenge(null);
|
setChallenge(null);
|
||||||
|
setAppPublicKey(null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async function sha256Hex(value: string): Promise<string> {
|
||||||
|
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 {
|
function hexToBase64(hex: string): string {
|
||||||
const bytes = hex.match(/.{2}/g)?.map((byte) => parseInt(byte, 16)) ?? [];
|
const bytes = hex.match(/.{2}/g)?.map((byte) => parseInt(byte, 16)) ?? [];
|
||||||
const binaryString = String.fromCharCode(...bytes);
|
const binaryString = String.fromCharCode(...bytes);
|
||||||
|
|
@ -122,6 +155,7 @@ export default function Wrapper({ children }: { children: ReactNode }) {
|
||||||
const identifier = params.get("identifier");
|
const identifier = params.get("identifier");
|
||||||
const redirect = params.get("redirect");
|
const redirect = params.get("redirect");
|
||||||
const challenge = params.get("challenge");
|
const challenge = params.get("challenge");
|
||||||
|
const appPublicKey = params.get("public_key");
|
||||||
if (!identifier || !redirect) {
|
if (!identifier || !redirect) {
|
||||||
setAllowChildern(true);
|
setAllowChildern(true);
|
||||||
return;
|
return;
|
||||||
|
|
@ -135,10 +169,18 @@ export default function Wrapper({ children }: { children: ReactNode }) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!appPublicKey) {
|
||||||
|
toast("error", "Missing app public key");
|
||||||
|
log(1, "tauth", "red", "Missing app public key");
|
||||||
|
setAllowChildern(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setAllowChildern(true);
|
setAllowChildern(true);
|
||||||
setIdentifier(identifier);
|
setIdentifier(identifier);
|
||||||
setRedirect(redirect);
|
setRedirect(redirect);
|
||||||
setChallenge(hexToBase64(challenge || ""));
|
setChallenge(hexToBase64(challenge || ""));
|
||||||
|
setAppPublicKey(appPublicKey);
|
||||||
setDialogOpen(true);
|
setDialogOpen(true);
|
||||||
});
|
});
|
||||||
}, [searchStr, load]);
|
}, [searchStr, load]);
|
||||||
|
|
@ -149,11 +191,13 @@ export default function Wrapper({ children }: { children: ReactNode }) {
|
||||||
const url = new URL(link);
|
const url = new URL(link);
|
||||||
const identifier = url.searchParams.get("identifier");
|
const identifier = url.searchParams.get("identifier");
|
||||||
const redirect = url.searchParams.get("redirect");
|
const redirect = url.searchParams.get("redirect");
|
||||||
|
const appPublicKey = url.searchParams.get("public_key");
|
||||||
|
|
||||||
if (identifier && redirect) {
|
if (identifier && redirect && appPublicKey) {
|
||||||
setIdentifier(identifier);
|
setIdentifier(identifier);
|
||||||
setRedirect(redirect);
|
setRedirect(redirect);
|
||||||
setChallenge(hexToBase64(url.searchParams.get("challenge") || ""));
|
setChallenge(hexToBase64(url.searchParams.get("challenge") || ""));
|
||||||
|
setAppPublicKey(appPublicKey);
|
||||||
setDialogOpen(true);
|
setDialogOpen(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -170,6 +214,7 @@ export default function Wrapper({ children }: { children: ReactNode }) {
|
||||||
setIdentifier(null);
|
setIdentifier(null);
|
||||||
setRedirect(null);
|
setRedirect(null);
|
||||||
setChallenge(null);
|
setChallenge(null);
|
||||||
|
setAppPublicKey(null);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -205,6 +250,7 @@ export default function Wrapper({ children }: { children: ReactNode }) {
|
||||||
setIdentifier(null);
|
setIdentifier(null);
|
||||||
setRedirect(null);
|
setRedirect(null);
|
||||||
setChallenge(null);
|
setChallenge(null);
|
||||||
|
setAppPublicKey(null);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Deny
|
Deny
|
||||||
|
|
|
||||||
1
todo.md
1
todo.md
|
|
@ -1 +1,2 @@
|
||||||
- Move legal to extra onboarding package
|
- Move legal to extra onboarding package
|
||||||
|
- Add a bunch of tests
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue