Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3524002
D10584.id35437.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
20 KB
Referenced Files
None
Subscribers
None
D10584.id35437.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D10584: [lib][native][web] Expose identity API by using a context
Attached
Detach File
Event Timeline
Log In to Comment