diff --git a/lib/types/identity-service-types.js b/lib/types/identity-service-types.js --- a/lib/types/identity-service-types.js +++ b/lib/types/identity-service-types.js @@ -62,3 +62,5 @@ +username?: ?string, +walletAddress?: ?string, }; + +export const ONE_TIME_KEYS_NUMBER: number = Object.freeze(10); diff --git a/lib/types/redux-types.js b/lib/types/redux-types.js --- a/lib/types/redux-types.js +++ b/lib/types/redux-types.js @@ -42,6 +42,7 @@ CalendarThreadFilter, SetCalendarDeletedFilterPayload, } from './filter-types.js'; +import type { UserLoginResponse } from './identity-service-types.js'; import type { IntegrityStore } from './integrity-types.js'; import type { KeyserverStore, @@ -340,6 +341,21 @@ +payload: RegisterResult, +loadingInfo: LoadingInfo, } + | { + +type: 'IDENTITY_REGISTER_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, + } + | { + +type: 'IDENTITY_REGISTER_FAILED', + +payload: Error, + +loadingInfo: LoadingInfo, + } + | { + +type: 'IDENTITY_REGISTER_SUCCESS', + +payload: UserLoginResponse, + +loadingInfo: LoadingInfo, + } | { +type: 'CHANGE_USER_PASSWORD_STARTED', +payload?: void, diff --git a/native/account/registration/registration-server-call.js b/native/account/registration/registration-server-call.js --- a/native/account/registration/registration-server-call.js +++ b/native/account/registration/registration-server-call.js @@ -6,13 +6,18 @@ import { keyserverRegisterActionTypes, keyserverRegister, + useIdentityRegister, + identityRegisterActionTypes, } from 'lib/actions/user-actions.js'; +import { getOneTimeKeyArray } from 'lib/shared/crypto-utils.js'; import type { LogInStartingPayload } from 'lib/types/account-types.js'; +import { ONE_TIME_KEYS_NUMBER } from 'lib/types/identity-service-types.js'; import { useServerCall, useDispatchActionPromise, } from 'lib/utils/action-utils.js'; import { useDispatch } from 'lib/utils/redux-utils.js'; +import { usingCommServicesAccessToken } from 'lib/utils/services-utils.js'; import { setURLPrefix } from 'lib/utils/url-utils.js'; import type { @@ -24,6 +29,7 @@ useNativeSetUserAvatar, useUploadSelectedMedia, } from '../../avatars/avatar-hooks.js'; +import { commRustModule, commCoreModule } from '../../native-modules.js'; import { NavContext } from '../../navigation/navigation-context.js'; import { useSelector } from '../../redux/redux-utils.js'; import { nativeLogInExtraInfoSelector } from '../../selectors/account-selectors.js'; @@ -68,17 +74,90 @@ ); const dispatchActionPromise = useDispatchActionPromise(); - const callRegister = useServerCall(keyserverRegister); + const callKeyserverRegister = useServerCall(keyserverRegister); + const callIdentityRegister = useIdentityRegister; - const registerUsernameAccount = React.useCallback( + const identityRegisterUsernameAccount = React.useCallback( + async (accountSelection: UsernameAccountSelection) => { + const [ + { + notificationIdentityPublicKeys, + primaryIdentityPublicKeys, + signature, + }, + notificationsOneTimeKeys, + primaryOneTimeKeys, + prekeys, + ] = await Promise.all([ + commCoreModule.getUserPublicKey(), + commCoreModule.getNotificationsOneTimeKeys(ONE_TIME_KEYS_NUMBER), + commCoreModule.getPrimaryOneTimeKeys(ONE_TIME_KEYS_NUMBER), + commCoreModule.generateAndGetPrekeys(), + ]); + const keyPayload = JSON.stringify({ + notificationIdentityPublicKeys, + primaryIdentityPublicKeys, + }); + const identityRegisterPromise = (async () => { + try { + await callIdentityRegister( + commRustModule, + accountSelection.username, + accountSelection.password, + keyPayload, + signature, + prekeys.contentPrekey, + prekeys.contentPrekeySignature, + prekeys.notifPrekey, + prekeys.notifPrekeySignature, + getOneTimeKeyArray(primaryOneTimeKeys), + getOneTimeKeyArray(notificationsOneTimeKeys), + ); + await setNativeCredentials({ + username: accountSelection.username, + password: accountSelection.password, + }); + } catch (e) { + if (e.message === 'username reserved') { + Alert.alert( + 'Username reserved', + 'This username is currently reserved. Please contact support@' + + 'comm.app if you would like to claim this account.', + ); + } else if (e.message === 'username already exists') { + Alert.alert( + 'Username taken', + 'An account with that username already exists', + ); + } else if (e.message === 'Unsupported version') { + Alert.alert( + AppOutOfDateAlertDetails.title, + AppOutOfDateAlertDetails.message, + ); + } else { + Alert.alert('Unknown error', 'Uhh... try again?'); + } + throw e; + } + })(); + void dispatchActionPromise( + identityRegisterActionTypes, + identityRegisterPromise, + ); + await identityRegisterPromise; + }, + [callIdentityRegister, dispatchActionPromise], + ); + + const keyserverRegisterUsernameAccount = React.useCallback( async ( accountSelection: UsernameAccountSelection, keyserverURL: string, ) => { const extraInfo = await logInExtraInfo(); - const registerPromise = (async () => { + const keyserverRegisterPromise = (async () => { try { - const result = await callRegister( + const result = await callKeyserverRegister( { ...extraInfo, username: accountSelection.username, @@ -118,13 +197,13 @@ })(); void dispatchActionPromise( keyserverRegisterActionTypes, - registerPromise, + keyserverRegisterPromise, undefined, ({ calendarQuery: extraInfo.calendarQuery }: LogInStartingPayload), ); - await registerPromise; + await keyserverRegisterPromise; }, - [logInExtraInfo, callRegister, dispatchActionPromise], + [logInExtraInfo, callKeyserverRegister, dispatchActionPromise], ); const siweServerCall = useSIWEServerCall(); @@ -139,8 +218,16 @@ return; } const { accountSelection, avatarData, keyserverURL } = input; - if (accountSelection.accountType === 'username') { - await registerUsernameAccount(accountSelection, keyserverURL); + if ( + accountSelection.accountType === 'username' && + !usingCommServicesAccessToken + ) { + await keyserverRegisterUsernameAccount( + accountSelection, + keyserverURL, + ); + } else if (accountSelection.accountType === 'username') { + await identityRegisterUsernameAccount(accountSelection); } else { try { await siweServerCall(accountSelection, { @@ -166,7 +253,13 @@ } }, ), - [currentStep, registerUsernameAccount, siweServerCall, dispatch], + [ + currentStep, + keyserverRegisterUsernameAccount, + identityRegisterUsernameAccount, + siweServerCall, + dispatch, + ], ); // STEP 2: SETTING AVATAR