Page MenuHomePhabricator

D10584.id35437.diff
No OneTemporary

D10584.id35437.diff

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
@@ -24,3 +24,8 @@
+deviceID: string,
+commServicesAccessToken: string,
};
+
+export interface IdentityServiceClient {
+ +deleteUser: () => Promise<void>,
+ +getKeyserverKeys: (string) => Promise<?OutboundKeyInfoResponse>,
+}
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,76 @@
+// @flow
+
+import * as React from 'react';
+
+import { IdentityClientContext } from 'lib/shared/identity-client-context.js';
+import type {
+ IdentityServiceClient,
+ OutboundKeyInfoResponse,
+} from 'lib/types/identity-service-types.js';
+
+import { commRustModule } from '../native-modules.js';
+import { useSelector } from '../redux/redux-utils.js';
+import { getContentSigningKey } from '../utils/crypto-utils.js';
+
+type Props = {
+ +children: React.Node,
+};
+function IdentityServiceContextProvider(props: Props): React.Node {
+ const { children } = props;
+
+ const userID = useSelector(state => state.currentUserInfo?.id);
+ const accessToken = useSelector(state => state.commServicesAccessToken);
+ const [deviceID, setDeviceID] = React.useState<?string>();
+
+ React.useEffect(() => {
+ void (async () => {
+ const contentSigningKey = await getContentSigningKey();
+ setDeviceID(contentSigningKey);
+ })();
+ }, []);
+
+ const client = React.useMemo<?IdentityServiceClient>(() => {
+ if (!userID || !deviceID || !accessToken) {
+ return null;
+ }
+ return {
+ deleteUser: () =>
+ commRustModule.deleteUser(userID, deviceID, accessToken),
+ getKeyserverKeys: async (keyserverID: string) => {
+ 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
+ ) {
+ return null;
+ }
+ return resultObject;
+ },
+ };
+ }, [accessToken, deviceID, userID]);
+
+ const value = React.useMemo(
+ () => ({
+ identityClient: client,
+ }),
+ [client],
+ );
+
+ return (
+ <IdentityClientContext.Provider value={value}>
+ {children}
+ </IdentityClientContext.Provider>
+ );
+}
+
+export default IdentityServiceContextProvider;
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 ConnectedStatusBar from './connected-status-bar.react.js';
import { SQLiteDataHandler } from './data/sqlite-data-handler.js';
import ErrorBoundary from './error-boundary.react.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';
@@ -295,58 +296,60 @@
return (
<GestureHandlerRootView style={styles.app}>
<StaffContextProvider>
- <TunnelbrokerProvider initMessage={tunnelbrokerInitMessage}>
- <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 />
- <IdentityHandler />
- </PersistedStateGate>
- {navigation}
- </RegistrationContextProvider>
- </BottomSheetProvider>
- </MessageSearchProvider>
- </MarkdownContextProvider>
- </NativeEditThreadAvatarProvider>
- </EditUserAvatarProvider>
- </MediaCacheProvider>
- </ENSCacheProvider>
- </ActionSheetProvider>
- </SafeAreaProvider>
- </MessageEditingContextProvider>
- </InputStateContainer>
- </RootContext.Provider>
- </NavContext.Provider>
- </FeatureFlagsProvider>
- </TunnelbrokerProvider>
+ <IdentityServiceContextProvider>
+ <TunnelbrokerProvider initMessage={tunnelbrokerInitMessage}>
+ <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 />
+ <IdentityHandler />
+ </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';
@@ -12,23 +13,30 @@
import * as IdentityClient from '../protobufs/identity-client.cjs';
import { Empty } from '../protobufs/identity-structs.cjs';
-class IdentityServiceClientWrapper {
+class IdentityServiceClientWrapper implements IdentityServiceClient {
authClient: ?IdentityAuthClient.IdentityClientServicePromiseClient;
- unauthorizedClient: ?IdentityClient.IdentityClientServicePromiseClient;
+ unauthorizedClient: IdentityClient.IdentityClientServicePromiseClient;
- constructor() {
- this.authClient = null;
- this.unauthorizedClient = null;
+ constructor(authLayer: ?IdentityServiceAuthLayer) {
+ if (authLayer) {
+ this.authClient =
+ IdentityServiceClientWrapper.createAuthClient(authLayer);
+ }
+ this.unauthorizedClient =
+ IdentityServiceClientWrapper.createUnauthorizedClient();
}
- 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,15 +49,16 @@
unaryInterceptors: [versionInterceptor, authInterceptor],
};
- this.authClient = new IdentityAuthClient.IdentityClientServicePromiseClient(
+ return new IdentityAuthClient.IdentityClientServicePromiseClient(
identitySocketAddr,
null,
authClientOpts,
);
}
- async initUnauthorizedClient(): Promise<void> {
- const identitySocketAddr = this.determineSocketAddr();
+ static createUnauthorizedClient(): IdentityClient.IdentityClientServicePromiseClient {
+ const identitySocketAddr =
+ IdentityServiceClientWrapper.determineSocketAddr();
const versionInterceptor = new VersionInterceptor<Request, Response>();
@@ -57,83 +66,55 @@
unaryInterceptors: [versionInterceptor],
};
- this.unauthorizedClient =
- new IdentityClient.IdentityClientServicePromiseClient(
- identitySocketAddr,
- null,
- unauthorizedClientOpts,
- );
+ return new IdentityClient.IdentityClientServicePromiseClient(
+ identitySocketAddr,
+ null,
+ unauthorizedClientOpts,
+ );
}
- async deleteUser(
- 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');
}
- }
-
- async getKeyserverKeys(
- userID: string,
- deviceID: string,
- accessToken: string,
- keyserverID: string,
- ): Promise<?OutboundKeyInfoResponse> {
- if (!this.authClient) {
- const authLayer: IdentityServiceAuthLayer = {
- userID,
- deviceID,
- commServicesAccessToken: accessToken,
+ await this.authClient.deleteUser(new Empty());
+ };
+
+ 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>

File Metadata

Mime Type
text/plain
Expires
Tue, Dec 24, 10:57 AM (1 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2699755
Default Alt Text
D10584.id35437.diff (20 KB)

Event Timeline