diff --git a/lib/types/identity-service-types.js b/lib/types/identity-service-types.js index 982145486f..6ea2031ee0 100644 --- a/lib/types/identity-service-types.js +++ b/lib/types/identity-service-types.js @@ -53,3 +53,5 @@ export type IdentityRegisterResult = { +accessToken: string, +username: string, }; + +export const ONE_TIME_KEYS_NUMBER = 10; diff --git a/lib/types/redux-types.js b/lib/types/redux-types.js index 37c41bda5c..b77aafed16 100644 --- a/lib/types/redux-types.js +++ b/lib/types/redux-types.js @@ -44,6 +44,7 @@ import type { CalendarThreadFilter, SetCalendarDeletedFilterPayload, } from './filter-types.js'; +import type { IdentityRegisterResult } from './identity-service-types.js'; import type { IntegrityStore } from './integrity-types.js'; import type { KeyserverStore, @@ -374,6 +375,21 @@ export type BaseAction = +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: IdentityRegisterResult, + +loadingInfo: LoadingInfo, + } | { +type: 'CHANGE_KEYSERVER_USER_PASSWORD_STARTED', +payload?: void, diff --git a/native/account/register-panel.react.js b/native/account/register-panel.react.js index 3e3b4d25d7..396c92e7ae 100644 --- a/native/account/register-panel.react.js +++ b/native/account/register-panel.react.js @@ -46,7 +46,11 @@ import SWMansionIcon from '../components/swmansion-icon.react.js'; import { useSelector } from '../redux/redux-utils.js'; import { nativeLogInExtraInfoSelector } from '../selectors/account-selectors.js'; import type { KeyPressEvent } from '../types/react-native.js'; -import { AppOutOfDateAlertDetails } from '../utils/alert-messages.js'; +import { + AppOutOfDateAlertDetails, + UsernameReservedAlertDetails, + UsernameTakenAlertDetails, +} from '../utils/alert-messages.js'; import Alert from '../utils/alert.js'; import { nativeNotificationsSessionCreator } from '../utils/crypto-utils.js'; import { type StateContainer } from '../utils/state-container.js'; @@ -365,16 +369,15 @@ class RegisterPanel extends React.PureComponent { } 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.', + UsernameReservedAlertDetails.title, + UsernameReservedAlertDetails.message, [{ text: 'OK', onPress: this.onUsernameAlertAcknowledged }], { cancelable: false }, ); } else if (e.message === 'username_taken') { Alert.alert( - 'Username taken', - 'An account with that username already exists', + UsernameTakenAlertDetails.title, + UsernameTakenAlertDetails.message, [{ text: 'OK', onPress: this.onUsernameAlertAcknowledged }], { cancelable: false }, ); diff --git a/native/account/registration/registration-server-call.js b/native/account/registration/registration-server-call.js index f6cd9075b7..da7f7f1d9e 100644 --- a/native/account/registration/registration-server-call.js +++ b/native/account/registration/registration-server-call.js @@ -6,11 +6,14 @@ import { setDataLoadedActionType } from 'lib/actions/client-db-store-actions.js' import { keyserverRegisterActionTypes, keyserverRegister, + useIdentityRegister, + identityRegisterActionTypes, } from 'lib/actions/user-actions.js'; import type { LogInStartingPayload } from 'lib/types/account-types.js'; import { useServerCall } from 'lib/utils/action-utils.js'; import { useDispatchActionPromise } from 'lib/utils/redux-promise-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,7 +27,11 @@ import { } from '../../avatars/avatar-hooks.js'; import { useSelector } from '../../redux/redux-utils.js'; import { nativeLogInExtraInfoSelector } from '../../selectors/account-selectors.js'; -import { AppOutOfDateAlertDetails } from '../../utils/alert-messages.js'; +import { + AppOutOfDateAlertDetails, + UsernameReservedAlertDetails, + UsernameTakenAlertDetails, +} from '../../utils/alert-messages.js'; import Alert from '../../utils/alert.js'; import { setNativeCredentials } from '../native-credentials.js'; import { useSIWEServerCall } from '../siwe-hooks.js'; @@ -59,17 +66,62 @@ function useRegistrationServerCall(): RegistrationServerCallInput => Promise { + const identityRegisterPromise = (async () => { + try { + const result = await callIdentityRegister( + accountSelection.username, + accountSelection.password, + ); + await setNativeCredentials({ + username: accountSelection.username, + password: accountSelection.password, + }); + return result; + } catch (e) { + if (e.message === 'username reserved') { + Alert.alert( + UsernameReservedAlertDetails.title, + UsernameReservedAlertDetails.message, + ); + } else if (e.message === 'username already exists') { + Alert.alert( + UsernameTakenAlertDetails.title, + UsernameTakenAlertDetails.message, + ); + } 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 registerUsernameAccount = React.useCallback( + 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, @@ -87,14 +139,13 @@ function useRegistrationServerCall(): RegistrationServerCallInput => Promise Promise Promise Promise { + await commCoreModule.initializeCryptoAccount(); + const [ + { blobPayload, signature }, + notificationsOneTimeKeys, + primaryOneTimeKeys, + prekeys, + ] = await Promise.all([ + commCoreModule.getUserPublicKey(), + commCoreModule.getNotificationsOneTimeKeys(ONE_TIME_KEYS_NUMBER), + commCoreModule.getPrimaryOneTimeKeys(ONE_TIME_KEYS_NUMBER), + commCoreModule.generateAndGetPrekeys(), + ]); + const registrationResult = await commRustModule.registerUser( + username, + password, + blobPayload, + signature, + prekeys.contentPrekey, + prekeys.contentPrekeySignature, + prekeys.notifPrekey, + prekeys.notifPrekeySignature, + getOneTimeKeyArray(primaryOneTimeKeys), + getOneTimeKeyArray(notificationsOneTimeKeys), + ); + const { userID, accessToken } = JSON.parse(registrationResult); + return { accessToken, userID, username }; + }, }; }, [getAuthMetadata]); diff --git a/native/utils/alert-messages.js b/native/utils/alert-messages.js index 655f42e962..c784845579 100644 --- a/native/utils/alert-messages.js +++ b/native/utils/alert-messages.js @@ -18,3 +18,15 @@ export const AppOutOfDateAlertDetails: AlertDetails = { 'Your app version is pretty old, and the server doesn’t know how ' + `to speak to it anymore. Please use the ${platformStore} to update!`, }; + +export const UsernameReservedAlertDetails: AlertDetails = { + title: 'Username reserved', + message: + 'This username is currently reserved. Please contact support@' + + 'comm.app if you would like to claim this account.', +}; + +export const UsernameTakenAlertDetails: AlertDetails = { + title: 'Username taken', + message: 'An account with that username already exists', +};