mattermost-mobile/app/managers/network_manager.ts
Elias Nahum b8c088cc70
Upgrade RN as well as update or replace other dependencies (#8011)
* start upgrade to RN 74

* migrate react-native-fs to expo-file-system

* exclude expo-asset module

* fix database manager remove directory

* fix: android network helper

* include expo on android

* temporarily disable android dep lock

* replace react-native-create-thumbnail with expo-video-thumnails

* update patches file version

* fix android build on 74

* create local library to replace MattermostManaged, Notifications and SplitView modules with new arch support

* migrate app to use new mattermost-rnutils library

* remove unused flipper class for android unsigned

* fix mattermost-rnutils android foldedObserver lifecycle

* use mattermost-rnutils on Android

* use mattermost-rnutils on iOS

* path react-native-navigation to not crash when activity is not NavigationActivity

* create local library for android share extension with new arch support

* Replace ShareModule with @mattermost/rnshare library

* remove ShareModule from android native code

* update react-intl

* update nodejs to 20.x.x npm to 10.x.x and dev deps

* update @gorhom/bottom-sheet

* use MattermostShare conditionally based on the platform

* update @react-native-camera-roll/camera-roll

* remove unused react-native-calendars

* fix metro config

* fix terminate session race condition

* remove unused analytics

* replace react-native-device-info with expo-application and expo-device

* update @react-native-clipboard/clipboard

* update @react-native-community/datetimepicker

* update @react-native-community/netinfo

* update @sentry/react-native

* update react-native-document-picker

* update react-native-gesture-handler

* update react-native-share

* update react-native-svg and react-native-svg-transformer

* update react-native-vector-icons

* update babel

* update react-native-shadow-2

* update semver

* remove react-native-svg-transformer and convert svg files to svg components

* fix @mattermost/rnshare new-arch build on android

* remove react-native-create-thumbnail resolution in build.gradle

* create @mattermost/hardware-keyboard library to replace hw-keyboard-events

* fix hardware-keyboard library

* fix rnutils library

* create @mattermost/keyboard-tracker library

* replace react-native-keyboard-tracking-view with @mattermost/keyboard-tracker

* fix: rnutils to not crash on lateinit context

* fix: rnutils delete database

* revert changes to session_manager

* Removed react-native-webview and added expo-web-browser instead

With expo-web-browser we no longer need the webview for SSO login
the SSO login is now done by using "custom Chrome tabs" on Android
and ASWebAuthenticationSession on iOS

* remove patch for react-native-keyboard-tracking-view

* replace react-native-linear-gradient with expo-linear-gradient

* replace react-native-in-app-review with expo-store-review

* fix: shared group database directory on ios

* replace react-native-fast-image with expo-image

* remove unusued type def for react-native-keyboard-tracking-view

* replace react-native-elements and react-native-button with @rneui

* node version

* update sizzling methods

* fix tests using jest-expo

* replace jail-monkey with expo-device

* update babel deps

* update typescript eslint

* update rn and expo

* react-native-document-picker @react-native-camera-roll/camera-roll @react-native-community/datetimepicker react-native-reanimated react-native-safe-area-context

* update patches

* update @sentry/react-native

* upgrade react-native-navigation

* update expo & expo-image

* upgrade to working version of @sentry/react-native

* update node, cocoapods, bundler, fastlane versions

* @testing-library/react-native and eslint-plugin-jest

* fix: FloatingTextInput causing a crash with reanimated

* update sentry, localize, @types/lodash and uuid

* fix floating text input label

* update react-native-video

* fix: cannot calculate shadow efficiently on some components

* fix: reduce motion warning for bottomSheet

* fix: shadow on YouTube component

* update react-native-webrtc expo and @typescript-eslint

* audit fix

* fix swizzling bad merge

* temp use of github dependency for @mattermost libraries

* feedback review

* feedback review

* npm audit fix

* update bundle deps

* update @mattermost/react-native-turbo-log

* update deps
2024-06-19 09:33:45 +08:00

143 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import Emm from '@mattermost/react-native-emm';
import {
type APIClientErrorEvent,
type APIClientErrorEventHandler,
getOrCreateAPIClient,
RetryTypes,
type APIClientConfiguration,
} from '@mattermost/react-native-network-client';
import {nativeApplicationVersion, nativeBuildVersion} from 'expo-application';
import {deviceName, osName, osVersion} from 'expo-device';
import {Alert, DeviceEventEmitter} from 'react-native';
import urlParse from 'url-parse';
import LocalConfig from '@assets/config.json';
import {Client} from '@client/rest';
import * as ClientConstants from '@client/rest/constants';
import ClientError from '@client/rest/error';
import {CERTIFICATE_ERRORS} from '@constants/network';
import {DEFAULT_LOCALE, getLocalizedMessage, t} from '@i18n';
import ManagedApp from '@init/managed_app';
import {logDebug, logError} from '@utils/log';
import {getCSRFFromCookie} from '@utils/security';
const CLIENT_CERTIFICATE_IMPORT_ERROR_CODES = [-103, -104, -105, -108];
const CLIENT_CERTIFICATE_MISSING_ERROR_CODE = -200;
const SERVER_CERTIFICATE_INVALID = -299;
class NetworkManager {
private clients: Record<string, Client> = {};
private DEFAULT_CONFIG: APIClientConfiguration = {
headers: {
'X-Requested-With': 'XMLHttpRequest',
...LocalConfig.CustomRequestHeaders,
},
sessionConfiguration: {
allowsCellularAccess: true,
waitsForConnectivity: false,
httpMaximumConnectionsPerHost: 10,
cancelRequestsOnUnauthorized: true,
},
retryPolicyConfiguration: {
type: RetryTypes.EXPONENTIAL_RETRY,
retryLimit: 3,
exponentialBackoffBase: 2,
exponentialBackoffScale: 0.5,
},
requestAdapterConfiguration: {
bearerAuthTokenResponseHeader: 'token',
},
};
public init = async (serverCredentials: ServerCredential[]) => {
for await (const {serverUrl, token} of serverCredentials) {
try {
await this.createClient(serverUrl, token);
} catch (error) {
logError('NetworkManager init error', error);
}
}
};
public invalidateClient = (serverUrl: string) => {
this.clients[serverUrl]?.invalidate();
delete this.clients[serverUrl];
};
public getClient = (serverUrl: string) => {
const client = this.clients[serverUrl];
if (!client) {
throw new Error(`${serverUrl} client not found`);
}
return client;
};
public createClient = async (serverUrl: string, bearerToken?: string) => {
const config = await this.buildConfig();
try {
const {client} = await getOrCreateAPIClient(serverUrl, config, this.clientErrorEventHandler);
const csrfToken = await getCSRFFromCookie(serverUrl);
this.clients[serverUrl] = new Client(client, serverUrl, bearerToken, csrfToken);
} catch (error) {
throw new ClientError(serverUrl, {
message: 'Cant find this server. Check spelling and URL format.',
intl: {
id: 'apps.error.network.no_server',
defaultMessage: 'Cant find this server. Check spelling and URL format.',
},
url: serverUrl,
details: error,
});
}
return this.clients[serverUrl];
};
private buildConfig = async () => {
const userAgent = `Mattermost Mobile/${nativeApplicationVersion}+${nativeBuildVersion} (${osName}; ${osVersion}; ${deviceName})`;
const managedConfig = ManagedApp.enabled ? Emm.getManagedConfig<ManagedConfig>() : undefined;
const headers: Record<string, string> = {
[ClientConstants.HEADER_USER_AGENT]: userAgent,
...this.DEFAULT_CONFIG.headers,
};
const config = {
...this.DEFAULT_CONFIG,
sessionConfiguration: {
...this.DEFAULT_CONFIG.sessionConfiguration,
timeoutIntervalForRequest: managedConfig?.timeout ? parseInt(managedConfig.timeout, 10) : this.DEFAULT_CONFIG.sessionConfiguration?.timeoutIntervalForRequest,
timeoutIntervalForResource: managedConfig?.timeoutVPN ? parseInt(managedConfig.timeoutVPN, 10) : this.DEFAULT_CONFIG.sessionConfiguration?.timeoutIntervalForResource,
waitsForConnectivity: managedConfig?.useVPN === 'true',
},
headers,
};
return config;
};
private clientErrorEventHandler: APIClientErrorEventHandler = (event: APIClientErrorEvent) => {
if (CLIENT_CERTIFICATE_IMPORT_ERROR_CODES.includes(event.errorCode)) {
DeviceEventEmitter.emit(CERTIFICATE_ERRORS.CLIENT_CERTIFICATE_IMPORT_ERROR, event.serverUrl);
} else if (CLIENT_CERTIFICATE_MISSING_ERROR_CODE === event.errorCode) {
DeviceEventEmitter.emit(CERTIFICATE_ERRORS.CLIENT_CERTIFICATE_MISSING, event.serverUrl);
} else if (SERVER_CERTIFICATE_INVALID === event.errorCode) {
logDebug('Invalid SSL certificate:', event.errorDescription);
const parsed = urlParse(event.serverUrl);
Alert.alert(
getLocalizedMessage(DEFAULT_LOCALE, t('server.invalid.certificate.title'), 'Invalid SSL certificate'),
getLocalizedMessage(
DEFAULT_LOCALE,
t('server.invalid.certificate.description'),
'The certificate for this server is invalid.\nYou might be connecting to a server that is pretending to be “{hostname}” which could put your confidential information at risk.',
).replace('{hostname}', parsed.hostname),
);
}
};
}
export default new NetworkManager();