diff --git a/build-all.sh b/build-all.sh new file mode 100644 index 0000000..691e010 --- /dev/null +++ b/build-all.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# Windows +GOOS=windows GOARCH=amd64 go build -o ./bin/win/wireguard-go.exe ./wireguard-go + +# Linux +GOOS=linux GOARCH=amd64 go build -o ./bin/linux/wireguard-go ./wireguard-go + +# macOS Intel +GOOS=darwin GOARCH=amd64 go build -o ./bin/mac/wireguard-go ./wireguard-go + +# macOS ARM +GOOS=darwin GOARCH=arm64 go build -o ./bin/mac/wireguard-go-arm ./wireguard-go diff --git a/package-lock.json b/package-lock.json index 23a7628..242dd8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -85,7 +85,6 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -2879,7 +2878,6 @@ "integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -3150,7 +3148,6 @@ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3353,6 +3350,7 @@ "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "archiver-utils": "^2.1.0", "async": "^3.2.4", @@ -3372,6 +3370,7 @@ "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "glob": "^7.1.4", "graceful-fs": "^4.2.0", @@ -3393,7 +3392,8 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/archiver-utils/node_modules/readable-stream": { "version": "2.3.8", @@ -3401,6 +3401,7 @@ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -3416,7 +3417,8 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/archiver-utils/node_modules/string_decoder": { "version": "1.1.1", @@ -3424,6 +3426,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -3708,7 +3711,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", @@ -4326,6 +4328,7 @@ "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "buffer-crc32": "^0.2.13", "crc32-stream": "^4.0.2", @@ -4527,6 +4530,7 @@ "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "crc32": "bin/crc32.njs" }, @@ -4540,6 +4544,7 @@ "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^3.4.0" @@ -5021,7 +5026,6 @@ "integrity": "sha512-NoXo6Liy2heSklTI5OIZbCgXC1RzrDQsZkeEwXhdOro3FT1VBOvbubvscdPnjVuQ4AMwwv61oaH96AbiYg9EnQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "app-builder-lib": "25.1.8", "builder-util": "25.1.7", @@ -5241,6 +5245,7 @@ "integrity": "sha512-2ntkJ+9+0GFP6nAISiMabKt6eqBB0kX1QqHNWFWAXgi0VULKGisM46luRFpIBiU3u/TDmhZMM8tzvo2Abn3ayg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "app-builder-lib": "25.1.8", "archiver": "^5.3.1", @@ -5254,6 +5259,7 @@ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -5269,6 +5275,7 @@ "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "universalify": "^2.0.0" }, @@ -5282,6 +5289,7 @@ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 10.0.0" } @@ -6248,7 +6256,8 @@ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/fs-extra": { "version": "8.1.0", @@ -7184,7 +7193,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -7935,6 +7944,7 @@ "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "readable-stream": "^2.0.5" }, @@ -7947,7 +7957,8 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lazystream/node_modules/readable-stream": { "version": "2.3.8", @@ -7955,6 +7966,7 @@ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -7970,7 +7982,8 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lazystream/node_modules/string_decoder": { "version": "1.1.1", @@ -7978,6 +7991,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -8270,21 +8284,24 @@ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash.difference": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash.isequal": { "version": "4.5.0", @@ -8298,14 +8315,16 @@ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash.union": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/log-symbols": { "version": "4.1.0", @@ -9110,6 +9129,7 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -9795,7 +9815,8 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/progress": { "version": "2.0.3", @@ -9905,7 +9926,6 @@ "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz", "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", "license": "MIT", - "peer": true, "dependencies": { "fast-diff": "^1.3.0", "lodash.clonedeep": "^4.5.0", @@ -9939,7 +9959,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -9952,7 +9971,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -9987,7 +10005,6 @@ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", "license": "MIT", - "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" @@ -10134,6 +10151,7 @@ "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "minimatch": "^5.1.0" } @@ -10144,6 +10162,7 @@ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -10154,6 +10173,7 @@ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "license": "ISC", + "peer": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -10197,8 +10217,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -11477,6 +11496,7 @@ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -11947,7 +11967,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -12509,6 +12528,7 @@ "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "archiver-utils": "^3.0.4", "compress-commons": "^4.1.2", @@ -12524,6 +12544,7 @@ "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "glob": "^7.2.3", "graceful-fs": "^4.2.0", diff --git a/package.json b/package.json index aeb2cc7..d4a31c0 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,14 @@ { "from": "src/assets", "to": "assets" + }, + { + "from": "resources/wireguard-install", + "to": "wireguard-install" + }, + { + "from": "resources/wireguard", + "to": "wireguard" } ], "mac": { @@ -83,6 +91,7 @@ } }, "win": { + "requestedExecutionLevel": "requireAdministrator", "target": [ { "target": "nsis", @@ -126,4 +135,4 @@ "vite": "^5.4.7", "vitest": "^2.1.1" } -} +} \ No newline at end of file diff --git a/resources/wireguard-install/wireguard-installer.exe b/resources/wireguard-install/wireguard-installer.exe new file mode 100644 index 0000000..032922d Binary files /dev/null and b/resources/wireguard-install/wireguard-installer.exe differ diff --git a/resources/wireguard/mac/wg0.conf b/resources/wireguard/mac/wg0.conf new file mode 100644 index 0000000..5053efb --- /dev/null +++ b/resources/wireguard/mac/wg0.conf @@ -0,0 +1,10 @@ +[Interface] +PrivateKey = CEzCd25ufxbOjvRhMqLfkcdP/OziG5i6OkXCfMZrI1I= +Address = 10.0.0.2/24 +DNS = 1.1.1.1 + +[Peer] +PublicKey = jG+7H5thEiNjxY1XqI1R9oyMAMTIegLwE3tZkS1Rj2U= +Endpoint = 35.95.209.161:51820 +AllowedIPs = 10.0.0.0/24 +PersistentKeepalive = 25 diff --git a/resources/wireguard/windows/wg0.conf b/resources/wireguard/windows/wg0.conf new file mode 100644 index 0000000..5053efb --- /dev/null +++ b/resources/wireguard/windows/wg0.conf @@ -0,0 +1,10 @@ +[Interface] +PrivateKey = CEzCd25ufxbOjvRhMqLfkcdP/OziG5i6OkXCfMZrI1I= +Address = 10.0.0.2/24 +DNS = 1.1.1.1 + +[Peer] +PublicKey = jG+7H5thEiNjxY1XqI1R9oyMAMTIegLwE3tZkS1Rj2U= +Endpoint = 35.95.209.161:51820 +AllowedIPs = 10.0.0.0/24 +PersistentKeepalive = 25 diff --git a/src/electron/api/axiosClient.ts b/src/electron/api/axiosClient.ts index cc0acd5..ec2d7eb 100644 --- a/src/electron/api/axiosClient.ts +++ b/src/electron/api/axiosClient.ts @@ -4,6 +4,7 @@ import { getToken } from '../utils/tokenHelper.js'; import chalk from "chalk"; import { sendTokenExpired } from '../ipc/ipcHandler.js'; import https from 'https'; +import { getBaseURL } from './baseURL.js'; const TOKEN_KEY = 'ACCESS_TOKEN'; @@ -12,9 +13,7 @@ const httpsAgent = new https.Agent({ }); const api: AxiosInstance = axios.create({ - // https://dreadingly-unfighting-pandora.ngrok-free.dev/ - // https://daniela-nonprofessed-boastfully.ngrok-free.app/ - baseURL: 'https://daniela-nonprofessed-boastfully.ngrok-free.app/api/v1/va', // 🔁 your backend + baseURL: await getBaseURL(), // 🔁 your backend httpsAgent // timeout: 10000, }); @@ -31,7 +30,7 @@ api.interceptors.request.use( if (token) { config.headers['token'] = token; - config.headers['ngrok-skip-browser-warning'] = 'true'; + config.headers['ngrok-skip-browser-warning'] = 'true'; } return config; @@ -56,7 +55,7 @@ api.interceptors.response.use( (response: AxiosResponse) => response.data, async (error) => { - console.log(error , "Line 46") + console.log(error, "Line 46") const status = error?.response?.status; console.error('[Axios Error]', status); diff --git a/src/electron/api/baseURL.ts b/src/electron/api/baseURL.ts new file mode 100644 index 0000000..1982a4a --- /dev/null +++ b/src/electron/api/baseURL.ts @@ -0,0 +1,6 @@ +let CURRENT_BASE_URL = "https://portal-sf.docva.com"; + +export const getBaseURL = () => CURRENT_BASE_URL; +export const setBaseURL = (url: string) => { + CURRENT_BASE_URL = url; +}; diff --git a/src/electron/api/regionCheck.ts b/src/electron/api/regionCheck.ts index e4d1c45..b545c8f 100644 --- a/src/electron/api/regionCheck.ts +++ b/src/electron/api/regionCheck.ts @@ -1,11 +1,14 @@ import axios from "axios"; import https from "https"; +import { getBaseURL } from "./baseURL.js"; const httpsAgent = new https.Agent({ rejectUnauthorized: false }); export const checkRegion = async () => { - const baseURL = "https://daniela-nonprofessed-boastfully.ngrok-free.app"; + const baseURL = await getBaseURL(); + + console.log("checkRegion@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" ,baseURL) try { @@ -14,6 +17,8 @@ export const checkRegion = async () => { httpsAgent }); + console.log(res , "checkRegion") + return { success: true, status: res.status, @@ -21,33 +26,11 @@ export const checkRegion = async () => { }; } catch (error: any) { + console.log(error , "Line 29") const status = error?.response?.status || 500; console.log("Region Check Error:", status); - // 🔁 Auto retry if 403 — server blocked first try - if (status === 403) { - try { - const retry = await axios.get(`${baseURL}/api`, { - headers: { "ngrok-skip-browser-warning": "true" }, - httpsAgent - }); - - return { - success: true, - status: retry.status, - data: retry.data, - retry: true - }; - } catch (retryErr: any) { - return { - success: false, - status: retryErr?.response?.status || 500, - message: "403 Retry failed" - }; - } - } - return { success: false, status, diff --git a/src/electron/ipc/ipcHandler.ts b/src/electron/ipc/ipcHandler.ts index 8465665..d88f698 100644 --- a/src/electron/ipc/ipcHandler.ts +++ b/src/electron/ipc/ipcHandler.ts @@ -4,6 +4,8 @@ import { getActiveApp, handleLogin, takeScreenshot, startWindowPolling, getRunni import api from "../api/axiosClient.js"; import { getMainWindow } from '../main.js'; import { checkRegion } from "../api/regionCheck.js"; +import { startVPN, stopVPN } from "../vpn.js"; +import { getBaseURL, setBaseURL } from "../api/baseURL.js"; @@ -11,7 +13,19 @@ import { checkRegion } from "../api/regionCheck.js"; export const registerIPCHandlers = (mainWindow: BrowserWindow) => { console.log("⚙️ Registering IPC Handlers..."); - + + ipcMain.handle("GET_BASE_URL", () => { + return getBaseURL(); +}); + +// UPDATE Base URL +ipcMain.handle("UPDATE_BASE_URL", (event, url: string) => { + setBaseURL(url); + return { + updated: true, + baseURL: url + }; +}); ipcMain.handle("get-token", async (_, key: "ACCESS_TOKEN" | "REFRESH_TOKEN") => { return await getToken(key); @@ -554,4 +568,10 @@ export const sendTokenExpired = () => { }; -; +ipcMain.handle("vpn-connect", async () => { + return startVPN(); +}); + +ipcMain.handle("vpn-disconnect", async () => { + stopVPN(); +}); \ No newline at end of file diff --git a/src/electron/main.ts b/src/electron/main.ts index 943d6cc..9dbe4d0 100644 --- a/src/electron/main.ts +++ b/src/electron/main.ts @@ -8,6 +8,9 @@ import "./ipc/ipcHandler.js"; import path from "path"; import { fileURLToPath } from "url"; +import * as fs from "fs"; +import { execFile } from "child_process"; + app.setAppUserModelId("com.tracker.app"); const __filename = fileURLToPath(import.meta.url); @@ -52,12 +55,26 @@ app.on("second-instance", () => { } }); + +// CHECKING IF WIREGUARD EXIST - IF NOT INSTALLING IN CLIENT MACHINE +const wgPath = "C:\\Program Files\\WireGuard\\wireguard.exe"; + +if (!fs.existsSync(wgPath)) { + const installer = path.join(process.resourcesPath, "wireguard-install", "wireguard-installer.exe"); + + execFile(installer, ["/quiet"], (err) => { + if (err) console.error("WireGuard install failed:", err); + else console.log("WireGuard installed successfully."); + }); +} +// CHECKING IF WIREGUARD EXIST - IF NOT INSTALLING IN CLIENT MACHINE + + // --------------------------- // MAIN APP READY // --------------------------- app.on("ready", async () => { - splashWindow = new BrowserWindow({ width: 300, height: 300, @@ -68,7 +85,7 @@ app.on("ready", async () => { show: true, skipTaskbar: true, webPreferences: { - devTools: true, + devTools: false, } }); @@ -90,8 +107,8 @@ app.on("ready", async () => { // alwaysOnTop: true, // skipTaskbar: true, autoHideMenuBar: true, - frame: true, - show: false, + frame: true, + show: false, icon: resolveIcon(), webPreferences: { devTools: true, @@ -102,14 +119,14 @@ app.on("ready", async () => { }); - - // win.setAlwaysOnTop(true, 'screen-saver'); - // win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true }); - // win.setFullScreenable(false); - + + // win.setAlwaysOnTop(true, 'screen-saver'); + // win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true }); + // win.setFullScreenable(false); + // Cross-platform safe always-on-top const isMac = process.platform === "darwin"; - + if (isMac) { win.setAlwaysOnTop(true, "floating"); // best for macOS win.setVisibleOnAllWorkspaces(true); // NO fullscreen override @@ -117,7 +134,7 @@ app.on("ready", async () => { win.setAlwaysOnTop(true, "normal"); // safest for Windows + Zoom win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true }); win.setFullScreenable(false); -} + } mainWindow = win; @@ -164,17 +181,17 @@ app.on("ready", async () => { }); -// app.on('browser-window-focus', () => { -// globalShortcut.register('CommandOrControl+R', () => { -// // Do nothing; disables reload -// }); -// globalShortcut.register('F5', () => { -// // Do nothing; disables reload -// }); -// globalShortcut.register('CommandOrControl+Shift+I', () => { -// // Do nothing; disables DevTools -// }); -// }); +app.on('browser-window-focus', () => { + globalShortcut.register('CommandOrControl+R', () => { + // Do nothing; disables reload + }); + globalShortcut.register('F5', () => { + // Do nothing; disables reload + }); + globalShortcut.register('CommandOrControl+Shift+I', () => { + // Do nothing; disables DevTools + }); +}); // app.on('browser-window-blur', () => { // globalShortcut.unregisterAll(); diff --git a/src/electron/preload.cts b/src/electron/preload.cts index 171a4ef..2864150 100644 --- a/src/electron/preload.cts +++ b/src/electron/preload.cts @@ -65,8 +65,14 @@ contextBridge.exposeInMainWorld('electron', { getLeaveList: () => ipcRenderer.invoke("get-leave-list"), getAdjustmentsList:(vaId: string) => ipcRenderer.invoke("get-adjustments-list",vaId), - checkRegion: () => ipcRenderer.invoke("check-region") + checkRegion: () => ipcRenderer.invoke("check-region"), + connectVPN: () => ipcRenderer.invoke("vpn-connect"), + disconnectVPN: () => ipcRenderer.invoke("vpn-disconnect"), + + getBaseURL: () => ipcRenderer.invoke("GET_BASE_URL"), + updateBaseURL: (url: string) => ipcRenderer.invoke("UPDATE_BASE_URL", url), + } satisfies Window['electron']); // function ipcInvoke( diff --git a/src/electron/tray.test.ts b/src/electron/tray.test.ts index e149a07..9af5928 100644 --- a/src/electron/tray.test.ts +++ b/src/electron/tray.test.ts @@ -35,7 +35,7 @@ test('', () => { expect(template[0].label).toEqual('Show'); template[0]?.click?.(null as any, null as any, null as any); expect(mainWindow.show).toHaveBeenCalled(); - expect(app.dock.show).toHaveBeenCalled(); + expect(app.dock!.show).toHaveBeenCalled(); template[1]?.click?.(null as any, null as any, null as any); expect(app.quit).toHaveBeenCalled(); diff --git a/src/electron/utils/utilityFunctions.ts b/src/electron/utils/utilityFunctions.ts index 0a15c7d..d8523d5 100644 --- a/src/electron/utils/utilityFunctions.ts +++ b/src/electron/utils/utilityFunctions.ts @@ -8,6 +8,7 @@ import { saveToken } from "./tokenHelper.js"; import { activeWindow } from "get-windows"; import { exec } from "child_process"; import { getUIPath } from "../pathResolver.js"; +import { getBaseURL } from "../api/baseURL.js"; const httpsAgent = new https.Agent({ rejectUnauthorized: false @@ -61,14 +62,16 @@ export const handleLogin = async (credentials: { email: string, password: string // Call your login API console.log("🟡 login Request received", credentials); + let baseURL = getBaseURL() + console.log("app.getAppPath()", app.getAppPath()); console.log("UIPATH", getUIPath()); - console.log("Doom 1"); + console.log("Doom 1" , `${baseURL}/api/v1/va/login`); try { console.log("➡️ Calling API..."); const response = await axios.post( - 'https://daniela-nonprofessed-boastfully.ngrok-free.app/api/v1/va/login', + `${baseURL}/api/v1/va/login`, { userDetails: { ...credentials } }, { headers: { "ngrok-skip-browser-warning": 69420 }, httpsAgent } ); diff --git a/src/electron/vpn.ts b/src/electron/vpn.ts new file mode 100644 index 0000000..19596b9 --- /dev/null +++ b/src/electron/vpn.ts @@ -0,0 +1,223 @@ +import { app } from "electron"; +import { exec, execFile } from "child_process"; +import fs from "fs"; +import os from "os"; +import path from "path"; + +// +// ------------------ HELPERS ------------------ +// + +// Promise wrapper for exec() +function execPromise(cmd: string): Promise { + return new Promise((resolve, reject) => { + exec(cmd, (err, stdout, stderr) => { + if (err) return reject(stderr || err); + resolve(stdout); + }); + }); +} + +// Detect dev vs production +function isDev() { + return !app.isPackaged; +} + +// +// ------------------ PATH RESOLVERS ------------------ +// + +// WireGuard installer path (Windows only) +// function getWireGuardInstallerPath(): string { +// return isDev() +// ? path.join(process.cwd(), "resources", "wireguard-install", "wireguard-installer.exe") +// : path.join(process.resourcesPath, "wireguard-install", "wireguard-installer.exe"); +// } + +function getWireGuardInstallerPath(): string { + const devPath = path.join(process.cwd(), "resources", "wireguard-install", "wireguard-installer.exe"); + + // When running "npm run dev", use devPath ALWAYS + if (!app.isPackaged) { + console.log("DEV MODE Installer Path:", devPath); + return devPath; + } + + // Production build path + const prodPath = path.join(process.resourcesPath, "wireguard-install", "wireguard-installer.exe"); + console.log("PROD MODE Installer Path:", prodPath); + return prodPath; +} + + +// OS-specific wg0.conf +function getConfigPath(): string { + const base = isDev() + ? path.join(process.cwd(), "resources", "wireguard") + : path.join(process.resourcesPath, "wireguard"); + + if (process.platform === "win32") { + return path.join(base, "windows", "wg0.conf"); + } + + if (process.platform === "darwin") { + return path.join(base, "macos", "wg0.conf"); + } + + throw new Error("Unsupported OS"); +} + +// Detect installed WireGuard.exe on Windows +function findWireGuardCLI(): string | null { + const possiblePaths = [ + "C:\\Program Files\\WireGuard\\wireguard.exe", + "C:\\Program Files (x86)\\WireGuard\\wireguard.exe" + ]; + + for (const p of possiblePaths) { + if (fs.existsSync(p)) return p; + } + + return null; +} + +// +// ------------------ WINDOWS INSTALL LOGIC ------------------ +// + +// Install WireGuard silently +async function ensureWireGuardInstalled(): Promise { + let cli = findWireGuardCLI(); + if (cli) return cli; + + // Installer path + const installer = getWireGuardInstallerPath(); + if (!fs.existsSync(installer)) { + throw new Error("WireGuard installer not found in resources."); + } + + console.log("WireGuard not found. Installing silently..."); + await execPromise(`"${installer}" /quiet`); + + cli = findWireGuardCLI(); + if (!cli) throw new Error("WireGuard installation failed."); + + console.log("WireGuard installed successfully:", cli); + return cli; +} + +// +// ------------------ WINDOWS CONNECT/DISCONNECT ------------------ +// + +// async function connectWindows(): Promise { +// const cli = await ensureWireGuardInstalled(); +// const conf = getConfigPath(); + +// // Disable GUI auto popup +// await execPromise( +// `reg add "HKCU\\Software\\WireGuard" /v SuppressTray /t REG_DWORD /d 1 /f` +// ); + +// return new Promise((resolve, reject) => { +// execFile(cli, ["/installtunnelservice", conf], (err) => { +// if (err) return reject("Failed to connect VPN: " + err); +// resolve("Windows VPN connected without GUI"); +// }); +// }); +// } + +// let wgRuntimeProcess: any = null; + +// async function connectWindows(): Promise { +// const cli = await ensureWireGuardInstalled(); +// const conf = getConfigPath(); + +// return new Promise((resolve, reject) => { +// wgRuntimeProcess = execFile(cli, ["/tunnelservice", conf], (err) => { +// if (err) return reject("VPN connection error: " + err); +// }); + +// // Wait a bit for interface to come up +// setTimeout(() => resolve("Windows VPN connected silently"), 800); +// }); +// } + + +async function connectWindows(): Promise { + const cli = await ensureWireGuardInstalled(); + const conf = getConfigPath(); + + // Disable GUI popup and silent mode (ignore errors) + await execPromise(`reg add "HKCU\\Software\\WireGuard" /v HideTrayIcon /t REG_DWORD /d 1 /f`).catch(() => {}); + await execPromise(`reg add "HKCU\\Software\\WireGuard" /v SuppressTray /t REG_DWORD /d 1 /f`).catch(() => {}); + await execPromise(`reg delete "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" /v WireGuard /f`).catch(() => {}); + + // Start background service + await execPromise(`sc start WireGuardManager`).catch(() => {}); + + return new Promise((resolve, reject) => { + execFile(cli, ["/installtunnelservice", conf], (err) => { + if (err) return reject("VPN connection failed: " + err); + resolve("Windows VPN connected silently"); + }); + }); +} + +// function disconnectWindows(): Promise { +// const cli = findWireGuardCLI(); +// if (!cli) return Promise.reject("WireGuard CLI not found"); + +// return execPromise(`"${cli}" /uninstalltunnelservice wg0`); +// } + +async function disconnectWindows(): Promise { + const cli = findWireGuardCLI(); + if (!cli) throw new Error("WireGuard CLI not found"); + + // 1. Remove the installed tunnel service + await execPromise(`"${cli}" /uninstalltunnelservice wg0`); + + // 2. Ensure background service is still running (optional clean-up) + // Windows sometimes marks the service as "stopped" after uninstall + await execPromise(`sc stop WireGuardTunnel$wg0`).catch(() => { }); + await execPromise(`sc stop WireGuardManager`).catch(() => { }); + + return "Windows VPN disconnected"; +} + + +// +// ------------------ MACOS CONNECT/DISCONNECT ------------------ +// + +function connectMac(): Promise { + const conf = getConfigPath(); + return execPromise(`sudo wg-quick up "${conf}"`).then(() => "macOS VPN connected"); +} + +function disconnectMac(): Promise { + return execPromise(`sudo wg-quick down wg0`).then(() => "macOS VPN disconnected"); +} + +// +// ------------------ PUBLIC API ------------------ +// + +export function startVPN(): Promise { + const platform = os.platform(); + + if (platform === "win32") return connectWindows(); + if (platform === "darwin") return connectMac(); + + return Promise.reject("Unsupported OS"); +} + +export function stopVPN(): Promise { + const platform = os.platform(); + + if (platform === "win32") return disconnectWindows(); + if (platform === "darwin") return disconnectMac(); + + return Promise.reject("Unsupported OS"); +} diff --git a/src/ui/layout/DashboardLayout.tsx b/src/ui/layout/DashboardLayout.tsx index c24749b..c071a1c 100644 --- a/src/ui/layout/DashboardLayout.tsx +++ b/src/ui/layout/DashboardLayout.tsx @@ -167,7 +167,7 @@ const DashboardLayout = () => { `Timer will continue running. Please stop manually when ready.` ); - + console.log("✅ Alert shown, timer continues running"); }, [selectedProject]); @@ -262,11 +262,11 @@ const DashboardLayout = () => { ); // STEP 6: Update UI (restore window) - console.log("🪟 STEP 6: Restoring window..."); - await window.electron.toggleCloseBtn(true); - await window.electron.resizeWindow(500, 600); - toggleWindowSize.current = true; - console.log("✅ Window restored"); + console.log("🪟 STEP 6: Restoring window..."); + await window.electron.toggleCloseBtn(true); + await window.electron.resizeWindow(500, 600); + toggleWindowSize.current = true; + console.log("✅ Window restored"); // Allow React to process the state update await new Promise(resolve => setTimeout(resolve, 50)); @@ -333,7 +333,7 @@ const DashboardLayout = () => { } } - + } catch (error) { console.error("❌ Error refreshing project list:", error); @@ -590,7 +590,7 @@ const DashboardLayout = () => { if (!selectedProject?.projectId) return console.log(selectedProject?.projectId, "SelectedProject ID") - socketRef.current = io("https://daniela-nonprofessed-boastfully.ngrok-free.app", { + socketRef.current = io("https://quality-friendly-goldfish.ngrok-free.app", { transports: ["websocket"], secure: true, rejectUnauthorized: false, @@ -726,9 +726,39 @@ const DashboardLayout = () => { // return `${hrs}h ${mins}m `; }; + + const [checkIp, setCheckIp] = useState(false) + useEffect(() => { + setTimeout(() => { + fetch('https://api.ipify.org/?format=json').then((res) => console.log("IPPPPPPPPPPPPPP", res)) + }, 5000) + }, [checkIp]) + + return ( <>
+ {/* + + */} + {/* Header */} {isTracking &&
diff --git a/src/ui/pages/Vpn/VpnGuard.tsx b/src/ui/pages/Vpn/VpnGuard.tsx index f4bea63..9bf8c2f 100644 --- a/src/ui/pages/Vpn/VpnGuard.tsx +++ b/src/ui/pages/Vpn/VpnGuard.tsx @@ -1,25 +1,32 @@ import React, { useEffect, useState } from "react"; +import { Shield, ShieldAlert, RefreshCw, Wifi } from "lucide-react"; interface Props { children: React.ReactNode; } const VpnGuard: React.FC = ({ children }) => { + + const VPN_API = "http://10.0.0.2:3000"; + const [checking, setChecking] = useState(true); const [vpnConnected, setVpnConnected] = useState(true); + const [isRetrying, setIsRetrying] = useState(false); const checkVPN = async () => { - setChecking(true) try { - const res = await window.electron.checkRegion(); - console.log("VpnGuard", res) - if (res.success) { - setVpnConnected(true); - } - } catch { + setChecking(true); + + const res = await window.electron?.checkRegion(); + console.log("VpnGuard", res); + + setVpnConnected(res?.success === true); + } catch (error) { + console.error("VPN check failed:", error); setVpnConnected(false); } finally { setChecking(false); + setIsRetrying(false); } }; @@ -27,32 +34,121 @@ const VpnGuard: React.FC = ({ children }) => { checkVPN(); }, []); - if (checking) { + const connectVPN = async () => { + setChecking(true); + try { + const res = await window.electron.connectVPN(); + console.log("connectVPN result → ", res); + + // Only proceed if VPN actually connected + if (res === "Windows VPN connected silently") { + + const vpnRes = await window.electron.updateBaseURL(VPN_API); + console.log("vpnRes", vpnRes); + + if (vpnRes) { + // Run VPN check again AFTER URL changes + await checkVPN(); + } else { + console.warn("Base URL updated but health check failed"); + } + } + } catch (error) { + console.log(error); + } finally { + setChecking(false); + } + }; + + + // Checking state + if (checking && !isRetrying) { return ( -
- - Checking VPN... +
+
+
+
+
+
+ +
+
+
+

+ Verifying Connection +

+

Checking VPN status...

+
+ +
+
); } + // VPN not connected state if (!vpnConnected) { return ( -
-
-

VPN Required

-

Please connect to your company VPN to continue.

+
+
+
+
+ {/* Icon with animation */} +
+
+
+
+
+ +
+
- + {/* Title */} +

+ VPN Required +

+ + {/* Description */} +

+ Please connect to your company VPN to access this application. +

+ + {/* Retry button */} + + + {/* Help text */} +
+

+ Need help? Contact IT support at{" "} + + support@company.com + +

+
+
); } return <>{children}; + }; -export default VpnGuard; +export default VpnGuard; \ No newline at end of file diff --git a/types.d.ts b/types.d.ts index 70f38ce..d080cd6 100644 --- a/types.d.ts +++ b/types.d.ts @@ -252,6 +252,13 @@ interface Window { }>; checkRegion: () => Promise; + connectVPN: () => Promise; + disconnectVPN: () => Promise; + getBaseURL: () => Promise; + updateBaseURL: (url: string) => Promise<{ + updated: boolean; + baseURL: string; + }>; }; }