From 6acd5d1501e2924a5797870017d09cca022121b9 Mon Sep 17 00:00:00 2001 From: Gerzon Z Date: Fri, 18 Feb 2022 11:46:30 -0400 Subject: [PATCH 01/13] dehydrate login methods from rocketchat.js --- app/definitions/ILoggedUser.ts | 18 +- app/lib/rocketchat/rocketchat.js | 2 +- app/lib/rocketchat/services/connect.ts | 222 +++++++++++++++++++++++++ app/lib/rocketchat/services/sdk.ts | 16 ++ 4 files changed, 255 insertions(+), 3 deletions(-) create mode 100644 app/lib/rocketchat/services/connect.ts diff --git a/app/definitions/ILoggedUser.ts b/app/definitions/ILoggedUser.ts index 380bcd86c0b..0b083cd9ade 100644 --- a/app/definitions/ILoggedUser.ts +++ b/app/definitions/ILoggedUser.ts @@ -8,11 +8,25 @@ export interface ILoggedUser { language?: string; status: string; statusText?: string; + customFields: object; + statusLivechat: string; + emails: string[]; roles: string[]; avatarETag?: string; - showMessageInMainThread: boolean; isFromWebView: boolean; - enableMessageParserEarlyAdoption?: boolean; + settings?: { + preferences: { + showMessageInMainThread: boolean; + enableMessageParserEarlyAdoption: boolean; + }; + }; +} + +export interface ILoginResult { + status: string; + authToken: string; + userId: string; + me: ILoggedUser; } export type TLoggedUserModel = ILoggedUser & Model; diff --git a/app/lib/rocketchat/rocketchat.js b/app/lib/rocketchat/rocketchat.js index b2171eacdaa..6a38c6d0853 100644 --- a/app/lib/rocketchat/rocketchat.js +++ b/app/lib/rocketchat/rocketchat.js @@ -74,7 +74,7 @@ const CERTIFICATE_KEY = 'RC_CERTIFICATE_KEY'; export const THEME_PREFERENCES_KEY = 'RC_THEME_PREFERENCES_KEY'; export const CRASH_REPORT_KEY = 'RC_CRASH_REPORT_KEY'; export const ANALYTICS_EVENTS_KEY = 'RC_ANALYTICS_EVENTS_KEY'; -const MIN_ROCKETCHAT_VERSION = '0.70.0'; +export const MIN_ROCKETCHAT_VERSION = '0.70.0'; const STATUSES = ['offline', 'online', 'away', 'busy']; diff --git a/app/lib/rocketchat/services/connect.ts b/app/lib/rocketchat/services/connect.ts new file mode 100644 index 00000000000..bf9aeca1b62 --- /dev/null +++ b/app/lib/rocketchat/services/connect.ts @@ -0,0 +1,222 @@ +import RNFetchBlob from 'rn-fetch-blob'; +import { Rocketchat as RocketchatClient, settings as RocketChatSettings } from '@rocket.chat/sdk'; + +import { useSsl } from '../../../utils/url'; +import { selectServerFailure } from '../../../actions/server'; +import { twoFactor } from '../../../utils/twoFactor'; +import { compareServerVersion } from '../../utils'; +import { store } from '../../auxStore'; +import { loginRequest, setUser } from '../../../actions/login'; +import sdk from './sdk'; +import I18n from '../../../i18n'; +import { MIN_ROCKETCHAT_VERSION } from '../rocketchat'; +import { ILoggedUser } from '../../../definitions'; + +interface ICredentials { + user?: string; + password?: string; + username?: string; + ldapPass?: string; + ldap?: boolean; + ldapOptions?: object; + crowdPassword?: string; + crowd?: boolean; + code?: string; + totp?: { + login: ICredentials; + code: string; + }; +} + +async function login(credentials: ICredentials, isFromWebView = false) { + // RC 0.64.0 + await sdk.login(credentials); + const result = sdk.currentLogin?.result; + if (result) { + const user = { + id: result.userId, + token: result.authToken, + username: result.me.username, + name: result.me.name, + language: result.me.language, + status: result.me.status, + statusText: result.me.statusText, + customFields: result.me.customFields, + statusLivechat: result.me.statusLivechat, + emails: result.me.emails, + roles: result.me.roles, + avatarETag: result.me.avatarETag, + isFromWebView, + showMessageInMainThread: result.me.settings?.preferences?.showMessageInMainThread ?? true, + enableMessageParserEarlyAdoption: result.me.settings?.preferences?.enableMessageParserEarlyAdoption ?? true + }; + return user; + } +} + +function loginTOTP(params: ICredentials, loginEmailPassword?: boolean, isFromWebView = false): Promise { + return new Promise(async (resolve, reject) => { + try { + const result = await login(params, isFromWebView); + if (result) { + return resolve(result); + } + } catch (e: any) { + if (e.data?.error && (e.data.error === 'totp-required' || e.data.error === 'totp-invalid')) { + const { details } = e.data; + try { + const code = await twoFactor({ method: details?.method || 'totp', invalid: details?.error === 'totp-invalid' }); + + if (loginEmailPassword) { + store.dispatch(setUser({ username: params.user || params.username })); + + // Force normalized params for 2FA starting RC 3.9.0. + const serverVersion = store.getState().server.version; + if (compareServerVersion(serverVersion as string, 'greaterThanOrEqualTo', '3.9.0')) { + const user = params.user ?? params.username; + const password = params.password ?? params.ldapPass ?? params.crowdPassword; + params = { user, password }; + } + + return resolve(loginTOTP({ ...params, code: code?.twoFactorCode }, loginEmailPassword)); + } + + return resolve( + loginTOTP({ + totp: { + login: { + ...params + }, + code: code?.twoFactorCode + } + }) + ); + } catch { + // twoFactor was canceled + return reject(); + } + } else { + reject(e); + } + } + }); +} + +function loginWithPassword({ user, password }: { user: string; password: string }) { + let params: ICredentials = { user, password }; + const state = store.getState(); + + if (state.settings.LDAP_Enable) { + params = { + username: user, + ldapPass: password, + ldap: true, + ldapOptions: {} + }; + } else if (state.settings.CROWD_Enable) { + params = { + username: user, + crowdPassword: password, + crowd: true + }; + } + + return loginTOTP(params, true); +} + +async function loginOAuthOrSso(params: ICredentials, isFromWebView = true) { + const result = await loginTOTP(params, false, isFromWebView); + store.dispatch(loginRequest({ resume: result.token }, false, isFromWebView)); +} + +function abort() { + if (sdk) { + return sdk.abort(); + } + return new AbortController(); +} + +function checkAndReopen() { + return sdk.checkAndReopen(); +} + +function disconnect() { + return sdk.disconnect(); +} + +async function getServerInfo(server: string) { + try { + const response = await RNFetchBlob.fetch('GET', `${server}/api/info`, { ...RocketChatSettings.customHeaders }); + try { + // Try to resolve as json + const jsonRes = response.json(); + if (!jsonRes?.success) { + return { + success: false, + message: I18n.t('Not_RC_Server', { contact: I18n.t('Contact_your_server_admin') }) + }; + } + if (compareServerVersion(jsonRes.version, 'lowerThan', MIN_ROCKETCHAT_VERSION)) { + return { + success: false, + message: I18n.t('Invalid_server_version', { + currentVersion: jsonRes.version, + minVersion: MIN_ROCKETCHAT_VERSION + }) + }; + } + return jsonRes; + } catch (error) { + // Request is successful, but response isn't a json + } + } catch (e: any) { + if (e?.message) { + if (e.message === 'Aborted') { + store.dispatch(selectServerFailure()); + throw e; + } + return { + success: false, + message: e.message + }; + } + } + + return { + success: false, + message: I18n.t('Not_RC_Server', { contact: I18n.t('Contact_your_server_admin') }) + }; +} + +async function getWebsocketInfo({ server }: { server: string }) { + const sdk = new RocketchatClient({ host: server, protocol: 'ddp', useSsl: useSsl(server) }); + + try { + await sdk.connect(); + } catch (err: any) { + if (err.message && err.message.includes('400')) { + return { + success: false, + message: I18n.t('Websocket_disabled', { contact: I18n.t('Contact_your_server_admin') }) + }; + } + } + + sdk.disconnect(); + + return { + success: true + }; +} + +export { + login, + loginTOTP, + loginWithPassword, + loginOAuthOrSso, + checkAndReopen, + abort, + disconnect, + getServerInfo, + getWebsocketInfo +}; diff --git a/app/lib/rocketchat/services/sdk.ts b/app/lib/rocketchat/services/sdk.ts index 41c124b1143..2c61239478b 100644 --- a/app/lib/rocketchat/services/sdk.ts +++ b/app/lib/rocketchat/services/sdk.ts @@ -6,10 +6,14 @@ import { twoFactor } from '../../../utils/twoFactor'; import { useSsl } from '../../../utils/url'; import reduxStore from '../../createStore'; import { Serialized, MatchPathPattern, OperationParams, PathFor, ResultFor } from '../../../definitions/rest/helpers'; +import { ILoginResult } from '../../../definitions'; class Sdk { private sdk: typeof Rocketchat; private code: any; + currentLogin: { + result: ILoginResult; + } | null = null; // TODO: We need to stop returning the SDK after all methods are dehydrated initialize(server: string) { @@ -158,6 +162,18 @@ class Sdk { onStreamData(...args: any[]) { return this.sdk.onStreamData(...args); } + + login(...args: any[]) { + return this.sdk.login(...args); + } + + checkAndReopen() { + return this.sdk.checkAndReopen(); + } + + abort() { + return this.sdk.abort(); + } } const sdk = new Sdk(); From 3aed0513bcb74513f5efd5911672bdecb3be6f18 Mon Sep 17 00:00:00 2001 From: Gerzon Z Date: Fri, 25 Feb 2022 11:31:28 -0400 Subject: [PATCH 02/13] export icredentials --- app/definitions/ICredentials.ts | 15 +++++++++++++++ app/definitions/index.ts | 1 + app/lib/rocketchat/services/connect.ts | 18 +----------------- 3 files changed, 17 insertions(+), 17 deletions(-) create mode 100644 app/definitions/ICredentials.ts diff --git a/app/definitions/ICredentials.ts b/app/definitions/ICredentials.ts new file mode 100644 index 00000000000..072b8470e5a --- /dev/null +++ b/app/definitions/ICredentials.ts @@ -0,0 +1,15 @@ +export interface ICredentials { + user?: string; + password?: string; + username?: string; + ldapPass?: string; + ldap?: boolean; + ldapOptions?: object; + crowdPassword?: string; + crowd?: boolean; + code?: string; + totp?: { + login: ICredentials; + code: string; + }; +} diff --git a/app/definitions/index.ts b/app/definitions/index.ts index c11e91b1a7d..621300b942e 100644 --- a/app/definitions/index.ts +++ b/app/definitions/index.ts @@ -24,6 +24,7 @@ export * from './IServerHistory'; export * from './IRocketChat'; export * from './ICertificate'; export * from './IUrl'; +export * from './ICredentials'; export interface IBaseScreen, S extends string> { navigation: StackNavigationProp; diff --git a/app/lib/rocketchat/services/connect.ts b/app/lib/rocketchat/services/connect.ts index bf9aeca1b62..1a2af2f8794 100644 --- a/app/lib/rocketchat/services/connect.ts +++ b/app/lib/rocketchat/services/connect.ts @@ -10,23 +10,7 @@ import { loginRequest, setUser } from '../../../actions/login'; import sdk from './sdk'; import I18n from '../../../i18n'; import { MIN_ROCKETCHAT_VERSION } from '../rocketchat'; -import { ILoggedUser } from '../../../definitions'; - -interface ICredentials { - user?: string; - password?: string; - username?: string; - ldapPass?: string; - ldap?: boolean; - ldapOptions?: object; - crowdPassword?: string; - crowd?: boolean; - code?: string; - totp?: { - login: ICredentials; - code: string; - }; -} +import { ICredentials, ILoggedUser } from '../../../definitions'; async function login(credentials: ICredentials, isFromWebView = false) { // RC 0.64.0 From 1afc7940282ea6e1e3ee52b7c7a28d505b33ab50 Mon Sep 17 00:00:00 2001 From: Gerzon Z Date: Fri, 25 Feb 2022 15:34:05 -0400 Subject: [PATCH 03/13] dehydrate login methods from rocketchat.js --- app/containers/LoginServices.tsx | 2 +- app/containers/MessageBox/index.tsx | 8 +- app/definitions/ILoggedUser.ts | 25 ++-- app/definitions/IRocketChat.ts | 1 + app/lib/rocketchat/rocketchat.js | 157 ++----------------------- app/lib/rocketchat/services/connect.ts | 99 ++++++++++++++-- app/lib/rocketchat/services/sdk.ts | 8 +- app/views/AuthenticationWebView.tsx | 1 + 8 files changed, 115 insertions(+), 186 deletions(-) diff --git a/app/containers/LoginServices.tsx b/app/containers/LoginServices.tsx index aab5c889e2f..4495c7e888f 100644 --- a/app/containers/LoginServices.tsx +++ b/app/containers/LoginServices.tsx @@ -234,7 +234,7 @@ class LoginServices extends React.PureComponent { AppleAuthentication.AppleAuthenticationScope.EMAIL ] }); - + // @ts-ignore await RocketChat.loginOAuthOrSso({ fullName, email, identityToken }); } catch { logEvent(events.ENTER_WITH_APPLE_F); diff --git a/app/containers/MessageBox/index.tsx b/app/containers/MessageBox/index.tsx index 3c924df6f00..de1666223b7 100644 --- a/app/containers/MessageBox/index.tsx +++ b/app/containers/MessageBox/index.tsx @@ -49,6 +49,7 @@ import { sanitizeLikeString } from '../../lib/database/utils'; import { CustomIcon } from '../../lib/Icons'; import { IMessage } from '../../definitions/IMessage'; import { forceJpgExtension } from './forceJpgExtension'; +import { IUser } from '../../definitions'; if (isAndroid) { require('./EmojiKeyboard'); @@ -80,12 +81,7 @@ interface IMessageBoxProps { editing: boolean; threadsEnabled: boolean; isFocused(): boolean; - user: { - id: string; - _id: string; - username: string; - token: string; - }; + user: IUser; roomType: string; tmid: string; replyWithMention: boolean; diff --git a/app/definitions/ILoggedUser.ts b/app/definitions/ILoggedUser.ts index 0b083cd9ade..d83f87fa5e9 100644 --- a/app/definitions/ILoggedUser.ts +++ b/app/definitions/ILoggedUser.ts @@ -1,28 +1,29 @@ import Model from '@nozbe/watermelondb/Model'; +import { IUserEmail } from './IUser'; +import { UserStatus } from './UserStatus'; + export interface ILoggedUser { id: string; token: string; username: string; name: string; language?: string; - status: string; + status: UserStatus; statusText?: string; - customFields: object; - statusLivechat: string; - emails: string[]; - roles: string[]; + customFields?: { + [key: string]: any; + }; + statusLivechat?: string; + emails?: IUserEmail[]; + roles?: string[]; avatarETag?: string; isFromWebView: boolean; - settings?: { - preferences: { - showMessageInMainThread: boolean; - enableMessageParserEarlyAdoption: boolean; - }; - }; + showMessageInMainThread: boolean; + enableMessageParserEarlyAdoption: boolean; } -export interface ILoginResult { +export interface ILoginResultFromServer { status: string; authToken: string; userId: string; diff --git a/app/definitions/IRocketChat.ts b/app/definitions/IRocketChat.ts index 654e2c92c0d..91d701a5d15 100644 --- a/app/definitions/IRocketChat.ts +++ b/app/definitions/IRocketChat.ts @@ -4,6 +4,7 @@ type TRocketChat = typeof rocketchat; export interface IRocketChat extends TRocketChat { sdk: any; + shareSDK: any; activeUsersSubTimeout: any; roomsSub: any; } diff --git a/app/lib/rocketchat/rocketchat.js b/app/lib/rocketchat/rocketchat.js index 6a38c6d0853..b0199ea85de 100644 --- a/app/lib/rocketchat/rocketchat.js +++ b/app/lib/rocketchat/rocketchat.js @@ -65,6 +65,7 @@ import getUserInfo from './services/getUserInfo'; // Services import sdk from './services/sdk'; import toggleFavorite from './services/toggleFavorite'; +import { login, loginTOTP, loginWithPassword, loginOAuthOrSso, getLoginServices, _determineAuthType } from './services/connect'; import * as restAPis from './services/restApi'; const TOKEN_KEY = 'reactnativemeteor_usertoken'; @@ -487,103 +488,10 @@ const RocketChat = { return this.methodCallWrapper('e2e.resetOwnE2EKey'); }, - loginTOTP(params, loginEmailPassword, isFromWebView = false) { - return new Promise(async (resolve, reject) => { - try { - const result = await this.login(params, isFromWebView); - return resolve(result); - } catch (e) { - if (e.data?.error && (e.data.error === 'totp-required' || e.data.error === 'totp-invalid')) { - const { details } = e.data; - try { - const code = await twoFactor({ method: details?.method || 'totp', invalid: details?.error === 'totp-invalid' }); - - if (loginEmailPassword) { - reduxStore.dispatch(setUser({ username: params.user || params.username })); - - // Force normalized params for 2FA starting RC 3.9.0. - const serverVersion = reduxStore.getState().server.version; - if (compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '3.9.0')) { - const user = params.user ?? params.username; - const password = params.password ?? params.ldapPass ?? params.crowdPassword; - params = { user, password }; - } - - return resolve(this.loginTOTP({ ...params, code: code?.twoFactorCode }, loginEmailPassword)); - } - - return resolve( - this.loginTOTP({ - totp: { - login: { - ...params - }, - code: code?.twoFactorCode - } - }) - ); - } catch { - // twoFactor was canceled - return reject(); - } - } else { - reject(e); - } - } - }); - }, - - loginWithPassword({ user, password }) { - let params = { user, password }; - const state = reduxStore.getState(); - - if (state.settings.LDAP_Enable) { - params = { - username: user, - ldapPass: password, - ldap: true, - ldapOptions: {} - }; - } else if (state.settings.CROWD_Enable) { - params = { - username: user, - crowdPassword: password, - crowd: true - }; - } - - return this.loginTOTP(params, true); - }, - - async loginOAuthOrSso(params, isFromWebView = true) { - const result = await this.loginTOTP(params, false, isFromWebView); - reduxStore.dispatch(loginRequest({ resume: result.token }, false, isFromWebView)); - }, - - async login(credentials, isFromWebView = false) { - const sdk = this.shareSDK || this.sdk; - // RC 0.64.0 - await sdk.login(credentials); - const { result } = sdk.currentLogin; - const user = { - id: result.userId, - token: result.authToken, - username: result.me.username, - name: result.me.name, - language: result.me.language, - status: result.me.status, - statusText: result.me.statusText, - customFields: result.me.customFields, - statusLivechat: result.me.statusLivechat, - emails: result.me.emails, - roles: result.me.roles, - avatarETag: result.me.avatarETag, - isFromWebView, - showMessageInMainThread: result.me.settings?.preferences?.showMessageInMainThread ?? true, - enableMessageParserEarlyAdoption: result.me.settings?.preferences?.enableMessageParserEarlyAdoption ?? true - }; - return user; - }, + loginTOTP, + loginWithPassword, + loginOAuthOrSso, + login, logout, logoutOtherLocations() { const { id: userId } = reduxStore.getState().login.user; @@ -928,59 +836,8 @@ const RocketChat = { prefs = { ...prefs, ...param }; return UserPreferences.setMapAsync(SORT_PREFS_KEY, prefs); }, - async getLoginServices(server) { - try { - let loginServices = []; - const loginServicesResult = await fetch(`${server}/api/v1/settings.oauth`).then(response => response.json()); - - if (loginServicesResult.success && loginServicesResult.services) { - const { services } = loginServicesResult; - loginServices = services; - - const loginServicesReducer = loginServices.reduce((ret, item) => { - const name = item.name || item.buttonLabelText || item.service; - const authType = this._determineAuthType(item); - - if (authType !== 'not_supported') { - ret[name] = { ...item, name, authType }; - } - - return ret; - }, {}); - reduxStore.dispatch(setLoginServices(loginServicesReducer)); - } else { - reduxStore.dispatch(setLoginServices({})); - } - } catch (error) { - console.log(error); - reduxStore.dispatch(setLoginServices({})); - } - }, - _determineAuthType(services) { - const { name, custom, showButton = true, service } = services; - - const authName = name || service; - - if (custom && showButton) { - return 'oauth_custom'; - } - - if (service === 'saml') { - return 'saml'; - } - - if (service === 'cas') { - return 'cas'; - } - - if (authName === 'apple' && isIOS) { - return 'apple'; - } - - // TODO: remove this after other oauth providers are implemented. e.g. Drupal, github_enterprise - const availableOAuth = ['facebook', 'github', 'gitlab', 'google', 'linkedin', 'meteor-developer', 'twitter', 'wordpress']; - return availableOAuth.includes(authName) ? 'oauth' : 'not_supported'; - }, + getLoginServices, + _determineAuthType, roomTypeToApiType, readThreads(tmid) { const serverVersion = reduxStore.getState().server.version; diff --git a/app/lib/rocketchat/services/connect.ts b/app/lib/rocketchat/services/connect.ts index 1a2af2f8794..b7058c2fdec 100644 --- a/app/lib/rocketchat/services/connect.ts +++ b/app/lib/rocketchat/services/connect.ts @@ -6,18 +6,29 @@ import { selectServerFailure } from '../../../actions/server'; import { twoFactor } from '../../../utils/twoFactor'; import { compareServerVersion } from '../../utils'; import { store } from '../../auxStore'; -import { loginRequest, setUser } from '../../../actions/login'; +import { loginRequest, setLoginServices, setUser } from '../../../actions/login'; import sdk from './sdk'; import I18n from '../../../i18n'; import { MIN_ROCKETCHAT_VERSION } from '../rocketchat'; -import { ICredentials, ILoggedUser } from '../../../definitions'; +import { ICredentials, ILoggedUser, IRocketChat } from '../../../definitions'; +import { isIOS } from '../../../utils/deviceInfo'; -async function login(credentials: ICredentials, isFromWebView = false) { +interface IServices { + [index: string]: string | boolean; + name: string; + custom: boolean; + showButton: boolean; + buttonLabelText: string; + service: string; +} + +async function login(this: IRocketChat, credentials: ICredentials, isFromWebView = false): Promise { + const sdk = this.shareSDK || this.sdk; // RC 0.64.0 await sdk.login(credentials); const result = sdk.currentLogin?.result; if (result) { - const user = { + const user: ILoggedUser = { id: result.userId, token: result.authToken, username: result.me.username, @@ -38,10 +49,15 @@ async function login(credentials: ICredentials, isFromWebView = false) { } } -function loginTOTP(params: ICredentials, loginEmailPassword?: boolean, isFromWebView = false): Promise { +function loginTOTP( + this: IRocketChat, + params: ICredentials, + loginEmailPassword?: boolean, + isFromWebView = false +): Promise { return new Promise(async (resolve, reject) => { try { - const result = await login(params, isFromWebView); + const result = await this.login(params, isFromWebView); if (result) { return resolve(result); } @@ -62,11 +78,11 @@ function loginTOTP(params: ICredentials, loginEmailPassword?: boolean, isFromWeb params = { user, password }; } - return resolve(loginTOTP({ ...params, code: code?.twoFactorCode }, loginEmailPassword)); + return resolve(this.loginTOTP({ ...params, code: code?.twoFactorCode }, loginEmailPassword)); } return resolve( - loginTOTP({ + this.loginTOTP({ totp: { login: { ...params @@ -86,7 +102,7 @@ function loginTOTP(params: ICredentials, loginEmailPassword?: boolean, isFromWeb }); } -function loginWithPassword({ user, password }: { user: string; password: string }) { +function loginWithPassword(this: IRocketChat, { user, password }: { user: string; password: string }) { let params: ICredentials = { user, password }; const state = store.getState(); @@ -105,11 +121,11 @@ function loginWithPassword({ user, password }: { user: string; password: string }; } - return loginTOTP(params, true); + return this.loginTOTP(params, true); } -async function loginOAuthOrSso(params: ICredentials, isFromWebView = true) { - const result = await loginTOTP(params, false, isFromWebView); +async function loginOAuthOrSso(this: IRocketChat, params: ICredentials, isFromWebView = true) { + const result = await this.loginTOTP(params, false, isFromWebView); store.dispatch(loginRequest({ resume: result.token }, false, isFromWebView)); } @@ -193,6 +209,61 @@ async function getWebsocketInfo({ server }: { server: string }) { }; } +async function getLoginServices(this: IRocketChat, server: string) { + try { + let loginServices = []; + const loginServicesResult = await fetch(`${server}/api/v1/settings.oauth`).then(response => response.json()); + + if (loginServicesResult.success && loginServicesResult.services) { + const { services } = loginServicesResult; + loginServices = services; + + const loginServicesReducer = loginServices.reduce((ret: IServices[], item: IServices) => { + const name = item.name || item.buttonLabelText || item.service; + const authType = this._determineAuthType(item); + + if (authType !== 'not_supported') { + ret[name as unknown as number] = { ...item, name, authType }; + } + + return ret; + }, {}); + store.dispatch(setLoginServices(loginServicesReducer)); + } else { + store.dispatch(setLoginServices({})); + } + } catch (error) { + console.log(error); + store.dispatch(setLoginServices({})); + } +} + +function _determineAuthType(services: IServices) { + const { name, custom, showButton = true, service } = services; + + const authName = name || service; + + if (custom && showButton) { + return 'oauth_custom'; + } + + if (service === 'saml') { + return 'saml'; + } + + if (service === 'cas') { + return 'cas'; + } + + if (authName === 'apple' && isIOS) { + return 'apple'; + } + + // TODO: remove this after other oauth providers are implemented. e.g. Drupal, github_enterprise + const availableOAuth = ['facebook', 'github', 'gitlab', 'google', 'linkedin', 'meteor-developer', 'twitter', 'wordpress']; + return availableOAuth.includes(authName) ? 'oauth' : 'not_supported'; +} + export { login, loginTOTP, @@ -202,5 +273,7 @@ export { abort, disconnect, getServerInfo, - getWebsocketInfo + getWebsocketInfo, + getLoginServices, + _determineAuthType }; diff --git a/app/lib/rocketchat/services/sdk.ts b/app/lib/rocketchat/services/sdk.ts index 2c61239478b..13af977e2c2 100644 --- a/app/lib/rocketchat/services/sdk.ts +++ b/app/lib/rocketchat/services/sdk.ts @@ -6,13 +6,13 @@ import { twoFactor } from '../../../utils/twoFactor'; import { useSsl } from '../../../utils/url'; import reduxStore from '../../createStore'; import { Serialized, MatchPathPattern, OperationParams, PathFor, ResultFor } from '../../../definitions/rest/helpers'; -import { ILoginResult } from '../../../definitions'; +import { ICredentials, ILoginResultFromServer } from '../../../definitions'; class Sdk { private sdk: typeof Rocketchat; private code: any; currentLogin: { - result: ILoginResult; + result: ILoginResultFromServer; } | null = null; // TODO: We need to stop returning the SDK after all methods are dehydrated @@ -163,8 +163,8 @@ class Sdk { return this.sdk.onStreamData(...args); } - login(...args: any[]) { - return this.sdk.login(...args); + login(credentials: ICredentials) { + return this.sdk.login(credentials); } checkAndReopen() { diff --git a/app/views/AuthenticationWebView.tsx b/app/views/AuthenticationWebView.tsx index ac304fbfb5e..d9eb5a1114a 100644 --- a/app/views/AuthenticationWebView.tsx +++ b/app/views/AuthenticationWebView.tsx @@ -102,6 +102,7 @@ class AuthenticationWebView extends React.PureComponent Date: Fri, 25 Feb 2022 16:09:21 -0400 Subject: [PATCH 04/13] remove unused imports --- app/lib/rocketchat/rocketchat.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/lib/rocketchat/rocketchat.js b/app/lib/rocketchat/rocketchat.js index b0199ea85de..2a068b1ddcf 100644 --- a/app/lib/rocketchat/rocketchat.js +++ b/app/lib/rocketchat/rocketchat.js @@ -7,7 +7,7 @@ import RNFetchBlob from 'rn-fetch-blob'; import { setActiveUsers } from '../../actions/activeUsers'; import { connectRequest, connectSuccess, disconnect } from '../../actions/connect'; import { encryptionInit } from '../../actions/encryption'; -import { loginRequest, setLoginServices, setUser } from '../../actions/login'; +import { loginRequest, setUser } from '../../actions/login'; import { updatePermission } from '../../actions/permissions'; import { selectServerFailure } from '../../actions/server'; import { updateSettings } from '../../actions/settings'; @@ -17,10 +17,8 @@ import I18n from '../../i18n'; import { getDeviceToken } from '../../notifications/push'; import { getBundleId, isIOS } from '../../utils/deviceInfo'; import EventEmitter from '../../utils/events'; -import fetch from '../../utils/fetch'; import log from '../../utils/log'; import SSLPinning from '../../utils/sslPinning'; -import { twoFactor } from '../../utils/twoFactor'; import { useSsl } from '../../utils/url'; import database from '../database'; import { sanitizeLikeString } from '../database/utils'; From ab8ff58fba1ec581d6b1d1b5b24a799db7e7c63e Mon Sep 17 00:00:00 2001 From: Gerzon Z Date: Sat, 26 Feb 2022 13:48:03 -0400 Subject: [PATCH 05/13] dehydrate abort, checkAndReopen and disconnect --- app/definitions/ILoggedUser.ts | 27 +++++++++++++++---- app/lib/rocketchat/rocketchat.js | 36 ++++++++++++-------------- app/lib/rocketchat/services/connect.ts | 36 +++++++++++--------------- 3 files changed, 54 insertions(+), 45 deletions(-) diff --git a/app/definitions/ILoggedUser.ts b/app/definitions/ILoggedUser.ts index d83f87fa5e9..b9864b2d4f7 100644 --- a/app/definitions/ILoggedUser.ts +++ b/app/definitions/ILoggedUser.ts @@ -1,6 +1,6 @@ import Model from '@nozbe/watermelondb/Model'; -import { IUserEmail } from './IUser'; +import { IUserEmail, IUserSettings } from './IUser'; import { UserStatus } from './UserStatus'; export interface ILoggedUser { @@ -18,16 +18,33 @@ export interface ILoggedUser { emails?: IUserEmail[]; roles?: string[]; avatarETag?: string; - isFromWebView: boolean; - showMessageInMainThread: boolean; - enableMessageParserEarlyAdoption: boolean; + showMessageInMainThread?: boolean; + isFromWebView?: boolean; + enableMessageParserEarlyAdoption?: boolean; } export interface ILoginResultFromServer { status: string; authToken: string; userId: string; - me: ILoggedUser; + me: { + id: string; + token: string; + username: string; + name: string; + language?: string; + status: UserStatus; + statusText?: string; + customFields?: { + [key: string]: any; + }; + statusLivechat?: string; + emails?: IUserEmail[]; + roles?: string[]; + avatarETag?: string; + isFromWebView?: boolean; + settings: IUserSettings; + }; } export type TLoggedUserModel = ILoggedUser & Model; diff --git a/app/lib/rocketchat/rocketchat.js b/app/lib/rocketchat/rocketchat.js index 2a068b1ddcf..5d39f760b40 100644 --- a/app/lib/rocketchat/rocketchat.js +++ b/app/lib/rocketchat/rocketchat.js @@ -5,7 +5,7 @@ import { Rocketchat as RocketchatClient, settings as RocketChatSettings } from ' import { InteractionManager } from 'react-native'; import RNFetchBlob from 'rn-fetch-blob'; import { setActiveUsers } from '../../actions/activeUsers'; -import { connectRequest, connectSuccess, disconnect } from '../../actions/connect'; +import { connectRequest, connectSuccess, disconnect as disconnectAction } from '../../actions/connect'; import { encryptionInit } from '../../actions/encryption'; import { loginRequest, setUser } from '../../actions/login'; import { updatePermission } from '../../actions/permissions'; @@ -63,7 +63,17 @@ import getUserInfo from './services/getUserInfo'; // Services import sdk from './services/sdk'; import toggleFavorite from './services/toggleFavorite'; -import { login, loginTOTP, loginWithPassword, loginOAuthOrSso, getLoginServices, _determineAuthType } from './services/connect'; +import { + login, + loginTOTP, + loginWithPassword, + loginOAuthOrSso, + getLoginServices, + determineAuthType, + disconnect, + checkAndReopen, + abort +} from './services/connect'; import * as restAPis from './services/restApi'; const TOKEN_KEY = 'reactnativemeteor_usertoken'; @@ -167,21 +177,9 @@ const RocketChat = { return listener && listener.stop(); }, // Abort all requests and create a new AbortController - abort() { - if (this.controller) { - this.controller.abort(); - if (this.sdk) { - this.sdk.abort(); - } - } - this.controller = new AbortController(); - }, - checkAndReopen() { - return this?.sdk?.checkAndReopen(); - }, - disconnect() { - this.sdk = sdk.disconnect(); - }, + abort, + checkAndReopen, + disconnect, connect({ server, user, logoutOnError = false }) { return new Promise(resolve => { if (this?.sdk?.client?.host === server) { @@ -257,7 +255,7 @@ const RocketChat = { }); this.closeListener = this.sdk.onStreamData('close', () => { - reduxStore.dispatch(disconnect()); + reduxStore.dispatch(disconnectAction()); }); this.usersListener = this.sdk.onStreamData( @@ -835,7 +833,7 @@ const RocketChat = { return UserPreferences.setMapAsync(SORT_PREFS_KEY, prefs); }, getLoginServices, - _determineAuthType, + determineAuthType, roomTypeToApiType, readThreads(tmid) { const serverVersion = reduxStore.getState().server.version; diff --git a/app/lib/rocketchat/services/connect.ts b/app/lib/rocketchat/services/connect.ts index b7058c2fdec..0b0d8489881 100644 --- a/app/lib/rocketchat/services/connect.ts +++ b/app/lib/rocketchat/services/connect.ts @@ -10,7 +10,7 @@ import { loginRequest, setLoginServices, setUser } from '../../../actions/login' import sdk from './sdk'; import I18n from '../../../i18n'; import { MIN_ROCKETCHAT_VERSION } from '../rocketchat'; -import { ICredentials, ILoggedUser, IRocketChat } from '../../../definitions'; +import { ICredentials, ILoggedUser } from '../../../definitions'; import { isIOS } from '../../../utils/deviceInfo'; interface IServices { @@ -22,10 +22,9 @@ interface IServices { service: string; } -async function login(this: IRocketChat, credentials: ICredentials, isFromWebView = false): Promise { - const sdk = this.shareSDK || this.sdk; +async function login(credentials: ICredentials, isFromWebView = false): Promise { // RC 0.64.0 - await sdk.login(credentials); + await sdk.current.login(credentials); const result = sdk.currentLogin?.result; if (result) { const user: ILoggedUser = { @@ -49,15 +48,10 @@ async function login(this: IRocketChat, credentials: ICredentials, isFromWebView } } -function loginTOTP( - this: IRocketChat, - params: ICredentials, - loginEmailPassword?: boolean, - isFromWebView = false -): Promise { +function loginTOTP(params: ICredentials, loginEmailPassword?: boolean, isFromWebView = false): Promise { return new Promise(async (resolve, reject) => { try { - const result = await this.login(params, isFromWebView); + const result = await login(params, isFromWebView); if (result) { return resolve(result); } @@ -78,11 +72,11 @@ function loginTOTP( params = { user, password }; } - return resolve(this.loginTOTP({ ...params, code: code?.twoFactorCode }, loginEmailPassword)); + return resolve(loginTOTP({ ...params, code: code?.twoFactorCode }, loginEmailPassword)); } return resolve( - this.loginTOTP({ + loginTOTP({ totp: { login: { ...params @@ -102,7 +96,7 @@ function loginTOTP( }); } -function loginWithPassword(this: IRocketChat, { user, password }: { user: string; password: string }) { +function loginWithPassword({ user, password }: { user: string; password: string }) { let params: ICredentials = { user, password }; const state = store.getState(); @@ -121,11 +115,11 @@ function loginWithPassword(this: IRocketChat, { user, password }: { user: string }; } - return this.loginTOTP(params, true); + return loginTOTP(params, true); } -async function loginOAuthOrSso(this: IRocketChat, params: ICredentials, isFromWebView = true) { - const result = await this.loginTOTP(params, false, isFromWebView); +async function loginOAuthOrSso(params: ICredentials, isFromWebView = true) { + const result = await loginTOTP(params, false, isFromWebView); store.dispatch(loginRequest({ resume: result.token }, false, isFromWebView)); } @@ -209,7 +203,7 @@ async function getWebsocketInfo({ server }: { server: string }) { }; } -async function getLoginServices(this: IRocketChat, server: string) { +async function getLoginServices(server: string) { try { let loginServices = []; const loginServicesResult = await fetch(`${server}/api/v1/settings.oauth`).then(response => response.json()); @@ -220,7 +214,7 @@ async function getLoginServices(this: IRocketChat, server: string) { const loginServicesReducer = loginServices.reduce((ret: IServices[], item: IServices) => { const name = item.name || item.buttonLabelText || item.service; - const authType = this._determineAuthType(item); + const authType = determineAuthType(item); if (authType !== 'not_supported') { ret[name as unknown as number] = { ...item, name, authType }; @@ -238,7 +232,7 @@ async function getLoginServices(this: IRocketChat, server: string) { } } -function _determineAuthType(services: IServices) { +function determineAuthType(services: IServices) { const { name, custom, showButton = true, service } = services; const authName = name || service; @@ -275,5 +269,5 @@ export { getServerInfo, getWebsocketInfo, getLoginServices, - _determineAuthType + determineAuthType }; From 3aa227e699a46644c31a4c77c886d877cc50f219 Mon Sep 17 00:00:00 2001 From: Gerzon Z Date: Wed, 2 Mar 2022 12:42:40 -0400 Subject: [PATCH 06/13] update: ILoginResultFromServer remove: `shareSDK` from IRocketChat update: `getWebsocketInfo` add: connect method to SDK --- app/definitions/ILoggedUser.ts | 24 ++++++------------------ app/definitions/IRocketChat.ts | 1 - app/lib/rocketchat/services/connect.ts | 5 ++--- app/lib/rocketchat/services/sdk.ts | 4 ++++ 4 files changed, 12 insertions(+), 22 deletions(-) diff --git a/app/definitions/ILoggedUser.ts b/app/definitions/ILoggedUser.ts index b9864b2d4f7..c13d420fb63 100644 --- a/app/definitions/ILoggedUser.ts +++ b/app/definitions/ILoggedUser.ts @@ -23,28 +23,16 @@ export interface ILoggedUser { enableMessageParserEarlyAdoption?: boolean; } +export interface ILoggedUserResultFromServer + extends Omit { + settings: IUserSettings; +} + export interface ILoginResultFromServer { status: string; authToken: string; userId: string; - me: { - id: string; - token: string; - username: string; - name: string; - language?: string; - status: UserStatus; - statusText?: string; - customFields?: { - [key: string]: any; - }; - statusLivechat?: string; - emails?: IUserEmail[]; - roles?: string[]; - avatarETag?: string; - isFromWebView?: boolean; - settings: IUserSettings; - }; + me: ILoggedUserResultFromServer; } export type TLoggedUserModel = ILoggedUser & Model; diff --git a/app/definitions/IRocketChat.ts b/app/definitions/IRocketChat.ts index 91d701a5d15..654e2c92c0d 100644 --- a/app/definitions/IRocketChat.ts +++ b/app/definitions/IRocketChat.ts @@ -4,7 +4,6 @@ type TRocketChat = typeof rocketchat; export interface IRocketChat extends TRocketChat { sdk: any; - shareSDK: any; activeUsersSubTimeout: any; roomsSub: any; } diff --git a/app/lib/rocketchat/services/connect.ts b/app/lib/rocketchat/services/connect.ts index 0b0d8489881..a3e9c352315 100644 --- a/app/lib/rocketchat/services/connect.ts +++ b/app/lib/rocketchat/services/connect.ts @@ -1,7 +1,6 @@ import RNFetchBlob from 'rn-fetch-blob'; -import { Rocketchat as RocketchatClient, settings as RocketChatSettings } from '@rocket.chat/sdk'; +import { settings as RocketChatSettings } from '@rocket.chat/sdk'; -import { useSsl } from '../../../utils/url'; import { selectServerFailure } from '../../../actions/server'; import { twoFactor } from '../../../utils/twoFactor'; import { compareServerVersion } from '../../utils'; @@ -183,7 +182,7 @@ async function getServerInfo(server: string) { } async function getWebsocketInfo({ server }: { server: string }) { - const sdk = new RocketchatClient({ host: server, protocol: 'ddp', useSsl: useSsl(server) }); + sdk.initialize(server); try { await sdk.connect(); diff --git a/app/lib/rocketchat/services/sdk.ts b/app/lib/rocketchat/services/sdk.ts index 13af977e2c2..a23f6621794 100644 --- a/app/lib/rocketchat/services/sdk.ts +++ b/app/lib/rocketchat/services/sdk.ts @@ -174,6 +174,10 @@ class Sdk { abort() { return this.sdk.abort(); } + + connect() { + return this.sdk.connect(); + } } const sdk = new Sdk(); From 06c9c7979d35ea724e5d6584b98d06d39815d8b5 Mon Sep 17 00:00:00 2001 From: Gerzon Z Date: Fri, 4 Mar 2022 11:34:31 -0400 Subject: [PATCH 07/13] add: `connect` and `stopListener` to `connect.ts` update: `login`, `abort`, `checkAndReopen` and`getWebsocketInfo` methods chore: dehydrate methods from `rocketchat.js` to `connect.ts` update: IRocketChat interface remove: methods from `sdk.ts` --- app/definitions/IRocketChat.ts | 10 + app/lib/rocketchat/rocketchat.js | 290 +------------------------ app/lib/rocketchat/services/connect.ts | 258 +++++++++++++++++++++- app/lib/rocketchat/services/sdk.ts | 18 +- 4 files changed, 270 insertions(+), 306 deletions(-) diff --git a/app/definitions/IRocketChat.ts b/app/definitions/IRocketChat.ts index 654e2c92c0d..e9401067bde 100644 --- a/app/definitions/IRocketChat.ts +++ b/app/definitions/IRocketChat.ts @@ -3,6 +3,16 @@ import rocketchat from '../lib/rocketchat'; type TRocketChat = typeof rocketchat; export interface IRocketChat extends TRocketChat { + closeListener: any; + usersListener: any; + notifyAllListener: any; + rolesListener: any; + notifyLoggedListener: any; + activeUsers: any; + _setUserTimer: any; + connectedListener: any; + connectingListener: any; + connectTimeout: any; sdk: any; activeUsersSubTimeout: any; roomsSub: any; diff --git a/app/lib/rocketchat/rocketchat.js b/app/lib/rocketchat/rocketchat.js index 8a852a43048..10a2399cb35 100644 --- a/app/lib/rocketchat/rocketchat.js +++ b/app/lib/rocketchat/rocketchat.js @@ -72,7 +72,11 @@ import { determineAuthType, disconnect, checkAndReopen, - abort + abort, + getServerInfo, + getWebsocketInfo, + stopListener, + connect } from './services/connect'; import * as restAPis from './services/restApi'; @@ -84,8 +88,7 @@ export const THEME_PREFERENCES_KEY = 'RC_THEME_PREFERENCES_KEY'; export const CRASH_REPORT_KEY = 'RC_CRASH_REPORT_KEY'; export const ANALYTICS_EVENTS_KEY = 'RC_ANALYTICS_EVENTS_KEY'; export const MIN_ROCKETCHAT_VERSION = '0.70.0'; - -const STATUSES = ['offline', 'online', 'away', 'busy']; +export const STATUSES = ['offline', 'online', 'away', 'busy']; const RocketChat = { TOKEN_KEY, @@ -110,287 +113,14 @@ const RocketChat = { } }, canOpenRoom, - async getWebsocketInfo({ server }) { - const sdk = new RocketchatClient({ host: server, protocol: 'ddp', useSsl: useSsl(server) }); - - try { - await sdk.connect(); - } catch (err) { - if (err.message && err.message.includes('400')) { - return { - success: false, - message: I18n.t('Websocket_disabled', { contact: I18n.t('Contact_your_server_admin') }) - }; - } - } - - sdk.disconnect(); - - return { - success: true - }; - }, - async getServerInfo(server) { - try { - const response = await RNFetchBlob.fetch('GET', `${server}/api/info`, { ...RocketChatSettings.customHeaders }); - try { - // Try to resolve as json - const jsonRes = response.json(); - if (!jsonRes?.success) { - return { - success: false, - message: I18n.t('Not_RC_Server', { contact: I18n.t('Contact_your_server_admin') }) - }; - } - if (compareServerVersion(jsonRes.version, 'lowerThan', MIN_ROCKETCHAT_VERSION)) { - return { - success: false, - message: I18n.t('Invalid_server_version', { - currentVersion: jsonRes.version, - minVersion: MIN_ROCKETCHAT_VERSION - }) - }; - } - return jsonRes; - } catch (error) { - // Request is successful, but response isn't a json - } - } catch (e) { - if (e?.message) { - if (e.message === 'Aborted') { - reduxStore.dispatch(selectServerFailure()); - throw e; - } - return { - success: false, - message: e.message - }; - } - } - - return { - success: false, - message: I18n.t('Not_RC_Server', { contact: I18n.t('Contact_your_server_admin') }) - }; - }, - stopListener(listener) { - return listener && listener.stop(); - }, + getWebsocketInfo, + getServerInfo, + stopListener, // Abort all requests and create a new AbortController abort, checkAndReopen, disconnect, - connect({ server, user, logoutOnError = false }) { - return new Promise(resolve => { - if (this?.sdk?.client?.host === server) { - return resolve(); - } else { - this.disconnect(); - database.setActiveDB(server); - } - reduxStore.dispatch(connectRequest()); - - if (this.connectTimeout) { - clearTimeout(this.connectTimeout); - } - - if (this.connectingListener) { - this.connectingListener.then(this.stopListener); - } - - if (this.connectedListener) { - this.connectedListener.then(this.stopListener); - } - - if (this.closeListener) { - this.closeListener.then(this.stopListener); - } - - if (this.usersListener) { - this.usersListener.then(this.stopListener); - } - - if (this.notifyAllListener) { - this.notifyAllListener.then(this.stopListener); - } - - if (this.rolesListener) { - this.rolesListener.then(this.stopListener); - } - - if (this.notifyLoggedListener) { - this.notifyLoggedListener.then(this.stopListener); - } - - this.unsubscribeRooms(); - - EventEmitter.emit('INQUIRY_UNSUBSCRIBE'); - - this.sdk = sdk.initialize(server); - this.getSettings(); - - this.sdk - .connect() - .then(() => { - console.log('connected'); - }) - .catch(err => { - console.log('connect error', err); - }); - - this.connectingListener = this.sdk.onStreamData('connecting', () => { - reduxStore.dispatch(connectRequest()); - }); - - this.connectedListener = this.sdk.onStreamData('connected', () => { - const { connected } = reduxStore.getState().meteor; - if (connected) { - return; - } - reduxStore.dispatch(connectSuccess()); - const { server: currentServer } = reduxStore.getState().server; - if (user?.token && server === currentServer) { - reduxStore.dispatch(loginRequest({ resume: user.token }, logoutOnError)); - } - }); - - this.closeListener = this.sdk.onStreamData('close', () => { - reduxStore.dispatch(disconnectAction()); - }); - - this.usersListener = this.sdk.onStreamData( - 'users', - protectedFunction(ddpMessage => RocketChat._setUser(ddpMessage)) - ); - - this.notifyAllListener = this.sdk.onStreamData( - 'stream-notify-all', - protectedFunction(async ddpMessage => { - const { eventName } = ddpMessage.fields; - if (/public-settings-changed/.test(eventName)) { - const { _id, value } = ddpMessage.fields.args[1]; - const db = database.active; - const settingsCollection = db.get('settings'); - try { - const settingsRecord = await settingsCollection.find(_id); - const { type } = defaultSettings[_id]; - if (type) { - await db.action(async () => { - await settingsRecord.update(u => { - u[type] = value; - }); - }); - } - reduxStore.dispatch(updateSettings(_id, value)); - } catch (e) { - log(e); - } - } - }) - ); - - this.rolesListener = this.sdk.onStreamData( - 'stream-roles', - protectedFunction(ddpMessage => onRolesChanged(ddpMessage)) - ); - - // RC 4.1 - this.sdk.onStreamData('stream-user-presence', ddpMessage => { - const userStatus = ddpMessage.fields.args[0]; - const { uid } = ddpMessage.fields; - const [, status, statusText] = userStatus; - const newStatus = { status: STATUSES[status], statusText }; - reduxStore.dispatch(setActiveUsers({ [uid]: newStatus })); - - const { user: loggedUser } = reduxStore.getState().login; - if (loggedUser && loggedUser.id === uid) { - reduxStore.dispatch(setUser(newStatus)); - } - }); - - this.notifyLoggedListener = this.sdk.onStreamData( - 'stream-notify-logged', - protectedFunction(async ddpMessage => { - const { eventName } = ddpMessage.fields; - - // `user-status` event is deprecated after RC 4.1 in favor of `stream-user-presence/${uid}` - if (/user-status/.test(eventName)) { - this.activeUsers = this.activeUsers || {}; - if (!this._setUserTimer) { - this._setUserTimer = setTimeout(() => { - const activeUsersBatch = this.activeUsers; - InteractionManager.runAfterInteractions(() => { - reduxStore.dispatch(setActiveUsers(activeUsersBatch)); - }); - this._setUserTimer = null; - return (this.activeUsers = {}); - }, 10000); - } - const userStatus = ddpMessage.fields.args[0]; - const [id, , status, statusText] = userStatus; - this.activeUsers[id] = { status: STATUSES[status], statusText }; - - const { user: loggedUser } = reduxStore.getState().login; - if (loggedUser && loggedUser.id === id) { - reduxStore.dispatch(setUser({ status: STATUSES[status], statusText })); - } - } else if (/updateAvatar/.test(eventName)) { - const { username, etag } = ddpMessage.fields.args[0]; - const db = database.active; - const userCollection = db.get('users'); - try { - const [userRecord] = await userCollection.query(Q.where('username', Q.eq(username))).fetch(); - await db.action(async () => { - await userRecord.update(u => { - u.avatarETag = etag; - }); - }); - } catch { - // We can't create a new record since we don't receive the user._id - } - } else if (/permissions-changed/.test(eventName)) { - const { _id, roles } = ddpMessage.fields.args[1]; - const db = database.active; - const permissionsCollection = db.get('permissions'); - try { - const permissionsRecord = await permissionsCollection.find(_id); - await db.action(async () => { - await permissionsRecord.update(u => { - u.roles = roles; - }); - }); - reduxStore.dispatch(updatePermission(_id, roles)); - } catch (err) { - // - } - } else if (/Users:NameChanged/.test(eventName)) { - const userNameChanged = ddpMessage.fields.args[0]; - const db = database.active; - const userCollection = db.get('users'); - try { - const userRecord = await userCollection.find(userNameChanged._id); - await db.action(async () => { - await userRecord.update(u => { - Object.assign(u, userNameChanged); - }); - }); - } catch { - // User not found - await db.action(async () => { - await userCollection.create(u => { - u._raw = sanitizedRaw({ id: userNameChanged._id }, userCollection.schema); - Object.assign(u, userNameChanged); - }); - }); - } - } - }) - ); - - resolve(); - }); - }, - + connect, async shareExtensionInit(server) { database.setShareDB(server); diff --git a/app/lib/rocketchat/services/connect.ts b/app/lib/rocketchat/services/connect.ts index a3e9c352315..7eabd29c2fe 100644 --- a/app/lib/rocketchat/services/connect.ts +++ b/app/lib/rocketchat/services/connect.ts @@ -1,6 +1,15 @@ import RNFetchBlob from 'rn-fetch-blob'; import { settings as RocketChatSettings } from '@rocket.chat/sdk'; - +import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; +import { InteractionManager } from 'react-native'; +import { Q } from '@nozbe/watermelondb'; + +import log from '../../../utils/log'; +import { onRolesChanged } from '../../methods/getRoles'; +import { UserStatus } from '../../../definitions/UserStatus'; +import { setActiveUsers } from '../../../actions/activeUsers'; +import protectedFunction from '../../methods/helpers/protectedFunction'; +import database from '../../database'; import { selectServerFailure } from '../../../actions/server'; import { twoFactor } from '../../../utils/twoFactor'; import { compareServerVersion } from '../../utils'; @@ -8,9 +17,15 @@ import { store } from '../../auxStore'; import { loginRequest, setLoginServices, setUser } from '../../../actions/login'; import sdk from './sdk'; import I18n from '../../../i18n'; -import { MIN_ROCKETCHAT_VERSION } from '../rocketchat'; -import { ICredentials, ILoggedUser } from '../../../definitions'; +import RocketChat, { MIN_ROCKETCHAT_VERSION, STATUSES } from '../rocketchat'; +import { ICredentials, ILoggedUser, IRocketChat, IUser } from '../../../definitions'; import { isIOS } from '../../../utils/deviceInfo'; +import { connectRequest, connectSuccess, disconnect as disconnectAction } from '../../../actions/connect'; +import { updatePermission } from '../../../actions/permissions'; +import EventEmitter from '../../../utils/events'; +import { updateSettings } from '../../../actions/settings'; +import defaultSettings from '../../../constants/settings'; +import getSettings from '../../methods/getSettings'; interface IServices { [index: string]: string | boolean; @@ -21,10 +36,233 @@ interface IServices { service: string; } +// FIXME: Remove `this` context +function connect( + this: IRocketChat, + { server, user, logoutOnError = false }: { server: string; user: IUser; logoutOnError: boolean } +) { + return new Promise(resolve => { + if (sdk.current?.client?.host === server) { + return resolve(); + } + disconnect(); + database.setActiveDB(server); + + store.dispatch(connectRequest()); + + if (this.connectTimeout) { + clearTimeout(this.connectTimeout); + } + + if (this.connectingListener) { + this.connectingListener.then(stopListener); + } + + if (this.connectedListener) { + this.connectedListener.then(stopListener); + } + + if (this.closeListener) { + this.closeListener.then(stopListener); + } + + if (this.usersListener) { + this.usersListener.then(stopListener); + } + + if (this.notifyAllListener) { + this.notifyAllListener.then(stopListener); + } + + if (this.rolesListener) { + this.rolesListener.then(stopListener); + } + + if (this.notifyLoggedListener) { + this.notifyLoggedListener.then(stopListener); + } + + this.unsubscribeRooms(); + + EventEmitter.emit('INQUIRY_UNSUBSCRIBE'); + + sdk.initialize(server); + getSettings(); + + sdk.current + .connect() + .then(() => { + console.log('connected'); + }) + .catch((err: unknown) => { + console.log('connect error', err); + }); + + this.connectingListener = sdk.current.onStreamData('connecting', () => { + store.dispatch(connectRequest()); + }); + + this.connectedListener = sdk.current.onStreamData('connected', () => { + const { connected } = store.getState().meteor; + if (connected) { + return; + } + store.dispatch(connectSuccess()); + const { server: currentServer } = store.getState().server; + if (user?.token && server === currentServer) { + store.dispatch(loginRequest({ resume: user.token }, logoutOnError)); + } + }); + + this.closeListener = sdk.current.onStreamData('close', () => { + store.dispatch(disconnectAction()); + }); + + this.usersListener = sdk.current.onStreamData( + 'users', + protectedFunction((ddpMessage: any) => RocketChat._setUser(ddpMessage)) + ); + + this.notifyAllListener = sdk.current.onStreamData( + 'stream-notify-all', + protectedFunction(async (ddpMessage: { fields: { args?: any; eventName: string } }) => { + const { eventName } = ddpMessage.fields; + if (/public-settings-changed/.test(eventName)) { + const { _id, value } = ddpMessage.fields.args[1]; + const db = database.active; + const settingsCollection = db.get('settings'); + try { + const settingsRecord = await settingsCollection.find(_id); + // @ts-ignore + const { type } = defaultSettings[_id]; + if (type) { + await db.write(async () => { + await settingsRecord.update(u => { + // @ts-ignore + u[type] = value; + }); + }); + } + store.dispatch(updateSettings(_id, value)); + } catch (e) { + log(e); + } + } + }) + ); + + this.rolesListener = sdk.current.onStreamData( + 'stream-roles', + protectedFunction((ddpMessage: any) => onRolesChanged(ddpMessage)) + ); + + // RC 4.1 + sdk.current.onStreamData('stream-user-presence', (ddpMessage: { fields: { args?: any; uid?: any } }) => { + const userStatus = ddpMessage.fields.args[0]; + const { uid } = ddpMessage.fields; + const [, status, statusText] = userStatus; + const newStatus = { status: STATUSES[status], statusText }; + // @ts-ignore + store.dispatch(setActiveUsers({ [uid]: newStatus })); + + const { user: loggedUser } = store.getState().login; + if (loggedUser && loggedUser.id === uid) { + // @ts-ignore + store.dispatch(setUser(newStatus)); + } + }); + + this.notifyLoggedListener = sdk.current.onStreamData( + 'stream-notify-logged', + protectedFunction(async (ddpMessage: { fields: { args?: any; eventName?: any } }) => { + const { eventName } = ddpMessage.fields; + + // `user-status` event is deprecated after RC 4.1 in favor of `stream-user-presence/${uid}` + if (/user-status/.test(eventName)) { + this.activeUsers = this.activeUsers || {}; + if (!this._setUserTimer) { + this._setUserTimer = setTimeout(() => { + const activeUsersBatch = this.activeUsers; + InteractionManager.runAfterInteractions(() => { + store.dispatch(setActiveUsers(activeUsersBatch)); + }); + this._setUserTimer = null; + return (this.activeUsers = {}); + }, 10000); + } + const userStatus = ddpMessage.fields.args[0]; + const [id, , status, statusText] = userStatus; + this.activeUsers[id] = { status: STATUSES[status], statusText }; + + const { user: loggedUser } = store.getState().login; + if (loggedUser && loggedUser.id === id) { + store.dispatch(setUser({ status: STATUSES[status] as UserStatus, statusText })); + } + } else if (/updateAvatar/.test(eventName)) { + const { username, etag } = ddpMessage.fields.args[0]; + const db = database.active; + const userCollection = db.get('users'); + try { + const [userRecord] = await userCollection.query(Q.where('username', Q.eq(username))).fetch(); + await db.write(async () => { + await userRecord.update(u => { + u.avatarETag = etag; + }); + }); + } catch { + // We can't create a new record since we don't receive the user._id + } + } else if (/permissions-changed/.test(eventName)) { + const { _id, roles } = ddpMessage.fields.args[1]; + const db = database.active; + const permissionsCollection = db.get('permissions'); + try { + const permissionsRecord = await permissionsCollection.find(_id); + await db.write(async () => { + await permissionsRecord.update(u => { + u.roles = roles; + }); + }); + store.dispatch(updatePermission(_id, roles)); + } catch (err) { + // + } + } else if (/Users:NameChanged/.test(eventName)) { + const userNameChanged = ddpMessage.fields.args[0]; + const db = database.active; + const userCollection = db.get('users'); + try { + const userRecord = await userCollection.find(userNameChanged._id); + await db.write(async () => { + await userRecord.update(u => { + Object.assign(u, userNameChanged); + }); + }); + } catch { + // User not found + await db.write(async () => { + await userCollection.create(u => { + u._raw = sanitizedRaw({ id: userNameChanged._id }, userCollection.schema); + Object.assign(u, userNameChanged); + }); + }); + } + } + }) + ); + + resolve(); + }); +} + +function stopListener(listener: any): boolean { + return listener && listener.stop(); +} + async function login(credentials: ICredentials, isFromWebView = false): Promise { // RC 0.64.0 await sdk.current.login(credentials); - const result = sdk.currentLogin?.result; + const result = sdk.current.currentLogin?.result; if (result) { const user: ILoggedUser = { id: result.userId, @@ -123,14 +361,14 @@ async function loginOAuthOrSso(params: ICredentials, isFromWebView = true) { } function abort() { - if (sdk) { - return sdk.abort(); + if (sdk.current) { + return sdk.current.abort(); } return new AbortController(); } function checkAndReopen() { - return sdk.checkAndReopen(); + return sdk.current.checkAndReopen(); } function disconnect() { @@ -185,7 +423,7 @@ async function getWebsocketInfo({ server }: { server: string }) { sdk.initialize(server); try { - await sdk.connect(); + await sdk.current.connect(); } catch (err: any) { if (err.message && err.message.includes('400')) { return { @@ -195,7 +433,7 @@ async function getWebsocketInfo({ server }: { server: string }) { } } - sdk.disconnect(); + sdk.current.disconnect(); return { success: true @@ -264,9 +502,11 @@ export { loginOAuthOrSso, checkAndReopen, abort, + connect, disconnect, getServerInfo, getWebsocketInfo, + stopListener, getLoginServices, determineAuthType }; diff --git a/app/lib/rocketchat/services/sdk.ts b/app/lib/rocketchat/services/sdk.ts index a23f6621794..079a79ecc95 100644 --- a/app/lib/rocketchat/services/sdk.ts +++ b/app/lib/rocketchat/services/sdk.ts @@ -6,7 +6,7 @@ import { twoFactor } from '../../../utils/twoFactor'; import { useSsl } from '../../../utils/url'; import reduxStore from '../../createStore'; import { Serialized, MatchPathPattern, OperationParams, PathFor, ResultFor } from '../../../definitions/rest/helpers'; -import { ICredentials, ILoginResultFromServer } from '../../../definitions'; +import { ILoginResultFromServer } from '../../../definitions'; class Sdk { private sdk: typeof Rocketchat; @@ -162,22 +162,6 @@ class Sdk { onStreamData(...args: any[]) { return this.sdk.onStreamData(...args); } - - login(credentials: ICredentials) { - return this.sdk.login(credentials); - } - - checkAndReopen() { - return this.sdk.checkAndReopen(); - } - - abort() { - return this.sdk.abort(); - } - - connect() { - return this.sdk.connect(); - } } const sdk = new Sdk(); From edbb15daff4d427ce40d5355c41ad38a5b87ee80 Mon Sep 17 00:00:00 2001 From: Gerzon Z Date: Fri, 4 Mar 2022 11:49:09 -0400 Subject: [PATCH 08/13] remove: unused imports and leftovers --- app/lib/rocketchat/rocketchat.js | 14 ++------------ app/lib/rocketchat/services/sdk.ts | 4 ---- app/views/AuthenticationWebView.tsx | 1 - 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/app/lib/rocketchat/rocketchat.js b/app/lib/rocketchat/rocketchat.js index 10a2399cb35..26b83218273 100644 --- a/app/lib/rocketchat/rocketchat.js +++ b/app/lib/rocketchat/rocketchat.js @@ -1,25 +1,16 @@ import { Q } from '@nozbe/watermelondb'; import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; import AsyncStorage from '@react-native-community/async-storage'; -import { Rocketchat as RocketchatClient, settings as RocketChatSettings } from '@rocket.chat/sdk'; import { InteractionManager } from 'react-native'; -import RNFetchBlob from 'rn-fetch-blob'; import { setActiveUsers } from '../../actions/activeUsers'; -import { connectRequest, connectSuccess, disconnect as disconnectAction } from '../../actions/connect'; import { encryptionInit } from '../../actions/encryption'; -import { loginRequest, setUser } from '../../actions/login'; -import { updatePermission } from '../../actions/permissions'; -import { selectServerFailure } from '../../actions/server'; -import { updateSettings } from '../../actions/settings'; +import { setUser } from '../../actions/login'; import { shareSelectServer, shareSetSettings, shareSetUser } from '../../actions/share'; import defaultSettings from '../../constants/settings'; -import I18n from '../../i18n'; import { getDeviceToken } from '../../notifications/push'; import { getBundleId, isIOS } from '../../utils/deviceInfo'; -import EventEmitter from '../../utils/events'; import log from '../../utils/log'; import SSLPinning from '../../utils/sslPinning'; -import { useSsl } from '../../utils/url'; import database from '../database'; import { sanitizeLikeString } from '../database/utils'; import { Encryption } from '../encryption'; @@ -34,11 +25,10 @@ import { } from '../methods/enterpriseModules'; import { getCustomEmojis, setCustomEmojis } from '../methods/getCustomEmojis'; import { getPermissions, setPermissions } from '../methods/getPermissions'; -import { getRoles, onRolesChanged, setRoles } from '../methods/getRoles'; +import { getRoles, setRoles } from '../methods/getRoles'; import getRooms from '../methods/getRooms'; import getSettings, { getLoginSettings, setSettings, subscribeSettings } from '../methods/getSettings'; import getSlashCommands from '../methods/getSlashCommands'; -import protectedFunction from '../methods/helpers/protectedFunction'; import loadMessagesForRoom from '../methods/loadMessagesForRoom'; import loadMissedMessages from '../methods/loadMissedMessages'; import loadNextMessages from '../methods/loadNextMessages'; diff --git a/app/lib/rocketchat/services/sdk.ts b/app/lib/rocketchat/services/sdk.ts index 079a79ecc95..41c124b1143 100644 --- a/app/lib/rocketchat/services/sdk.ts +++ b/app/lib/rocketchat/services/sdk.ts @@ -6,14 +6,10 @@ import { twoFactor } from '../../../utils/twoFactor'; import { useSsl } from '../../../utils/url'; import reduxStore from '../../createStore'; import { Serialized, MatchPathPattern, OperationParams, PathFor, ResultFor } from '../../../definitions/rest/helpers'; -import { ILoginResultFromServer } from '../../../definitions'; class Sdk { private sdk: typeof Rocketchat; private code: any; - currentLogin: { - result: ILoginResultFromServer; - } | null = null; // TODO: We need to stop returning the SDK after all methods are dehydrated initialize(server: string) { diff --git a/app/views/AuthenticationWebView.tsx b/app/views/AuthenticationWebView.tsx index d9eb5a1114a..ac304fbfb5e 100644 --- a/app/views/AuthenticationWebView.tsx +++ b/app/views/AuthenticationWebView.tsx @@ -102,7 +102,6 @@ class AuthenticationWebView extends React.PureComponent Date: Tue, 8 Mar 2022 11:13:03 -0400 Subject: [PATCH 09/13] remove: unused import --- app/lib/rocketchat/rocketchat.js | 1 - ios/RocketChatRN.xcodeproj/project.pbxproj | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app/lib/rocketchat/rocketchat.js b/app/lib/rocketchat/rocketchat.js index 1931f00911d..cbcacdf009a 100644 --- a/app/lib/rocketchat/rocketchat.js +++ b/app/lib/rocketchat/rocketchat.js @@ -1,5 +1,4 @@ import { Q } from '@nozbe/watermelondb'; -import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; import AsyncStorage from '@react-native-community/async-storage'; import { InteractionManager } from 'react-native'; import { setActiveUsers } from '../../actions/activeUsers'; diff --git a/ios/RocketChatRN.xcodeproj/project.pbxproj b/ios/RocketChatRN.xcodeproj/project.pbxproj index ae9f0754d5e..f135845eb5e 100644 --- a/ios/RocketChatRN.xcodeproj/project.pbxproj +++ b/ios/RocketChatRN.xcodeproj/project.pbxproj @@ -958,8 +958,8 @@ "${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh", "${PODS_ROOT}/hermes-engine/destroot/Library/Frameworks/iphoneos/hermes.framework", "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiMeetSDK/JitsiMeetSDK.framework/JitsiMeetSDK", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiMeetSDK/WebRTC.framework/WebRTC", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/WebRTC/WebRTC.framework/WebRTC", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL/OpenSSL.framework/OpenSSL", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( @@ -1179,8 +1179,8 @@ "${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh", "${PODS_ROOT}/hermes-engine/destroot/Library/Frameworks/iphoneos/hermes.framework", "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiMeetSDK/JitsiMeetSDK.framework/JitsiMeetSDK", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiMeetSDK/WebRTC.framework/WebRTC", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/WebRTC/WebRTC.framework/WebRTC", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL/OpenSSL.framework/OpenSSL", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( @@ -1869,7 +1869,7 @@ COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 i386"; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -1924,7 +1924,7 @@ COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 i386"; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; From 1f7f99bdce4f60e7e25bad4eeccb315e77b13f92 Mon Sep 17 00:00:00 2001 From: Gerzon Z Date: Tue, 8 Mar 2022 11:13:57 -0400 Subject: [PATCH 10/13] Revert "remove: unused import" This reverts commit d52e642f4a1785eb451e91a3659b453286ae5364. --- app/lib/rocketchat/rocketchat.js | 1 + ios/RocketChatRN.xcodeproj/project.pbxproj | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/lib/rocketchat/rocketchat.js b/app/lib/rocketchat/rocketchat.js index cbcacdf009a..1931f00911d 100644 --- a/app/lib/rocketchat/rocketchat.js +++ b/app/lib/rocketchat/rocketchat.js @@ -1,4 +1,5 @@ import { Q } from '@nozbe/watermelondb'; +import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; import AsyncStorage from '@react-native-community/async-storage'; import { InteractionManager } from 'react-native'; import { setActiveUsers } from '../../actions/activeUsers'; diff --git a/ios/RocketChatRN.xcodeproj/project.pbxproj b/ios/RocketChatRN.xcodeproj/project.pbxproj index f135845eb5e..ae9f0754d5e 100644 --- a/ios/RocketChatRN.xcodeproj/project.pbxproj +++ b/ios/RocketChatRN.xcodeproj/project.pbxproj @@ -958,8 +958,8 @@ "${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh", "${PODS_ROOT}/hermes-engine/destroot/Library/Frameworks/iphoneos/hermes.framework", "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiMeetSDK/JitsiMeetSDK.framework/JitsiMeetSDK", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/WebRTC/WebRTC.framework/WebRTC", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL/OpenSSL.framework/OpenSSL", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiMeetSDK/WebRTC.framework/WebRTC", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( @@ -1179,8 +1179,8 @@ "${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh", "${PODS_ROOT}/hermes-engine/destroot/Library/Frameworks/iphoneos/hermes.framework", "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiMeetSDK/JitsiMeetSDK.framework/JitsiMeetSDK", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/WebRTC/WebRTC.framework/WebRTC", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL/OpenSSL.framework/OpenSSL", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiMeetSDK/WebRTC.framework/WebRTC", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( @@ -1869,7 +1869,7 @@ COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 i386"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -1924,7 +1924,7 @@ COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 i386"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; From 5a4f02b048db8488afc443b7a37a4da670f7abbb Mon Sep 17 00:00:00 2001 From: Gerzon Z Date: Tue, 8 Mar 2022 11:14:24 -0400 Subject: [PATCH 11/13] remove: unused import --- app/lib/rocketchat/rocketchat.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/lib/rocketchat/rocketchat.js b/app/lib/rocketchat/rocketchat.js index 1931f00911d..cbcacdf009a 100644 --- a/app/lib/rocketchat/rocketchat.js +++ b/app/lib/rocketchat/rocketchat.js @@ -1,5 +1,4 @@ import { Q } from '@nozbe/watermelondb'; -import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; import AsyncStorage from '@react-native-community/async-storage'; import { InteractionManager } from 'react-native'; import { setActiveUsers } from '../../actions/activeUsers'; From 6015349ee1b93c0b5de4caef9ba524f1e19ccf8d Mon Sep 17 00:00:00 2001 From: Gerzon Z Date: Tue, 8 Mar 2022 11:38:46 -0400 Subject: [PATCH 12/13] fix: login error --- app/lib/rocketchat/services/connect.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/lib/rocketchat/services/connect.ts b/app/lib/rocketchat/services/connect.ts index 7eabd29c2fe..e7f24d0a878 100644 --- a/app/lib/rocketchat/services/connect.ts +++ b/app/lib/rocketchat/services/connect.ts @@ -25,7 +25,6 @@ import { updatePermission } from '../../../actions/permissions'; import EventEmitter from '../../../utils/events'; import { updateSettings } from '../../../actions/settings'; import defaultSettings from '../../../constants/settings'; -import getSettings from '../../methods/getSettings'; interface IServices { [index: string]: string | boolean; @@ -87,7 +86,7 @@ function connect( EventEmitter.emit('INQUIRY_UNSUBSCRIBE'); sdk.initialize(server); - getSettings(); + this.getSettings(); sdk.current .connect() @@ -333,7 +332,7 @@ function loginTOTP(params: ICredentials, loginEmailPassword?: boolean, isFromWeb }); } -function loginWithPassword({ user, password }: { user: string; password: string }) { +function loginWithPassword({ user, password }: { user: string; password: string }): Promise { let params: ICredentials = { user, password }; const state = store.getState(); @@ -433,7 +432,7 @@ async function getWebsocketInfo({ server }: { server: string }) { } } - sdk.current.disconnect(); + sdk.disconnect(); return { success: true From d6ce877a0d75b9808417d0ba336a3e0b7a7233f8 Mon Sep 17 00:00:00 2001 From: Gerzon Z Date: Tue, 8 Mar 2022 11:41:00 -0400 Subject: [PATCH 13/13] fix: logout being `undefined` --- app/lib/methods/logout.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/lib/methods/logout.ts b/app/lib/methods/logout.ts index 0e53ed123bf..e9e3daebe22 100644 --- a/app/lib/methods/logout.ts +++ b/app/lib/methods/logout.ts @@ -12,6 +12,7 @@ import log from '../../utils/log'; import { E2E_PRIVATE_KEY, E2E_PUBLIC_KEY, E2E_RANDOM_PASSWORD_KEY } from '../encryption/constants'; import UserPreferences from '../userPreferences'; import { ICertificate, IRocketChat } from '../../definitions'; +import sdk from '../rocketchat/services/sdk'; async function removeServerKeys({ server, userId }: { server: string; userId?: string | null }) { await UserPreferences.removeItem(`${RocketChat.TOKEN_KEY}-${server}`); @@ -116,13 +117,13 @@ export default async function logout(this: IRocketChat, { server }: { server: st try { // RC 0.60.0 - await this.sdk.logout(); + await sdk.current.logout(); } catch (e) { log(e); } - if (this.sdk) { - this.sdk = null; + if (sdk.current) { + sdk.disconnect(); } await removeServerData({ server });