From 0dfeb10e838374ec87d9fc1363207e9159abcad6 Mon Sep 17 00:00:00 2001 From: Vijay A Date: Tue, 16 Jan 2024 07:46:02 +0530 Subject: Extract string for i18n --- src/components/settings/settings/EditSettingsForm.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/components') diff --git a/src/components/settings/settings/EditSettingsForm.tsx b/src/components/settings/settings/EditSettingsForm.tsx index 1672a1411..70887af0f 100644 --- a/src/components/settings/settings/EditSettingsForm.tsx +++ b/src/components/settings/settings/EditSettingsForm.tsx @@ -238,6 +238,10 @@ const messages = defineMessages({ id: 'settings.app.updateStatusUpToDate', defaultMessage: 'You are using the latest version of Ferdium', }, + servicesUpdateStatusUpToDate: { + id: 'settings.app.servicesUpdateStatusUpToDate', + defaultMessage: 'Your services are up-to-date', + }, currentVersion: { id: 'settings.app.currentVersion', defaultMessage: 'Current version:', @@ -1117,7 +1121,10 @@ class EditSettingsForm extends Component { ) : (

-  Your services are up-to-date. +   + {intl.formatMessage( + messages.servicesUpdateStatusUpToDate, + )}

)} -- cgit v1.2.3-54-g00ecf From 711181751f0a5ee183b74514a621e4aaa6da3dd7 Mon Sep 17 00:00:00 2001 From: André Oliveira <37463445+SpecialAro@users.noreply.github.com> Date: Fri, 26 Jan 2024 02:06:35 +0000 Subject: feat: self signed certificates bypass (#1545) * feat: self signed certificates bypass * fix lint and vscode setting * Fix some mistakes and comments * forgot this one [skip ci] --- .vscode/settings.json | 2 +- src/@types/stores.types.ts | 1 + .../settings/settings/EditSettingsForm.tsx | 61 +++++++++++++++++++++- src/config.ts | 1 + src/containers/settings/EditSettingsScreen.tsx | 16 ++++++ src/environment-remote.ts | 4 ++ src/helpers/certs-helpers.ts | 25 +++++++++ src/i18n/locales/en-US.json | 6 ++- src/index.ts | 39 ++++++++++++++ 9 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 src/helpers/certs-helpers.ts (limited to 'src/components') diff --git a/.vscode/settings.json b/.vscode/settings.json index 5060e4994..42a06efe9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -17,7 +17,7 @@ // "explorer.confirmDelete": false, // "explorer.confirmDragAndDrop": false, - "eslint.runtime": "node", + // "eslint.runtime": "node", "eslint.format.enable": true, "eslint.workingDirectories": [{ "mode": "auto" }], // "eslint.packageManager": "npm", diff --git a/src/@types/stores.types.ts b/src/@types/stores.types.ts index d036f8ee1..c0670ee87 100644 --- a/src/@types/stores.types.ts +++ b/src/@types/stores.types.ts @@ -92,6 +92,7 @@ export interface AppStore extends TypedStore { darkMode: boolean; enableSpellchecking: boolean; enableTranslator: boolean; + useSelfSignedCertificates: boolean; fetchDataInterval: 4; get(key: string): any; getAppCacheSizeRequest: () => void; diff --git a/src/components/settings/settings/EditSettingsForm.tsx b/src/components/settings/settings/EditSettingsForm.tsx index 70887af0f..226dbac76 100644 --- a/src/components/settings/settings/EditSettingsForm.tsx +++ b/src/components/settings/settings/EditSettingsForm.tsx @@ -15,6 +15,7 @@ import Infobox from '../../ui/Infobox'; import { H1, H2, H3, H5 } from '../../ui/headline'; import { ferdiumVersion, + userDataCertsPath, userDataPath, userDataRecipesPath, } from '../../../environment-remote'; @@ -262,6 +263,20 @@ const messages = defineMessages({ id: 'settings.app.form.splitColumns', defaultMessage: 'Number of columns', }, + warningSelfSignedCertificates: { + id: 'settings.app.warningSelfSignedCertificates', + defaultMessage: + 'WARNING: Only enable this feature if you know what you are doing. Enabling this is a security risk and should only be used for testing purposes.', + }, + infoOpenCertificatesFolder: { + id: 'settings.app.infoOpenCertificatesFolder', + defaultMessage: + 'To install a certificate, click the button below to open the certificates folder and copy it into the folder. After that you can refresh the service (CTRL/CMD + R). To remove/uninstall, simply delete the certificate file and restart Ferdium.', + }, + buttonOpenFerdiumCertsFolder: { + id: 'settings.app.buttonOpenFerdiumCertsFolder', + defaultMessage: 'Open certificates folder', + }, }); const Hr = (): ReactElement => ( @@ -387,8 +402,12 @@ class EditSettingsForm extends Component { updateButtonLabelMessage = messages.updateStatusAvailable; } - const { lockingFeatureEnabled, scheduledDNDEnabled, reloadAfterResume } = - window['ferdium'].stores.settings.all.app; + const { + lockingFeatureEnabled, + scheduledDNDEnabled, + reloadAfterResume, + useSelfSignedCertificates, + } = window['ferdium'].stores.settings.all.app; let cacheSize; let notCleared; @@ -411,6 +430,7 @@ class EditSettingsForm extends Component { const profileFolder = userDataPath(); const recipeFolder = userDataRecipesPath(); + const certsFolder = userDataCertsPath(); return (
@@ -947,6 +967,43 @@ class EditSettingsForm extends Component { {intl.formatMessage(messages.appRestartRequired)}

+ + + {useSelfSignedCertificates && ( +
+

+ {intl.formatMessage(messages.infoOpenCertificatesFolder)} +

+
+
+
+ )} + +

+ {intl.formatMessage(messages.warningSelfSignedCertificates)} +

+
( + settings.all.app.useSelfSignedCertificates, + DEFAULT_APP_SETTINGS.useSelfSignedCertificates, + ), + default: DEFAULT_APP_SETTINGS.useSelfSignedCertificates, + type: 'checkbox', + }, spellcheckerLanguage: { label: intl.formatMessage(globalMessages.spellcheckerLanguage), value: ifUndefined( diff --git a/src/environment-remote.ts b/src/environment-remote.ts index 7662d69a0..346a75e97 100644 --- a/src/environment-remote.ts +++ b/src/environment-remote.ts @@ -48,6 +48,10 @@ export function userDataRecipesPath(...segments: string[]): string { return userDataPath('recipes', ...[segments].flat()); } +export function userDataCertsPath(...segments: string[]): string { + return userDataPath('certs', ...[segments].flat()); +} + const useLocalAPI = process.env.USE_LOCAL_API; export const useLiveAPI = process.env.USE_LIVE_API; diff --git a/src/helpers/certs-helpers.ts b/src/helpers/certs-helpers.ts new file mode 100644 index 000000000..a81e7e365 --- /dev/null +++ b/src/helpers/certs-helpers.ts @@ -0,0 +1,25 @@ +import { readdirSync, readFileSync, ensureDirSync } from 'fs-extra'; +import { join } from 'node:path'; +import { userDataCertsPath } from '../environment-remote'; + +export function removeNewLines(string: string) { + return string.replaceAll(/\r?\n|\r/g, ''); +} + +export function readCerts() { + const certsFolder = userDataCertsPath(); + + ensureDirSync(certsFolder); + + const certs: string[] = []; + + for (const file of readdirSync(certsFolder)) { + const cert = readFileSync(join(certsFolder, file), { + encoding: 'utf8', + flag: 'r', + }); + certs.push(removeNewLines(cert)); + } + + return certs; +} diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index eb8053fec..d2856e87a 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json @@ -188,6 +188,7 @@ "settings.account.yourLicense": "Your Ferdium License:", "settings.app.accentColorInfo": "Write your color choice in a CSS-compatible format. (Default: {defaultAccentColor} or clear the input field)", "settings.app.buttonInstallUpdate": "Restart & install update", + "settings.app.buttonOpenFerdiumCertsFolder": "Open certificates folder", "settings.app.buttonOpenFerdiumProfileFolder": "Open Profile folder", "settings.app.buttonOpenFerdiumServiceRecipesFolder": "Open Service Recipes folder", "settings.app.buttonOpenImportExport": "Import / Export", @@ -262,6 +263,7 @@ "settings.app.form.universalDarkMode": "Enable universal Dark Mode", "settings.app.form.useGrayscaleServices": "Use grayscale services", "settings.app.form.useHorizontalStyle": "Use horizontal style", + "settings.app.form.useSelfSignedCertificates": "Enable self-signed certificates", "settings.app.form.useTouchIdToUnlock": "Allow using TouchID to unlock Ferdium", "settings.app.form.wakeUpHibernationSplay": "Splay hibernate/wake cycles to reduce load", "settings.app.form.wakeUpHibernationStrategy": "Hibernation strategy after automatic wake up", @@ -276,6 +278,7 @@ "settings.app.headlineUpdates": "Updates", "settings.app.hibernateInfo": "By default, Ferdium will keep all your services open and loaded in the background so they are ready when you want to use them. Service Hibernation will unload your services after a specified amount. This is useful to save RAM or keeping services from slowing down your computer.", "settings.app.inactivityLockInfo": "Minutes of inactivity, after which Ferdium should automatically lock. Use 0 to disable", + "settings.app.infoOpenCertificatesFolder": "To install a certificate, click the button below to open the certificates folder and copy it into the folder. After that you can refresh the service (CTRL/CMD + R). To remove/uninstall, simply delete the certificate file and restart Ferdium.", "settings.app.lockInfo": "Password Lock allows you to keep your messages protected.\nUsing Password Lock, you will be prompted to enter your password everytime you start Ferdium or lock Ferdium yourself using the lock symbol in the bottom left corner or the shortcut {lockShortcut}.", "settings.app.lockedPassword": "Password", "settings.app.lockedPasswordInfo": "Please make sure to set a password you'll remember.\nIf you loose this password, you will have to reinstall Ferdium.", @@ -306,6 +309,7 @@ "settings.app.updateStatusAvailable": "Update available, downloading...", "settings.app.updateStatusSearching": "Searching for updates...", "settings.app.updateStatusUpToDate": "You are using the latest version of Ferdium", + "settings.app.warningSelfSignedCertificates": "WARNING: Only enable this feature if you know what you are doing. Enabling this is a security risk and should only be used for testing purposes.", "settings.invite.headline": "Invite Friends", "settings.navigation.account": "Account", "settings.navigation.availableServices": "Available services", @@ -495,4 +499,4 @@ "workspaceDrawer.workspaceFeatureInfo": "

Ferdium Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.

You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.

", "workspaceDrawer.workspacesSettingsTooltip": "Edit workspaces settings", "workspaces.switchingIndicator.switchingTo": "Switching to" -} \ No newline at end of file +} diff --git a/src/index.ts b/src/index.ts index e466b4ab1..8419d5cf9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -50,6 +50,7 @@ import { openExternalUrl } from './helpers/url-helpers'; import userAgent from './helpers/userAgent-helpers'; import { translateTo } from './helpers/translation-helpers'; import { darkThemeGrayDarkest } from './themes/legacy'; +import { readCerts, removeNewLines } from './helpers/certs-helpers'; const debug = require('./preload-safe-debug')('Ferdium:App'); @@ -752,3 +753,41 @@ app.on('will-finish-launching', () => { }); }); }); + +app.on( + 'certificate-error', + (event, _webContents, _url, _error, certificate, callback) => { + // On certificate error we disable default behaviour (stop loading the page) + // and we then say "it is all fine - true" to the callback + event.preventDefault(); + + const useSelfSignedCertificates = + retrieveSettingValue( + 'useSelfSignedCertificates', + DEFAULT_APP_SETTINGS.useSelfSignedCertificates, + ) === true; + + // Check if the certificate is trusted + if (!useSelfSignedCertificates) { + callback(false); + return; + } + + const trustedCerts = readCerts(); + if (!trustedCerts) { + callback(false); + return; + } + + const isTrustedCert = trustedCerts.includes( + removeNewLines(certificate.data), + ); + + if (isTrustedCert) { + callback(true); + return; + } + + callback(false); + }, +); -- cgit v1.2.3-54-g00ecf From dfda3b7206c907e8fcc7802120ebd0bbbcba717a Mon Sep 17 00:00:00 2001 From: Vijay A Date: Sun, 11 Feb 2024 09:44:29 +0530 Subject: remove unused '@types/react-loader' pkg --- package.json | 1 - pnpm-lock.yaml | 9 --------- src/components/ui/loader/index.tsx | 4 ++-- 3 files changed, 2 insertions(+), 12 deletions(-) (limited to 'src/components') diff --git a/package.json b/package.json index 54a65eec4..3a3a89570 100644 --- a/package.json +++ b/package.json @@ -153,7 +153,6 @@ "@types/react": "18.2.55", "@types/react-color": "3.0.11", "@types/react-dom": "18.2.19", - "@types/react-loader": "2.4.8", "@types/react-transition-group": "4.4.10", "@types/route-parser": "0.1.7", "@types/semver": "7.5.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8fbb2c0ee..e033c29c1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -318,9 +318,6 @@ devDependencies: '@types/react-dom': specifier: 18.2.19 version: 18.2.19 - '@types/react-loader': - specifier: 2.4.8 - version: 2.4.8 '@types/react-transition-group': specifier: 4.4.10 version: 4.4.10 @@ -3093,12 +3090,6 @@ packages: '@types/react': 18.2.55 dev: true - /@types/react-loader@2.4.8: - resolution: {integrity: sha512-tcUpbl7JRPxaskhjQsLMsMt8BVkbquqzjMdb+ud3dJdhBcaJr9Wbmrx5t2UG6Ikc7DHu47jEC82ob7disr5rHw==} - dependencies: - '@types/react': 18.2.55 - dev: true - /@types/react-transition-group@4.4.10: resolution: {integrity: sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==} dependencies: diff --git a/src/components/ui/loader/index.tsx b/src/components/ui/loader/index.tsx index 2cee00d96..2c6e2bff4 100644 --- a/src/components/ui/loader/index.tsx +++ b/src/components/ui/loader/index.tsx @@ -29,11 +29,11 @@ class LoaderComponent extends Component { const { classes, className, - size = 36, + size = 100, color = this.props.stores?.settings.app.accentColor, loaded = false, } = this.props; - const loaderColor = color || '#FFFFFF'; + const loaderColor = color ?? '#FFFFFF'; return (
Date: Sun, 11 Feb 2024 09:50:32 +0530 Subject: minor refactoring to remove duplication with a constant --- src/components/settings/account/AccountDashboard.tsx | 8 ++++++-- src/components/settings/team/TeamDashboard.tsx | 4 ++-- src/components/ui/InfoBar.tsx | 7 ++++++- src/components/ui/Infobox.tsx | 7 ++++++- src/components/ui/button/index.tsx | 3 ++- src/components/ui/loader/index.tsx | 3 ++- src/config.ts | 2 ++ .../workspaces/components/WorkspaceSwitchingIndicator.tsx | 3 ++- src/themes/default/index.ts | 3 ++- 9 files changed, 30 insertions(+), 10 deletions(-) (limited to 'src/components') diff --git a/src/components/settings/account/AccountDashboard.tsx b/src/components/settings/account/AccountDashboard.tsx index ffa684458..eab019084 100644 --- a/src/components/settings/account/AccountDashboard.tsx +++ b/src/components/settings/account/AccountDashboard.tsx @@ -7,7 +7,11 @@ import { H1, H2 } from '../../ui/headline'; import Loader from '../../ui/loader'; import Button from '../../ui/button'; import Infobox from '../../ui/infobox/index'; -import { LOCAL_SERVER, LIVE_FRANZ_API } from '../../../config'; +import { + DEFAULT_LOADER_COLOR, + LOCAL_SERVER, + LIVE_FRANZ_API, +} from '../../../config'; import User from '../../../models/User'; const messages = defineMessages({ @@ -123,7 +127,7 @@ class AccountDashboard extends Component { )} {!isUsingWithoutAccount && ( <> - {isLoading && } + {isLoading && } {!isLoading && userInfoRequestFailed && ( {
- {isLoading && } + {isLoading && } {!isLoading && userInfoRequestFailed && ( { className="contentWrapper" style={{ display: 'flex', gap: '8px' }} > - + {ctaLabel}
diff --git a/src/components/ui/Infobox.tsx b/src/components/ui/Infobox.tsx index 742717ed7..14e1a581c 100644 --- a/src/components/ui/Infobox.tsx +++ b/src/components/ui/Infobox.tsx @@ -6,6 +6,7 @@ import { noop } from 'lodash'; import { observer } from 'mobx-react'; import Loader from './loader/index'; import Icon from './icon'; +import { DEFAULT_LOADER_COLOR } from '../../config'; const icons = { 'checkbox-marked-circle-outline': mdiCheckboxMarkedCircleOutline, @@ -84,7 +85,11 @@ class Infobox extends Component { className="contentWrapper" style={{ display: 'flex', gap: '8px' }} > - + {ctaLabel}
diff --git a/src/components/ui/button/index.tsx b/src/components/ui/button/index.tsx index a2194e34d..3247072a9 100644 --- a/src/components/ui/button/index.tsx +++ b/src/components/ui/button/index.tsx @@ -8,6 +8,7 @@ import withStyles, { WithStylesProps } from 'react-jss'; import Loader from '../loader/index'; import { Theme } from '../../../themes'; import { IFormField } from '../typings/generic'; +import { DEFAULT_LOADER_COLOR } from '../../../config'; type ButtonType = | 'primary' @@ -194,7 +195,7 @@ class ButtonComponent extends Component { <> {showLoader && (
- +
)}
diff --git a/src/components/ui/loader/index.tsx b/src/components/ui/loader/index.tsx index 2c6e2bff4..c0ae15028 100644 --- a/src/components/ui/loader/index.tsx +++ b/src/components/ui/loader/index.tsx @@ -4,6 +4,7 @@ import injectStyle, { WithStylesProps } from 'react-jss'; import { Oval } from 'react-loader-spinner'; import { inject } from 'mobx-react'; import { FerdiumStores } from '../../../@types/stores.types'; +import { DEFAULT_LOADER_COLOR } from '../../../config'; const styles = () => ({ container: { @@ -33,7 +34,7 @@ class LoaderComponent extends Component { color = this.props.stores?.settings.app.accentColor, loaded = false, } = this.props; - const loaderColor = color ?? '#FFFFFF'; + const loaderColor = color ?? DEFAULT_LOADER_COLOR; return (
{ return (
- +

{`${intl.formatMessage(messages.switchingTo)} ${nextWorkspaceName}`}

diff --git a/src/themes/default/index.ts b/src/themes/default/index.ts index cc886f299..ac04a6e3b 100644 --- a/src/themes/default/index.ts +++ b/src/themes/default/index.ts @@ -3,6 +3,7 @@ import { cloneDeep } from 'lodash'; import * as legacyStyles from '../legacy'; import type IStyleTypes from '../IStyleTypes'; +import { DEFAULT_LOADER_COLOR } from '../../config'; export default (brandPrimary: string) => { if (!brandPrimary) { @@ -14,7 +15,7 @@ export default (brandPrimary: string) => { const brandDanger = '#d9534f'; const uiFontSize = 14; const colorBackground = legacyStyles.themeGrayLighter; - const colorContentBackground = '#FFFFFF'; + const colorContentBackground = DEFAULT_LOADER_COLOR; const colorText = legacyStyles.themeGrayDark; const inputColor = legacyStyles.themeGray; const inputBackground = legacyStyles.themeGrayLightest; -- cgit v1.2.3-54-g00ecf From 226257cd862451abccc28894e2b0a3270c6790e9 Mon Sep 17 00:00:00 2001 From: Vijay A Date: Sun, 11 Feb 2024 12:07:30 +0530 Subject: rename features to better convey type (without migration) --- src/components/layout/Sidebar.tsx | 2 +- src/components/settings/settings/EditSettingsForm.tsx | 8 ++++---- src/config.ts | 4 ++-- src/containers/settings/EditServiceScreen.tsx | 4 ++-- src/containers/settings/EditSettingsScreen.tsx | 14 +++++++------- src/lib/Menu.ts | 4 ++-- src/stores/AppStore.ts | 4 ++-- src/stores/SettingsStore.ts | 4 ++-- 8 files changed, 22 insertions(+), 22 deletions(-) (limited to 'src/components') diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index e423e408b..1106113f0 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -318,7 +318,7 @@ class Sidebar extends Component { ) : null} - {stores!.settings.all.app.lockingFeatureEnabled ? ( + {stores!.settings.all.app.isLockingFeatureEnabled ? (