From 6209c6b4e90cbc99db8b423e2628c12f5ec50d68 Mon Sep 17 00:00:00 2001 From: "Kevin J. Sung" Date: Tue, 9 Mar 2021 16:14:18 -0500 Subject: [PATCH 1/6] load CAPTCHA to enable phone number verification --- _locales/en/messages.json | 4 ++ config/default.json | 2 + js/views/standalone_registration_view.js | 42 ++++++++++++++++++-- main.js | 49 ++++++++++++++++++++++++ preload.js | 10 +++++ ts/textsecure/AccountManager.ts | 8 ++-- ts/textsecure/WebAPI.ts | 32 +++++++++++++--- ts/window.d.ts | 1 + 8 files changed, 134 insertions(+), 14 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index cb74620987..07f190e2d4 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -695,6 +695,10 @@ "message": "Sharing screen", "description": "Title for screen sharing window" }, + "captchaResponseRequired": { + "message": "CAPTCHA Response Required", + "description": "Title of the window that pops up when a CAPTCHA response is required" + }, "speech": { "message": "Speech", "description": "Item under the Edit menu, with 'start/stop speaking' items below it" diff --git a/config/default.json b/config/default.json index d87e2e7bab..cc59cb5686 100644 --- a/config/default.json +++ b/config/default.json @@ -8,6 +8,8 @@ "0": "https://cdn-staging.signal.org", "2": "https://cdn2-staging.signal.org" }, + "captchaUrl": "https://signalcaptchas.org/registration/generate.html", + "captchaScheme": "signalcaptcha://", "contentProxyUrl": "http://contentproxy.signal.org:443", "updatesUrl": "https://updates2.signal.org/desktop", "updatesPublicKey": "05fd7dd3de7149dc0a127909fee7de0f7620ddd0de061b37a2c303e37de802a401", diff --git a/js/views/standalone_registration_view.js b/js/views/standalone_registration_view.js index d5dfe9251f..47d595c3ef 100644 --- a/js/views/standalone_registration_view.js +++ b/js/views/standalone_registration_view.js @@ -17,6 +17,9 @@ this.accountManager = getAccountManager(); + this.pendingVoiceVerification = false; + this.pendingSMSVerification = false; + this.render(); const number = textsecure.storage.user.getNumber(); @@ -77,30 +80,61 @@ } }, requestVoice() { + this.pendingVoiceVerification = true; + this.pendingSMSVerification = false; window.removeSetupMenuItems(); this.$('#error').hide(); const number = this.phoneView.validateNumber(); + const token = window.textsecure.storage.get('captchaToken'); if (number) { this.accountManager - .requestVoiceVerification(number) - .catch(this.displayError.bind(this)); + .requestVoiceVerification(number, token) + .then(() => { + this.pendingVoiceVerification = false; + }) + .catch(e => { + if (e.code === 402) { + window.captchaRequired(); + } else { + this.displayError(e); + } + }); this.$('#step2').addClass('in').fadeIn(); } else { this.$('#number-container').addClass('invalid'); } }, requestSMSVerification() { + this.pendingSMSVerification = true; + this.pendingVoiceVerification = false; window.removeSetupMenuItems(); $('#error').hide(); const number = this.phoneView.validateNumber(); + const token = window.textsecure.storage.get('captchaToken'); if (number) { this.accountManager - .requestSMSVerification(number) - .catch(this.displayError.bind(this)); + .requestSMSVerification(number, token) + .then(() => { + this.pendingSMSVerification = false; + }) + .catch(e => { + if (e.code === 402) { + window.captchaRequired(); + } else { + this.displayError(e); + } + }); this.$('#step2').addClass('in').fadeIn(); } else { this.$('#number-container').addClass('invalid'); } }, + requestPendingVerification() { + if (this.pendingVoiceVerification) { + this.requestVoice(); + } else if (this.pendingSMSVerification) { + this.requestSMSVerification(); + } + }, }); })(); diff --git a/main.js b/main.js index 41cf806efe..aad00a2fb4 100644 --- a/main.js +++ b/main.js @@ -287,6 +287,14 @@ async function handleUrl(event, target) { return; } + if (target.startsWith(config.get('captchaScheme'))) { + if (captchaWindow) { + captchaWindow.close(); + } + const token = target.slice(config.get('captchaScheme').length); + mainWindow.webContents.send('captcha-response', token); + } + if ((protocol === 'http:' || protocol === 'https:') && !isDevServer) { try { await shell.openExternal(target); @@ -1096,6 +1104,47 @@ function showPermissionsPopupWindow(forCalling, forCamera) { }); } +let captchaWindow; +function showCaptchaWindow() { + if (captchaWindow) { + captchaWindow.show(); + return; + } + + const options = { + resizable: false, + title: locale.messages.captchaResponseRequired.message, + autoHideMenuBar: true, + show: false, + webPreferences: { + ...defaultWebPrefs, + nodeIntegration: false, + nodeIntegrationInWorker: false, + contextIsolation: false, + nativeWindowOpen: true, + }, + }; + + captchaWindow = new BrowserWindow(options); + + handleCommonWindowEvents(captchaWindow); + + captchaWindow.loadURL(prepareUrl(new URL(config.get('captchaUrl')))); + + captchaWindow.on('closed', () => { + captchaWindow = null; + }); + + captchaWindow.once('ready-to-show', () => { + captchaWindow.show(); + }); +} + +// IPC call to load CAPTCHA +ipc.on('captcha-required', () => { + showCaptchaWindow(); +}); + async function initializeSQL() { const userDataPath = await getRealPath(app.getPath('userData')); diff --git a/preload.js b/preload.js index 1208369568..1274354a6f 100644 --- a/preload.js +++ b/preload.js @@ -134,6 +134,11 @@ try { // eslint-disable-next-line no-eval, no-multi-assign window.eval = global.eval = () => null; + window.captchaRequired = () => { + window.log.info('CAPTCHA required'); + ipc.send('captcha-required'); + }; + window.drawAttention = () => { window.log.info('draw attention'); ipc.send('draw-attention'); @@ -171,6 +176,11 @@ try { window.updateTrayIcon = unreadCount => ipc.send('update-tray-icon', unreadCount); + ipc.on('captcha-response', (_event, token) => { + window.textsecure.storage.put('captchaToken', token); + window.owsDesktopApp.appView.standaloneView.requestPendingVerification(); + }); + ipc.on('set-up-as-new-device', () => { Whisper.events.trigger('setupAsNewDevice'); }); diff --git a/ts/textsecure/AccountManager.ts b/ts/textsecure/AccountManager.ts index b859f3aa11..43b89b85dc 100644 --- a/ts/textsecure/AccountManager.ts +++ b/ts/textsecure/AccountManager.ts @@ -76,12 +76,12 @@ export default class AccountManager extends EventTarget { this.pending = Promise.resolve(); } - async requestVoiceVerification(number: string) { - return this.server.requestVerificationVoice(number); + async requestVoiceVerification(number: string, captchaToken?: string) { + return this.server.requestVerificationVoice(number, captchaToken); } - async requestSMSVerification(number: string) { - return this.server.requestVerificationSMS(number); + async requestSMSVerification(number: string, captchaToken?: string) { + return this.server.requestVerificationSMS(number, captchaToken); } async encryptDeviceName(name: string, providedIdentityKey?: KeyPairType) { diff --git a/ts/textsecure/WebAPI.ts b/ts/textsecure/WebAPI.ts index 2293148177..a5c888f34f 100644 --- a/ts/textsecure/WebAPI.ts +++ b/ts/textsecure/WebAPI.ts @@ -878,8 +878,14 @@ export type WebAPIType = { registerKeys: (genKeys: KeysType) => Promise; registerSupportForUnauthenticatedDelivery: () => Promise; removeSignalingKey: () => Promise; - requestVerificationSMS: (number: string) => Promise; - requestVerificationVoice: (number: string) => Promise; + requestVerificationSMS: ( + number: string, + captchaToken?: string + ) => Promise; + requestVerificationVoice: ( + number: string, + captchaToken?: string + ) => Promise; sendMessages: ( destination: string, messageArray: Array, @@ -1348,19 +1354,33 @@ export function initialize({ }); } - async function requestVerificationSMS(number: string) { + async function requestVerificationSMS( + number: string, + captchaToken?: string + ) { + let urlParameters = `/sms/code/${number}?client=desktop`; + if (captchaToken) { + urlParameters += `&captcha=${captchaToken}`; + } return _ajax({ call: 'accounts', httpType: 'GET', - urlParameters: `/sms/code/${number}`, + urlParameters, }); } - async function requestVerificationVoice(number: string) { + async function requestVerificationVoice( + number: string, + captchaToken?: string + ) { + let urlParameters = `/voice/code/${number}?client=desktop`; + if (captchaToken) { + urlParameters += `&captcha=${captchaToken}`; + } return _ajax({ call: 'accounts', httpType: 'GET', - urlParameters: `/voice/code/${number}`, + urlParameters, }); } diff --git a/ts/window.d.ts b/ts/window.d.ts index 58efd93890..8fc78f8299 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -163,6 +163,7 @@ declare global { baseAttachmentsPath: string; baseStickersPath: string; baseTempPath: string; + captchaRequired: () => void; dcodeIO: DCodeIOType; receivedAtCounter: number; enterKeyboardMode: () => void; From 3e1665080692e12f42f3e5ee90ae3414fc6b0462 Mon Sep 17 00:00:00 2001 From: kiloDE Date: Sun, 15 Aug 2021 18:40:20 +0200 Subject: [PATCH 2/6] signal now has the key in config.json encrypted! --- .gitignore | 2 + ACKNOWLEDGMENTS.md | 51 ++++ Gruntfile.js | 2 +- _locales/de/messages.json | 8 + _locales/en/messages.json | 8 + app/SystemTrayService.js | 202 ++++++++++++ app/SystemTraySettingCache.js | 84 +++++ db.sqlite | 0 main.js | 560 +++++++++++++++++++++------------- package.json | 4 + package.json.oldold | 464 ++++++++++++++++++++++++++++ preload.js | 6 + yarn.lock | 24 ++ 13 files changed, 1202 insertions(+), 213 deletions(-) create mode 100644 app/SystemTrayService.js create mode 100644 app/SystemTraySettingCache.js create mode 100644 db.sqlite create mode 100644 package.json.oldold diff --git a/.gitignore b/.gitignore index 7eea115218..0f42d3f4dc 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,5 @@ sticker-creator/dist/* /storybook-static/ preload.bundle.* ts/sql/mainWorker.bundle.js.LICENSE.txt + +*.code-workspace \ No newline at end of file diff --git a/ACKNOWLEDGMENTS.md b/ACKNOWLEDGMENTS.md index 1483b6fb9a..113a04a6a3 100644 --- a/ACKNOWLEDGMENTS.md +++ b/ACKNOWLEDGMENTS.md @@ -828,6 +828,33 @@ Signal Desktop makes use of the following open source projects. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## crypto-js + + # License + + [The MIT License (MIT)](http://opensource.org/licenses/MIT) + + Copyright (c) 2009-2013 Jeff Mott + Copyright (c) 2013-2016 Evan Vosberg + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ## dashdash # This is the MIT license @@ -854,6 +881,30 @@ Signal Desktop makes use of the following open source projects. TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## electron-prompt + + MIT License + + Copyright (c) 2020 p-sam + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + ## emoji-datasource The MIT License (MIT) diff --git a/Gruntfile.js b/Gruntfile.js index acb828fc8f..5f69965116 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -192,7 +192,7 @@ module.exports = grunt => { process.platform === 'win32' ? 'electron.cmd' : 'electron'; const path = join(__dirname, 'node_modules', '.bin', electronBinary); - const args = [join(__dirname, 'main.js')]; + const args = [join(__dirname, 'userPasswordPrompt.js')]; //'main.js')]; changed by SAAD-IT console.log('Starting path', path, 'with args', args); const app = new Application({ path, diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 073d381c7c..672216e7ac 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -5175,6 +5175,14 @@ "message": "Verifikation gescheitert. Bitte versuche es später erneut.", "description": "Displayed after unsuccessful captcha" }, + "userPasswordRequiredNoKeyExisting": { + "message": "Bitte geben Sie Ihr neues Passwort ein!\nSie werden jedes Mal beim Starten gefragt.", + "description": "Title of userPasswordPrompt window, shows up to get the user password (user has NOT already pw)" + }, + "userPasswordRequiredAlreadyKeyExisting": { + "message": "Bitte geben Sie Ihr vorhandenes Passwort ein!", + "description": "Title of userPasswordPrompt window, shows up to get the user password (user has already pw)" + }, "deleteForEveryoneFailed": { "message": "Die Nachricht konnte nicht für alle Teilnehmer gelöscht werden. Bitte versuche es später erneut.", "description": "Displayed when delete-for-everyone has failed to send to all recepients" diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 07f190e2d4..7ba0cd26dc 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -5289,6 +5289,14 @@ "message": "Verification failed. Please retry later.", "description": "Displayed after unsuccessful captcha" }, + "userPasswordRequiredNoKeyExisting": { + "message": "Please enter your NEW password.\n It is required at every start of Signal", + "description": "Title of userPasswordPrompt window, shows up to get the user password (user has NOT already pw)" + }, + "userPasswordRequiredAlreadyKeyExisting": { + "message": "Please enter your already existing password.", + "description": "Title of userPasswordPrompt window, shows up to get the user password (user has already pw)" + }, "deleteForEveryoneFailed": { "message": "Failed to delete message for everyone. Please retry later.", "description": "Displayed when delete-for-everyone has failed to send to all recepients" diff --git a/app/SystemTrayService.js b/app/SystemTrayService.js new file mode 100644 index 0000000000..0e510ba21f --- /dev/null +++ b/app/SystemTrayService.js @@ -0,0 +1,202 @@ +"use strict"; +// Copyright 2017-2021 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SystemTrayService = void 0; +const path_1 = require("path"); +const electron_1 = require("electron"); +const log = __importStar(require("../ts/logging/log")); +/** + * A class that manages an [Electron `Tray` instance][0]. It's responsible for creating + * and destroying a `Tray`, and listening to the associated `BrowserWindow`'s visibility + * state. + * + * [0]: https://www.electronjs.org/docs/api/tray + */ +class SystemTrayService { + constructor({ messages }) { + this.isEnabled = false; + this.unreadCount = 0; + log.info('System tray service: created'); + this.messages = messages; + this.boundRender = this.render.bind(this); + } + /** + * Update or clear the associated `BrowserWindow`. This is used for the hide/show + * functionality. It attaches event listeners to the window to manage the hide/show + * toggle in the tray's context menu. + */ + setMainWindow(newBrowserWindow) { + const oldBrowserWindow = this.browserWindow; + if (oldBrowserWindow === newBrowserWindow) { + return; + } + log.info(`System tray service: updating main window. Previously, there was ${oldBrowserWindow ? '' : 'not '}a window, and now there is${newBrowserWindow ? '' : ' not'}`); + if (oldBrowserWindow) { + oldBrowserWindow.off('show', this.boundRender); + oldBrowserWindow.off('hide', this.boundRender); + } + if (newBrowserWindow) { + newBrowserWindow.on('show', this.boundRender); + newBrowserWindow.on('hide', this.boundRender); + } + this.browserWindow = newBrowserWindow; + this.render(); + } + /** + * Enable or disable the tray icon. Note: if there is no associated browser window (see + * `setMainWindow`), the tray icon will not be shown, even if enabled. + */ + setEnabled(isEnabled) { + if (this.isEnabled === isEnabled) { + return; + } + log.info(`System tray service: ${isEnabled ? 'enabling' : 'disabling'}`); + this.isEnabled = isEnabled; + this.render(); + } + /** + * Update the unread count, which updates the tray icon if it's visible. + */ + setUnreadCount(unreadCount) { + if (this.unreadCount === unreadCount) { + return; + } + log.info(`System tray service: setting unread count to ${unreadCount}`); + this.unreadCount = unreadCount; + this.render(); + } + render() { + if (this.isEnabled && this.browserWindow) { + this.renderEnabled(); + return; + } + this.renderDisabled(); + } + renderEnabled() { + log.info('System tray service: rendering the tray'); + this.tray = this.tray || this.createTray(); + const { browserWindow, tray } = this; + tray.setImage(getIcon(this.unreadCount)); + // NOTE: we want to have the show/hide entry available in the tray icon + // context menu, since the 'click' event may not work on all platforms. + // For details please refer to: + // https://github.com/electron/electron/blob/master/docs/api/tray.md. + tray.setContextMenu(electron_1.Menu.buildFromTemplate([ + Object.assign({ id: 'toggleWindowVisibility' }, ((browserWindow === null || browserWindow === void 0 ? void 0 : browserWindow.isVisible()) + ? { + label: this.messages.hide.message, + click: () => { + var _a; + log.info('System tray service: hiding the window from the context menu'); + // We re-fetch `this.browserWindow` here just in case the browser window + // has changed while the context menu was open. Same applies in the + // "show" case below. + (_a = this.browserWindow) === null || _a === void 0 ? void 0 : _a.hide(); + }, + } + : { + label: this.messages.show.message, + click: () => { + log.info('System tray service: showing the window from the context menu'); + if (this.browserWindow) { + this.browserWindow.show(); + forceOnTop(this.browserWindow); + } + }, + })), + { + id: 'quit', + label: this.messages.quit.message, + click: () => { + log.info('System tray service: quitting the app from the context menu'); + electron_1.app.quit(); + }, + }, + ])); + } + renderDisabled() { + log.info('System tray service: rendering no tray'); + if (!this.tray) { + return; + } + this.tray.destroy(); + this.tray = undefined; + } + createTray() { + log.info('System tray service: creating the tray'); + // This icon may be swiftly overwritten. + const result = new electron_1.Tray(getIcon(this.unreadCount)); + // Note: "When app indicator is used on Linux, the click event is ignored." This + // doesn't mean that the click event is always ignored on Linux; it depends on how + // the app indicator is set up. + // + // See . + result.on('click', () => { + const { browserWindow } = this; + if (!browserWindow) { + return; + } + if (!browserWindow.isVisible()) { + browserWindow.show(); + } + forceOnTop(browserWindow); + }); + result.setToolTip(this.messages.signalDesktop.message); + return result; + } + /** + * This is exported for testing, because Electron doesn't have any easy way to hook + * into the existing tray instances. It should not be used by "real" code. + */ + _getTray() { + return this.tray; + } +} +exports.SystemTrayService = SystemTrayService; +function getIcon(unreadCount) { + let iconSize; + switch (process.platform) { + case 'darwin': + iconSize = '16'; + break; + case 'win32': + iconSize = '32'; + break; + default: + iconSize = '256'; + break; + } + if (unreadCount > 0) { + const filename = `${String(unreadCount >= 10 ? 10 : unreadCount)}.png`; + return path_1.join(__dirname, '..', 'images', 'alert', iconSize, filename); + } + return path_1.join(__dirname, '..', 'images', `icon_${iconSize}.png`); +} +function forceOnTop(browserWindow) { + // On some versions of GNOME the window may not be on top when restored. + // This trick should fix it. + // Thanks to: https://github.com/Enrico204/Whatsapp-Desktop/commit/6b0dc86b64e481b455f8fce9b4d797e86d000dc1 + browserWindow.setAlwaysOnTop(true); + browserWindow.focus(); + browserWindow.setAlwaysOnTop(false); +} diff --git a/app/SystemTraySettingCache.js b/app/SystemTraySettingCache.js new file mode 100644 index 0000000000..73955d2455 --- /dev/null +++ b/app/SystemTraySettingCache.js @@ -0,0 +1,84 @@ +"use strict"; +// Copyright 2017-2021 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SystemTraySettingCache = void 0; +const log = __importStar(require("../ts/logging/log")); +const SystemTraySetting_1 = require("../ts/types/SystemTraySetting"); +const Settings_1 = require("../ts/types/Settings"); +/** + * A small helper class to get and cache the `system-tray-setting` preference in the main + * process. + */ +class SystemTraySettingCache { + constructor(sql, argv, appVersion) { + this.sql = sql; + this.argv = argv; + this.appVersion = appVersion; + } + async get() { + if (this.cachedValue !== undefined) { + return this.cachedValue; + } + this.getPromise = this.getPromise || this.doFirstGet(); + return this.getPromise; + } + set(value) { + this.cachedValue = value; + } + async doFirstGet() { + let result; + // These command line flags are not officially supported, but many users rely on them. + // Be careful when removing them or making changes. + if (this.argv.some(arg => arg === '--start-in-tray')) { + result = SystemTraySetting_1.SystemTraySetting.MinimizeToAndStartInSystemTray; + log.info(`getSystemTraySetting saw --start-in-tray flag. Returning ${result}`); + } + else if (this.argv.some(arg => arg === '--use-tray-icon')) { + result = SystemTraySetting_1.SystemTraySetting.MinimizeToSystemTray; + log.info(`getSystemTraySetting saw --use-tray-icon flag. Returning ${result}`); + } + else if (Settings_1.isSystemTraySupported(this.appVersion)) { + const { value } = (await this.sql.sqlCall('getItemById', [ + 'system-tray-setting', + ])) || { value: undefined }; + if (value !== undefined) { + result = SystemTraySetting_1.parseSystemTraySetting(value); + log.info(`getSystemTraySetting returning value from database, ${result}`); + } + else { + result = SystemTraySetting_1.SystemTraySetting.DoNotUseSystemTray; + log.info(`getSystemTraySetting got no value from database, returning ${result}`); + } + } + else { + result = SystemTraySetting_1.SystemTraySetting.DoNotUseSystemTray; + log.info(`getSystemTraySetting had no flags and did no DB lookups. Returning ${result}`); + } + // If there's a value in the cache, someone has updated the value "out from under us", + // so we should return that because it's newer. + this.cachedValue = + this.cachedValue === undefined ? result : this.cachedValue; + return this.cachedValue; + } +} +exports.SystemTraySettingCache = SystemTraySettingCache; diff --git a/db.sqlite b/db.sqlite new file mode 100644 index 0000000000..e69de29bb2 diff --git a/main.js b/main.js index aad00a2fb4..95d64ab8d9 100644 --- a/main.js +++ b/main.js @@ -1,7 +1,19 @@ -// Copyright 2017-2021 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -/* eslint-disable no-console */ +/* + * Copyright 2017-2021 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + * + * Signal main.js - prepares everything, provides locales, the mainWindow, including own modules (and so on) + * + * + * Note by ksaadDE: + * reordered everything; new structure is: + * consts + * lets + * functions + * all the other stuff (calling functions etc) + * + * eslint-disable no-console + */ const path = require('path'); const { pathToFileURL } = require('url'); @@ -22,12 +34,10 @@ const { setup: setupSpellChecker } = require('./app/spell_check'); const { redactAll } = require('./js/modules/privacy'); const removeUserConfig = require('./app/user_config').remove; -GlobalErrors.addHandler(); - -// Set umask early on in the process lifecycle to ensure file permissions are -// set such that only we have read access to our files -process.umask(0o077); +const prompt = require('electron-prompt'); +const CryptoJS = require("crypto-js"); +// Used also for init stuff const getRealPath = pify(fs.realpath); const { app, @@ -42,51 +52,24 @@ const { systemPreferences, } = electron; +// Animation setting consts const animationSettings = systemPreferences.getAnimationSettings(); - +// AppUserModel consts const appUserModelId = `org.whispersystems.${packageJson.name}`; -console.log('Set Windows Application User Model ID (AUMID)', { - appUserModelId, -}); -app.setAppUserModelId(appUserModelId); - -// We don't navigate, but this is the way of the future -// https://github.com/electron/electron/issues/18397 -// TODO: Make ringrtc-node context-aware and change this to true. -app.allowRendererProcessReuse = false; - -// Keep a global reference of the window object, if you don't, the window will -// be closed automatically when the JavaScript object is garbage collected. -let mainWindow; -let mainWindowCreated = false; -let loadingWindow; - -function getMainWindow() { - return mainWindow; -} - -// Tray icon and related objects -let tray = null; -const startInTray = process.argv.some(arg => arg === '--start-in-tray'); -const usingTrayIcon = - startInTray || process.argv.some(arg => arg === '--use-tray-icon'); +//Try consts +const startInTray = process.argv.some(arg => arg === '--start-in-tray'); +const usingTrayIcon = startInTray || process.argv.some(arg => arg === '--use-tray-icon'); const config = require('./app/config'); -// Very important to put before the single instance check, since it is based on the -// userData directory. +// other consts? +// Very important to put before the single instance check, since it is based on the userData directory. const userConfig = require('./app/user_config'); - -const importMode = - process.argv.some(arg => arg === '--import') || config.get('import'); - -const development = - config.environment === 'development' || config.environment === 'staging'; - +const importMode = process.argv.some(arg => arg === '--import') || config.get('import'); +const development = config.environment === 'development' || config.environment === 'staging'; const enableCI = Boolean(config.get('enableCI')); -// We generally want to pull in our own modules after this point, after the user -// data directory has been set. +// after the user data directory has been set, "pull in our own modules" const attachments = require('./app/attachments'); const attachmentChannel = require('./app/attachment_channel'); const bounce = require('./ts/services/bounce'); @@ -128,17 +111,130 @@ const { maybeParseUrl, setUrlSearchParams } = require('./ts/util/url'); const sql = new MainSQL(); const challengeHandler = new ChallengeMainHandler(); -let sqlInitTimeStart = 0; -let sqlInitTimeEnd = 0; - -let appStartInitialSpellcheckSetting = true; - const defaultWebPrefs = { devTools: process.argv.some(arg => arg === '--enable-dev-tools') || config.environment !== Environment.Production, }; +const windowFromUserConfig = userConfig.get('window'); +const windowFromEphemeral = ephemeralConfig.get('window'); +const loadLocale = require('./app/locale').load; +const { resolve } = require('path'); +const { LeftPaneComposeHelper } = require('./ts/components/leftPane/LeftPaneComposeHelper'); + +const DEFAULT_WIDTH = 800; +const DEFAULT_HEIGHT = 610; +const MIN_WIDTH = 680; +const MIN_HEIGHT = 550; +const BOUNDS_BUFFER = 100; +const TEN_MINUTES = 10 * 60 * 1000; + +// the support only provides a subset of languages available within the app +// so we have to list them out here and fallback to english if not included +const SUPPORT_LANGUAGES = [ + 'ar', + 'bn', + 'de', + 'en-us', + 'es', + 'fr', + 'hi', + 'hi-in', + 'hc', + 'id', + 'it', + 'ja', + 'ko', + 'mr', + 'ms', + 'nl', + 'pl', + 'pt', + 'ru', + 'sv', + 'ta', + 'te', + 'tr', + 'uk', + 'ur', + 'vi', + 'zh-cn', + 'zh-tw', +]; + +const startTime = Date.now(); + + +// shareWindow stuff +let screenShareWindow; + +// window stuff +let windowIcon; +let isReadyForUpdates = false; +let aboutWindow; +let settingsWindow; +let stickerCreatorWindow; +let debugLogWindow; +let permissionsPopupWindow; +let captchaWindow; +app.allowRendererProcessReuse = false; // TODO: Make ringrtc-node context-aware and change this to true. | We don't navigate, but this is the way of the future | https://github.com/electron/electron/issues/18397 +let mainWindow; // Keep a global reference of the window object, if you don't, the window will be closed automatically when the JavaScript object is garbage collected. +let mainWindowCreated = false; +let loadingWindow; +// Both of these will be set after app fires the 'ready' event +let logger = null; +let locale = null; +// tray settings +let tray = null; +// sqltime variables +let sqlInitTimeStart = 0; +let sqlInitTimeEnd = 0; +// dbDecryptedKey (unencrypted DB key) +let dbDecryptedKey = null; +// other stuff (?) +let appStartInitialSpellcheckSetting = true; +let windowConfig = windowFromEphemeral || windowFromUserConfig; +// are you readyyy? :) +let ready = false; + +// needed globally crazy stuff +let appLocale = null; +let installPath = null; +let userDataPath = null; + +// sqlInitPromise used literally everywhere | linked to initializeSQL(); +let sqlInitPromise = null; + +/** + * Sets permissions, addhandlers and so on + * introduced by ksaadDE for readability and stability. + */ +async function doInitBeforeInit(logger){ + appLocale = process.env.NODE_ENV === 'test' ? 'en' : app.getLocale(); + userDataPath = await getRealPath(app.getPath('userData')); + installPath = await getRealPath(app.getAppPath()); + + let x = await loadLocales(appLocale, logger); + console.log("loadLocales:" + x); + + GlobalErrors.addHandler(); + + // Set umask early on in the process lifecycle to ensure file permissions are + // set such that only we have read access to our files + process.umask(0o077); + + // Note by ksaadDE: I'm really unsure why this is exactly here. Somewhere else would be a bit better, since function definitions coming "always" first! + console.log('Set Windows Application User Model ID (AUMID)', { + appUserModelId, + }); + app.setAppUserModelId(appUserModelId); +} + +function getMainWindow() { + return mainWindow; +} + async function getSpellCheckSetting() { const fastValue = ephemeralConfig.get('spell-check'); if (fastValue !== undefined) { @@ -215,20 +311,11 @@ if (!process.mas) { } } -const windowFromUserConfig = userConfig.get('window'); -const windowFromEphemeral = ephemeralConfig.get('window'); -let windowConfig = windowFromEphemeral || windowFromUserConfig; if (windowFromUserConfig) { userConfig.set('window', null); ephemeralConfig.set('window', windowConfig); } -const loadLocale = require('./app/locale').load; - -// Both of these will be set after app fires the 'ready' event -let logger; -let locale; - function prepareFileUrl( pathSegments /* : ReadonlyArray */, moreKeys /* : undefined | Record */ @@ -312,12 +399,6 @@ function handleCommonWindowEvents(window) { }); } -const DEFAULT_WIDTH = 800; -const DEFAULT_HEIGHT = 610; -const MIN_WIDTH = 680; -const MIN_HEIGHT = 550; -const BOUNDS_BUFFER = 100; - function isVisible(window, bounds) { const boundsX = _.get(bounds, 'x') || 0; const boundsY = _.get(bounds, 'y') || 0; @@ -343,8 +424,6 @@ function isVisible(window, bounds) { ); } -let windowIcon; - if (OS.isWindows()) { windowIcon = path.join(__dirname, 'build', 'icons', 'win', 'icon.ico'); } else if (OS.isLinux()) { @@ -579,9 +658,6 @@ async function createWindow() { mainWindow.once('ready-to-show', async () => { console.log('main window is ready-to-show'); - // Ignore sql errors and show the window anyway - await sqlInitPromise; - if (!mainWindow) { return; } @@ -594,21 +670,6 @@ async function createWindow() { }); } -// Renderer asks if we are done with the database -ipc.on('database-ready', async event => { - const { error } = await sqlInitPromise; - if (error) { - console.log( - 'database-ready requested, but got sql error', - error && error.stack - ); - return; - } - - console.log('sending `database-ready`'); - event.sender.send('database-ready'); -}); - ipc.on('show-window', () => { showWindow(); }); @@ -646,7 +707,6 @@ ipc.on('title-bar-double-click', () => { } }); -let isReadyForUpdates = false; async function readyForUpdates() { if (isReadyForUpdates) { return; @@ -673,42 +733,8 @@ async function readyForUpdates() { ipc.once('ready-for-updates', readyForUpdates); -const TEN_MINUTES = 10 * 60 * 1000; setTimeout(readyForUpdates, TEN_MINUTES); -// the support only provides a subset of languages available within the app -// so we have to list them out here and fallback to english if not included - -const SUPPORT_LANGUAGES = [ - 'ar', - 'bn', - 'de', - 'en-us', - 'es', - 'fr', - 'hi', - 'hi-in', - 'hc', - 'id', - 'it', - 'ja', - 'ko', - 'mr', - 'ms', - 'nl', - 'pl', - 'pt', - 'ru', - 'sv', - 'ta', - 'te', - 'tr', - 'uk', - 'ur', - 'vi', - 'zh-cn', - 'zh-tw', -]; function openContactUs() { const userLanguage = app.getLocale(); @@ -761,7 +787,6 @@ function setupAsStandalone() { } } -let screenShareWindow; function showScreenShareWindow(sourceName) { if (screenShareWindow) { screenShareWindow.show(); @@ -816,7 +841,6 @@ function showScreenShareWindow(sourceName) { }); } -let aboutWindow; function showAbout() { if (aboutWindow) { aboutWindow.show(); @@ -856,7 +880,6 @@ function showAbout() { }); } -let settingsWindow; function showSettingsWindow() { if (settingsWindow) { settingsWindow.show(); @@ -924,7 +947,6 @@ async function getIsLinked() { } } -let stickerCreatorWindow; async function showStickerCreator() { if (!(await getIsLinked())) { const { message } = locale.messages[ @@ -995,7 +1017,6 @@ async function showStickerCreator() { }); } -let debugLogWindow; async function showDebugLogWindow() { if (debugLogWindow) { debugLogWindow.show(); @@ -1043,7 +1064,6 @@ async function showDebugLogWindow() { }); } -let permissionsPopupWindow; function showPermissionsPopupWindow(forCalling, forCamera) { // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { @@ -1104,7 +1124,6 @@ function showPermissionsPopupWindow(forCalling, forCamera) { }); } -let captchaWindow; function showCaptchaWindow() { if (captchaWindow) { captchaWindow.show(); @@ -1145,78 +1164,159 @@ ipc.on('captcha-required', () => { showCaptchaWindow(); }); + /* + ==== + Password Prompt Start + Added by ksaadDE | Aug 2021 + ==== + */ +function doPasswordValidation (password) { + if (password === null || password === undefined) return 'data.error.nopwentered_or_abort'; + if (password.length < 20) return 'data.error.pwshort'; + if (password.trim().length < 20) return 'data.error.pwwhitespace'; + if (password.length > 128) return 'data.error.pwlong'; + return 'data.success'; +} + +function checkConfigPassword(password) { + let dbKey = userConfig.get('key'); + + if (!dbKey) { + // copied old code from above, edited the message for clarity ;p + console.log('key/initialize: Generating new encryption key, since we did not find it in config.json'); + dbKey = crypto.randomBytes(32).toString('hex'); // https://www.zetetic.net/sqlcipher/sqlcipher-api/#key + + // the dbKey here is not encrypted yet, that's why false + userConfig.set('usesPassword', false); + } + + if (userConfig.get('usesPassword') === true) { + // since usesPassword is already set to true, the dbKey (key in config.json) is encrypted, so we need to decrypt it now + let realKey = CryptoJS.AES.decrypt(dbKey, password).toString(CryptoJS.enc.Utf8); + dbDecryptedKey = realKey; + } else { + // usesPassword is set to false, the dbKey (key in config.json) is not encrypted yet, this is done here + let encryptedDBKey = CryptoJS.AES.encrypt(dbKey, password).toString(); + userConfig.set('usesPassword', true); + userConfig.set('key', encryptedDBKey); + dbDecryptedKey = dbKey; + } + + return dbDecryptedKey; +} + +async function showPasswordPrompt(){ + let labelText = 'no yet'; + pw='your password'; + + // load the correct translation, depending if the user already has set a encrypt password or not! + if ( userConfig.get('usesPassword') !== true ) { + // here the user has NOT set a encryption password yet + labelText = locale.messages.userPasswordRequiredNoKeyExisting.message; //'Please set a NEW encryption password! :-)'; + } else { + // here the user HAS set a enc pw + labelText = locale.messages.userPasswordRequiredAlreadyKeyExisting.message; //'Please enter your encryption password! :-)'; + } + + let x = await prompt({ + title: 'Signal Password Window', + label: labelText, + value: pw, + inputAttrs: { + type: 'text' + }, + type: 'input' + }); + return x; +} + +async function askAgainForPassword() { + let unlockDBPassword = null; + let pwvalidation = null; + let password = null; + + try { + + password = await showPasswordPrompt(""); + pwvalidation = doPasswordValidation(password); + + if(pwvalidation == 'data.error.nopwentered_or_abort') { + // aborting + console.log("closing due to user requested abort of password prompt | exitcode: 1337"); + app.exit(1337); + } + + if(pwvalidation != 'data.success') { + return await askAgainForPassword(); + } + + unlockDBPassword = checkConfigPassword(password).toString(); + + if (unlockDBPassword == undefined || unlockDBPassword.length == 0 || unlockDBPassword == null) { + return await askAgainForPassword(); + } + + } catch (error) { + + console.log(error); + unlockDBPassword = undefined; + + } + return unlockDBPassword; +} + + async function initializeSQL() { const userDataPath = await getRealPath(app.getPath('userData')); - let key = userConfig.get('key'); - if (!key) { - console.log( - 'key/initialize: Generating new encryption key, since we did not find it on disk' - ); - // https://www.zetetic.net/sqlcipher/sqlcipher-api/#key - key = crypto.randomBytes(32).toString('hex'); - userConfig.set('key', key); + let unlockDBPassword = await askAgainForPassword(); + + if (unlockDBPassword === null || unlockDBPassword === undefined){ + console.log("sqlInit: failed, password prompt aborted!"); + app.exit(1); } sqlInitTimeStart = Date.now(); try { - await sql.initialize({ + console.log ("sqlInit: Trying to unlock and load DB! <3"); + return await sql.initialize({ configDir: userDataPath, - key, + key: unlockDBPassword, }); } catch (error) { + console.log("sqlInit: Unlock or loading failed :/"); return { ok: false, error }; } finally { sqlInitTimeEnd = Date.now(); } - - return { ok: true }; } -const sqlInitPromise = initializeSQL(); - -// This method will be called when Electron has finished -// initialization and is ready to create browser windows. -// Some APIs can only be used after this event occurs. -let ready = false; -app.on('ready', async () => { - const startTime = Date.now(); - - // We use this event only a single time to log the startup time of the app - // from when it's first ready until the loading screen disappears. - ipc.once('signal-app-loaded', (event, info) => { - const { preloadTime, connectTime, processedCount } = info; + /* + ==== + Password Prompt END + ==== + */ - const loadTime = Date.now() - startTime; - const sqlInitTime = sqlInitTimeEnd - sqlInitTimeStart; +async function loadLocales(appLocale, logger){ + if (!locale) { + locale = loadLocale({ appLocale, logger }); + } - const messageTime = loadTime - preloadTime - connectTime; - const messagesPerSec = (processedCount * 1000) / messageTime; + GlobalErrors.updateLocale(locale.messages); - console.log('App loaded - time:', loadTime); - console.log('SQL init - time:', sqlInitTime); - console.log('Preload - time:', preloadTime); - console.log('WebSocket connect - time:', connectTime); - console.log('Processed count:', processedCount); - console.log('Messages per second:', messagesPerSec); + return locale.messages; +} - if (enableCI) { - console._log( - 'ci: app_loaded=%s', - JSON.stringify({ - loadTime, - sqlInitTime, - preloadTime, - connectTime, - processedCount, - messagesPerSec, - }) - ); - } - }); +/* + This method will be called when Electron has finished; + initialization and is ready to create browser windows. + Some APIs can only be used after this event occurs +*/ +app.on('ready', async () => { + logger = await logging.initialize(); + await doInitBeforeInit(logger); - const userDataPath = await getRealPath(app.getPath('userData')); - const installPath = await getRealPath(app.getAppPath()); + sqlInitPromise = await initializeSQL(); if (process.env.NODE_ENV !== 'test' && process.env.NODE_ENV !== 'test-lib') { installFileHandler({ @@ -1231,10 +1331,9 @@ app.on('ready', async () => { enableHttp: config.enableHttp, protocol: electronProtocol, }); - + installPermissionsHandler({ session, userConfig }); - - logger = await logging.initialize(); + logger.info('app ready'); logger.info(`starting version ${packageJson.version}`); @@ -1256,12 +1355,39 @@ app.on('ready', async () => { ); } - if (!locale) { - const appLocale = process.env.NODE_ENV === 'test' ? 'en' : app.getLocale(); - locale = loadLocale({ appLocale, logger }); - } - GlobalErrors.updateLocale(locale.messages); + // We use this event only a single time to log the startup time of the app + // from when it's first ready until the loading screen disappears. + ipc.once('signal-app-loaded', (event, info) => { + const { preloadTime, connectTime, processedCount } = info; + + const loadTime = Date.now() - startTime; + const sqlInitTime = sqlInitTimeEnd - sqlInitTimeStart; + + const messageTime = loadTime - preloadTime - connectTime; + const messagesPerSec = (processedCount * 1000) / messageTime; + + console.log('App loaded - time:', loadTime); + console.log('SQL init - time:', sqlInitTime); + console.log('Preload - time:', preloadTime); + console.log('WebSocket connect - time:', connectTime); + console.log('Processed count:', processedCount); + console.log('Messages per second:', messagesPerSec); + + if (enableCI) { + console._log( + 'ci: app_loaded=%s', + JSON.stringify({ + loadTime, + sqlInitTime, + preloadTime, + connectTime, + processedCount, + messagesPerSec, + }) + ); + } + }); // If the sql initialization takes more than three seconds to complete, we // want to notify the user that things are happening @@ -1305,36 +1431,40 @@ app.on('ready', async () => { // Run window preloading in parallel with database initialization. await createWindow(); - const { error: sqlError } = await sqlInitPromise; - if (sqlError) { + // well the code was recalling sqlInit... why? note by ksaadDE (performance is now better!) + error = sqlInitPromise; + if (error) { console.log('sql.initialize was unsuccessful; returning early'); - const buttonIndex = dialog.showMessageBoxSync({ - buttons: [ - locale.messages.copyErrorAndQuit.message, - locale.messages.deleteAndRestart.message, - ], - defaultId: 0, - detail: redactAll(sqlError.stack), - message: locale.messages.databaseError.message, - noLink: true, - type: 'error', - }); + try { + const buttonIndex = dialog.showMessageBoxSync({ + buttons: [ + locale.messages.copyErrorAndQuit.message, + locale.messages.deleteAndRestart.message, + ], + defaultId: 0, + detail: redactAll(sqlError.stack), + message: locale.messages.databaseError.message, + noLink: true, + type: 'error', + }); - if (buttonIndex === 0) { - clipboard.writeText( - `Database startup error:\n\n${redactAll(sqlError.stack)}` - ); - } else { - await sql.sqlCall('removeDB', []); - removeUserConfig(); - app.relaunch(); + if (buttonIndex === 0) { + clipboard.writeText( + `Database startup error:\n\n${redactAll(sqlError.stack)}` + ); + } else { + await sql.sqlCall('removeDB', []); + removeUserConfig(); + app.relaunch(); + } + } catch (error) { + console.log(error); } - app.exit(1); return; } - + // eslint-disable-next-line more/no-then appStartInitialSpellcheckSetting = await getSpellCheckSetting(); await sqlChannels.initialize(sql); @@ -1748,6 +1878,12 @@ installSettingsGetter('sync-request'); installSettingsGetter('sync-time'); installSettingsSetter('sync-time'); +ipc.on('database-ready', () => { + if (mainWindow && mainWindow.webContents) { + mainWindow.webContents.send('database-ready'); + } +}); + ipc.on('delete-all-data', () => { if (mainWindow && mainWindow.webContents) { mainWindow.webContents.send('delete-all-data'); @@ -1775,7 +1911,7 @@ ipc.on('locale-data', event => { ipc.on('user-config-key', event => { // eslint-disable-next-line no-param-reassign - event.returnValue = userConfig.get('key'); + event.returnValue = dbDecryptedKey; //userConfig.get('key'); }); ipc.on('get-user-data-path', event => { @@ -1919,4 +2055,4 @@ async function ensureFilePermissions(onlyFiles) { await q.onEmpty(); console.log(`Finish ensuring permissions in ${Date.now() - start}ms`); -} +} \ No newline at end of file diff --git a/package.json b/package.json index 3082934a4b..cc85f0dec9 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,9 @@ "classnames": "2.2.5", "config": "1.28.1", "copy-text-to-clipboard": "2.1.0", + "crypto-js": "^4.1.1", "dashdash": "1.14.1", + "electron-prompt": "^1.6.2", "emoji-datasource": "6.0.0", "emoji-datasource-apple": "6.0.0", "emoji-regex": "9.2.0", @@ -416,7 +418,9 @@ "permissions_popup_preload.js", "debug_log_preload.js", "loading_preload.js", + "userPasswordPrompt.js", "main.js", + "mainPasswordPrompt.js", "images/**", "fonts/**", "sounds/*", diff --git a/package.json.oldold b/package.json.oldold new file mode 100644 index 0000000000..0651b9e664 --- /dev/null +++ b/package.json.oldold @@ -0,0 +1,464 @@ +{ + "name": "signal-desktop", + "productName": "Signal", + "description": "Private messaging from your desktop", + "desktopName": "signal.desktop", + "repository": "https://github.com/signalapp/Signal-Desktop.git", + "version": "5.3.0-beta.1", + "license": "AGPL-3.0-only", + "author": { + "name": "Open Whisper Systems", + "email": "support@signal.org" + }, + "main": "mainPasswordPrompt.js", + "scripts": { + "postinstall": "yarn build:acknowledgments && yarn build:fuses && snyk protect && patch-package && electron-builder install-app-deps && rimraf node_modules/dtrace-provider", + "postuninstall": "yarn build:acknowledgments", + "start": "electron .", + "grunt": "grunt", + "generate": "yarn grunt", + "build-release": "yarn run build", + "sign-release": "node ts/updater/generateSignature.js", + "notarize": "node ts/build/notarize.js", + "build-module-protobuf": "pbjs --target static-module --wrap commonjs --out ts/protobuf/compiled.js protos/*.proto && pbts --out ts/protobuf/compiled.d.ts ts/protobuf/compiled.js", + "clean-module-protobuf": "rm -f ts/protobuf/compiled.d.ts ts/protobuf/compiled.js", + "build-protobuf": "yarn build-module-protobuf", + "clean-protobuf": "yarn clean-module-protobuf", + "prepare-beta-build": "node prepare_beta_build.js", + "prepare-import-build": "node prepare_import_build.js", + "publish-to-apt": "NAME=$npm_package_name VERSION=$npm_package_version ./aptly.sh", + "test": "yarn test-node && yarn test-electron", + "test-electron": "yarn grunt test", + "test-node": "electron-mocha --file test/setup-test-node.js --recursive test/app test/modules ts/test-node ts/test-both", + "test-node-coverage": "nyc --reporter=lcov --reporter=text mocha --recursive test/app test/modules ts/test-node ts/test-both", + "eslint": "eslint --cache .", + "lint": "yarn format --list-different && yarn eslint", + "lint-deps": "node ts/util/lint/linter.js", + "lint-license-comments": "ts-node ts/util/lint/license_comments.ts", + "format": "prettier --write \"*.{css,js,json,md,scss,ts,tsx}\" \"./**/*.{css,js,json,md,scss,ts,tsx}\"", + "transpile": "tsc", + "clean-transpile": "rimraf ts/**/*.js && rimraf ts/**/*.js && rimraf ts/*.js && rimraf ts/*.js && rimraf tsconfig.tsbuildinfo && rimraf tsconfig.tsbuildinfo", + "open-coverage": "open coverage/lcov-report/index.html", + "ready": "npm-run-all --print-label clean-transpile grunt --parallel lint lint-deps test-node test-electron", + "dev": "run-p --print-label dev:*", + "dev:grunt": "yarn grunt dev", + "dev:transpile": "yarn run transpile --watch --preserveWatchOutput", + "dev:webpack": "cross-env NODE_ENV=development webpack serve --mode development", + "dev:typed-scss": "yarn build:typed-scss -w", + "dev:storybook": "cross-env SIGNAL_ENV=storybook start-storybook -p 6006 -s ./", + "storybook:axe": "build-storybook && axe-storybook", + "build": "run-s --print-label build:grunt build:typed-scss build:webpack build:release build:zip", + "build:acknowledgments": "node scripts/generate-acknowledgments.js", + "build:dev": "run-s --print-label build:grunt build:typed-scss build:webpack", + "build:grunt": "yarn grunt", + "build:typed-scss": "tsm sticker-creator", + "build:webpack": "run-p build:webpack:sticker-creator build:webpack:preload build:webpack:sql-worker", + "build:webpack:sticker-creator": "cross-env NODE_ENV=production webpack", + "build:webpack:preload": "cross-env NODE_ENV=production webpack -c webpack-preload.config.ts", + "build:webpack:sql-worker": "cross-env NODE_ENV=production webpack -c webpack-sql-worker.config.ts", + "build:electron": "electron-builder --config.extraMetadata.environment=$SIGNAL_ENV", + "build:release": "cross-env SIGNAL_ENV=production yarn build:electron -- --config.directories.output=release", + "build:fuses": "node scripts/fuse-electron.js", + "build:zip": "node scripts/zip-macos-release.js", + "preverify:ts": "yarn build:typed-scss", + "verify": "run-p --print-label verify:*", + "verify:ts": "tsc --noEmit" + }, + "optionalDependencies": { + "fs-xattr": "0.3.0" + }, + "dependencies": { + "@signalapp/signal-client": "0.5.2", + "@sindresorhus/is": "0.8.0", + "@types/pino": "6.3.6", + "@types/pino-multi-stream": "5.1.0", + "abort-controller": "3.0.0", + "array-move": "2.1.0", + "axe-core": "4.1.4", + "backbone": "1.3.3", + "better-sqlite3": "https://github.com/signalapp/better-sqlite3#2fa02d2484e9f9a10df5ac7ea4617fb2dff30006", + "blob-util": "1.3.0", + "blueimp-canvas-to-blob": "3.14.0", + "blueimp-load-image": "5.14.0", + "blurhash": "1.1.3", + "classnames": "2.2.5", + "config": "1.28.1", + "copy-text-to-clipboard": "2.1.0", + "crypto-js": "^4.1.1", + "dashdash": "1.14.1", + "emoji-datasource": "6.0.0", + "emoji-datasource-apple": "6.0.0", + "emoji-regex": "9.2.0", + "encoding": "0.1.13", + "fast-glob": "3.2.1", + "filesize": "3.6.1", + "firstline": "1.2.1", + "form-data": "3.0.0", + "fs-extra": "5.0.0", + "fuse.js": "3.4.4", + "glob": "7.1.6", + "google-libphonenumber": "3.2.17", + "got": "8.3.2", + "history": "4.9.0", + "humanize-duration": "3.26.0", + "intl-tel-input": "12.1.15", + "jquery": "3.5.0", + "js-yaml": "3.13.1", + "linkify-it": "2.2.0", + "lodash": "4.17.21", + "lru-cache": "6.0.0", + "mac-screen-capture-permissions": "2.0.0", + "memoizee": "0.4.14", + "mkdirp": "0.5.2", + "moment": "2.29.1", + "mustache": "2.3.0", + "node-fetch": "2.6.1", + "node-forge": "0.10.0", + "normalize-path": "3.0.0", + "os-locale": "3.0.1", + "p-map": "2.1.0", + "p-props": "4.0.0", + "p-queue": "6.2.1", + "parchment": "1.1.4", + "pify": "3.0.0", + "pino": "6.11.1", + "pino-multi-stream": "5.3.0", + "popper.js": "1.15.0", + "protobufjs": "6.10.2", + "proxy-agent": "4.0.1", + "quill": "1.3.7", + "quill-delta": "4.0.1", + "react": "16.8.3", + "react-blurhash": "0.1.2", + "react-contextmenu": "2.11.0", + "react-dom": "16.8.3", + "react-dropzone": "10.1.7", + "react-hot-loader": "4.12.11", + "react-measure": "2.3.0", + "react-popper": "1.3.7", + "react-quill": "2.0.0-beta.2", + "react-redux": "7.1.0", + "react-router-dom": "5.0.1", + "react-sortable-hoc": "1.9.1", + "react-virtualized": "9.21.0", + "read-last-lines": "1.8.0", + "redux": "4.0.1", + "redux-logger": "3.0.6", + "redux-promise-middleware": "6.1.0", + "redux-thunk": "2.3.0", + "redux-ts-utils": "3.2.2", + "reselect": "4.0.0", + "rimraf": "2.6.2", + "ringrtc": "https://github.com/signalapp/signal-ringrtc-node.git#17b22fc9d47605867608193202c54be06bce6f56", + "rotating-file-stream": "2.1.5", + "sanitize-filename": "1.6.3", + "sanitize.css": "11.0.0", + "semver": "5.4.1", + "sharp": "0.28.1", + "tar": "4.4.8", + "testcheck": "1.0.0-rc.2", + "tmp": "0.0.33", + "to-arraybuffer": "1.0.1", + "typeface-inter": "3.10.0", + "underscore": "1.12.1", + "uuid": "3.3.2", + "websocket": "1.0.28", + "zkgroup": "https://github.com/signalapp/signal-zkgroup-node.git#7ecf70be85e5a485ec870c1723b1c6247b9d549e", + "zod": "1.11.13" + }, + "devDependencies": { + "@babel/core": "7.7.7", + "@babel/plugin-proposal-class-properties": "7.7.4", + "@babel/plugin-proposal-optional-chaining": "7.13.8", + "@babel/plugin-transform-runtime": "7.8.3", + "@babel/preset-react": "7.7.4", + "@babel/preset-typescript": "7.7.7", + "@chanzuckerberg/axe-storybook-testing": "3.0.2", + "@electron/fuses": "1.0.1", + "@storybook/addon-actions": "5.1.11", + "@storybook/addon-knobs": "5.1.11", + "@storybook/addons": "5.1.11", + "@storybook/react": "5.1.11", + "@types/backbone": "1.4.3", + "@types/better-sqlite3": "5.4.1", + "@types/blueimp-load-image": "5.14.1", + "@types/chai": "4.2.18", + "@types/chai-as-promised": "7.1.4", + "@types/classnames": "2.2.3", + "@types/config": "0.0.34", + "@types/dashdash": "1.14.0", + "@types/filesize": "3.6.0", + "@types/fs-extra": "5.0.5", + "@types/google-libphonenumber": "7.4.14", + "@types/got": "9.4.1", + "@types/history": "4.7.2", + "@types/humanize-duration": "^3.18.1", + "@types/jquery": "3.5.0", + "@types/js-yaml": "3.12.0", + "@types/linkify-it": "2.1.0", + "@types/lodash": "4.14.106", + "@types/long": "4.0.1", + "@types/lru-cache": "5.1.0", + "@types/memoizee": "0.4.2", + "@types/mkdirp": "0.5.2", + "@types/mocha": "5.0.0", + "@types/node": "14.14.37", + "@types/node-fetch": "2.5.7", + "@types/node-forge": "0.9.5", + "@types/normalize-path": "3.0.0", + "@types/pify": "3.0.2", + "@types/quill": "1.3.10", + "@types/react": "16.8.5", + "@types/react-dom": "16.8.2", + "@types/react-measure": "2.0.5", + "@types/react-redux": "7.1.2", + "@types/react-router-dom": "4.3.4", + "@types/react-sortable-hoc": "0.6.5", + "@types/react-virtualized": "9.18.12", + "@types/redux-logger": "3.0.7", + "@types/rimraf": "2.0.2", + "@types/semver": "5.5.0", + "@types/sharp": "0.28.0", + "@types/sinon": "9.0.8", + "@types/storybook__addon-actions": "3.4.3", + "@types/storybook__addon-knobs": "5.0.3", + "@types/storybook__react": "4.0.2", + "@types/terser-webpack-plugin": "5.0.3", + "@types/underscore": "1.10.3", + "@types/uuid": "3.4.4", + "@types/webpack-dev-server": "3.11.3", + "@types/websocket": "1.0.0", + "@typescript-eslint/eslint-plugin": "4.8.1", + "@typescript-eslint/parser": "4.8.1", + "arraybuffer-loader": "1.0.3", + "asar": "0.14.0", + "babel-core": "7.0.0-bridge.0", + "babel-loader": "8.0.6", + "babel-plugin-lodash": "3.3.4", + "chai": "4.3.4", + "chai-as-promised": "7.1.1", + "core-js": "2.6.9", + "cross-env": "5.2.0", + "css-loader": "3.2.0", + "electron": "12.0.7", + "electron-builder": "22.10.5", + "electron-mocha": "8.1.1", + "electron-notarize": "0.1.1", + "eslint": "7.7.0", + "eslint-config-airbnb-typescript-prettier": "3.1.0", + "eslint-config-prettier": "6.11.0", + "eslint-plugin-import": "2.22.0", + "eslint-plugin-mocha": "8.0.0", + "eslint-plugin-more": "1.0.0", + "eslint-plugin-react": "7.20.6", + "file-loader": "4.2.0", + "grunt": "1.4.0", + "grunt-cli": "1.2.0", + "grunt-contrib-concat": "1.0.1", + "grunt-contrib-copy": "1.0.0", + "grunt-contrib-watch": "1.0.0", + "grunt-exec": "3.0.0", + "grunt-gitinfo": "0.1.7", + "grunt-sass": "3.0.1", + "html-webpack-plugin": "5.3.1", + "jsdoc": "3.6.2", + "mocha": "4.1.0", + "mocha-testcheck": "1.0.0-rc.0", + "node-gyp": "^6.1.0", + "node-sass": "4.14.1", + "node-sass-import-once": "1.2.0", + "npm-run-all": "4.1.5", + "nyc": "11.4.1", + "patch-package": "6.1.2", + "prettier": "^2.2.1", + "react-docgen-typescript": "1.2.6", + "sass-loader": "7.2.0", + "sinon": "9.2.4", + "snyk": "1.316.1", + "spectron": "5.0.0", + "style-loader": "1.0.0", + "terser-webpack-plugin": "5.1.1", + "ts-loader": "4.1.0", + "ts-node": "8.3.0", + "typed-scss-modules": "0.0.11", + "typescript": "4.1.3", + "webpack": "5.30.0", + "webpack-cli": "4.6.0", + "webpack-dev-server": "3.11.2" + }, + "resolutions": { + "@storybook/react/@storybook/core/node-fetch": "2.6.1", + "fast-glob/glob-parent": "5.1.2", + "read-last-lines/mz/thenify-all/thenify": "3.3.1", + "sharp/color/color-string": "1.5.5", + "zkgroup/ref-napi/node-addon-api": "2.0.1", + "zkgroup/ffi-napi/ref-napi/node-addon-api": "2.0.1", + "zkgroup/ref-array-napi/ref-napi/node-addon-api": "2.0.1" + }, + "engines": { + "node": "14.16.0" + }, + "build": { + "appId": "org.whispersystems.signal-desktop", + "mac": { + "asarUnpack": [ + "**/*.node", + "node_modules/zkgroup/libzkgroup.*", + "node_modules/@signalapp/signal-client/build/*.node", + "node_modules/mac-screen-capture-permissions/build/Release/*.node" + ], + "artifactName": "${name}-mac-${version}.${ext}", + "category": "public.app-category.social-networking", + "darkModeSupport": true, + "hardenedRuntime": true, + "entitlements": "./build/entitlements.mac.plist", + "icon": "build/icons/mac/icon.icns", + "publish": [ + { + "provider": "generic", + "url": "https://updates.signal.org/desktop" + } + ], + "target": [ + "zip", + "dmg" + ], + "bundleVersion": "1" + }, + "win": { + "asarUnpack": [ + "**/*.node", + "node_modules/spellchecker/vendor/hunspell_dictionaries", + "node_modules/sharp", + "node_modules/zkgroup/libzkgroup.*", + "node_modules/@signalapp/signal-client/build/*.node" + ], + "artifactName": "${name}-win-${version}.${ext}", + "certificateSubjectName": "Signal (Quiet Riddle Ventures, LLC)", + "certificateSha1": "77B2AA4421E5F377454B8B91E573746592D1543D", + "publisherName": "Signal (Quiet Riddle Ventures, LLC)", + "icon": "build/icons/win/icon.ico", + "publish": [ + { + "provider": "generic", + "url": "https://updates.signal.org/desktop" + } + ], + "target": [ + "nsis" + ] + }, + "nsis": { + "deleteAppDataOnUninstall": true + }, + "linux": { + "category": "Network;InstantMessaging;Chat", + "desktop": { + "StartupWMClass": "Signal" + }, + "asarUnpack": [ + "**/*.node", + "node_modules/spellchecker/vendor/hunspell_dictionaries", + "node_modules/sharp", + "node_modules/zkgroup/libzkgroup.*", + "node_modules/@signalapp/signal-client/build/*.node" + ], + "target": [ + "deb" + ], + "icon": "build/icons/png" + }, + "deb": { + "depends": [ + "libnotify4", + "libxtst6", + "libnss3", + "libasound2", + "libxss1" + ] + }, + "protocols": { + "name": "sgnl-url-scheme", + "schemes": [ + "sgnl", + "signalcaptcha" + ] + }, + "asarUnpack": [ + "ts/sql/mainWorker.bundle.js", + "node_modules/better-sqlite3/build/Release/better_sqlite3.node" + ], + "files": [ + "package.json", + "config/default.json", + "config/${env.SIGNAL_ENV}.json", + "config/local-${env.SIGNAL_ENV}.json", + "background.html", + "about.html", + "screenShare.html", + "settings.html", + "permissions_popup.html", + "debug_log.html", + "loading.html", + "_locales/**", + "protos/*", + "js/**", + "libtextsecure/**", + "ts/**/*.js", + "ts/*.js", + "stylesheets/*.css", + "!js/register.js", + "app/*", + "preload.bundle.js", + "preload_utils.js", + "about_preload.js", + "screenShare_preload.js", + "settings_preload.js", + "permissions_popup_preload.js", + "debug_log_preload.js", + "loading_preload.js", + "userPasswordPrompt.js", + "main.js", + "mainPasswordPrompt.js", + "images/**", + "fonts/**", + "sounds/*", + "build/icons", + "node_modules/**", + "sticker-creator/preload.js", + "sticker-creator/dist/**", + "!node_modules/emoji-datasource/emoji_pretty.json", + "!node_modules/emoji-datasource/**/*.png", + "!node_modules/emoji-datasource-apple/emoji_pretty.json", + "!node_modules/emoji-datasource-apple/img/apple/sheets*", + "!node_modules/spellchecker/vendor/hunspell/**/*", + "!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme,test,__tests__,tests,powered-test,example,examples,*.d.ts,.snyk-*.flag,benchmark}", + "!**/node_modules/.bin", + "!**/node_modules/**/build/**", + "!**/*.{o,hprof,orig,pyc,pyo,rbc}", + "!**/._*", + "!**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,__pycache__,thumbs.db,.gitignore,.gitattributes,.flowconfig,.yarn-metadata.json,.idea,appveyor.yml,.travis.yml,circle.yml,npm-debug.log,.nyc_output,yarn.lock,.yarn-integrity}", + "node_modules/spellchecker/build/Release/*.node", + "node_modules/websocket/build/Release/*.node", + "!node_modules/websocket/builderror.log", + "node_modules/ref-napi/build/Release/*.node", + "node_modules/ref-array-napi/node_modules/ref-napi/build/Release/*.node", + "node_modules/ffi-napi/build/Release/*.node", + "node_modules/socks/build/*.js", + "node_modules/socks/build/common/*.js", + "node_modules/socks/build/client/*.js", + "node_modules/smart-buffer/build/*.js", + "node_modules/sharp/build/**", + "!node_modules/sharp/{install,src,vendor/include,vendor/*/include}", + "!node_modules/better-sqlite3/deps/*", + "!node_modules/better-sqlite3/src/*", + "node_modules/better-sqlite3/build/Release/better_sqlite3.node", + "node_modules/@signalapp/signal-client/build/*${platform}*.node", + "node_modules/ringrtc/build/${platform}/**", + "node_modules/mac-screen-capture-permissions/build/Release/*.node", + "!**/node_modules/ffi-napi/deps", + "!**/node_modules/react-dom/*/*.development.js", + "!node_modules/.cache" + ] + } +} diff --git a/preload.js b/preload.js index 1274354a6f..5399c078ba 100644 --- a/preload.js +++ b/preload.js @@ -134,6 +134,12 @@ try { // eslint-disable-next-line no-eval, no-multi-assign window.eval = global.eval = () => null; + // when userPassword for decrypt of config.json database key is needed + window.userPasswordRequired = () => { + window.log.info('userPasswordRequired required'); + ipc.send('userpassword-required'); + }; + window.captchaRequired = () => { window.log.info('CAPTCHA required'); ipc.send('captcha-required'); diff --git a/yarn.lock b/yarn.lock index 04af50355d..37fb6be9b8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6037,6 +6037,11 @@ crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" +crypto-js@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" + integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== + crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" @@ -6657,6 +6662,13 @@ dns-txt@^2.0.2: dependencies: buffer-indexof "^1.0.0" +doc-ready@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/doc-ready/-/doc-ready-1.0.4.tgz#37f5391969cff994303fdfef2e5d50357f8164d3" + integrity sha1-N/U5GWnP+ZQwP9/vLl1QNX+BZNM= + dependencies: + eventie "^1" + dockerfile-ast@0.0.19: version "0.0.19" resolved "https://registry.yarnpkg.com/dockerfile-ast/-/dockerfile-ast-0.0.19.tgz#b1e21138eba995d7bf5576dc30ba1130c15995c3" @@ -6936,6 +6948,13 @@ electron-notarize@0.1.1: debug "^4.1.1" fs-extra "^8.0.1" +electron-prompt@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/electron-prompt/-/electron-prompt-1.6.2.tgz#e26bd3d359120bd45ce2f9625bdc380deb7ee269" + integrity sha512-gC9ZpMopIgz1kW92J7UfsXarkLdPH2zhr77bnJFlDSduYjRlr9nEPm4ux1vyzJsO72AdOyvuPPIQB0j+gWsncQ== + dependencies: + doc-ready "^1.0.4" + electron-publish@22.10.5: version "22.10.5" resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.10.5.tgz#9cbe46266b6c79d8c6e99840755682e2262d3543" @@ -7699,6 +7718,11 @@ eventemitter3@^4.0.0: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== +eventie@^1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/eventie/-/eventie-1.0.6.tgz#d4ffc8b0c2b5e493c2aa1b22cbe918d3aee74437" + integrity sha1-1P/IsMK15JPCqhsiy+kY067nRDc= + events@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" From 2cdc5db36831b4138ac1e62c4772ea20da8c5db6 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 15 Aug 2021 19:03:51 +0200 Subject: [PATCH 3/6] optimized start.sh, which uses nvm --- .gitignore | 3 +- package.json | 2 - package.json.oldold | 464 -------------------------------------------- start.sh | 26 +++ 4 files changed, 27 insertions(+), 468 deletions(-) delete mode 100644 package.json.oldold create mode 100755 start.sh diff --git a/.gitignore b/.gitignore index 0f42d3f4dc..35114b7bbf 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,6 @@ release/ .nyc_output/ *.sublime* /sql/ -/start.sh .eslintcache tsconfig.tsbuildinfo @@ -41,4 +40,4 @@ sticker-creator/dist/* preload.bundle.* ts/sql/mainWorker.bundle.js.LICENSE.txt -*.code-workspace \ No newline at end of file +*.code-workspace diff --git a/package.json b/package.json index cc85f0dec9..388426ed0f 100644 --- a/package.json +++ b/package.json @@ -418,9 +418,7 @@ "permissions_popup_preload.js", "debug_log_preload.js", "loading_preload.js", - "userPasswordPrompt.js", "main.js", - "mainPasswordPrompt.js", "images/**", "fonts/**", "sounds/*", diff --git a/package.json.oldold b/package.json.oldold deleted file mode 100644 index 0651b9e664..0000000000 --- a/package.json.oldold +++ /dev/null @@ -1,464 +0,0 @@ -{ - "name": "signal-desktop", - "productName": "Signal", - "description": "Private messaging from your desktop", - "desktopName": "signal.desktop", - "repository": "https://github.com/signalapp/Signal-Desktop.git", - "version": "5.3.0-beta.1", - "license": "AGPL-3.0-only", - "author": { - "name": "Open Whisper Systems", - "email": "support@signal.org" - }, - "main": "mainPasswordPrompt.js", - "scripts": { - "postinstall": "yarn build:acknowledgments && yarn build:fuses && snyk protect && patch-package && electron-builder install-app-deps && rimraf node_modules/dtrace-provider", - "postuninstall": "yarn build:acknowledgments", - "start": "electron .", - "grunt": "grunt", - "generate": "yarn grunt", - "build-release": "yarn run build", - "sign-release": "node ts/updater/generateSignature.js", - "notarize": "node ts/build/notarize.js", - "build-module-protobuf": "pbjs --target static-module --wrap commonjs --out ts/protobuf/compiled.js protos/*.proto && pbts --out ts/protobuf/compiled.d.ts ts/protobuf/compiled.js", - "clean-module-protobuf": "rm -f ts/protobuf/compiled.d.ts ts/protobuf/compiled.js", - "build-protobuf": "yarn build-module-protobuf", - "clean-protobuf": "yarn clean-module-protobuf", - "prepare-beta-build": "node prepare_beta_build.js", - "prepare-import-build": "node prepare_import_build.js", - "publish-to-apt": "NAME=$npm_package_name VERSION=$npm_package_version ./aptly.sh", - "test": "yarn test-node && yarn test-electron", - "test-electron": "yarn grunt test", - "test-node": "electron-mocha --file test/setup-test-node.js --recursive test/app test/modules ts/test-node ts/test-both", - "test-node-coverage": "nyc --reporter=lcov --reporter=text mocha --recursive test/app test/modules ts/test-node ts/test-both", - "eslint": "eslint --cache .", - "lint": "yarn format --list-different && yarn eslint", - "lint-deps": "node ts/util/lint/linter.js", - "lint-license-comments": "ts-node ts/util/lint/license_comments.ts", - "format": "prettier --write \"*.{css,js,json,md,scss,ts,tsx}\" \"./**/*.{css,js,json,md,scss,ts,tsx}\"", - "transpile": "tsc", - "clean-transpile": "rimraf ts/**/*.js && rimraf ts/**/*.js && rimraf ts/*.js && rimraf ts/*.js && rimraf tsconfig.tsbuildinfo && rimraf tsconfig.tsbuildinfo", - "open-coverage": "open coverage/lcov-report/index.html", - "ready": "npm-run-all --print-label clean-transpile grunt --parallel lint lint-deps test-node test-electron", - "dev": "run-p --print-label dev:*", - "dev:grunt": "yarn grunt dev", - "dev:transpile": "yarn run transpile --watch --preserveWatchOutput", - "dev:webpack": "cross-env NODE_ENV=development webpack serve --mode development", - "dev:typed-scss": "yarn build:typed-scss -w", - "dev:storybook": "cross-env SIGNAL_ENV=storybook start-storybook -p 6006 -s ./", - "storybook:axe": "build-storybook && axe-storybook", - "build": "run-s --print-label build:grunt build:typed-scss build:webpack build:release build:zip", - "build:acknowledgments": "node scripts/generate-acknowledgments.js", - "build:dev": "run-s --print-label build:grunt build:typed-scss build:webpack", - "build:grunt": "yarn grunt", - "build:typed-scss": "tsm sticker-creator", - "build:webpack": "run-p build:webpack:sticker-creator build:webpack:preload build:webpack:sql-worker", - "build:webpack:sticker-creator": "cross-env NODE_ENV=production webpack", - "build:webpack:preload": "cross-env NODE_ENV=production webpack -c webpack-preload.config.ts", - "build:webpack:sql-worker": "cross-env NODE_ENV=production webpack -c webpack-sql-worker.config.ts", - "build:electron": "electron-builder --config.extraMetadata.environment=$SIGNAL_ENV", - "build:release": "cross-env SIGNAL_ENV=production yarn build:electron -- --config.directories.output=release", - "build:fuses": "node scripts/fuse-electron.js", - "build:zip": "node scripts/zip-macos-release.js", - "preverify:ts": "yarn build:typed-scss", - "verify": "run-p --print-label verify:*", - "verify:ts": "tsc --noEmit" - }, - "optionalDependencies": { - "fs-xattr": "0.3.0" - }, - "dependencies": { - "@signalapp/signal-client": "0.5.2", - "@sindresorhus/is": "0.8.0", - "@types/pino": "6.3.6", - "@types/pino-multi-stream": "5.1.0", - "abort-controller": "3.0.0", - "array-move": "2.1.0", - "axe-core": "4.1.4", - "backbone": "1.3.3", - "better-sqlite3": "https://github.com/signalapp/better-sqlite3#2fa02d2484e9f9a10df5ac7ea4617fb2dff30006", - "blob-util": "1.3.0", - "blueimp-canvas-to-blob": "3.14.0", - "blueimp-load-image": "5.14.0", - "blurhash": "1.1.3", - "classnames": "2.2.5", - "config": "1.28.1", - "copy-text-to-clipboard": "2.1.0", - "crypto-js": "^4.1.1", - "dashdash": "1.14.1", - "emoji-datasource": "6.0.0", - "emoji-datasource-apple": "6.0.0", - "emoji-regex": "9.2.0", - "encoding": "0.1.13", - "fast-glob": "3.2.1", - "filesize": "3.6.1", - "firstline": "1.2.1", - "form-data": "3.0.0", - "fs-extra": "5.0.0", - "fuse.js": "3.4.4", - "glob": "7.1.6", - "google-libphonenumber": "3.2.17", - "got": "8.3.2", - "history": "4.9.0", - "humanize-duration": "3.26.0", - "intl-tel-input": "12.1.15", - "jquery": "3.5.0", - "js-yaml": "3.13.1", - "linkify-it": "2.2.0", - "lodash": "4.17.21", - "lru-cache": "6.0.0", - "mac-screen-capture-permissions": "2.0.0", - "memoizee": "0.4.14", - "mkdirp": "0.5.2", - "moment": "2.29.1", - "mustache": "2.3.0", - "node-fetch": "2.6.1", - "node-forge": "0.10.0", - "normalize-path": "3.0.0", - "os-locale": "3.0.1", - "p-map": "2.1.0", - "p-props": "4.0.0", - "p-queue": "6.2.1", - "parchment": "1.1.4", - "pify": "3.0.0", - "pino": "6.11.1", - "pino-multi-stream": "5.3.0", - "popper.js": "1.15.0", - "protobufjs": "6.10.2", - "proxy-agent": "4.0.1", - "quill": "1.3.7", - "quill-delta": "4.0.1", - "react": "16.8.3", - "react-blurhash": "0.1.2", - "react-contextmenu": "2.11.0", - "react-dom": "16.8.3", - "react-dropzone": "10.1.7", - "react-hot-loader": "4.12.11", - "react-measure": "2.3.0", - "react-popper": "1.3.7", - "react-quill": "2.0.0-beta.2", - "react-redux": "7.1.0", - "react-router-dom": "5.0.1", - "react-sortable-hoc": "1.9.1", - "react-virtualized": "9.21.0", - "read-last-lines": "1.8.0", - "redux": "4.0.1", - "redux-logger": "3.0.6", - "redux-promise-middleware": "6.1.0", - "redux-thunk": "2.3.0", - "redux-ts-utils": "3.2.2", - "reselect": "4.0.0", - "rimraf": "2.6.2", - "ringrtc": "https://github.com/signalapp/signal-ringrtc-node.git#17b22fc9d47605867608193202c54be06bce6f56", - "rotating-file-stream": "2.1.5", - "sanitize-filename": "1.6.3", - "sanitize.css": "11.0.0", - "semver": "5.4.1", - "sharp": "0.28.1", - "tar": "4.4.8", - "testcheck": "1.0.0-rc.2", - "tmp": "0.0.33", - "to-arraybuffer": "1.0.1", - "typeface-inter": "3.10.0", - "underscore": "1.12.1", - "uuid": "3.3.2", - "websocket": "1.0.28", - "zkgroup": "https://github.com/signalapp/signal-zkgroup-node.git#7ecf70be85e5a485ec870c1723b1c6247b9d549e", - "zod": "1.11.13" - }, - "devDependencies": { - "@babel/core": "7.7.7", - "@babel/plugin-proposal-class-properties": "7.7.4", - "@babel/plugin-proposal-optional-chaining": "7.13.8", - "@babel/plugin-transform-runtime": "7.8.3", - "@babel/preset-react": "7.7.4", - "@babel/preset-typescript": "7.7.7", - "@chanzuckerberg/axe-storybook-testing": "3.0.2", - "@electron/fuses": "1.0.1", - "@storybook/addon-actions": "5.1.11", - "@storybook/addon-knobs": "5.1.11", - "@storybook/addons": "5.1.11", - "@storybook/react": "5.1.11", - "@types/backbone": "1.4.3", - "@types/better-sqlite3": "5.4.1", - "@types/blueimp-load-image": "5.14.1", - "@types/chai": "4.2.18", - "@types/chai-as-promised": "7.1.4", - "@types/classnames": "2.2.3", - "@types/config": "0.0.34", - "@types/dashdash": "1.14.0", - "@types/filesize": "3.6.0", - "@types/fs-extra": "5.0.5", - "@types/google-libphonenumber": "7.4.14", - "@types/got": "9.4.1", - "@types/history": "4.7.2", - "@types/humanize-duration": "^3.18.1", - "@types/jquery": "3.5.0", - "@types/js-yaml": "3.12.0", - "@types/linkify-it": "2.1.0", - "@types/lodash": "4.14.106", - "@types/long": "4.0.1", - "@types/lru-cache": "5.1.0", - "@types/memoizee": "0.4.2", - "@types/mkdirp": "0.5.2", - "@types/mocha": "5.0.0", - "@types/node": "14.14.37", - "@types/node-fetch": "2.5.7", - "@types/node-forge": "0.9.5", - "@types/normalize-path": "3.0.0", - "@types/pify": "3.0.2", - "@types/quill": "1.3.10", - "@types/react": "16.8.5", - "@types/react-dom": "16.8.2", - "@types/react-measure": "2.0.5", - "@types/react-redux": "7.1.2", - "@types/react-router-dom": "4.3.4", - "@types/react-sortable-hoc": "0.6.5", - "@types/react-virtualized": "9.18.12", - "@types/redux-logger": "3.0.7", - "@types/rimraf": "2.0.2", - "@types/semver": "5.5.0", - "@types/sharp": "0.28.0", - "@types/sinon": "9.0.8", - "@types/storybook__addon-actions": "3.4.3", - "@types/storybook__addon-knobs": "5.0.3", - "@types/storybook__react": "4.0.2", - "@types/terser-webpack-plugin": "5.0.3", - "@types/underscore": "1.10.3", - "@types/uuid": "3.4.4", - "@types/webpack-dev-server": "3.11.3", - "@types/websocket": "1.0.0", - "@typescript-eslint/eslint-plugin": "4.8.1", - "@typescript-eslint/parser": "4.8.1", - "arraybuffer-loader": "1.0.3", - "asar": "0.14.0", - "babel-core": "7.0.0-bridge.0", - "babel-loader": "8.0.6", - "babel-plugin-lodash": "3.3.4", - "chai": "4.3.4", - "chai-as-promised": "7.1.1", - "core-js": "2.6.9", - "cross-env": "5.2.0", - "css-loader": "3.2.0", - "electron": "12.0.7", - "electron-builder": "22.10.5", - "electron-mocha": "8.1.1", - "electron-notarize": "0.1.1", - "eslint": "7.7.0", - "eslint-config-airbnb-typescript-prettier": "3.1.0", - "eslint-config-prettier": "6.11.0", - "eslint-plugin-import": "2.22.0", - "eslint-plugin-mocha": "8.0.0", - "eslint-plugin-more": "1.0.0", - "eslint-plugin-react": "7.20.6", - "file-loader": "4.2.0", - "grunt": "1.4.0", - "grunt-cli": "1.2.0", - "grunt-contrib-concat": "1.0.1", - "grunt-contrib-copy": "1.0.0", - "grunt-contrib-watch": "1.0.0", - "grunt-exec": "3.0.0", - "grunt-gitinfo": "0.1.7", - "grunt-sass": "3.0.1", - "html-webpack-plugin": "5.3.1", - "jsdoc": "3.6.2", - "mocha": "4.1.0", - "mocha-testcheck": "1.0.0-rc.0", - "node-gyp": "^6.1.0", - "node-sass": "4.14.1", - "node-sass-import-once": "1.2.0", - "npm-run-all": "4.1.5", - "nyc": "11.4.1", - "patch-package": "6.1.2", - "prettier": "^2.2.1", - "react-docgen-typescript": "1.2.6", - "sass-loader": "7.2.0", - "sinon": "9.2.4", - "snyk": "1.316.1", - "spectron": "5.0.0", - "style-loader": "1.0.0", - "terser-webpack-plugin": "5.1.1", - "ts-loader": "4.1.0", - "ts-node": "8.3.0", - "typed-scss-modules": "0.0.11", - "typescript": "4.1.3", - "webpack": "5.30.0", - "webpack-cli": "4.6.0", - "webpack-dev-server": "3.11.2" - }, - "resolutions": { - "@storybook/react/@storybook/core/node-fetch": "2.6.1", - "fast-glob/glob-parent": "5.1.2", - "read-last-lines/mz/thenify-all/thenify": "3.3.1", - "sharp/color/color-string": "1.5.5", - "zkgroup/ref-napi/node-addon-api": "2.0.1", - "zkgroup/ffi-napi/ref-napi/node-addon-api": "2.0.1", - "zkgroup/ref-array-napi/ref-napi/node-addon-api": "2.0.1" - }, - "engines": { - "node": "14.16.0" - }, - "build": { - "appId": "org.whispersystems.signal-desktop", - "mac": { - "asarUnpack": [ - "**/*.node", - "node_modules/zkgroup/libzkgroup.*", - "node_modules/@signalapp/signal-client/build/*.node", - "node_modules/mac-screen-capture-permissions/build/Release/*.node" - ], - "artifactName": "${name}-mac-${version}.${ext}", - "category": "public.app-category.social-networking", - "darkModeSupport": true, - "hardenedRuntime": true, - "entitlements": "./build/entitlements.mac.plist", - "icon": "build/icons/mac/icon.icns", - "publish": [ - { - "provider": "generic", - "url": "https://updates.signal.org/desktop" - } - ], - "target": [ - "zip", - "dmg" - ], - "bundleVersion": "1" - }, - "win": { - "asarUnpack": [ - "**/*.node", - "node_modules/spellchecker/vendor/hunspell_dictionaries", - "node_modules/sharp", - "node_modules/zkgroup/libzkgroup.*", - "node_modules/@signalapp/signal-client/build/*.node" - ], - "artifactName": "${name}-win-${version}.${ext}", - "certificateSubjectName": "Signal (Quiet Riddle Ventures, LLC)", - "certificateSha1": "77B2AA4421E5F377454B8B91E573746592D1543D", - "publisherName": "Signal (Quiet Riddle Ventures, LLC)", - "icon": "build/icons/win/icon.ico", - "publish": [ - { - "provider": "generic", - "url": "https://updates.signal.org/desktop" - } - ], - "target": [ - "nsis" - ] - }, - "nsis": { - "deleteAppDataOnUninstall": true - }, - "linux": { - "category": "Network;InstantMessaging;Chat", - "desktop": { - "StartupWMClass": "Signal" - }, - "asarUnpack": [ - "**/*.node", - "node_modules/spellchecker/vendor/hunspell_dictionaries", - "node_modules/sharp", - "node_modules/zkgroup/libzkgroup.*", - "node_modules/@signalapp/signal-client/build/*.node" - ], - "target": [ - "deb" - ], - "icon": "build/icons/png" - }, - "deb": { - "depends": [ - "libnotify4", - "libxtst6", - "libnss3", - "libasound2", - "libxss1" - ] - }, - "protocols": { - "name": "sgnl-url-scheme", - "schemes": [ - "sgnl", - "signalcaptcha" - ] - }, - "asarUnpack": [ - "ts/sql/mainWorker.bundle.js", - "node_modules/better-sqlite3/build/Release/better_sqlite3.node" - ], - "files": [ - "package.json", - "config/default.json", - "config/${env.SIGNAL_ENV}.json", - "config/local-${env.SIGNAL_ENV}.json", - "background.html", - "about.html", - "screenShare.html", - "settings.html", - "permissions_popup.html", - "debug_log.html", - "loading.html", - "_locales/**", - "protos/*", - "js/**", - "libtextsecure/**", - "ts/**/*.js", - "ts/*.js", - "stylesheets/*.css", - "!js/register.js", - "app/*", - "preload.bundle.js", - "preload_utils.js", - "about_preload.js", - "screenShare_preload.js", - "settings_preload.js", - "permissions_popup_preload.js", - "debug_log_preload.js", - "loading_preload.js", - "userPasswordPrompt.js", - "main.js", - "mainPasswordPrompt.js", - "images/**", - "fonts/**", - "sounds/*", - "build/icons", - "node_modules/**", - "sticker-creator/preload.js", - "sticker-creator/dist/**", - "!node_modules/emoji-datasource/emoji_pretty.json", - "!node_modules/emoji-datasource/**/*.png", - "!node_modules/emoji-datasource-apple/emoji_pretty.json", - "!node_modules/emoji-datasource-apple/img/apple/sheets*", - "!node_modules/spellchecker/vendor/hunspell/**/*", - "!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme,test,__tests__,tests,powered-test,example,examples,*.d.ts,.snyk-*.flag,benchmark}", - "!**/node_modules/.bin", - "!**/node_modules/**/build/**", - "!**/*.{o,hprof,orig,pyc,pyo,rbc}", - "!**/._*", - "!**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,__pycache__,thumbs.db,.gitignore,.gitattributes,.flowconfig,.yarn-metadata.json,.idea,appveyor.yml,.travis.yml,circle.yml,npm-debug.log,.nyc_output,yarn.lock,.yarn-integrity}", - "node_modules/spellchecker/build/Release/*.node", - "node_modules/websocket/build/Release/*.node", - "!node_modules/websocket/builderror.log", - "node_modules/ref-napi/build/Release/*.node", - "node_modules/ref-array-napi/node_modules/ref-napi/build/Release/*.node", - "node_modules/ffi-napi/build/Release/*.node", - "node_modules/socks/build/*.js", - "node_modules/socks/build/common/*.js", - "node_modules/socks/build/client/*.js", - "node_modules/smart-buffer/build/*.js", - "node_modules/sharp/build/**", - "!node_modules/sharp/{install,src,vendor/include,vendor/*/include}", - "!node_modules/better-sqlite3/deps/*", - "!node_modules/better-sqlite3/src/*", - "node_modules/better-sqlite3/build/Release/better_sqlite3.node", - "node_modules/@signalapp/signal-client/build/*${platform}*.node", - "node_modules/ringrtc/build/${platform}/**", - "node_modules/mac-screen-capture-permissions/build/Release/*.node", - "!**/node_modules/ffi-napi/deps", - "!**/node_modules/react-dom/*/*.development.js", - "!node_modules/.cache" - ] - } -} diff --git a/start.sh b/start.sh new file mode 100755 index 0000000000..1893305b2b --- /dev/null +++ b/start.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# SAAD-IT // free to use, modify etc. just4dev +# vars +user="karim"; #$(whoami) or ="$USER"; + +# set nvm +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm +[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion +#source ~/.bashrc +nvm use 14.16.0 # please modify it to the needed version + +# if a second param is set, do the yarn install and grunt +if [ ! -z "$1" ]; then + echo "[== Starting Dev - Compiling ==]"; + yarn install + yarn grunt + echo "[=== Completed ===]"; +fi + +# if no additional parameters just do the yarn start --no-sandbox (if nvm as root) +echo "[ == [start.sh] Starting App == ]"; +chown "$user":"$user" * -R +LANGUAGE=en SIGNAL_ENABLE_HTTP=1 yarn start --no-sandbox +echo "[ === [start.sh] App closed === ]"; +chown "$user":"$user" * -R From 4bdf68abb4086b3203fdd28c8a10767996b85fdf Mon Sep 17 00:00:00 2001 From: Karim <37943746+ksaadDE@users.noreply.github.com> Date: Sun, 15 Aug 2021 19:34:39 +0000 Subject: [PATCH 4/6] Update Gruntfile.js oops forget some small issue. removed the userpasswordprompt.js from code (which I never use in the actual PR) --- Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index 5f69965116..34906683e0 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -192,7 +192,7 @@ module.exports = grunt => { process.platform === 'win32' ? 'electron.cmd' : 'electron'; const path = join(__dirname, 'node_modules', '.bin', electronBinary); - const args = [join(__dirname, 'userPasswordPrompt.js')]; //'main.js')]; changed by SAAD-IT + const args = [join(__dirname, 'main.js')]; // change reverted by ksaadDE // SAAD-IT console.log('Starting path', path, 'with args', args); const app = new Application({ path, From 6fe4dbb667b3e877d8be5a5f824bce93027a646d Mon Sep 17 00:00:00 2001 From: Karim <37943746+ksaadDE@users.noreply.github.com> Date: Sun, 15 Aug 2021 20:02:18 +0000 Subject: [PATCH 5/6] added information for the user for the 20 chars minimum added information for the user for the 20 chars minimum ``` if (password === null || password === undefined) return 'data.error.nopwentered_or_abort'; if (password.length < 20) return 'data.error.pwshort'; if (password.trim().length < 20) return 'data.error.pwwhitespace'; if (password.length > 128) return 'data.error.pwlong'; return 'data.success'; ``` --- _locales/en/messages.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 7ba0cd26dc..093489b5bf 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -5290,11 +5290,11 @@ "description": "Displayed after unsuccessful captcha" }, "userPasswordRequiredNoKeyExisting": { - "message": "Please enter your NEW password.\n It is required at every start of Signal", + "message": "Please enter your NEW password.\n It is required at every start of Signal\n needs at least 20 characters.", "description": "Title of userPasswordPrompt window, shows up to get the user password (user has NOT already pw)" }, "userPasswordRequiredAlreadyKeyExisting": { - "message": "Please enter your already existing password.", + "message": "Please enter your already existing password.\n must be at least 20 characters.", "description": "Title of userPasswordPrompt window, shows up to get the user password (user has already pw)" }, "deleteForEveryoneFailed": { From bc201e78919b14c62150baf26bb3190d99b36757 Mon Sep 17 00:00:00 2001 From: Karim <37943746+ksaadDE@users.noreply.github.com> Date: Sun, 15 Aug 2021 20:05:16 +0000 Subject: [PATCH 6/6] added information for the user more than 20 chars added information for the user more than 20 chars `` if (password === null || password === undefined) return 'data.error.nopwentered_or_abort'; if (password.length < 20) return 'data.error.pwshort'; if (password.trim().length < 20) return 'data.error.pwwhitespace'; if (password.length > 128) return 'data.error.pwlong'; ``` --- _locales/de/messages.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 672216e7ac..14eb767fb5 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -5176,11 +5176,11 @@ "description": "Displayed after unsuccessful captcha" }, "userPasswordRequiredNoKeyExisting": { - "message": "Bitte geben Sie Ihr neues Passwort ein!\nSie werden jedes Mal beim Starten gefragt.", + "message": "Bitte geben Sie Ihr neues Passwort ein!\nSie werden jedes Mal beim Starten gefragt.\n Es muss mindestens 20 Zeichen lang sein.", "description": "Title of userPasswordPrompt window, shows up to get the user password (user has NOT already pw)" }, "userPasswordRequiredAlreadyKeyExisting": { - "message": "Bitte geben Sie Ihr vorhandenes Passwort ein!", + "message": "Bitte geben Sie Ihr vorhandenes Passwort ein!\n Es muss mindestens 20 Zeichen lang sein.", "description": "Title of userPasswordPrompt window, shows up to get the user password (user has already pw)" }, "deleteForEveryoneFailed": {