Page MenuHomePhabricator

D10584.diff
No OneTemporary

D10584.diff

diff --git a/lib/actions/user-actions.js b/lib/actions/user-actions.js
--- a/lib/actions/user-actions.js
+++ b/lib/actions/user-actions.js
@@ -8,6 +8,7 @@
sortCalendarQueryPerKeyserver,
} from '../keyserver-conn/keyserver-call-utils.js';
import { preRequestUserStateSelector } from '../selectors/account-selectors.js';
+import { IdentityClientContext } from '../shared/identity-client-context.js';
import threadWatcher from '../shared/thread-watcher.js';
import type {
LogOutResult,
@@ -29,7 +30,6 @@
UpdateUserAvatarResponse,
} from '../types/avatar-types.js';
import type { RawEntryInfo, CalendarQuery } from '../types/entry-types.js';
-import type { IdentityServiceClient } from '../types/identity-service-types';
import type {
RawMessageInfo,
MessageTruncationStatuses,
@@ -169,23 +169,15 @@
failed: 'DELETE_IDENTITY_ACCOUNT_FAILED',
});
-function useDeleteIdentityAccount(): (
- client: IdentityServiceClient,
- deviceID: ?string,
-) => Promise<void> {
- const userID = useSelector(state => state.currentUserInfo?.id);
- const accessToken = useSelector(state => state.commServicesAccessToken);
- const deleteIdentityAccount = React.useCallback(
- async (client: IdentityServiceClient, deviceID: ?string) => {
- if (!userID || !accessToken || !deviceID) {
- throw new Error('missing identity service auth metadata');
- }
- await client.deleteUser(userID, deviceID, accessToken);
- },
- [userID, accessToken],
- );
-
- return deleteIdentityAccount;
+function useDeleteIdentityAccount(): () => Promise<void> {
+ const client = React.useContext(IdentityClientContext);
+ const identityClient = client?.identityClient;
+ return React.useCallback(() => {
+ if (!identityClient) {
+ throw new Error('Identity service client is not initialized');
+ }
+ return identityClient.deleteUser();
+ }, [identityClient]);
}
const registerActionTypes = Object.freeze({
diff --git a/lib/shared/identity-client-context.js b/lib/shared/identity-client-context.js
new file mode 100644
--- /dev/null
+++ b/lib/shared/identity-client-context.js
@@ -0,0 +1,14 @@
+// @flow
+
+import * as React from 'react';
+
+import type { IdentityServiceClient } from '../types/identity-service-types.js';
+
+export type IdentityClientContextType = {
+ +identityClient: ?IdentityServiceClient,
+};
+
+const IdentityClientContext: React.Context<?IdentityClientContextType> =
+ React.createContext<?IdentityClientContextType>();
+
+export { IdentityClientContext };
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
@@ -20,11 +20,8 @@
};
export interface IdentityServiceClient {
- +deleteUser: (
- userID: string,
- deviceID: string,
- accessToken: string,
- ) => Promise<void>;
+ +deleteUser: () => Promise<void>;
+ +getKeyserverKeys: string => Promise<?OutboundKeyInfoResponse>;
}
export type IdentityServiceAuthLayer = {
diff --git a/native/identity-service/identity-service-context-provider.react.js b/native/identity-service/identity-service-context-provider.react.js
new file mode 100644
--- /dev/null
+++ b/native/identity-service/identity-service-context-provider.react.js
@@ -0,0 +1,107 @@
+// @flow
+
+import * as React from 'react';
+
+import { IdentityClientContext } from 'lib/shared/identity-client-context.js';
+import type {
+ IdentityServiceClient,
+ OutboundKeyInfoResponse,
+ UserLoginResponse,
+} from 'lib/types/identity-service-types.js';
+
+import { getCommServicesAuthMetadataEmitter } from '../event-emitters/csa-auth-metadata-emitter.js';
+import { commCoreModule, commRustModule } from '../native-modules.js';
+import { getContentSigningKey } from '../utils/crypto-utils.js';
+
+type Props = {
+ +children: React.Node,
+};
+function IdentityServiceContextProvider(props: Props): React.Node {
+ const { children } = props;
+
+ const authMetadataPromiseRef =
+ React.useRef<?Promise<{ +userID: ?string, +accessToken: ?string }>>();
+ if (!authMetadataPromiseRef.current) {
+ authMetadataPromiseRef.current = (async () => {
+ const { userID, accessToken } =
+ await commCoreModule.getCommServicesAuthMetadata();
+ return { userID, accessToken };
+ })();
+ }
+
+ React.useEffect(() => {
+ const metadataEmitter = getCommServicesAuthMetadataEmitter();
+ const subscription = metadataEmitter.addListener(
+ 'commServicesAuthMetadata',
+ (authMetadata: UserLoginResponse) => {
+ authMetadataPromiseRef.current = Promise.resolve({
+ userID: authMetadata.userId,
+ accessToken: authMetadata.accessToken,
+ });
+ },
+ );
+ return () => subscription.remove();
+ }, []);
+
+ const getAuthMetadata = React.useCallback<
+ () => Promise<{
+ +deviceID: string,
+ +userID: string,
+ +accessToken: string,
+ }>,
+ >(async () => {
+ const deviceID = await getContentSigningKey();
+ const authMetadata = await authMetadataPromiseRef.current;
+ const userID = authMetadata?.userID;
+ const accessToken = authMetadata?.accessToken;
+ if (!deviceID || !userID || !accessToken) {
+ throw new Error('Identity service client is not initialized');
+ }
+ return { deviceID, userID, accessToken };
+ }, []);
+
+ const client = React.useMemo<?IdentityServiceClient>(() => {
+ return {
+ deleteUser: async () => {
+ const { deviceID, userID, accessToken } = await getAuthMetadata();
+ return commRustModule.deleteUser(userID, deviceID, accessToken);
+ },
+ getKeyserverKeys: async (keyserverID: string) => {
+ const { deviceID, userID, accessToken } = await getAuthMetadata();
+ const result = await commRustModule.getKeyserverKeys(
+ userID,
+ deviceID,
+ accessToken,
+ keyserverID,
+ );
+ const resultObject: OutboundKeyInfoResponse = JSON.parse(result);
+ if (
+ !resultObject.payload ||
+ !resultObject.payloadSignature ||
+ !resultObject.contentPrekey ||
+ !resultObject.contentPrekeySignature ||
+ !resultObject.notifPrekey ||
+ !resultObject.notifPrekeySignature
+ ) {
+ throw new Error('Invalid response from Identity service');
+ }
+ return resultObject;
+ },
+ };
+ }, [getAuthMetadata]);
+
+ const value = React.useMemo(
+ () => ({
+ identityClient: client,
+ }),
+ [client],
+ );
+
+ return (
+ <IdentityClientContext.Provider value={value}>
+ {children}
+ </IdentityClientContext.Provider>
+ );
+}
+
+export default IdentityServiceContextProvider;
diff --git a/native/profile/delete-account.react.js b/native/profile/delete-account.react.js
--- a/native/profile/delete-account.react.js
+++ b/native/profile/delete-account.react.js
@@ -21,12 +21,10 @@
import type { ProfileNavigationProp } from './profile.react.js';
import { deleteNativeCredentialsFor } from '../account/native-credentials.js';
import Button from '../components/button.react.js';
-import { commRustModule } from '../native-modules.js';
import type { NavigationRoute } from '../navigation/route-names.js';
import { useSelector } from '../redux/redux-utils.js';
import { useStyles } from '../themes/colors.js';
import Alert from '../utils/alert.js';
-import { getContentSigningKey } from '../utils/crypto-utils.js';
const keyserverLoadingStatusSelector = createLoadingStatusSelector(
deleteKeyserverAccountActionTypes,
@@ -87,8 +85,7 @@
const deleteIdentityAction = React.useCallback(async () => {
try {
- const deviceID = await getContentSigningKey();
- return await callDeleteIdentityAccount(commRustModule, deviceID);
+ return await callDeleteIdentityAccount();
} catch (e) {
Alert.alert(
'Unknown error deleting account',
diff --git a/native/root.react.js b/native/root.react.js
--- a/native/root.react.js
+++ b/native/root.react.js
@@ -45,6 +45,7 @@
import { SQLiteDataHandler } from './data/sqlite-data-handler.js';
import ErrorBoundary from './error-boundary.react.js';
import { peerToPeerMessageHandler } from './handlers/peer-to-peer-message-handler.js';
+import IdentityServiceContextProvider from './identity-service/identity-service-context-provider.react.js';
import InputStateContainer from './input/input-state-container.react.js';
import LifecycleHandler from './lifecycle/lifecycle-handler.react.js';
import MarkdownContextProvider from './markdown/markdown-context-provider.react.js';
@@ -296,60 +297,62 @@
return (
<GestureHandlerRootView style={styles.app}>
<StaffContextProvider>
- <TunnelbrokerProvider
- initMessage={tunnelbrokerInitMessage}
- peerToPeerMessageHandler={peerToPeerMessageHandler}
- >
- <FeatureFlagsProvider>
- <NavContext.Provider value={navContext}>
- <RootContext.Provider value={rootContext}>
- <InputStateContainer>
- <MessageEditingContextProvider>
- <SafeAreaProvider initialMetrics={initialWindowMetrics}>
- <ActionSheetProvider>
- <ENSCacheProvider provider={provider}>
- <MediaCacheProvider
- persistence={filesystemMediaCache}
- >
- <EditUserAvatarProvider>
- <NativeEditThreadAvatarProvider>
- <MarkdownContextProvider>
- <MessageSearchProvider>
- <BottomSheetProvider>
- <RegistrationContextProvider>
- <SQLiteDataHandler />
- <ConnectedStatusBar />
- <ReduxPersistGate
- persistor={getPersistor()}
- >
- {gated}
- </ReduxPersistGate>
- <PersistedStateGate>
- <KeyserverConnectionsHandler
- socketComponent={Socket}
- detectUnsupervisedBackgroundRef={
- detectUnsupervisedBackgroundRef
- }
- />
- <VersionSupportedChecker />
- </PersistedStateGate>
- {navigation}
- </RegistrationContextProvider>
- </BottomSheetProvider>
- </MessageSearchProvider>
- </MarkdownContextProvider>
- </NativeEditThreadAvatarProvider>
- </EditUserAvatarProvider>
- </MediaCacheProvider>
- </ENSCacheProvider>
- </ActionSheetProvider>
- </SafeAreaProvider>
- </MessageEditingContextProvider>
- </InputStateContainer>
- </RootContext.Provider>
- </NavContext.Provider>
- </FeatureFlagsProvider>
- </TunnelbrokerProvider>
+ <IdentityServiceContextProvider>
+ <TunnelbrokerProvider
+ initMessage={tunnelbrokerInitMessage}
+ peerToPeerMessageHandler={peerToPeerMessageHandler}
+ >
+ <FeatureFlagsProvider>
+ <NavContext.Provider value={navContext}>
+ <RootContext.Provider value={rootContext}>
+ <InputStateContainer>
+ <MessageEditingContextProvider>
+ <SafeAreaProvider initialMetrics={initialWindowMetrics}>
+ <ActionSheetProvider>
+ <ENSCacheProvider provider={provider}>
+ <MediaCacheProvider
+ persistence={filesystemMediaCache}
+ >
+ <EditUserAvatarProvider>
+ <NativeEditThreadAvatarProvider>
+ <MarkdownContextProvider>
+ <MessageSearchProvider>
+ <BottomSheetProvider>
+ <RegistrationContextProvider>
+ <SQLiteDataHandler />
+ <ConnectedStatusBar />
+ <ReduxPersistGate
+ persistor={getPersistor()}
+ >
+ {gated}
+ </ReduxPersistGate>
+ <PersistedStateGate>
+ <KeyserverConnectionsHandler
+ socketComponent={Socket}
+ detectUnsupervisedBackgroundRef={
+ detectUnsupervisedBackgroundRef
+ }
+ />
+ <VersionSupportedChecker />
+ </PersistedStateGate>
+ {navigation}
+ </RegistrationContextProvider>
+ </BottomSheetProvider>
+ </MessageSearchProvider>
+ </MarkdownContextProvider>
+ </NativeEditThreadAvatarProvider>
+ </EditUserAvatarProvider>
+ </MediaCacheProvider>
+ </ENSCacheProvider>
+ </ActionSheetProvider>
+ </SafeAreaProvider>
+ </MessageEditingContextProvider>
+ </InputStateContainer>
+ </RootContext.Provider>
+ </NavContext.Provider>
+ </FeatureFlagsProvider>
+ </TunnelbrokerProvider>
+ </IdentityServiceContextProvider>
</StaffContextProvider>
</GestureHandlerRootView>
);
diff --git a/web/grpc/identity-service-client-wrapper.js b/web/grpc/identity-service-client-wrapper.js
--- a/web/grpc/identity-service-client-wrapper.js
+++ b/web/grpc/identity-service-client-wrapper.js
@@ -3,6 +3,7 @@
import identityServiceConfig from 'lib/facts/identity-service.js';
import type {
IdentityServiceAuthLayer,
+ IdentityServiceClient,
OutboundKeyInfoResponse,
} from 'lib/types/identity-service-types.js';
@@ -10,25 +11,31 @@
import * as IdentityAuthClient from '../protobufs/identity-auth-client.cjs';
import * as IdentityAuthStructs from '../protobufs/identity-auth-structs.cjs';
import { Empty } from '../protobufs/identity-unauth-structs.cjs';
-import * as IdentityClient from '../protobufs/identity-unauth.cjs';
+import * as IdentityUnauthClient from '../protobufs/identity-unauth.cjs';
-class IdentityServiceClientWrapper {
+class IdentityServiceClientWrapper implements IdentityServiceClient {
authClient: ?IdentityAuthClient.IdentityClientServicePromiseClient;
- unauthorizedClient: ?IdentityClient.IdentityClientServicePromiseClient;
+ unauthClient: IdentityUnauthClient.IdentityClientServicePromiseClient;
- constructor() {
- this.authClient = null;
- this.unauthorizedClient = null;
+ constructor(authLayer: ?IdentityServiceAuthLayer) {
+ if (authLayer) {
+ this.authClient =
+ IdentityServiceClientWrapper.createAuthClient(authLayer);
+ }
+ this.unauthClient = IdentityServiceClientWrapper.createUnauthClient();
}
- determineSocketAddr(): string {
+ static determineSocketAddr(): string {
return process.env.IDENTITY_SOCKET_ADDR ?? identityServiceConfig.defaultURL;
}
- async initAuthClient(authLayer: IdentityServiceAuthLayer): Promise<void> {
+ static createAuthClient(
+ authLayer: IdentityServiceAuthLayer,
+ ): IdentityAuthClient.IdentityClientServicePromiseClient {
const { userID, deviceID, commServicesAccessToken } = authLayer;
- const identitySocketAddr = this.determineSocketAddr();
+ const identitySocketAddr =
+ IdentityServiceClientWrapper.determineSocketAddr();
const versionInterceptor = new VersionInterceptor<Request, Response>();
const authInterceptor = new AuthInterceptor<Request, Response>(
@@ -41,103 +48,72 @@
unaryInterceptors: [versionInterceptor, authInterceptor],
};
- this.authClient = new IdentityAuthClient.IdentityClientServicePromiseClient(
+ return new IdentityAuthClient.IdentityClientServicePromiseClient(
identitySocketAddr,
null,
authClientOpts,
);
}
- async initUnauthorizedClient(): Promise<void> {
- const identitySocketAddr = this.determineSocketAddr();
+ static createUnauthClient(): IdentityUnauthClient.IdentityClientServicePromiseClient {
+ const identitySocketAddr =
+ IdentityServiceClientWrapper.determineSocketAddr();
const versionInterceptor = new VersionInterceptor<Request, Response>();
- const unauthorizedClientOpts = {
+ const unauthClientOpts = {
unaryInterceptors: [versionInterceptor],
};
- this.unauthorizedClient =
- new IdentityClient.IdentityClientServicePromiseClient(
- identitySocketAddr,
- null,
- unauthorizedClientOpts,
- );
+ return new IdentityUnauthClient.IdentityClientServicePromiseClient(
+ identitySocketAddr,
+ null,
+ unauthClientOpts,
+ );
}
- deleteUser: (
- userID: string,
- deviceID: string,
- accessToken: string,
- ) => Promise<void> = async (
- userID: string,
- deviceID: string,
- accessToken: string,
- ): Promise<void> => {
+ deleteUser: () => Promise<void> = async () => {
if (!this.authClient) {
- const authLayer: IdentityServiceAuthLayer = {
- userID,
- deviceID,
- commServicesAccessToken: accessToken,
- };
- await this.initAuthClient(authLayer);
- }
-
- if (this.authClient) {
- await this.authClient.deleteUser(new Empty());
- } else {
throw new Error('Identity service client is not initialized');
}
+ await this.authClient.deleteUser(new Empty());
};
- async getKeyserverKeys(
- userID: string,
- deviceID: string,
- accessToken: string,
- keyserverID: string,
- ): Promise<?OutboundKeyInfoResponse> {
- if (!this.authClient) {
- const authLayer: IdentityServiceAuthLayer = {
- userID,
- deviceID,
- commServicesAccessToken: accessToken,
+ getKeyserverKeys: (keyserverID: string) => Promise<?OutboundKeyInfoResponse> =
+ async (keyserverID: string) => {
+ const client = this.authClient;
+ if (!client) {
+ throw new Error('Identity service client is not initialized');
+ }
+
+ const request = new IdentityAuthStructs.OutboundKeysForUserRequest();
+ request.setUserId(keyserverID);
+ const response = await client.getKeyserverKeys(request);
+ const keyserverInfo = response.getKeyserverInfo();
+ if (!response.hasKeyserverInfo() || !keyserverInfo) {
+ return null;
+ }
+
+ const identityInfo = keyserverInfo.getIdentityInfo();
+ const contentPreKey = keyserverInfo.getContentPrekey();
+ const notifPreKey = keyserverInfo.getNotifPrekey();
+
+ if (!identityInfo || !contentPreKey || !notifPreKey) {
+ return null;
+ }
+
+ return {
+ payload: identityInfo.getPayload(),
+ payloadSignature: identityInfo.getPayloadSignature(),
+ socialProof: identityInfo.getSocialProof(),
+ contentPrekey: contentPreKey.getPrekey(),
+ contentPrekeySignature: contentPreKey.getPrekeySignature(),
+ notifPrekey: notifPreKey.getPrekey(),
+ notifPrekeySignature: notifPreKey.getPrekeySignature(),
+ oneTimeContentPrekey: keyserverInfo.getOneTimeContentPrekey(),
+ oneTimeNotifPrekey: keyserverInfo.getOneTimeNotifPrekey(),
};
- await this.initAuthClient(authLayer);
- }
-
- const client = this.authClient;
- if (!client) {
- throw new Error('Identity service client is not initialized');
- }
-
- const request = new IdentityAuthStructs.OutboundKeysForUserRequest();
- request.setUserId(keyserverID);
- const response = await client.getKeyserverKeys(request);
- const keyserverInfo = response.getKeyserverInfo();
- if (!response.hasKeyserverInfo() || !keyserverInfo) {
- return null;
- }
-
- const identityInfo = keyserverInfo.getIdentityInfo();
- const contentPreKey = keyserverInfo.getContentPrekey();
- const notifPreKey = keyserverInfo.getNotifPrekey();
-
- if (!identityInfo || !contentPreKey || !notifPreKey) {
- return null;
- }
-
- return {
- payload: identityInfo.getPayload(),
- payloadSignature: identityInfo.getPayloadSignature(),
- socialProof: identityInfo.getSocialProof(),
- contentPrekey: contentPreKey.getPrekey(),
- contentPrekeySignature: contentPreKey.getPrekeySignature(),
- notifPrekey: notifPreKey.getPrekey(),
- notifPrekeySignature: notifPreKey.getPrekeySignature(),
- oneTimeContentPrekey: keyserverInfo.getOneTimeContentPrekey(),
- oneTimeNotifPrekey: keyserverInfo.getOneTimeNotifPrekey(),
};
- }
}
export { IdentityServiceClientWrapper };
diff --git a/web/grpc/identity-service-context-provider.react.js b/web/grpc/identity-service-context-provider.react.js
new file mode 100644
--- /dev/null
+++ b/web/grpc/identity-service-context-provider.react.js
@@ -0,0 +1,50 @@
+// @flow
+
+import * as React from 'react';
+
+import { IdentityClientContext } from 'lib/shared/identity-client-context.js';
+import type { IdentityServiceClient } from 'lib/types/identity-service-types.js';
+
+import { IdentityServiceClientWrapper } from './identity-service-client-wrapper.js';
+import { useSelector } from '../redux/redux-utils.js';
+
+type Props = {
+ +children: React.Node,
+};
+function IdentityServiceContextProvider(props: Props): React.Node {
+ const { children } = props;
+ const [client, setClient] = React.useState<?IdentityServiceClient>();
+
+ const userID = useSelector(state => state.currentUserInfo?.id);
+ const accessToken = useSelector(state => state.commServicesAccessToken);
+ const deviceID = useSelector(
+ state => state.cryptoStore?.primaryIdentityKeys.ed25519,
+ );
+
+ React.useEffect(() => {
+ let authLayer = null;
+ if (userID && deviceID && accessToken) {
+ authLayer = {
+ userID,
+ deviceID,
+ commServicesAccessToken: accessToken,
+ };
+ }
+ setClient(new IdentityServiceClientWrapper(authLayer));
+ }, [accessToken, deviceID, userID]);
+
+ const value = React.useMemo(
+ () => ({
+ identityClient: client,
+ }),
+ [client],
+ );
+
+ return (
+ <IdentityClientContext.Provider value={value}>
+ {children}
+ </IdentityClientContext.Provider>
+ );
+}
+
+export default IdentityServiceContextProvider;
diff --git a/web/root.js b/web/root.js
--- a/web/root.js
+++ b/web/root.js
@@ -21,6 +21,7 @@
import { SQLiteDataHandler } from './database/sqlite-data-handler.js';
import { localforageConfig } from './database/utils/constants.js';
import ErrorBoundary from './error-boundary.react.js';
+import IdentityServiceContextProvider from './grpc/identity-service-context-provider.react.js';
import { defaultWebState } from './redux/default-state.js';
import InitialReduxStateGate from './redux/initial-state-gate.js';
import { persistConfig } from './redux/persist.js';
@@ -43,14 +44,16 @@
<ErrorBoundary>
<InitialReduxStateGate persistor={persistor}>
<GetOrCreateCryptoStoreProvider>
- <WebNotificationsSessionCreatorProvider>
- <Router history={history.getHistoryObject()}>
- <Route path="*" component={App} />
- </Router>
- <KeyserverConnectionsHandler socketComponent={Socket} />
- <SQLiteDataHandler />
- <IntegrityHandler />
- </WebNotificationsSessionCreatorProvider>
+ <IdentityServiceContextProvider>
+ <WebNotificationsSessionCreatorProvider>
+ <Router history={history.getHistoryObject()}>
+ <Route path="*" component={App} />
+ </Router>
+ <KeyserverConnectionsHandler socketComponent={Socket} />
+ <SQLiteDataHandler />
+ <IntegrityHandler />
+ </WebNotificationsSessionCreatorProvider>
+ </IdentityServiceContextProvider>
</GetOrCreateCryptoStoreProvider>
</InitialReduxStateGate>
</ErrorBoundary>
diff --git a/web/settings/account-delete-modal.react.js b/web/settings/account-delete-modal.react.js
--- a/web/settings/account-delete-modal.react.js
+++ b/web/settings/account-delete-modal.react.js
@@ -17,7 +17,6 @@
import css from './account-delete-modal.css';
import Button, { buttonThemes } from '../components/button.react.js';
-import { IdentityServiceClientWrapper } from '../grpc/identity-service-client-wrapper.js';
import Modal from '../modals/modal.react.js';
import { useSelector } from '../redux/redux-utils.js';
@@ -40,17 +39,6 @@
const inputDisabled =
isDeleteKeyserverAccountLoading || isDeleteIdentityAccountLoading;
- const deviceID = useSelector(
- state => state.cryptoStore?.primaryIdentityKeys.ed25519,
- );
-
- const identityServiceClientWrapperRef =
- React.useRef<?IdentityServiceClientWrapper>(null);
- if (!identityServiceClientWrapperRef.current) {
- identityServiceClientWrapperRef.current =
- new IdentityServiceClientWrapper();
- }
- const identityServiceClient = identityServiceClientWrapperRef.current;
const callDeleteIdentityAccount = useDeleteIdentityAccount();
const callDeleteKeyserverAccount = useDeleteKeyserverAccount();
@@ -98,10 +86,7 @@
const deleteIdentityAction = React.useCallback(async () => {
try {
setIdentityErrorMessage('');
- const response = await callDeleteIdentityAccount(
- identityServiceClient,
- deviceID,
- );
+ const response = await callDeleteIdentityAccount();
popModal();
return response;
} catch (e) {
@@ -110,7 +95,7 @@
);
throw e;
}
- }, [callDeleteIdentityAccount, deviceID, identityServiceClient, popModal]);
+ }, [callDeleteIdentityAccount, popModal]);
const onDelete = React.useCallback(
(event: SyntheticEvent<HTMLButtonElement>) => {

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 24, 8:22 AM (19 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2574683
Default Alt Text
D10584.diff (26 KB)

Event Timeline