v1.8.0 #429

Merged
LukeGus merged 198 commits from dev-1.8.0 into main 2025-11-05 16:36:16 +00:00
5 changed files with 144 additions and 38 deletions
Showing only changes of commit 00e19f054f - Show all commits

View File

@@ -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");

View File

@@ -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() && (

View File

@@ -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) {
iframe.contentWindow.postMessage(
{ type: "INJECT_SCRIPT", script: injectedScript },
"*",
);
iframe.contentWindow.eval(injectedScript);
try {
iframe.contentWindow.eval(injectedScript);
} catch (evalError) {
iframe.contentWindow.postMessage(
{ type: "INJECT_SCRIPT", script: 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 = () => {

View File

@@ -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");

View File

@@ -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() && (