Introduce isStagingServer util method

This commit is contained in:
Fedor Indutny 2024-09-04 11:12:45 -07:00 committed by GitHub
parent 4cdb6fab08
commit cd44a7a033
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 80 additions and 71 deletions

View file

@ -15,7 +15,7 @@ import {
// In production mode, NODE_ENV cannot be customized by the user // In production mode, NODE_ENV cannot be customized by the user
if (app.isPackaged) { if (app.isPackaged) {
setEnvironment(Environment.Production, false); setEnvironment(Environment.PackagedApp, false);
} else { } else {
setEnvironment( setEnvironment(
parseEnvironment(process.env.NODE_ENV || 'development'), parseEnvironment(process.env.NODE_ENV || 'development'),
@ -27,7 +27,7 @@ if (app.isPackaged) {
process.env.NODE_ENV = getEnvironment(); process.env.NODE_ENV = getEnvironment();
process.env.NODE_CONFIG_DIR = join(__dirname, '..', 'config'); process.env.NODE_CONFIG_DIR = join(__dirname, '..', 'config');
if (getEnvironment() === Environment.Production) { if (getEnvironment() === Environment.PackagedApp) {
// harden production config against the local env // harden production config against the local env
process.env.NODE_CONFIG = ''; process.env.NODE_CONFIG = '';
process.env.NODE_CONFIG_STRICT_MODE = ''; process.env.NODE_CONFIG_STRICT_MODE = '';
@ -47,7 +47,7 @@ if (getEnvironment() === Environment.Production) {
// eslint-disable-next-line @typescript-eslint/no-var-requires // eslint-disable-next-line @typescript-eslint/no-var-requires
const config: IConfig = require('config'); const config: IConfig = require('config');
if (getEnvironment() !== Environment.Production) { if (getEnvironment() !== Environment.PackagedApp) {
config.util.getConfigSources().forEach(source => { config.util.getConfigSources().forEach(source => {
console.log(`config: Using config source ${basename(source.name)}`); console.log(`config: Using config source ${basename(source.name)}`);
}); });

View file

@ -199,7 +199,7 @@ const cliOptions = cliParser.parse(process.argv);
const defaultWebPrefs = { const defaultWebPrefs = {
devTools: devTools:
process.argv.some(arg => arg === '--enable-dev-tools') || process.argv.some(arg => arg === '--enable-dev-tools') ||
getEnvironment() !== Environment.Production || getEnvironment() !== Environment.PackagedApp ||
!isProduction(app.getVersion()), !isProduction(app.getVersion()),
spellcheck: false, spellcheck: false,
// https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/platform/runtime_enabled_features.json5 // https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/platform/runtime_enabled_features.json5
@ -2713,7 +2713,7 @@ ipc.on('get-config', async event => {
certificateAuthority: config.get<string>('certificateAuthority'), certificateAuthority: config.get<string>('certificateAuthority'),
environment: environment:
!isTestEnvironment(getEnvironment()) && ciMode !isTestEnvironment(getEnvironment()) && ciMode
? Environment.Production ? Environment.PackagedApp
: getEnvironment(), : getEnvironment(),
isMockTestEnvironment: Boolean(process.env.MOCK_TEST), isMockTestEnvironment: Boolean(process.env.MOCK_TEST),
ciMode, ciMode,

View file

@ -12,7 +12,7 @@ import { HashType, CipherType, UUID_BYTE_SIZE } from './types/Crypto';
import { ProfileDecryptError } from './types/errors'; import { ProfileDecryptError } from './types/errors';
import { getBytesSubarray } from './util/uuidToBytes'; import { getBytesSubarray } from './util/uuidToBytes';
import { logPadSize } from './util/logPadding'; import { logPadSize } from './util/logPadding';
import { Environment } from './environment'; import { Environment, getEnvironment } from './environment';
export { HashType, CipherType }; export { HashType, CipherType };
@ -636,7 +636,7 @@ export function encryptAttachment({
throw new Error(`${logId}: invalid length attachment keys`); throw new Error(`${logId}: invalid length attachment keys`);
} }
if (dangerousTestOnlyIv && window.getEnvironment() !== Environment.Test) { if (dangerousTestOnlyIv && getEnvironment() !== Environment.Test) {
throw new Error(`${logId}: Used dangerousTestOnlyIv outside tests!`); throw new Error(`${logId}: Used dangerousTestOnlyIv outside tests!`);
} }

View file

@ -126,6 +126,7 @@ import { SendStatus } from './messages/MessageSendState';
import * as Stickers from './types/Stickers'; import * as Stickers from './types/Stickers';
import * as Errors from './types/errors'; import * as Errors from './types/errors';
import { InstallScreenStep } from './types/InstallScreen'; import { InstallScreenStep } from './types/InstallScreen';
import { getEnvironment } from './environment';
import { SignalService as Proto } from './protobuf'; import { SignalService as Proto } from './protobuf';
import { import {
onRetryRequest, onRetryRequest,
@ -348,7 +349,7 @@ export async function startApp(): Promise<void> {
const { upgradeMessageSchema } = window.Signal.Migrations; const { upgradeMessageSchema } = window.Signal.Migrations;
log.info('background page reloaded'); log.info('background page reloaded');
log.info('environment:', window.getEnvironment()); log.info('environment:', getEnvironment());
let newVersion = false; let newVersion = false;
let lastVersion: string | undefined; let lastVersion: string | undefined;

View file

@ -2,7 +2,6 @@
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import React from 'react'; import React from 'react';
import { Environment, getEnvironment } from '../environment';
import type { LocalizerType } from '../types/I18N'; import type { LocalizerType } from '../types/I18N';
import type { NavTabPanelProps } from './NavTabs'; import type { NavTabPanelProps } from './NavTabs';
import { WhatsNewLink } from './WhatsNewLink'; import { WhatsNewLink } from './WhatsNewLink';
@ -11,6 +10,7 @@ import type { UnreadStats } from '../util/countUnreadStats';
type ChatsTabProps = Readonly<{ type ChatsTabProps = Readonly<{
otherTabsUnreadStats: UnreadStats; otherTabsUnreadStats: UnreadStats;
i18n: LocalizerType; i18n: LocalizerType;
isStaging: boolean;
hasPendingUpdate: boolean; hasPendingUpdate: boolean;
hasFailedStorySends: boolean; hasFailedStorySends: boolean;
navTabsCollapsed: boolean; navTabsCollapsed: boolean;
@ -25,6 +25,7 @@ type ChatsTabProps = Readonly<{
export function ChatsTab({ export function ChatsTab({
otherTabsUnreadStats, otherTabsUnreadStats,
i18n, i18n,
isStaging,
hasPendingUpdate, hasPendingUpdate,
hasFailedStorySends, hasFailedStorySends,
navTabsCollapsed, navTabsCollapsed,
@ -60,9 +61,9 @@ export function ChatsTab({
{renderMiniPlayer({ shouldFlow: false })} {renderMiniPlayer({ shouldFlow: false })}
<div className="module-splash-screen__logo module-img--80 module-logo-blue" /> <div className="module-splash-screen__logo module-img--80 module-logo-blue" />
<h3 className="Inbox__welcome"> <h3 className="Inbox__welcome">
{getEnvironment() !== Environment.Staging {isStaging
? i18n('icu:welcomeToSignal') ? 'THIS IS A STAGING DESKTOP'
: 'THIS IS A STAGING DESKTOP'} : i18n('icu:welcomeToSignal')}
</h3> </h3>
<p className="Inbox__whatsnew"> <p className="Inbox__whatsnew">
<WhatsNewLink i18n={i18n} showWhatsNewModal={showWhatsNewModal} /> <WhatsNewLink i18n={i18n} showWhatsNewModal={showWhatsNewModal} />

View file

@ -34,7 +34,7 @@ export function QrCode(props: PropsType): ReactElement {
// simulator primary, which has a debug-only option to paste the linking URL instead of // simulator primary, which has a debug-only option to paste the linking URL instead of
// scanning it. (By the time you read this comment Android may have a similar feature.) // scanning it. (By the time you read this comment Android may have a similar feature.)
const onDoubleClick = () => { const onDoubleClick = () => {
if (getEnvironment() === Environment.Production) { if (getEnvironment() === Environment.PackagedApp) {
return; return;
} }
if (data instanceof Uint8Array) { if (data instanceof Uint8Array) {

View file

@ -42,7 +42,7 @@ export function InstallScreenChoosingDeviceNameStep({
normalizedName.length <= MAX_DEVICE_NAME_LENGTH; normalizedName.length <= MAX_DEVICE_NAME_LENGTH;
let maybeBackupInput: JSX.Element | undefined; let maybeBackupInput: JSX.Element | undefined;
if (getEnvironment() !== Environment.Production) { if (getEnvironment() !== Environment.PackagedApp) {
maybeBackupInput = ( maybeBackupInput = (
<label className="module-InstallScreenChoosingDeviceNameStep__input"> <label className="module-InstallScreenChoosingDeviceNameStep__input">
{/* Since this is only for testing - we don't require translation */} {/* Since this is only for testing - we don't require translation */}

View file

@ -58,6 +58,7 @@ function Simulation({
return ( return (
<InstallScreenQrCodeNotScannedStep <InstallScreenQrCodeNotScannedStep
i18n={i18n} i18n={i18n}
isStaging={false}
provisioningUrl={provisioningUrl} provisioningUrl={provisioningUrl}
updates={DEFAULT_UPDATES} updates={DEFAULT_UPDATES}
OS="macOS" OS="macOS"
@ -72,6 +73,7 @@ export function QrCodeLoading(): JSX.Element {
return ( return (
<InstallScreenQrCodeNotScannedStep <InstallScreenQrCodeNotScannedStep
i18n={i18n} i18n={i18n}
isStaging={false}
provisioningUrl={{ provisioningUrl={{
loadingState: LoadingState.Loading, loadingState: LoadingState.Loading,
}} }}
@ -88,6 +90,7 @@ export function QrCodeFailedToLoad(): JSX.Element {
return ( return (
<InstallScreenQrCodeNotScannedStep <InstallScreenQrCodeNotScannedStep
i18n={i18n} i18n={i18n}
isStaging={false}
provisioningUrl={{ provisioningUrl={{
loadingState: LoadingState.LoadFailed, loadingState: LoadingState.LoadFailed,
error: InstallScreenQRCodeError.Unknown, error: InstallScreenQRCodeError.Unknown,
@ -105,6 +108,7 @@ export function QrCodeLoaded(): JSX.Element {
return ( return (
<InstallScreenQrCodeNotScannedStep <InstallScreenQrCodeNotScannedStep
i18n={i18n} i18n={i18n}
isStaging={false}
provisioningUrl={LOADED_URL} provisioningUrl={LOADED_URL}
updates={DEFAULT_UPDATES} updates={DEFAULT_UPDATES}
OS="macOS" OS="macOS"
@ -164,6 +168,7 @@ export const WithUpdateKnobs: StoryFn<PropsType & { dialogType: DialogType }> =
return ( return (
<InstallScreenQrCodeNotScannedStep <InstallScreenQrCodeNotScannedStep
i18n={i18n} i18n={i18n}
isStaging={false}
provisioningUrl={LOADED_URL} provisioningUrl={LOADED_URL}
hasExpired hasExpired
updates={{ updates={{

View file

@ -19,7 +19,6 @@ import { InstallScreenSignalLogo } from './InstallScreenSignalLogo';
import { InstallScreenUpdateDialog } from './InstallScreenUpdateDialog'; import { InstallScreenUpdateDialog } from './InstallScreenUpdateDialog';
import { getClassNamesFor } from '../../util/getClassNamesFor'; import { getClassNamesFor } from '../../util/getClassNamesFor';
import type { UpdatesStateType } from '../../state/ducks/updates'; import type { UpdatesStateType } from '../../state/ducks/updates';
import { Environment, getEnvironment } from '../../environment';
// We can't always use destructuring assignment because of the complexity of this props // We can't always use destructuring assignment because of the complexity of this props
// type. // type.
@ -31,6 +30,7 @@ export type PropsType = Readonly<{
updates: UpdatesStateType; updates: UpdatesStateType;
currentVersion: string; currentVersion: string;
OS: string; OS: string;
isStaging: boolean;
retryGetQrCode: () => void; retryGetQrCode: () => void;
startUpdate: () => void; startUpdate: () => void;
}>; }>;
@ -46,6 +46,7 @@ export function InstallScreenQrCodeNotScannedStep({
currentVersion, currentVersion,
hasExpired, hasExpired,
i18n, i18n,
isStaging,
OS, OS,
provisioningUrl, provisioningUrl,
retryGetQrCode, retryGetQrCode,
@ -102,12 +103,12 @@ export function InstallScreenQrCodeNotScannedStep({
/> />
</li> </li>
</ol> </ol>
{getEnvironment() !== Environment.Staging ? ( {isStaging ? (
'THIS IS A STAGING DESKTOP'
) : (
<a target="_blank" rel="noreferrer" href={SUPPORT_PAGE}> <a target="_blank" rel="noreferrer" href={SUPPORT_PAGE}>
{i18n('icu:Install__support-link')} {i18n('icu:Install__support-link')}
</a> </a>
) : (
'THIS IS A STAGING DESKTOP'
)} )}
</div> </div>
</div> </div>

View file

@ -7,7 +7,7 @@ import * as log from './logging/log';
// Many places rely on this enum being a string. // Many places rely on this enum being a string.
export enum Environment { export enum Environment {
Development = 'development', Development = 'development',
Production = 'production', PackagedApp = 'production',
Staging = 'staging', Staging = 'staging',
Test = 'test', Test = 'test',
} }
@ -20,7 +20,7 @@ export function getEnvironment(): Environment {
// This should never happen—we should always have initialized the environment by this // This should never happen—we should always have initialized the environment by this
// point. It'd be nice to log here but the logger depends on the environment and we // point. It'd be nice to log here but the logger depends on the environment and we
// can't have circular dependencies. // can't have circular dependencies.
return Environment.Production; return Environment.PackagedApp;
} }
return environment; return environment;
} }
@ -42,7 +42,7 @@ export function setEnvironment(env: Environment, isMockTestEnv: boolean): void {
export const parseEnvironment = makeEnumParser( export const parseEnvironment = makeEnumParser(
Environment, Environment,
Environment.Production Environment.PackagedApp
); );
export const isTestEnvironment = (env: Environment): boolean => export const isTestEnvironment = (env: Environment): boolean =>

View file

@ -85,7 +85,7 @@ export function initialize(): void {
// A modern logging interface for the browser // A modern logging interface for the browser
function logAtLevel(level: LogLevel, ...args: ReadonlyArray<unknown>): void { function logAtLevel(level: LogLevel, ...args: ReadonlyArray<unknown>): void {
if (getEnvironment() !== Environment.Production) { if (getEnvironment() !== Environment.PackagedApp) {
const prefix = getLogLevelString(level) const prefix = getLogLevelString(level)
.toUpperCase() .toUpperCase()
.padEnd(levelMaxLength, ' '); .padEnd(levelMaxLength, ' ');

View file

@ -16,6 +16,7 @@ import { reducer } from './reducer';
import { dispatchItemsMiddleware } from '../shims/dispatchItemsMiddleware'; import { dispatchItemsMiddleware } from '../shims/dispatchItemsMiddleware';
import { isOlderThan } from '../util/timestamp'; import { isOlderThan } from '../util/timestamp';
import { SECOND } from '../util/durations'; import { SECOND } from '../util/durations';
import { getEnvironment } from '../environment';
declare global { declare global {
// We want to extend `window`'s properties, so we need an interface. // We want to extend `window`'s properties, so we need an interface.
@ -25,7 +26,7 @@ declare global {
} }
} }
const env = window.getEnvironment(); const env = getEnvironment();
// So Redux logging doesn't go to disk, and so we can get colors/styles // So Redux logging doesn't go to disk, and so we can get colors/styles
const directConsole = { const directConsole = {

View file

@ -7,6 +7,7 @@ import type { StateType as RootStateType } from '../reducer';
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions'; import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
import { useBoundActions } from '../../hooks/useBoundActions'; import { useBoundActions } from '../../hooks/useBoundActions';
import * as log from '../../logging/log'; import * as log from '../../logging/log';
import { getEnvironment, Environment } from '../../environment';
import { import {
START_INSTALLER, START_INSTALLER,
type StartInstallerActionType, type StartInstallerActionType,
@ -90,7 +91,7 @@ function openStandalone(): ThunkAction<
OpenStandaloneActionType OpenStandaloneActionType
> { > {
return dispatch => { return dispatch => {
if (window.getEnvironment() === 'production') { if (getEnvironment() === Environment.PackagedApp) {
return; return;
} }

View file

@ -61,7 +61,7 @@ export const hasExpired = createSelector(
getAutoDownloadUpdate, getAutoDownloadUpdate,
(_: StateType, { now = Date.now() }: HasExpiredOptionsType = {}) => now, (_: StateType, { now = Date.now() }: HasExpiredOptionsType = {}) => now,
(buildExpiration: number, autoDownloadUpdate: boolean, now: number) => { (buildExpiration: number, autoDownloadUpdate: boolean, now: number) => {
if (getEnvironment() !== Environment.Production && buildExpiration === 0) { if (getEnvironment() !== Environment.PackagedApp && buildExpiration === 0) {
return false; return false;
} }

View file

@ -14,6 +14,7 @@ import { TargetedMessageSource } from '../ducks/conversationsEnums';
import { useConversationsActions } from '../ducks/conversations'; import { useConversationsActions } from '../ducks/conversations';
import { useToastActions } from '../ducks/toast'; import { useToastActions } from '../ducks/toast';
import { strictAssert } from '../../util/assert'; import { strictAssert } from '../../util/assert';
import { isStagingServer } from '../../util/isStagingServer';
import { ToastType } from '../../types/Toast'; import { ToastType } from '../../types/Toast';
import { getNavTabsCollapsed } from '../selectors/items'; import { getNavTabsCollapsed } from '../selectors/items';
import { useItemsActions } from '../ducks/items'; import { useItemsActions } from '../ducks/items';
@ -146,6 +147,7 @@ export const SmartChatsTab = memo(function SmartChatsTab() {
<ChatsTab <ChatsTab
otherTabsUnreadStats={otherTabsUnreadStats} otherTabsUnreadStats={otherTabsUnreadStats}
i18n={i18n} i18n={i18n}
isStaging={isStagingServer()}
hasFailedStorySends={hasFailedStorySends} hasFailedStorySends={hasFailedStorySends}
hasPendingUpdate={hasPendingUpdate} hasPendingUpdate={hasPendingUpdate}
navTabsCollapsed={navTabsCollapsed} navTabsCollapsed={navTabsCollapsed}

View file

@ -17,6 +17,7 @@ import { WidthBreakpoint } from '../../components/_util';
import { InstallScreenStep } from '../../types/InstallScreen'; import { InstallScreenStep } from '../../types/InstallScreen';
import OS from '../../util/os/osMain'; import OS from '../../util/os/osMain';
import { fileToBytes } from '../../util/fileToBytes'; import { fileToBytes } from '../../util/fileToBytes';
import { isStagingServer } from '../../util/isStagingServer';
import * as log from '../../logging/log'; import * as log from '../../logging/log';
import { SmartToastManager } from './ToastManager'; import { SmartToastManager } from './ToastManager';
@ -70,6 +71,7 @@ export const SmartInstallScreen = memo(function SmartInstallScreen() {
startUpdate, startUpdate,
retryGetQrCode: startInstaller, retryGetQrCode: startInstaller,
OS: OS.getName(), OS: OS.getName(),
isStaging: isStagingServer(),
}, },
}; };
break; break;

View file

@ -11,23 +11,23 @@ import {
describe('environment utilities', () => { describe('environment utilities', () => {
describe('parseEnvironment', () => { describe('parseEnvironment', () => {
it('returns Environment.Production for non-strings', () => { it('returns Environment.PackagedApp for non-strings', () => {
assert.equal(parseEnvironment(undefined), Environment.Production); assert.equal(parseEnvironment(undefined), Environment.PackagedApp);
assert.equal(parseEnvironment(0), Environment.Production); assert.equal(parseEnvironment(0), Environment.PackagedApp);
}); });
it('returns Environment.Production for invalid strings', () => { it('returns Environment.PackagedApp for invalid strings', () => {
assert.equal(parseEnvironment(''), Environment.Production); assert.equal(parseEnvironment(''), Environment.PackagedApp);
assert.equal(parseEnvironment(' development '), Environment.Production); assert.equal(parseEnvironment(' development '), Environment.PackagedApp);
assert.equal(parseEnvironment('PRODUCTION'), Environment.Production); assert.equal(parseEnvironment('PRODUCTION'), Environment.PackagedApp);
}); });
it('parses "development" as Environment.Development', () => { it('parses "development" as Environment.Development', () => {
assert.equal(parseEnvironment('development'), Environment.Development); assert.equal(parseEnvironment('development'), Environment.Development);
}); });
it('parses "production" as Environment.Production', () => { it('parses "production" as Environment.PackagedApp', () => {
assert.equal(parseEnvironment('production'), Environment.Production); assert.equal(parseEnvironment('production'), Environment.PackagedApp);
}); });
it('parses "staging" as Environment.Staging', () => { it('parses "staging" as Environment.Staging', () => {
@ -42,7 +42,7 @@ describe('environment utilities', () => {
describe('isTestEnvironment', () => { describe('isTestEnvironment', () => {
it('returns false for non-test environments', () => { it('returns false for non-test environments', () => {
assert.isFalse(isTestEnvironment(Environment.Development)); assert.isFalse(isTestEnvironment(Environment.Development));
assert.isFalse(isTestEnvironment(Environment.Production)); assert.isFalse(isTestEnvironment(Environment.PackagedApp));
assert.isFalse(isTestEnvironment(Environment.Staging)); assert.isFalse(isTestEnvironment(Environment.Staging));
}); });

View file

@ -70,8 +70,8 @@ import * as log from '../logging/log';
import { maybeParseUrl, urlPathFromComponents } from '../util/url'; import { maybeParseUrl, urlPathFromComponents } from '../util/url';
import { SECOND } from '../util/durations'; import { SECOND } from '../util/durations';
import { safeParseNumber } from '../util/numbers'; import { safeParseNumber } from '../util/numbers';
import { isStagingServer } from '../util/isStagingServer';
import type { IWebSocketResource } from './WebsocketResources'; import type { IWebSocketResource } from './WebsocketResources';
import { Environment, getEnvironment } from '../environment';
// Note: this will break some code that expects to be able to use err.response when a // Note: this will break some code that expects to be able to use err.response when a
// web request fails, because it will force it to text. But it is very useful for // web request fails, because it will force it to text. But it is very useful for
@ -81,26 +81,11 @@ const DEFAULT_TIMEOUT = 30 * SECOND;
// Libsignal has internally configured values for domain names // Libsignal has internally configured values for domain names
// (and other connectivity params) of the services. // (and other connectivity params) of the services.
function resolveLibsignalNetEnvironment( function resolveLibsignalNetEnvironment(url: string): Net.Environment {
appEnv: Environment, if (isStagingServer(url)) {
url: string
): Net.Environment {
switch (appEnv) {
case Environment.Production:
return Net.Environment.Production;
case Environment.Development:
// In the case of the `Development` Desktop env,
// we should be checking the provided string value
// of `libsignalNetEnv`
if (/staging/i.test(url)) {
return Net.Environment.Staging; return Net.Environment.Staging;
} }
return Net.Environment.Production; return Net.Environment.Production;
case Environment.Test:
case Environment.Staging:
default:
return Net.Environment.Staging;
}
} }
function _createRedactor( function _createRedactor(
@ -1609,7 +1594,7 @@ export function initialize({
// for providing network layer API and related functionality. // for providing network layer API and related functionality.
// It's important to have a single instance of this class as it holds // It's important to have a single instance of this class as it holds
// resources that are shared across all other use cases. // resources that are shared across all other use cases.
const env = resolveLibsignalNetEnvironment(getEnvironment(), url); const env = resolveLibsignalNetEnvironment(url);
log.info(`libsignal net environment resolved to [${Net.Environment[env]}]`); log.info(`libsignal net environment resolved to [${Net.Environment[env]}]`);
const libsignalNet = new Net.Net(env, getUserAgent(version)); const libsignalNet = new Net.Net(env, getUserAgent(version));
libsignalNet.setIpv6Enabled(!disableIPv6); libsignalNet.setIpv6Enabled(!disableIPv6);

View file

@ -29,7 +29,7 @@ export function assertDev(
): asserts condition { ): asserts condition {
if (!condition) { if (!condition) {
const err = new Error(message); const err = new Error(message);
if (getEnvironment() !== Environment.Production) { if (getEnvironment() !== Environment.PackagedApp) {
if (getEnvironment() === Environment.Development) { if (getEnvironment() === Environment.Development) {
debugger; // eslint-disable-line no-debugger debugger; // eslint-disable-line no-debugger
} }

View file

@ -5,7 +5,7 @@ import { getEnvironment, Environment } from '../environment';
import * as log from '../logging/log'; import * as log from '../logging/log';
export function deprecated(message?: string): void { export function deprecated(message?: string): void {
if (getEnvironment() === Environment.Development) { if (getEnvironment() !== Environment.PackagedApp) {
log.error(`This method is deprecated: ${message}`); log.error(`This method is deprecated: ${message}`);
} }
} }

View file

@ -2,14 +2,10 @@
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import * as RemoteConfig from '../RemoteConfig'; import * as RemoteConfig from '../RemoteConfig';
import { Environment, getEnvironment } from '../environment'; import { isStagingServer } from './isStagingServer';
import { isStaging } from './version';
export function isBackupEnabled(): boolean { export function isBackupEnabled(): boolean {
if (getEnvironment() === Environment.Staging) { if (isStagingServer()) {
return true;
}
if (isStaging(window.getVersion())) {
return true; return true;
} }
return Boolean(RemoteConfig.isEnabled('desktop.backup.credentialFetch')); return Boolean(RemoteConfig.isEnabled('desktop.backup.credentialFetch'));

View file

@ -0,0 +1,17 @@
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { Environment, getEnvironment } from '../environment';
import { isStaging } from './version';
export function isStagingServer(
serverUrl = window.SignalContext.config.serverUrl
): boolean {
if (getEnvironment() === Environment.Staging) {
return true;
}
if (isStaging(window.getVersion())) {
return true;
}
return /staging/i.test(serverUrl);
}

2
ts/window.d.ts vendored
View file

@ -27,7 +27,6 @@ import type * as Crypto from './Crypto';
import type * as Curve from './Curve'; import type * as Curve from './Curve';
import type * as RemoteConfig from './RemoteConfig'; import type * as RemoteConfig from './RemoteConfig';
import type { OSType } from './util/os/shared'; import type { OSType } from './util/os/shared';
import type { getEnvironment } from './environment';
import type { LocalizerType, ThemeType } from './types/Util'; import type { LocalizerType, ThemeType } from './types/Util';
import type { Receipt } from './types/Receipt'; import type { Receipt } from './types/Receipt';
import type { ConversationController } from './ConversationController'; import type { ConversationController } from './ConversationController';
@ -194,7 +193,6 @@ declare global {
getConversations: () => ConversationModelCollectionType; getConversations: () => ConversationModelCollectionType;
getBuildCreation: () => number; getBuildCreation: () => number;
getBuildExpiration: () => number; getBuildExpiration: () => number;
getEnvironment: typeof getEnvironment;
getHostName: () => string; getHostName: () => string;
getInteractionMode: () => 'mouse' | 'keyboard'; getInteractionMode: () => 'mouse' | 'keyboard';
getServerPublicParams: () => string; getServerPublicParams: () => string;

View file

@ -9,7 +9,7 @@ import type { IPCType } from '../../window.d';
import { parseIntWithFallback } from '../../util/parseIntWithFallback'; import { parseIntWithFallback } from '../../util/parseIntWithFallback';
import { getSignalConnections } from '../../util/getSignalConnections'; import { getSignalConnections } from '../../util/getSignalConnections';
import { ThemeType } from '../../types/Util'; import { ThemeType } from '../../types/Util';
import { getEnvironment, Environment } from '../../environment'; import { Environment } from '../../environment';
import { SignalContext } from '../context'; import { SignalContext } from '../context';
import * as log from '../../logging/log'; import * as log from '../../logging/log';
import { formatCountForLogging } from '../../logging/formatCountForLogging'; import { formatCountForLogging } from '../../logging/formatCountForLogging';
@ -48,7 +48,6 @@ window.RETRY_DELAY = false;
window.platform = process.platform; window.platform = process.platform;
window.getTitle = () => title; window.getTitle = () => title;
window.getEnvironment = getEnvironment;
window.getAppInstance = () => config.appInstance; window.getAppInstance = () => config.appInstance;
window.getVersion = () => config.version; window.getVersion = () => config.version;
window.getBuildCreation = () => parseIntWithFallback(config.buildCreation, 0); window.getBuildCreation = () => parseIntWithFallback(config.buildCreation, 0);
@ -61,8 +60,8 @@ window.getBackupServerPublicParams = () => config.backupServerPublicParams;
window.getSfuUrl = () => config.sfuUrl; window.getSfuUrl = () => config.sfuUrl;
let title = config.name; let title = config.name;
if (getEnvironment() !== Environment.Production) { if (config.environment !== Environment.PackagedApp) {
title += ` - ${getEnvironment()}`; title += ` - ${config.environment}`;
} }
if (config.appInstance) { if (config.appInstance) {
title += ` - ${config.appInstance}`; title += ` - ${config.appInstance}`;
@ -169,7 +168,7 @@ window.logAuthenticatedConnect = () => {
window.open = () => null; window.open = () => null;
// Playwright uses `eval` for `.evaluate()` API // Playwright uses `eval` for `.evaluate()` API
if (config.ciMode !== 'full' && config.environment !== 'test') { if (config.ciMode !== 'full' && config.environment !== Environment.Test) {
// eslint-disable-next-line no-eval, no-multi-assign // eslint-disable-next-line no-eval, no-multi-assign
window.eval = global.eval = () => null; window.eval = global.eval = () => null;
} }