Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3361805
D12638.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
3 KB
Referenced Files
None
Subscribers
None
D12638.diff
View Options
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
@@ -76,6 +76,7 @@
} from '../types/tunnelbroker/peer-to-peer-message-types.js';
import {
userActionsP2PMessageTypes,
+ type PrimaryDeviceLogoutP2PMessage,
type SecondaryDeviceLogoutP2PMessage,
} from '../types/tunnelbroker/user-actions-peer-to-peer-message-types.js';
import type {
@@ -253,11 +254,82 @@
});
function usePrimaryDeviceLogOut(): () => Promise<LogOutResult> {
+ const identityContext = React.useContext(IdentityClientContext);
+ if (!identityContext) {
+ throw new Error('Identity service client is not initialized');
+ }
+
+ const { sendMessage } = useTunnelbroker();
const broadcastDeviceListUpdates = useBroadcastDeviceListUpdates();
const foreignPeerDevices = useSelector(getForeignPeerDevices);
const logOut = useLogOut(primaryDeviceLogOutOptions);
return React.useCallback(async () => {
+ const { identityClient, getAuthMetadata } = identityContext;
+ const authMetadata = await getAuthMetadata();
+ const { userID, deviceID: thisDeviceID } = authMetadata;
+ if (!thisDeviceID || !userID) {
+ throw new Error('No auth metadata');
+ }
+ const {
+ devices: [primaryDeviceID, ...secondaryDevices],
+ } = await fetchLatestDeviceList(identityClient, userID);
+ if (thisDeviceID !== primaryDeviceID) {
+ throw new Error('Used primary device logout on a non-primary device');
+ }
+
+ // create and send Olm Tunnelbroker messages to secondaryDevices
+ const { olmAPI } = getConfig();
+ await olmAPI.initializeCryptoAccount();
+ const messageContents: PrimaryDeviceLogoutP2PMessage = {
+ type: userActionsP2PMessageTypes.LOG_OUT_PRIMARY_DEVICE,
+ };
+ for (const deviceID of secondaryDevices) {
+ try {
+ const encryptedData = await olmAPI.encrypt(
+ JSON.stringify(messageContents),
+ deviceID,
+ );
+ const encryptedMessage: EncryptedMessage = {
+ type: peerToPeerMessageTypes.ENCRYPTED_MESSAGE,
+ senderInfo: { deviceID: thisDeviceID, userID },
+ encryptedData,
+ };
+ await sendMessage({
+ deviceID,
+ payload: JSON.stringify(encryptedMessage),
+ });
+ } catch {
+ try {
+ await createOlmSessionWithPeer(
+ authMetadata,
+ identityClient,
+ sendMessage,
+ userID,
+ deviceID,
+ );
+ const encryptedData = await olmAPI.encrypt(
+ JSON.stringify(messageContents),
+ deviceID,
+ );
+ const encryptedMessage: EncryptedMessage = {
+ type: peerToPeerMessageTypes.ENCRYPTED_MESSAGE,
+ senderInfo: { deviceID: thisDeviceID, userID },
+ encryptedData,
+ };
+ await sendMessage({
+ deviceID,
+ payload: JSON.stringify(encryptedMessage),
+ });
+ } catch (err) {
+ console.warn(
+ `Error sending primary device logout message to device ${deviceID}:`,
+ err,
+ );
+ }
+ }
+ }
+
// - logOut() performs device list update by calling Identity RPC
// - broadcastDeviceListUpdates asks peers to download it from identity
// so we need to call them in this order to make sure peers have latest
@@ -267,7 +339,13 @@
const logOutResult = await logOut();
await broadcastDeviceListUpdates(foreignPeerDevices);
return logOutResult;
- }, [broadcastDeviceListUpdates, foreignPeerDevices, logOut]);
+ }, [
+ broadcastDeviceListUpdates,
+ foreignPeerDevices,
+ identityContext,
+ logOut,
+ sendMessage,
+ ]);
}
const secondaryDeviceLogOutOptions = Object.freeze({
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Nov 25, 7:30 PM (21 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2580799
Default Alt Text
D12638.diff (3 KB)
Attached To
Mode
D12638: [lib] Send primary device logout message to secondary devices
Attached
Detach File
Event Timeline
Log In to Comment