From d96b366abd17577ceb6fca9a0ad9e7803bf757f4 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 3 Oct 2023 11:23:41 +0200 Subject: [PATCH 1/6] [TS migration] Migrate 'Session' lib to TypeScript --- .eslintrc.js | 1 + src/libs/Navigation/Navigation.js | 2 +- .../actions/Session/{index.js => index.ts} | 173 ++++++++---------- .../Session/updateSessionAuthTokens.js | 10 - .../Session/updateSessionAuthTokens.ts | 6 + src/types/onyx/Session.ts | 13 +- 6 files changed, 97 insertions(+), 108 deletions(-) rename src/libs/actions/Session/{index.js => index.ts} (83%) delete mode 100644 src/libs/actions/Session/updateSessionAuthTokens.js create mode 100644 src/libs/actions/Session/updateSessionAuthTokens.ts diff --git a/.eslintrc.js b/.eslintrc.js index b5b4add538f6..3b480fcc4639 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -163,6 +163,7 @@ module.exports = { }, ], curly: 'error', + 'you-dont-need-lodash-underscore/throttle': 'off', }, }, { diff --git a/src/libs/Navigation/Navigation.js b/src/libs/Navigation/Navigation.js index de6162685079..5cbd8e9b0af6 100644 --- a/src/libs/Navigation/Navigation.js +++ b/src/libs/Navigation/Navigation.js @@ -77,7 +77,7 @@ const getActiveRouteIndex = function (route, index) { /** * Main navigation method for redirecting to a route. * @param {String} route - * @param {String} type - Type of action to perform. Currently UP is supported. + * @param {String} [type] - Type of action to perform. Currently UP is supported. */ function navigate(route = ROUTES.HOME, type) { if (!canNavigate('navigate', {route})) { diff --git a/src/libs/actions/Session/index.js b/src/libs/actions/Session/index.ts similarity index 83% rename from src/libs/actions/Session/index.js rename to src/libs/actions/Session/index.ts index 117a092c3875..f294153da4a5 100644 --- a/src/libs/actions/Session/index.js +++ b/src/libs/actions/Session/index.ts @@ -1,7 +1,7 @@ -import Onyx from 'react-native-onyx'; -import _ from 'underscore'; -import lodashGet from 'lodash/get'; +import Onyx, {OnyxUpdate} from 'react-native-onyx'; import {Linking} from 'react-native'; +import {ValueOf} from 'type-fest'; +import throttle from 'lodash/throttle'; import clearCache from './clearCache'; import ONYXKEYS from '../../../ONYXKEYS'; import redirectToSignIn from '../SignInRedirect'; @@ -21,16 +21,18 @@ import ROUTES from '../../../ROUTES'; import * as ErrorUtils from '../../ErrorUtils'; import * as ReportUtils from '../../ReportUtils'; import {hideContextMenu} from '../../../pages/home/report/ContextMenu/ReportActionContextMenu'; +import Credentials from '../../../types/onyx/Credentials'; +import {AutoAuthState} from '../../../types/onyx/Session'; -let sessionAuthTokenType = ''; -let sessionAuthToken = null; -let authPromiseResolver = null; +let sessionAuthTokenType: string | null = ''; +let sessionAuthToken: string | null = null; +let authPromiseResolver: ((value: boolean) => void) | null = null; Onyx.connect({ key: ONYXKEYS.SESSION, callback: (session) => { - sessionAuthTokenType = lodashGet(session, 'authTokenType'); - sessionAuthToken = lodashGet(session, 'authToken'); + sessionAuthTokenType = session?.authTokenType ?? null; + sessionAuthToken = session?.authToken ?? null; if (sessionAuthToken && authPromiseResolver) { authPromiseResolver(true); @@ -39,13 +41,13 @@ Onyx.connect({ }, }); -let credentials = {}; +let credentials: Credentials = {}; Onyx.connect({ key: ONYXKEYS.CREDENTIALS, - callback: (val) => (credentials = val || {}), + callback: (value) => (credentials = value ?? {}), }); -let preferredLocale; +let preferredLocale: ValueOf | null = null; Onyx.connect({ key: ONYXKEYS.NVP_PREFERRED_LOCALE, callback: (val) => (preferredLocale = val), @@ -60,7 +62,7 @@ function signOut() { API.write('LogOut', { // Send current authToken because we will immediately clear it once triggering this command authToken: NetworkStore.getAuthToken(), - partnerUserID: lodashGet(credentials, 'autoGeneratedLogin', ''), + partnerUserID: credentials?.autoGeneratedLogin ?? '', partnerName: CONFIG.EXPENSIFY.PARTNER_NAME, partnerPassword: CONFIG.EXPENSIFY.PARTNER_PASSWORD, shouldRetry: false, @@ -73,10 +75,8 @@ function signOut() { /** * Checks if the account is an anonymous account. - * - * @return {boolean} */ -function isAnonymousUser() { +function isAnonymousUser(): boolean { return sessionAuthTokenType === 'anonymousAccount'; } @@ -98,11 +98,11 @@ function signOutAndRedirectToSignIn() { } /** - * @param {Function} callback The callback to execute if the action is allowed - * @param {Boolean} isAnonymousAction The action is allowed for anonymous or not - * @returns {Function} same callback if the action is allowed, otherwise a function that signs out and redirects to sign in + * @param callback The callback to execute if the action is allowed + * @param isAnonymousAction The action is allowed for anonymous or not + * @returns same callback if the action is allowed, otherwise a function that signs out and redirects to sign in */ -function checkIfActionIsAllowed(callback, isAnonymousAction = false) { +function checkIfActionIsAllowed unknown>(callback: TCallback, isAnonymousAction = false): TCallback | (() => void) { if (isAnonymousUser() && !isAnonymousAction) { return () => signOutAndRedirectToSignIn(); } @@ -111,11 +111,9 @@ function checkIfActionIsAllowed(callback, isAnonymousAction = false) { /** * Resend the validation link to the user that is validating their account - * - * @param {String} [login] */ function resendValidationLink(login = credentials.login) { - const optimisticData = [ + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -127,7 +125,7 @@ function resendValidationLink(login = credentials.login) { }, }, ]; - const successData = [ + const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -138,7 +136,7 @@ function resendValidationLink(login = credentials.login) { }, }, ]; - const failureData = [ + const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -155,11 +153,9 @@ function resendValidationLink(login = credentials.login) { /** * Request a new validate / magic code for user to sign in via passwordless flow - * - * @param {String} [login] */ function resendValidateCode(login = credentials.login) { - const optimisticData = [ + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -169,7 +165,7 @@ function resendValidateCode(login = credentials.login) { }, }, ]; - const successData = [ + const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -178,7 +174,7 @@ function resendValidateCode(login = credentials.login) { }, }, ]; - const failureData = [ + const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -187,16 +183,20 @@ function resendValidateCode(login = credentials.login) { }, }, ]; + API.write('RequestNewValidateCode', {email: login}, {optimisticData, successData, failureData}); } -/** +type OnyxData = { + optimisticData: OnyxUpdate[]; + successData: OnyxUpdate[]; + failureData: OnyxUpdate[]; +}; /** * Constructs the state object for the BeginSignIn && BeginAppleSignIn API calls. - * @returns {Object} */ -function signInAttemptState() { +function signInAttemptState(): OnyxData { return { optimisticData: [ { @@ -234,7 +234,6 @@ function signInAttemptState() { value: { isLoading: false, loadingForm: null, - // eslint-disable-next-line rulesdir/prefer-localization errors: ErrorUtils.getMicroSecondOnyxError('loginForm.cannotGetAccountDetails'), }, }, @@ -244,21 +243,17 @@ function signInAttemptState() { /** * Checks the API to see if an account exists for the given login. - * - * @param {String} login */ -function beginSignIn(login) { +function beginSignIn(email: string) { const {optimisticData, successData, failureData} = signInAttemptState(); - API.read('BeginSignIn', {email: login}, {optimisticData, successData, failureData}); + API.read('BeginSignIn', {email}, {optimisticData, successData, failureData}); } /** * Given an idToken from Sign in with Apple, checks the API to see if an account * exists for that email address and signs the user in if so. - * - * @param {String} idToken */ -function beginAppleSignIn(idToken) { +function beginAppleSignIn(idToken: string) { const {optimisticData, successData, failureData} = signInAttemptState(); API.write('SignInWithApple', {idToken, preferredLocale}, {optimisticData, successData, failureData}); } @@ -266,10 +261,8 @@ function beginAppleSignIn(idToken) { /** * Shows Google sign-in process, and if an auth token is successfully obtained, * passes the token on to the Expensify API to sign in with - * - * @param {String} token */ -function beginGoogleSignIn(token) { +function beginGoogleSignIn(token: string) { const {optimisticData, successData, failureData} = signInAttemptState(); API.write('SignInWithGoogle', {token, preferredLocale}, {optimisticData, successData, failureData}); } @@ -277,12 +270,9 @@ function beginGoogleSignIn(token) { /** * Will create a temporary login for the user in the passed authenticate response which is used when * re-authenticating after an authToken expires. - * - * @param {String} email - * @param {String} authToken */ -function signInWithShortLivedAuthToken(email, authToken) { - const optimisticData = [ +function signInWithShortLivedAuthToken(email: string, authToken: string) { + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -293,7 +283,7 @@ function signInWithShortLivedAuthToken(email, authToken) { }, ]; - const successData = [ + const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -303,7 +293,7 @@ function signInWithShortLivedAuthToken(email, authToken) { }, ]; - const failureData = [ + const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -325,11 +315,10 @@ function signInWithShortLivedAuthToken(email, authToken) { * then it will create a temporary login for them which is used when re-authenticating * after an authToken expires. * - * @param {String} validateCode 6 digit code required for login - * @param {String} [twoFactorAuthCode] + * @param validateCode - 6 digit code required for login */ -function signIn(validateCode, twoFactorAuthCode) { - const optimisticData = [ +function signIn(validateCode: string, twoFactorAuthCode?: string) { + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -341,7 +330,7 @@ function signIn(validateCode, twoFactorAuthCode) { }, ]; - const successData = [ + const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -359,7 +348,7 @@ function signIn(validateCode, twoFactorAuthCode) { }, ]; - const failureData = [ + const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -370,7 +359,7 @@ function signIn(validateCode, twoFactorAuthCode) { }, ]; - const params = { + const params: Record = { twoFactorAuthCode, email: credentials.login, preferredLocale, @@ -385,12 +374,12 @@ function signIn(validateCode, twoFactorAuthCode) { }); } -function signInWithValidateCode(accountID, code, twoFactorAuthCode = '') { +function signInWithValidateCode(accountID: number, code: string, twoFactorAuthCode = '') { // If this is called from the 2fa step, get the validateCode directly from onyx // instead of the one passed from the component state because the state is changing when this method is called. const validateCode = twoFactorAuthCode ? credentials.validateCode : code; - const optimisticData = [ + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -407,7 +396,7 @@ function signInWithValidateCode(accountID, code, twoFactorAuthCode = '') { }, ]; - const successData = [ + const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -431,7 +420,7 @@ function signInWithValidateCode(accountID, code, twoFactorAuthCode = '') { }, ]; - const failureData = [ + const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -461,7 +450,7 @@ function signInWithValidateCode(accountID, code, twoFactorAuthCode = '') { }); } -function signInWithValidateCodeAndNavigate(accountID, validateCode, twoFactorAuthCode = '') { +function signInWithValidateCodeAndNavigate(accountID: number, validateCode: string, twoFactorAuthCode = '') { signInWithValidateCode(accountID, validateCode, twoFactorAuthCode); Navigation.navigate(ROUTES.HOME); } @@ -473,14 +462,12 @@ function signInWithValidateCodeAndNavigate(accountID, validateCode, twoFactorAut * When the user gets authenticated, the component is unmounted and then remounted * when AppNavigator switches from PublicScreens to AuthScreens. * That's the reason why autoAuthState initialization is skipped while the last state is SIGNING_IN. - * - * @param {string} cachedAutoAuthState */ -function initAutoAuthState(cachedAutoAuthState) { +function initAutoAuthState(cachedAutoAuthState: AutoAuthState) { + const signedInStates: AutoAuthState[] = [CONST.AUTO_AUTH_STATE.SIGNING_IN, CONST.AUTO_AUTH_STATE.JUST_SIGNED_IN]; + Onyx.merge(ONYXKEYS.SESSION, { - autoAuthState: _.contains([CONST.AUTO_AUTH_STATE.SIGNING_IN, CONST.AUTO_AUTH_STATE.JUST_SIGNED_IN], cachedAutoAuthState) - ? CONST.AUTO_AUTH_STATE.JUST_SIGNED_IN - : CONST.AUTO_AUTH_STATE.NOT_STARTED, + autoAuthState: signedInStates.includes(cachedAutoAuthState) ? CONST.AUTO_AUTH_STATE.JUST_SIGNED_IN : CONST.AUTO_AUTH_STATE.NOT_STARTED, }); } @@ -495,22 +482,19 @@ function invalidateAuthToken() { /** * Sets the SupportToken - * @param {String} supportToken - * @param {String} email - * @param {Number} accountID */ -function setSupportAuthToken(supportToken, email, accountID) { - if (supportToken) { +function setSupportAuthToken(supportAuthToken: string, email: string, accountID: number) { + if (supportAuthToken) { Onyx.merge(ONYXKEYS.SESSION, { authToken: '1', - supportAuthToken: supportToken, + supportAuthToken, email, accountID, }); } else { Onyx.set(ONYXKEYS.SESSION, {}); } - NetworkStore.setSupportAuthToken(supportToken); + NetworkStore.setSupportAuthToken(supportAuthToken); } /** @@ -544,7 +528,7 @@ function clearAccountMessages() { // It's necessary to throttle requests to reauthenticate since calling this multiple times will cause Pusher to // reconnect each time when we only need to reconnect once. This way, if an authToken is expired and we try to // subscribe to a bunch of channels at once we will only reauthenticate and force reconnect Pusher once. -const reauthenticatePusher = _.throttle( +const reauthenticatePusher = throttle( () => { Log.info('[Pusher] Re-authenticating and then reconnecting'); Authentication.reauthenticate('AuthenticatePusher') @@ -557,18 +541,17 @@ const reauthenticatePusher = _.throttle( {trailing: false}, ); -/** - * @param {String} socketID - * @param {String} channelName - * @param {Function} callback - */ -function authenticatePusher(socketID, channelName, callback) { +type AuthenticatePusherCallback = (err: Error | null, response: Response | {auth: ''}) => void; + +function authenticatePusher(socketID: string, channelName: string, callback: AuthenticatePusherCallback) { Log.info('[PusherAuthorizer] Attempting to authorize Pusher', false, {channelName}); // We use makeRequestWithSideEffects here because we need to authorize to Pusher (an external service) each time a user connects to any channel. // eslint-disable-next-line rulesdir/no-api-side-effects-method API.makeRequestWithSideEffects('AuthenticatePusher', { + // eslint-disable-next-line @typescript-eslint/naming-convention socket_id: socketID, + // eslint-disable-next-line @typescript-eslint/naming-convention channel_name: channelName, shouldRetry: false, forceNetworkRequest: true, @@ -639,8 +622,8 @@ function requestUnlinkValidationLink() { API.write('RequestUnlinkValidationLink', {email: credentials.login}, {optimisticData, successData, failureData}); } -function unlinkLogin(accountID, validateCode) { - const optimisticData = [ +function unlinkLogin(accountID: number, validateCode: string) { + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -650,7 +633,7 @@ function unlinkLogin(accountID, validateCode) { }, }, ]; - const successData = [ + const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -667,7 +650,7 @@ function unlinkLogin(accountID, validateCode) { }, }, ]; - const failureData = [ + const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -693,11 +676,9 @@ function unlinkLogin(accountID, validateCode) { /** * Toggles two-factor authentication based on the `enable` parameter - * - * @param {Boolean} enable */ -function toggleTwoFactorAuth(enable) { - const optimisticData = [ +function toggleTwoFactorAuth(enable: boolean) { + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -707,7 +688,7 @@ function toggleTwoFactorAuth(enable) { }, ]; - const successData = [ + const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -717,7 +698,7 @@ function toggleTwoFactorAuth(enable) { }, ]; - const failureData = [ + const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.ACCOUNT, @@ -730,7 +711,7 @@ function toggleTwoFactorAuth(enable) { API.write(enable ? 'EnableTwoFactorAuth' : 'DisableTwoFactorAuth', {}, {optimisticData, successData, failureData}); } -function validateTwoFactorAuth(twoFactorAuthCode) { +function validateTwoFactorAuth(twoFactorAuthCode: string) { const optimisticData = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -771,14 +752,14 @@ function validateTwoFactorAuth(twoFactorAuthCode) { * Otherwise, the promise will resolve when the `authToken` in `ONYXKEYS.SESSION` becomes truthy via the Onyx callback. * The promise will not reject on failed login attempt. * - * @returns {Promise} A promise that resolves to `true` once the user is signed in. + * @returns A promise that resolves to `true` once the user is signed in. * @example * waitForUserSignIn().then(() => { * console.log('User is signed in!'); * }); */ -function waitForUserSignIn() { - return new Promise((resolve) => { +function waitForUserSignIn(): Promise { + return new Promise((resolve) => { if (sessionAuthToken) { resolve(true); } else { diff --git a/src/libs/actions/Session/updateSessionAuthTokens.js b/src/libs/actions/Session/updateSessionAuthTokens.js deleted file mode 100644 index 5be53c77a92c..000000000000 --- a/src/libs/actions/Session/updateSessionAuthTokens.js +++ /dev/null @@ -1,10 +0,0 @@ -import Onyx from 'react-native-onyx'; -import ONYXKEYS from '../../../ONYXKEYS'; - -/** - * @param {String} authToken - * @param {String} encryptedAuthToken - */ -export default function updateSessionAuthTokens(authToken, encryptedAuthToken) { - Onyx.merge(ONYXKEYS.SESSION, {authToken, encryptedAuthToken}); -} diff --git a/src/libs/actions/Session/updateSessionAuthTokens.ts b/src/libs/actions/Session/updateSessionAuthTokens.ts new file mode 100644 index 000000000000..da547eba0504 --- /dev/null +++ b/src/libs/actions/Session/updateSessionAuthTokens.ts @@ -0,0 +1,6 @@ +import Onyx from 'react-native-onyx'; +import ONYXKEYS from '../../../ONYXKEYS'; + +export default function updateSessionAuthTokens(authToken: string, encryptedAuthToken: string) { + Onyx.merge(ONYXKEYS.SESSION, {authToken, encryptedAuthToken}); +} diff --git a/src/types/onyx/Session.ts b/src/types/onyx/Session.ts index 75cb4f4818ad..ba7479e7e10c 100644 --- a/src/types/onyx/Session.ts +++ b/src/types/onyx/Session.ts @@ -1,3 +1,8 @@ +import {ValueOf} from 'type-fest'; +import CONST from '../../CONST'; + +type AutoAuthState = ValueOf; + type Session = { /** The user's email for the current session */ email?: string; @@ -5,13 +10,19 @@ type Session = { /** Currently logged in user authToken */ authToken?: string; + authTokenType?: string; + + supportAuthToken?: string; + /** Currently logged in user encrypted authToken */ encryptedAuthToken?: string; /** Currently logged in user accountID */ accountID?: number; - autoAuthState?: string; + autoAuthState?: AutoAuthState; }; export default Session; + +export type {AutoAuthState}; From 226614e8e292b968ce9ecd502a05cb8bf2f09912 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 16 Oct 2023 10:12:15 +0200 Subject: [PATCH 2/6] Create types for API calls --- src/libs/actions/Session/index.ts | 194 ++++++++++++++++++++++-------- 1 file changed, 145 insertions(+), 49 deletions(-) diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts index f294153da4a5..05dc9bd15b60 100644 --- a/src/libs/actions/Session/index.ts +++ b/src/libs/actions/Session/index.ts @@ -59,16 +59,26 @@ Onyx.connect({ function signOut() { Log.info('Flushing logs before signing out', true, {}, true); - API.write('LogOut', { + type LogOutParams = { + authToken: string | null; + partnerUserID: string; + partnerName: string; + partnerPassword: string; + shouldRetry: boolean; + }; + + const params: LogOutParams = { // Send current authToken because we will immediately clear it once triggering this command authToken: NetworkStore.getAuthToken(), partnerUserID: credentials?.autoGeneratedLogin ?? '', partnerName: CONFIG.EXPENSIFY.PARTNER_NAME, partnerPassword: CONFIG.EXPENSIFY.PARTNER_PASSWORD, shouldRetry: false, - }); + }; + + API.write('LogOut', params); clearCache().then(() => { - Log.info('Cleared all chache data', true, {}, true); + Log.info('Cleared all cache data', true, {}, true); }); Timing.clearData(); } @@ -148,7 +158,13 @@ function resendValidationLink(login = credentials.login) { }, ]; - API.write('RequestAccountValidationLink', {email: login}, {optimisticData, successData, failureData}); + type ResendValidationLinkParams = { + email?: string; + }; + + const params: ResendValidationLinkParams = {email: login}; + + API.write('RequestAccountValidationLink', params, {optimisticData, successData, failureData}); } /** @@ -184,7 +200,13 @@ function resendValidateCode(login = credentials.login) { }, ]; - API.write('RequestNewValidateCode', {email: login}, {optimisticData, successData, failureData}); + type RequestNewValidateCodeParams = { + email?: string; + }; + + const params: RequestNewValidateCodeParams = {email: login}; + + API.write('RequestNewValidateCode', params, {optimisticData, successData, failureData}); } type OnyxData = { @@ -246,7 +268,14 @@ function signInAttemptState(): OnyxData { */ function beginSignIn(email: string) { const {optimisticData, successData, failureData} = signInAttemptState(); - API.read('BeginSignIn', {email}, {optimisticData, successData, failureData}); + + type BeginSignInParams = { + email: string; + }; + + const params: BeginSignInParams = {email}; + + API.read('BeginSignIn', params, {optimisticData, successData, failureData}); } /** @@ -255,7 +284,15 @@ function beginSignIn(email: string) { */ function beginAppleSignIn(idToken: string) { const {optimisticData, successData, failureData} = signInAttemptState(); - API.write('SignInWithApple', {idToken, preferredLocale}, {optimisticData, successData, failureData}); + + type BeginAppleSignInParams = { + idToken: string; + preferredLocale: ValueOf | null; + }; + + const params: BeginAppleSignInParams = {idToken, preferredLocale}; + + API.write('SignInWithApple', params, {optimisticData, successData, failureData}); } /** @@ -264,7 +301,15 @@ function beginAppleSignIn(idToken: string) { */ function beginGoogleSignIn(token: string) { const {optimisticData, successData, failureData} = signInAttemptState(); - API.write('SignInWithGoogle', {token, preferredLocale}, {optimisticData, successData, failureData}); + + type BeginGoogleSignInParams = { + token: string; + preferredLocale: ValueOf | null; + }; + + const params: BeginGoogleSignInParams = {token, preferredLocale}; + + API.write('SignInWithGoogle', params, {optimisticData, successData, failureData}); } /** @@ -307,7 +352,16 @@ function signInWithShortLivedAuthToken(email: string, authToken: string) { // scene 1: the user is transitioning to newDot from a different account on oldDot. // scene 2: the user is transitioning to desktop app from a different account on web app. const oldPartnerUserID = credentials.login === email ? credentials.autoGeneratedLogin : ''; - API.read('SignInWithShortLivedAuthToken', {authToken, oldPartnerUserID, skipReauthentication: true}, {optimisticData, successData, failureData}); + + type SignInWithShortLivedAuthTokenParams = { + authToken: string; + oldPartnerUserID?: string; + skipReauthentication: boolean; + }; + + const params: SignInWithShortLivedAuthTokenParams = {authToken, oldPartnerUserID, skipReauthentication: true}; + + API.read('SignInWithShortLivedAuthToken', params, {optimisticData, successData, failureData}); } /** @@ -359,18 +413,28 @@ function signIn(validateCode: string, twoFactorAuthCode?: string) { }, ]; - const params: Record = { - twoFactorAuthCode, - email: credentials.login, - preferredLocale, - }; - - // Conditionally pass a password or validateCode to command since we temporarily allow both flows - if (validateCode || twoFactorAuthCode) { - params.validateCode = validateCode || credentials.validateCode; - } Device.getDeviceInfoWithID().then((deviceInfo) => { - API.write('SigninUser', {...params, deviceInfo}, {optimisticData, successData, failureData}); + type SignInUserParams = { + twoFactorAuthCode?: string; + email?: string; + preferredLocale: ValueOf | null; + validateCode?: string; + deviceInfo: string; + }; + + const params: SignInUserParams = { + twoFactorAuthCode, + email: credentials.login, + preferredLocale, + deviceInfo, + }; + + // Conditionally pass a password or validateCode to command since we temporarily allow both flows + if (validateCode || twoFactorAuthCode) { + params.validateCode = validateCode || credentials.validateCode; + } + + API.write('SigninUser', params, {optimisticData, successData, failureData}); }); } @@ -436,17 +500,23 @@ function signInWithValidateCode(accountID: number, code: string, twoFactorAuthCo }, ]; Device.getDeviceInfoWithID().then((deviceInfo) => { - API.write( - 'SigninUserWithLink', - { - accountID, - validateCode, - twoFactorAuthCode, - preferredLocale, - deviceInfo, - }, - {optimisticData, successData, failureData}, - ); + type SignInUserWithLinkParams = { + accountID: number; + validateCode?: string; + twoFactorAuthCode?: string; + preferredLocale: ValueOf | null; + deviceInfo: string; + }; + + const params: SignInUserWithLinkParams = { + accountID, + validateCode, + twoFactorAuthCode, + preferredLocale, + deviceInfo, + }; + + API.write('SigninUserWithLink', params, {optimisticData, successData, failureData}); }); } @@ -546,16 +616,27 @@ type AuthenticatePusherCallback = (err: Error | null, response: Response | {auth function authenticatePusher(socketID: string, channelName: string, callback: AuthenticatePusherCallback) { Log.info('[PusherAuthorizer] Attempting to authorize Pusher', false, {channelName}); - // We use makeRequestWithSideEffects here because we need to authorize to Pusher (an external service) each time a user connects to any channel. - // eslint-disable-next-line rulesdir/no-api-side-effects-method - API.makeRequestWithSideEffects('AuthenticatePusher', { + type AuthenticatePusherParams = { + // eslint-disable-next-line @typescript-eslint/naming-convention + socket_id: string; + // eslint-disable-next-line @typescript-eslint/naming-convention + channel_name: string; + shouldRetry: boolean; + forceNetworkRequest: boolean; + }; + + const params: AuthenticatePusherParams = { // eslint-disable-next-line @typescript-eslint/naming-convention socket_id: socketID, // eslint-disable-next-line @typescript-eslint/naming-convention channel_name: channelName, shouldRetry: false, forceNetworkRequest: true, - }) + }; + + // We use makeRequestWithSideEffects here because we need to authorize to Pusher (an external service) each time a user connects to any channel. + // eslint-disable-next-line rulesdir/no-api-side-effects-method + API.makeRequestWithSideEffects('AuthenticatePusher', params) .then((response) => { if (response.jsonCode === CONST.JSON_CODE.NOT_AUTHENTICATED) { Log.hmmm('[PusherAuthorizer] Unable to authenticate Pusher because authToken is expired'); @@ -619,7 +700,13 @@ function requestUnlinkValidationLink() { }, ]; - API.write('RequestUnlinkValidationLink', {email: credentials.login}, {optimisticData, successData, failureData}); + type RequestUnlinkValidationLinkParams = { + email?: string; + }; + + const params: RequestUnlinkValidationLinkParams = {email: credentials.login}; + + API.write('RequestUnlinkValidationLink', params, {optimisticData, successData, failureData}); } function unlinkLogin(accountID: number, validateCode: string) { @@ -660,18 +747,21 @@ function unlinkLogin(accountID: number, validateCode: string) { }, ]; - API.write( - 'UnlinkLogin', - { - accountID, - validateCode, - }, - { - optimisticData, - successData, - failureData, - }, - ); + type UnlinkLoginParams = { + accountID: number; + validateCode: string; + }; + + const params: UnlinkLoginParams = { + accountID, + validateCode, + }; + + API.write('UnlinkLogin', params, { + optimisticData, + successData, + failureData, + }); } /** @@ -742,7 +832,13 @@ function validateTwoFactorAuth(twoFactorAuthCode: string) { }, ]; - API.write('TwoFactorAuth_Validate', {twoFactorAuthCode}, {optimisticData, successData, failureData}); + type ValidateTwoFactorAuthParams = { + twoFactorAuthCode: string; + }; + + const params: ValidateTwoFactorAuthParams = {twoFactorAuthCode}; + + API.write('TwoFactorAuth_Validate', params, {optimisticData, successData, failureData}); } /** From 3491ef1672afb41d5772be3dcc133ae67c564527 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 16 Oct 2023 14:30:58 +0200 Subject: [PATCH 3/6] Empty commit From fb2829be7faf69b5e59477824d99cffde1db1728 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 16 Oct 2023 14:40:07 +0200 Subject: [PATCH 4/6] Fix typecheck --- src/libs/actions/Session/index.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts index 05dc9bd15b60..52f9a298009f 100644 --- a/src/libs/actions/Session/index.ts +++ b/src/libs/actions/Session/index.ts @@ -2,6 +2,7 @@ import Onyx, {OnyxUpdate} from 'react-native-onyx'; import {Linking} from 'react-native'; import {ValueOf} from 'type-fest'; import throttle from 'lodash/throttle'; +import {ChannelAuthorizationCallback} from 'pusher-js/with-encryption'; import clearCache from './clearCache'; import ONYXKEYS from '../../../ONYXKEYS'; import redirectToSignIn from '../SignInRedirect'; @@ -611,9 +612,7 @@ const reauthenticatePusher = throttle( {trailing: false}, ); -type AuthenticatePusherCallback = (err: Error | null, response: Response | {auth: ''}) => void; - -function authenticatePusher(socketID: string, channelName: string, callback: AuthenticatePusherCallback) { +function authenticatePusher(socketID: string, channelName: string, callback: ChannelAuthorizationCallback) { Log.info('[PusherAuthorizer] Attempting to authorize Pusher', false, {channelName}); type AuthenticatePusherParams = { From 5ac1366e488a8e447d857fd20d2aba91a65ed33f Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 16 Oct 2023 18:31:16 +0200 Subject: [PATCH 5/6] Fix type error --- src/libs/actions/Session/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts index 16ef5bc3885d..dbe3eb27438e 100644 --- a/src/libs/actions/Session/index.ts +++ b/src/libs/actions/Session/index.ts @@ -596,7 +596,7 @@ function clearAccountMessages() { }); } -function setAccountError(error) { +function setAccountError(error: string) { Onyx.merge(ONYXKEYS.ACCOUNT, {errors: ErrorUtils.getMicroSecondOnyxError(error)}); } From e2f5dc70e252237aa6e207c10b9e58dd0819b047 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Fri, 20 Oct 2023 08:33:58 +0200 Subject: [PATCH 6/6] Add comments to onyx types --- src/types/onyx/Credentials.ts | 12 ++++++++++++ src/types/onyx/Session.ts | 2 ++ 2 files changed, 14 insertions(+) diff --git a/src/types/onyx/Credentials.ts b/src/types/onyx/Credentials.ts index 13404a9a6643..6a22eeb5af89 100644 --- a/src/types/onyx/Credentials.ts +++ b/src/types/onyx/Credentials.ts @@ -1,17 +1,29 @@ type Credentials = { /** The email/phone the user logged in with */ login?: string; + + /** The password the user logged in with */ password?: string; + + /** The two factor auth code */ twoFactorAuthCode?: string; /** The validate code */ validateCode?: string; + /** The auto-generated login. */ autoGeneratedLogin?: string; + + /** The auto-generated password. */ autoGeneratedPassword?: string; + + /** The user's ID */ accountID?: number; + /** The user's ID for external integration */ partnerUserID?: string; + + /** The user's secret for external integration */ partnerUserSecret?: string; }; diff --git a/src/types/onyx/Session.ts b/src/types/onyx/Session.ts index 4cbde6f216e4..606723f17b82 100644 --- a/src/types/onyx/Session.ts +++ b/src/types/onyx/Session.ts @@ -11,8 +11,10 @@ type Session = { /** Currently logged in user authToken */ authToken?: string; + /** Currently logged in user authToken type */ authTokenType?: string; + /** Currently logged in user support authToken */ supportAuthToken?: string; /** Currently logged in user encrypted authToken */