v1.8.0 #429
@@ -72,12 +72,21 @@ function createWindow() {
|
||||
mainWindow.setMenuBarVisibility(false);
|
||||
}
|
||||
|
||||
mainWindow.webContents.setUserAgent(
|
||||
`Termix-Desktop/${appVersion} (${platform}; Electron/${electronVersion})`,
|
||||
const customUserAgent = `Termix-Desktop/${appVersion} (${platform}; Electron/${electronVersion})`;
|
||||
mainWindow.webContents.setUserAgent(customUserAgent);
|
||||
|
||||
mainWindow.webContents.session.webRequest.onBeforeSendHeaders(
|
||||
(details, callback) => {
|
||||
details.requestHeaders["X-Electron-App"] = "true";
|
||||
|
||||
details.requestHeaders["User-Agent"] = customUserAgent;
|
||||
|
||||
callback({ requestHeaders: details.requestHeaders });
|
||||
},
|
||||
);
|
||||
|
||||
if (isDev) {
|
||||
mainWindow.loadURL("http:://localhost:5173");
|
||||
mainWindow.loadURL("http://localhost:5173");
|
||||
mainWindow.webContents.openDevTools();
|
||||
} else {
|
||||
const indexPath = path.join(__dirname, "..", "dist", "index.html");
|
||||
|
||||
@@ -241,6 +241,22 @@ export function Auth({
|
||||
throw new Error(t("errors.loginFailed"));
|
||||
}
|
||||
|
||||
if (isInElectronWebView() && res.token) {
|
||||
try {
|
||||
localStorage.setItem("jwt", res.token);
|
||||
window.parent.postMessage(
|
||||
{
|
||||
type: "AUTH_SUCCESS",
|
||||
token: res.token,
|
||||
source: "auth_component",
|
||||
platform: "desktop",
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
"*",
|
||||
);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
const [meRes] = await Promise.all([getUserInfo()]);
|
||||
|
||||
setInternalLoggedIn(true);
|
||||
@@ -398,6 +414,22 @@ export function Auth({
|
||||
localStorage.setItem("jwt", res.token);
|
||||
}
|
||||
|
||||
if (isInElectronWebView() && res.token) {
|
||||
try {
|
||||
localStorage.setItem("jwt", res.token);
|
||||
window.parent.postMessage(
|
||||
{
|
||||
type: "AUTH_SUCCESS",
|
||||
token: res.token,
|
||||
source: "totp_auth_component",
|
||||
platform: "desktop",
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
"*",
|
||||
);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
setInternalLoggedIn(true);
|
||||
setLoggedIn(true);
|
||||
setIsAdmin(!!res.is_admin);
|
||||
@@ -485,6 +517,24 @@ export function Auth({
|
||||
|
||||
getUserInfo()
|
||||
.then((meRes) => {
|
||||
if (isInElectronWebView()) {
|
||||
const token = getCookie("jwt") || localStorage.getItem("jwt");
|
||||
if (token) {
|
||||
try {
|
||||
window.parent.postMessage(
|
||||
{
|
||||
type: "AUTH_SUCCESS",
|
||||
token: token,
|
||||
source: "oidc_callback",
|
||||
platform: "desktop",
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
"*",
|
||||
);
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
setInternalLoggedIn(true);
|
||||
setLoggedIn(true);
|
||||
setIsAdmin(!!meRes.is_admin);
|
||||
@@ -577,7 +627,8 @@ export function Auth({
|
||||
if (showServerConfig === null) {
|
||||
return (
|
||||
<div
|
||||
className={`w-[420px] max-w-full p-6 flex flex-col bg-dark-bg border-2 border-dark-border rounded-md ${className || ""}`}
|
||||
className={`w-[420px] max-w-full p-6 flex flex-col bg-dark-bg border-2 border-dark-border rounded-md overflow-y-auto my-2 ${className || ""}`}
|
||||
style={{ maxHeight: "calc(100vh - 1rem)" }}
|
||||
{...props}
|
||||
>
|
||||
<div className="flex items-center justify-center h-32">
|
||||
@@ -590,7 +641,8 @@ export function Auth({
|
||||
if (showServerConfig) {
|
||||
return (
|
||||
<div
|
||||
className={`w-[420px] max-w-full p-6 flex flex-col bg-dark-bg border-2 border-dark-border rounded-md ${className || ""}`}
|
||||
className={`w-[420px] max-w-full p-6 flex flex-col bg-dark-bg border-2 border-dark-border rounded-md overflow-y-auto my-2 ${className || ""}`}
|
||||
style={{ maxHeight: "calc(100vh - 1rem)" }}
|
||||
{...props}
|
||||
>
|
||||
<ServerConfigComponent
|
||||
@@ -645,7 +697,8 @@ export function Auth({
|
||||
if (dbHealthChecking && !dbConnectionFailed) {
|
||||
return (
|
||||
<div
|
||||
className={`w-[420px] max-w-full p-6 flex flex-col bg-dark-bg border-2 border-dark-border rounded-md ${className || ""}`}
|
||||
className={`w-[420px] max-w-full p-6 flex flex-col bg-dark-bg border-2 border-dark-border rounded-md overflow-y-auto my-2 ${className || ""}`}
|
||||
style={{ maxHeight: "calc(100vh - 1rem)" }}
|
||||
{...props}
|
||||
>
|
||||
<div className="flex items-center justify-center h-32">
|
||||
@@ -663,7 +716,8 @@ export function Auth({
|
||||
if (dbConnectionFailed) {
|
||||
return (
|
||||
<div
|
||||
className={`w-[420px] max-w-full p-6 flex flex-col bg-dark-bg border-2 border-dark-border rounded-md ${className || ""}`}
|
||||
className={`w-[420px] max-w-full p-6 flex flex-col bg-dark-bg border-2 border-dark-border rounded-md overflow-y-auto my-2 ${className || ""}`}
|
||||
style={{ maxHeight: "calc(100vh - 1rem)" }}
|
||||
{...props}
|
||||
>
|
||||
<div className="mb-6 text-center">
|
||||
@@ -722,7 +776,8 @@ export function Auth({
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-[420px] max-w-full p-6 flex flex-col bg-dark-bg border-2 border-dark-border rounded-md ${className || ""}`}
|
||||
className={`w-[420px] max-w-full p-6 flex flex-col bg-dark-bg border-2 border-dark-border rounded-md overflow-y-auto my-2 ${className || ""}`}
|
||||
style={{ maxHeight: "calc(100vh - 1rem)" }}
|
||||
{...props}
|
||||
>
|
||||
{isInElectronWebView() && (
|
||||
|
||||
@@ -57,16 +57,13 @@ export function ElectronLoginForm({
|
||||
|
||||
onAuthSuccess();
|
||||
} catch (err) {
|
||||
console.error("[ElectronLoginForm] Error saving JWT:", err);
|
||||
setError(t("errors.authTokenSaveFailed"));
|
||||
setIsAuthenticating(false);
|
||||
hasAuthenticatedRef.current = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("[ElectronLoginForm] Error processing message:", err);
|
||||
}
|
||||
} catch (err) {}
|
||||
};
|
||||
|
||||
window.addEventListener("message", handleMessage);
|
||||
@@ -99,7 +96,9 @@ export function ElectronLoginForm({
|
||||
let hasNotified = false;
|
||||
|
||||
function postJWTToParent(token, source) {
|
||||
if (hasNotified) return;
|
||||
if (hasNotified) {
|
||||
return;
|
||||
}
|
||||
hasNotified = true;
|
||||
|
||||
try {
|
||||
@@ -111,7 +110,6 @@ export function ElectronLoginForm({
|
||||
timestamp: Date.now()
|
||||
}, '*');
|
||||
} catch (e) {
|
||||
console.error('[Electron WebView] Error posting message:', e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +141,6 @@ export function ElectronLoginForm({
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Electron WebView] Error in checkAuth:', error);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -178,27 +175,23 @@ export function ElectronLoginForm({
|
||||
clearInterval(intervalId);
|
||||
}, 300000);
|
||||
|
||||
checkAuth();
|
||||
setTimeout(() => checkAuth(), 500);
|
||||
})();
|
||||
`;
|
||||
|
||||
try {
|
||||
if (iframe.contentWindow) {
|
||||
try {
|
||||
iframe.contentWindow.eval(injectedScript);
|
||||
} catch (evalError) {
|
||||
iframe.contentWindow.postMessage(
|
||||
{ type: "INJECT_SCRIPT", script: injectedScript },
|
||||
"*",
|
||||
);
|
||||
|
||||
iframe.contentWindow.eval(injectedScript);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(
|
||||
"[ElectronLoginForm] Cannot inject script due to cross-origin restrictions",
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("[ElectronLoginForm] Error in handleLoad:", err);
|
||||
}
|
||||
} catch (err) {}
|
||||
} catch (err) {}
|
||||
};
|
||||
|
||||
const handleError = () => {
|
||||
|
||||
@@ -1695,10 +1695,34 @@ export async function loginUser(
|
||||
try {
|
||||
const response = await authApi.post("/users/login", { username, password });
|
||||
|
||||
if (isElectron() && response.data.token) {
|
||||
const hasToken = response.data.token;
|
||||
|
||||
if (isElectron() && hasToken) {
|
||||
localStorage.setItem("jwt", response.data.token);
|
||||
}
|
||||
|
||||
const isInIframe =
|
||||
typeof window !== "undefined" && window.self !== window.top;
|
||||
|
||||
if (isInIframe && hasToken) {
|
||||
localStorage.setItem("jwt", response.data.token);
|
||||
|
||||
try {
|
||||
window.parent.postMessage(
|
||||
{
|
||||
type: "AUTH_SUCCESS",
|
||||
token: response.data.token,
|
||||
source: "login_api",
|
||||
platform: "desktop",
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
"*",
|
||||
);
|
||||
} catch (e) {
|
||||
console.error("[main-axios] Error posting message to parent:", e);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
token: response.data.token || "cookie-based",
|
||||
success: response.data.success,
|
||||
@@ -2027,6 +2051,35 @@ export async function verifyTOTPLogin(
|
||||
temp_token,
|
||||
totp_code,
|
||||
});
|
||||
|
||||
const hasToken = response.data.token;
|
||||
|
||||
if (isElectron() && hasToken) {
|
||||
localStorage.setItem("jwt", response.data.token);
|
||||
}
|
||||
|
||||
const isInIframe =
|
||||
typeof window !== "undefined" && window.self !== window.top;
|
||||
|
||||
if (isInIframe && hasToken) {
|
||||
localStorage.setItem("jwt", response.data.token);
|
||||
|
||||
try {
|
||||
window.parent.postMessage(
|
||||
{
|
||||
type: "AUTH_SUCCESS",
|
||||
token: response.data.token,
|
||||
source: "totp_verify",
|
||||
platform: "desktop",
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
"*",
|
||||
);
|
||||
} catch (e) {
|
||||
console.error("[main-axios] Error posting message to parent:", e);
|
||||
}
|
||||
}
|
||||
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
handleApiError(error as AxiosError, "verify TOTP login");
|
||||
|
||||
@@ -40,7 +40,6 @@ function postJWTToWebView() {
|
||||
const jwt = getCookie("jwt") || localStorage.getItem("jwt");
|
||||
|
||||
if (!jwt) {
|
||||
console.warn("JWT not found when trying to post to WebView");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -53,11 +52,7 @@ function postJWTToWebView() {
|
||||
timestamp: Date.now(),
|
||||
}),
|
||||
);
|
||||
|
||||
console.log("JWT posted to React Native WebView");
|
||||
} catch (error) {
|
||||
console.error("Failed to post JWT to WebView:", error);
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
interface AuthProps extends React.ComponentProps<"div"> {
|
||||
@@ -563,7 +558,8 @@ export function Auth({
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-full max-w-md flex flex-col bg-dark-bg ${className || ""}`}
|
||||
className={`w-full max-w-md flex flex-col bg-dark-bg overflow-y-auto my-2 ${className || ""}`}
|
||||
style={{ maxHeight: "calc(100vh - 1rem)" }}
|
||||
{...props}
|
||||
>
|
||||
{isReactNativeWebView() && (
|
||||
|
||||
Reference in New Issue
Block a user