diff --git a/package.json b/package.json index c536f05c..92dd7bc2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bluebubbles-server", - "version": "1.9.2", + "version": "1.9.3", "description": "BlueBubbles Server is the app that powers the BlueBubbles app ecosystem", "private": true, "workspaces": [ diff --git a/packages/server/.env.example b/packages/server/.env.example new file mode 100644 index 00000000..43c153db --- /dev/null +++ b/packages/server/.env.example @@ -0,0 +1,3 @@ +APPLEID= +APPLEIDPASS= +TEAMID= \ No newline at end of file diff --git a/packages/server/package.json b/packages/server/package.json index 4ef2251c..11eaf479 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "@bluebubbles/server", - "version": "1.9.2", + "version": "1.9.3", "main": "./dist/main.js", "license": "Apache-2.0", "author": { @@ -106,7 +106,7 @@ "macos-version": "^5.2.0", "mime-types": "^2.1.32", "minimist": "^1.2.6", - "ngrok": "^4.3.3", + "ngrok": "^5.0.0-beta.2", "node-forge": "^1.3.1", "node-mac-contacts": "^1.7.2", "node-mac-permissions": "^2.3.0", diff --git a/packages/server/scripts/electron-builder-config.js b/packages/server/scripts/electron-builder-config.js index 29e58780..c7fc6b7d 100644 --- a/packages/server/scripts/electron-builder-config.js +++ b/packages/server/scripts/electron-builder-config.js @@ -53,6 +53,9 @@ module.exports = { "NSAppleEventsUsageDescription": "BlueBubbles needs access to run AppleScripts", "NSSystemAdministrationUsageDescription": "BlueBubbles needs access to manage your system", }, + "signIgnore": [ + "ngrok" + ], "gatekeeperAssess": false, "minimumSystemVersion": "10.11.0" }, diff --git a/packages/server/src/server/api/privateApi/modes/dylibPlugins/index.ts b/packages/server/src/server/api/privateApi/modes/dylibPlugins/index.ts index 0de3b92e..4c94e367 100644 --- a/packages/server/src/server/api/privateApi/modes/dylibPlugins/index.ts +++ b/packages/server/src/server/api/privateApi/modes/dylibPlugins/index.ts @@ -33,8 +33,11 @@ export abstract class DylibPlugin { try { Server().log(`Killing process: ${this.parentApp}`, "debug"); await FileSystem.killProcess(this.parentApp); - } catch (ex) { - Server().log(`Failed to kill parent process (${this.parentApp})! Error: ${ex}`); + } catch (ex: any) { + const errStr = ((typeof ex === 'object') ? ex?.message ?? String(ex) : String(ex)).trim(); + if (!errStr.includes('No matching processes belonging to you were found')) { + Server().log(`Failed to kill parent process (${this.parentApp})! Error: ${errStr}`, 'debug'); + } } } diff --git a/packages/server/src/server/services/proxyServices/ngrokService/index.ts b/packages/server/src/server/services/proxyServices/ngrokService/index.ts index 2640b8b5..1d97ea02 100644 --- a/packages/server/src/server/services/proxyServices/ngrokService/index.ts +++ b/packages/server/src/server/services/proxyServices/ngrokService/index.ts @@ -24,6 +24,10 @@ export class NgrokService extends Proxy { const ngrokKey = Server().repo.getConfig("ngrok_key") as string; let ngrokProtocol = (Server().repo.getConfig("ngrok_protocol") as Ngrok.Protocol) ?? "http"; + if (isEmpty(ngrokKey)) { + throw new Error('You must provide an Auth Token to use the Ngrok Proxy Service!'); + } + const opts: Ngrok.Options = { port: Server().repo.getConfig("socket_port") ?? 1234, region: (Server().repo.getConfig("ngrok_region") as Ngrok.Region) ?? "us", @@ -65,14 +69,12 @@ export class NgrokService extends Proxy { } }; - // If we have a key, use it - if (ngrokKey !== null && ngrokKey !== undefined) { - opts.authtoken = safeTrim(ngrokKey); - await authtoken({ - authtoken: safeTrim(ngrokKey), - binPath: (bPath: string) => bPath.replace("app.asar", "app.asar.unpacked") - }); - } + // Apply the Ngrok auth token + opts.authtoken = safeTrim(ngrokKey); + await authtoken({ + authtoken: safeTrim(ngrokKey), + binPath: (bPath: string) => bPath.replace("app.asar", "app.asar.unpacked") + }); // If there is no key, force http if (isEmpty(ngrokKey)) { diff --git a/packages/ui/package.json b/packages/ui/package.json index 60a64401..fff713a4 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@bluebubbles/ui", - "version": "1.9.2", + "version": "1.9.3", "homepage": "./", "license": "Apache-2.0", "scripts": { diff --git a/packages/ui/src/app/components/fields/NgrokAuthTokenField.tsx b/packages/ui/src/app/components/fields/NgrokAuthTokenField.tsx index b9c7ca93..d98b56cb 100644 --- a/packages/ui/src/app/components/fields/NgrokAuthTokenField.tsx +++ b/packages/ui/src/app/components/fields/NgrokAuthTokenField.tsx @@ -47,6 +47,9 @@ export const NgrokAuthTokenField = ({ helpText }: NgrokAuthTokenFieldProps): JSX } else if (theNewNgrokToken.includes(' ')) { setNgrokTokenError('Invalid Ngrok Auth Token! Please check that you have copied it correctly.'); return; + } else if (theNewNgrokToken.length === 0) { + setNgrokTokenError('An Ngrok Auth Token is required to use the Ngrok proxy service!'); + return; } dispatch(setConfig({ name: 'ngrok_key', value: theNewNgrokToken })); @@ -60,7 +63,7 @@ export const NgrokAuthTokenField = ({ helpText }: NgrokAuthTokenFieldProps): JSX return ( - Ngrok Auth Token (Highly Recommended) + Ngrok Auth Token (Required) { const dispatch = useAppDispatch(); const dnsRef = useRef(null); + const ngrokRef = useRef(null); const alertRef = useRef(null); const proxyService: string = (useAppSelector(state => state.config.proxy_service) ?? '').toLowerCase().replace(' ', '-'); const address: string = useAppSelector(state => state.config.server_address) ?? ''; const port: number = useAppSelector(state => state.config.socket_port) ?? 1234; const [dnsModalOpen, setDnsModalOpen] = useBoolean(); + const [ngrokModalOpen, setNgrokModalOpen] = useBoolean(); const [requiresConfirmation, confirm] = useState((): string | null => { return null; }); @@ -64,14 +67,23 @@ export const ProxySetupField = ({ helpText, showAddress = true }: ProxySetupFiel value={proxyService} onChange={(e) => { if (!e.target.value || e.target.value.length === 0) return; - onSelectChange(e); + + let shouldSave = true; if (e.target.value === 'dynamic-dns') { + shouldSave = false; setDnsModalOpen.on(); + } else if (e.target.value === 'ngrok') { + shouldSave = false; + setNgrokModalOpen.on(); } else if (e.target.value === 'cloudflare') { confirm('confirmation'); } else if (e.target.value === 'lan-url') { saveLanUrl(); } + + if (shouldSave) { + onSelectChange(e); + } }} > @@ -106,12 +118,25 @@ export const ProxySetupField = ({ helpText, showAddress = true }: ProxySetupFiel dispatch(setConfig({ name: 'server_address', value: address }))} + onConfirm={(address) => { + dispatch(setConfig({ name: 'proxy_service', value: 'Dynamic DNS' })); + dispatch(setConfig({ name: 'server_address', value: address })); + }} isOpen={dnsModalOpen} port={port as number} onClose={() => setDnsModalOpen.off()} /> + { + dispatch(setConfig({ name: 'proxy_service', value: 'Ngrok' })); + dispatch(setConfig({ name: 'ngrok_key', value: token })); + }} + isOpen={ngrokModalOpen} + onClose={() => setNgrokModalOpen.off()} + /> + void; + onConfirm?: (address: string) => void; + isOpen: boolean; + modalRef: React.RefObject; + onClose: () => void; +} + +export const NgrokAuthTokenDialog = ({ + onCancel, + onConfirm, + isOpen, + modalRef, + onClose, +}: NgrokAuthTokenDialogProps): JSX.Element => { + const ngrokToken: string = (useAppSelector(state => state.config.ngrok_key) ?? ''); + const [authToken, setAuthToken] = useState(ngrokToken); + const [error, setError] = useState(''); + const isInvalid = (error ?? '').length > 0; + + return ( + onClose()} + > + + + + Set Your Ngrok Auth Token + + + + In order to use Ngrok, you must create a free account and generate an auth token. +
+ + If you have not done so yet, sign up for an account here + +
+ + Once you have signed up copy your auth token from your Ngrok dashboard here. + Then paste it in the field below. + +
+ + Ngrok Auth Token + { + setError(''); + setAuthToken(e.target.value); + }} + /> + {isInvalid ? ( + {error} + ) : null} + + +
+ + + + + +
+
+
+ ); +}; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index cd92cdc1..a0506879 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3889,11 +3889,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.18.tgz#06cb0eeb5a0175d26d99b7acf4db613ca30cb07f" integrity sha512-fwGw1uvQAzabxL1pyoknPlJIF2t7+K90uTqynleKRx24n3lYcxWa3+KByLhgkF8GEAK2c7hC8Ki0RkNM5H15jQ== -"@types/node@^8.10.50": - version "8.10.66" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" - integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== - "@types/numeral@^0.0.26": version "0.0.26" resolved "https://registry.yarnpkg.com/@types/numeral/-/numeral-0.0.26.tgz#cfab9842ef9349ce714b06722940ca7ebf8a6298" @@ -10645,17 +10640,16 @@ neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -ngrok@^4.3.3: - version "4.3.3" - resolved "https://registry.yarnpkg.com/ngrok/-/ngrok-4.3.3.tgz#c51a1c4af2271ac3c9092ede3b0975caf7833217" - integrity sha512-a2KApnkiG5urRxBPdDf76nNBQTnNNWXU0nXw0SsqsPI+Kmt2lGf9TdVYpYrHMnC+T9KhcNSWjCpWqBgC6QcFvw== +ngrok@^5.0.0-beta.2: + version "5.0.0-beta.2" + resolved "https://registry.yarnpkg.com/ngrok/-/ngrok-5.0.0-beta.2.tgz#7976690a592b27de9a91ff93892cfabda24360ad" + integrity sha512-UzsyGiJ4yTTQLCQD11k1DQaMwq2/SsztBg2b34zAqcyjS25qjDpogMKPaCKHwe/APRTHeel3iDXcVctk5CNaCQ== dependencies: - "@types/node" "^8.10.50" extract-zip "^2.0.1" got "^11.8.5" lodash.clonedeep "^4.5.0" uuid "^7.0.0 || ^8.0.0" - yaml "^1.10.0" + yaml "^2.2.2" optionalDependencies: hpagent "^0.1.2" @@ -14930,6 +14924,11 @@ yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== +yaml@^2.2.2: + version "2.3.4" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2" + integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA== + yargs-parser@^20.2.2: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"