Replace uses of checkDeviceTrust
with getDeviceVerificationStatus
(#10663)
matrix-org/matrix-js-sdk#3287 and matrix-org/matrix-js-sdk#3303 added a new API called getDeviceVerificationStatus. Let's use it.
This commit is contained in:
parent
aa8c0f5cc7
commit
d7bb8043ea
22 changed files with 286 additions and 161 deletions
|
@ -310,7 +310,11 @@ export default class DeviceListener {
|
|||
const newUnverifiedDeviceIds = new Set<string>();
|
||||
|
||||
const isCurrentDeviceTrusted =
|
||||
crossSigningReady && (await cli.checkDeviceTrust(cli.getUserId()!, cli.deviceId!).isCrossSigningVerified());
|
||||
crossSigningReady &&
|
||||
Boolean(
|
||||
(await cli.getCrypto()?.getDeviceVerificationStatus(cli.getUserId()!, cli.deviceId!))
|
||||
?.crossSigningVerified,
|
||||
);
|
||||
|
||||
// as long as cross-signing isn't ready,
|
||||
// you can't see or dismiss any device toasts
|
||||
|
@ -319,8 +323,10 @@ export default class DeviceListener {
|
|||
for (const device of devices) {
|
||||
if (device.deviceId === cli.deviceId) continue;
|
||||
|
||||
const deviceTrust = await cli.checkDeviceTrust(cli.getUserId()!, device.deviceId!);
|
||||
if (!deviceTrust.isCrossSigningVerified() && !this.dismissed.has(device.deviceId)) {
|
||||
const deviceTrust = await cli
|
||||
.getCrypto()!
|
||||
.getDeviceVerificationStatus(cli.getUserId()!, device.deviceId!);
|
||||
if (!deviceTrust?.crossSigningVerified && !this.dismissed.has(device.deviceId)) {
|
||||
if (this.ourDeviceIdsAtStart?.has(device.deviceId)) {
|
||||
oldUnverifiedDeviceIds.add(device.deviceId);
|
||||
} else {
|
||||
|
|
|
@ -1073,9 +1073,9 @@ export const Commands = [
|
|||
},
|
||||
);
|
||||
}
|
||||
const deviceTrust = await cli.checkDeviceTrust(userId, deviceId);
|
||||
const deviceTrust = await cli.getCrypto()?.getDeviceVerificationStatus(userId, deviceId);
|
||||
|
||||
if (deviceTrust.isVerified()) {
|
||||
if (deviceTrust?.isVerified()) {
|
||||
if (device.getFingerprint() === fingerprint) {
|
||||
throw new UserFriendlyError("Session already verified!");
|
||||
} else {
|
||||
|
|
|
@ -79,6 +79,7 @@ import PosthogTrackers from "../../../PosthogTrackers";
|
|||
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||
import { DirectoryMember, startDmOnFirstMessage } from "../../../utils/direct-messages";
|
||||
import { SdkContextClass } from "../../../contexts/SDKContext";
|
||||
import { asyncSome } from "../../../utils/arrays";
|
||||
|
||||
export interface IDevice extends DeviceInfo {
|
||||
ambiguous?: boolean;
|
||||
|
@ -101,22 +102,22 @@ export const disambiguateDevices = (devices: IDevice[]): void => {
|
|||
}
|
||||
};
|
||||
|
||||
export const getE2EStatus = (cli: MatrixClient, userId: string, devices: IDevice[]): E2EStatus => {
|
||||
export const getE2EStatus = async (cli: MatrixClient, userId: string, devices: IDevice[]): Promise<E2EStatus> => {
|
||||
const isMe = userId === cli.getUserId();
|
||||
const userTrust = cli.checkUserTrust(userId);
|
||||
if (!userTrust.isCrossSigningVerified()) {
|
||||
return userTrust.wasCrossSigningVerified() ? E2EStatus.Warning : E2EStatus.Normal;
|
||||
}
|
||||
|
||||
const anyDeviceUnverified = devices.some((device) => {
|
||||
const anyDeviceUnverified = await asyncSome(devices, async (device) => {
|
||||
const { deviceId } = device;
|
||||
// For your own devices, we use the stricter check of cross-signing
|
||||
// verification to encourage everyone to trust their own devices via
|
||||
// cross-signing so that other users can then safely trust you.
|
||||
// For other people's devices, the more general verified check that
|
||||
// includes locally verified devices can be used.
|
||||
const deviceTrust = cli.checkDeviceTrust(userId, deviceId);
|
||||
return isMe ? !deviceTrust.isCrossSigningVerified() : !deviceTrust.isVerified();
|
||||
const deviceTrust = await cli.getCrypto()?.getDeviceVerificationStatus(userId, deviceId);
|
||||
return isMe ? !deviceTrust?.crossSigningVerified : !deviceTrust?.isVerified();
|
||||
});
|
||||
return anyDeviceUnverified ? E2EStatus.Warning : E2EStatus.Verified;
|
||||
};
|
||||
|
@ -161,14 +162,20 @@ function useHasCrossSigningKeys(
|
|||
export function DeviceItem({ userId, device }: { userId: string; device: IDevice }): JSX.Element {
|
||||
const cli = useContext(MatrixClientContext);
|
||||
const isMe = userId === cli.getUserId();
|
||||
const deviceTrust = cli.checkDeviceTrust(userId, device.deviceId);
|
||||
const userTrust = cli.checkUserTrust(userId);
|
||||
// For your own devices, we use the stricter check of cross-signing
|
||||
// verification to encourage everyone to trust their own devices via
|
||||
// cross-signing so that other users can then safely trust you.
|
||||
// For other people's devices, the more general verified check that
|
||||
// includes locally verified devices can be used.
|
||||
const isVerified = isMe ? deviceTrust.isCrossSigningVerified() : deviceTrust.isVerified();
|
||||
|
||||
/** is the device verified? */
|
||||
const isVerified = useAsyncMemo(async () => {
|
||||
const deviceTrust = await cli.getCrypto()?.getDeviceVerificationStatus(userId, device.deviceId);
|
||||
if (!deviceTrust) return false;
|
||||
|
||||
// For your own devices, we use the stricter check of cross-signing
|
||||
// verification to encourage everyone to trust their own devices via
|
||||
// cross-signing so that other users can then safely trust you.
|
||||
// For other people's devices, the more general verified check that
|
||||
// includes locally verified devices can be used.
|
||||
return isMe ? deviceTrust.crossSigningVerified : deviceTrust.isVerified();
|
||||
}, [cli, userId, device]);
|
||||
|
||||
const classes = classNames("mx_UserInfo_device", {
|
||||
mx_UserInfo_device_verified: isVerified,
|
||||
|
@ -199,7 +206,10 @@ export function DeviceItem({ userId, device }: { userId: string; device: IDevice
|
|||
let trustedLabel: string | undefined;
|
||||
if (userTrust.isVerified()) trustedLabel = isVerified ? _t("Trusted") : _t("Not trusted");
|
||||
|
||||
if (isVerified) {
|
||||
if (isVerified === undefined) {
|
||||
// we're still deciding if the device is verified
|
||||
return <div className={classes} title={device.deviceId} />;
|
||||
} else if (isVerified) {
|
||||
return (
|
||||
<div className={classes} title={device.deviceId}>
|
||||
<div className={iconClasses} />
|
||||
|
@ -232,15 +242,17 @@ function DevicesSection({
|
|||
|
||||
const [isExpanded, setExpanded] = useState(false);
|
||||
|
||||
if (loading) {
|
||||
const deviceTrusts = useAsyncMemo(() => {
|
||||
const cryptoApi = cli.getCrypto();
|
||||
if (!cryptoApi) return Promise.resolve(undefined);
|
||||
return Promise.all(devices.map((d) => cryptoApi.getDeviceVerificationStatus(userId, d.deviceId)));
|
||||
}, [cli, userId, devices]);
|
||||
|
||||
if (loading || deviceTrusts === undefined) {
|
||||
// still loading
|
||||
return <Spinner />;
|
||||
}
|
||||
if (devices === null) {
|
||||
return <p>{_t("Unable to load session list")}</p>;
|
||||
}
|
||||
const isMe = userId === cli.getUserId();
|
||||
const deviceTrusts = devices.map((d) => cli.checkDeviceTrust(userId, d.deviceId));
|
||||
|
||||
let expandSectionDevices: IDevice[] = [];
|
||||
const unverifiedDevices: IDevice[] = [];
|
||||
|
@ -258,7 +270,7 @@ function DevicesSection({
|
|||
// cross-signing so that other users can then safely trust you.
|
||||
// For other people's devices, the more general verified check that
|
||||
// includes locally verified devices can be used.
|
||||
const isVerified = isMe ? deviceTrust.isCrossSigningVerified() : deviceTrust.isVerified();
|
||||
const isVerified = deviceTrust && (isMe ? deviceTrust.crossSigningVerified : deviceTrust.isVerified());
|
||||
|
||||
if (isVerified) {
|
||||
expandSectionDevices.push(device);
|
||||
|
@ -1611,10 +1623,12 @@ const UserInfo: React.FC<IProps> = ({ user, room, onClose, phase = RightPanelPha
|
|||
const isRoomEncrypted = useIsEncrypted(cli, room);
|
||||
const devices = useDevices(user.userId) ?? [];
|
||||
|
||||
let e2eStatus: E2EStatus | undefined;
|
||||
if (isRoomEncrypted && devices) {
|
||||
e2eStatus = getE2EStatus(cli, user.userId, devices);
|
||||
}
|
||||
const e2eStatus = useAsyncMemo(async () => {
|
||||
if (!isRoomEncrypted || !devices) {
|
||||
return undefined;
|
||||
}
|
||||
return await getE2EStatus(cli, user.userId, devices);
|
||||
}, [cli, isRoomEncrypted, user.userId, devices]);
|
||||
|
||||
const classes = ["mx_UserInfo"];
|
||||
|
||||
|
|
|
@ -265,6 +265,8 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
public static contextType = RoomContext;
|
||||
public context!: React.ContextType<typeof RoomContext>;
|
||||
|
||||
private unmounted = false;
|
||||
|
||||
public constructor(props: EventTileProps, context: React.ContextType<typeof MatrixClientContext>) {
|
||||
super(props, context);
|
||||
|
||||
|
@ -420,6 +422,7 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
this.props.mxEvent.removeListener(MatrixEventEvent.RelationsCreated, this.onReactionsCreated);
|
||||
}
|
||||
this.props.mxEvent.off(ThreadEvent.Update, this.updateThread);
|
||||
this.unmounted = false;
|
||||
}
|
||||
|
||||
public componentDidUpdate(prevProps: Readonly<EventTileProps>, prevState: Readonly<IState>): void {
|
||||
|
@ -561,7 +564,7 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
this.verifyEvent();
|
||||
};
|
||||
|
||||
private verifyEvent(): void {
|
||||
private async verifyEvent(): Promise<void> {
|
||||
// if the event was edited, show the verification info for the edit, not
|
||||
// the original
|
||||
const mxEvent = this.props.mxEvent.replacingEvent() ?? this.props.mxEvent;
|
||||
|
@ -590,7 +593,14 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
}
|
||||
|
||||
const eventSenderTrust =
|
||||
encryptionInfo.sender && MatrixClientPeg.get().checkDeviceTrust(senderId, encryptionInfo.sender.deviceId);
|
||||
senderId &&
|
||||
encryptionInfo.sender &&
|
||||
(await MatrixClientPeg.get()
|
||||
.getCrypto()
|
||||
?.getDeviceVerificationStatus(senderId, encryptionInfo.sender.deviceId));
|
||||
|
||||
if (this.unmounted) return;
|
||||
|
||||
if (!eventSenderTrust) {
|
||||
this.setState({ verified: E2EState.Unknown });
|
||||
return;
|
||||
|
|
|
@ -33,6 +33,7 @@ import MemberAvatar from "./../avatars/MemberAvatar";
|
|||
import DisambiguatedProfile from "../messages/DisambiguatedProfile";
|
||||
import UserIdentifierCustomisations from "../../../customisations/UserIdentifier";
|
||||
import { E2EState } from "./E2EIcon";
|
||||
import { asyncSome } from "../../../utils/arrays";
|
||||
|
||||
interface IProps {
|
||||
member: RoomMember;
|
||||
|
@ -127,15 +128,15 @@ export default class MemberTile extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
const devices = cli.getStoredDevicesForUser(userId);
|
||||
const anyDeviceUnverified = devices.some((device) => {
|
||||
const anyDeviceUnverified = await asyncSome(devices, async (device) => {
|
||||
const { deviceId } = device;
|
||||
// For your own devices, we use the stricter check of cross-signing
|
||||
// verification to encourage everyone to trust their own devices via
|
||||
// cross-signing so that other users can then safely trust you.
|
||||
// For other people's devices, the more general verified check that
|
||||
// includes locally verified devices can be used.
|
||||
const deviceTrust = cli.checkDeviceTrust(userId, deviceId);
|
||||
return isMe ? !deviceTrust.isCrossSigningVerified() : !deviceTrust.isVerified();
|
||||
const deviceTrust = await cli.getCrypto()?.getDeviceVerificationStatus(userId, deviceId);
|
||||
return !deviceTrust || (isMe ? !deviceTrust.crossSigningVerified : !deviceTrust.isVerified());
|
||||
});
|
||||
this.setState({
|
||||
e2eStatus: anyDeviceUnverified ? E2EState.Warning : E2EState.Verified,
|
||||
|
|
|
@ -26,14 +26,15 @@ import Spinner from "../elements/Spinner";
|
|||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
import { deleteDevicesWithInteractiveAuth } from "./devices/deleteDevices";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import { isDeviceVerified } from "../../../utils/device/isDeviceVerified";
|
||||
import { fetchExtendedDeviceInformation } from "./devices/useOwnDevices";
|
||||
import { DevicesDictionary, ExtendedDevice } from "./devices/types";
|
||||
|
||||
interface IProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
devices: IMyDevice[];
|
||||
devices?: DevicesDictionary;
|
||||
deviceLoadError?: string;
|
||||
selectedDevices: string[];
|
||||
deleting?: boolean;
|
||||
|
@ -47,7 +48,6 @@ export default class DevicesPanel extends React.Component<IProps, IState> {
|
|||
public constructor(props: IProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
devices: [],
|
||||
selectedDevices: [],
|
||||
};
|
||||
this.loadDevices = this.loadDevices.bind(this);
|
||||
|
@ -70,18 +70,16 @@ export default class DevicesPanel extends React.Component<IProps, IState> {
|
|||
|
||||
private loadDevices(): void {
|
||||
const cli = this.context;
|
||||
cli.getDevices().then(
|
||||
(resp) => {
|
||||
fetchExtendedDeviceInformation(cli).then(
|
||||
(devices) => {
|
||||
if (this.unmounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState((state, props) => {
|
||||
const deviceIds = resp.devices.map((device) => device.device_id);
|
||||
const selectedDevices = state.selectedDevices.filter((deviceId) => deviceIds.includes(deviceId));
|
||||
return {
|
||||
devices: resp.devices || [],
|
||||
selectedDevices,
|
||||
devices: devices,
|
||||
selectedDevices: state.selectedDevices.filter((deviceId) => devices.hasOwnProperty(deviceId)),
|
||||
};
|
||||
});
|
||||
},
|
||||
|
@ -119,10 +117,6 @@ export default class DevicesPanel extends React.Component<IProps, IState> {
|
|||
return idA < idB ? -1 : idA > idB ? 1 : 0;
|
||||
}
|
||||
|
||||
private isDeviceVerified(device: IMyDevice): boolean | null {
|
||||
return isDeviceVerified(this.context, device.device_id);
|
||||
}
|
||||
|
||||
private onDeviceSelectionToggled = (device: IMyDevice): void => {
|
||||
if (this.unmounted) {
|
||||
return;
|
||||
|
@ -205,15 +199,15 @@ export default class DevicesPanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
private renderDevice = (device: IMyDevice): JSX.Element => {
|
||||
const myDeviceId = this.context.getDeviceId();
|
||||
const myDevice = this.state.devices.find((device) => device.device_id === myDeviceId);
|
||||
private renderDevice = (device: ExtendedDevice): JSX.Element => {
|
||||
const myDeviceId = this.context.getDeviceId()!;
|
||||
const myDevice = this.state.devices?.[myDeviceId];
|
||||
|
||||
const isOwnDevice = device.device_id === myDeviceId;
|
||||
|
||||
// If our own device is unverified, it can't verify other
|
||||
// devices, it can only request verification for itself
|
||||
const canBeVerified = (myDevice && this.isDeviceVerified(myDevice)) || isOwnDevice;
|
||||
const canBeVerified = (myDevice && myDevice.isVerified) || isOwnDevice;
|
||||
|
||||
return (
|
||||
<DevicesPanelEntry
|
||||
|
@ -221,7 +215,7 @@ export default class DevicesPanel extends React.Component<IProps, IState> {
|
|||
device={device}
|
||||
selected={this.state.selectedDevices.includes(device.device_id)}
|
||||
isOwnDevice={isOwnDevice}
|
||||
verified={this.isDeviceVerified(device)}
|
||||
verified={device.isVerified}
|
||||
canBeVerified={canBeVerified}
|
||||
onDeviceChange={this.loadDevices}
|
||||
onDeviceToggled={this.onDeviceSelectionToggled}
|
||||
|
@ -242,21 +236,21 @@ export default class DevicesPanel extends React.Component<IProps, IState> {
|
|||
return <Spinner />;
|
||||
}
|
||||
|
||||
const myDeviceId = this.context.getDeviceId();
|
||||
const myDevice = devices.find((device) => device.device_id === myDeviceId);
|
||||
const myDeviceId = this.context.getDeviceId()!;
|
||||
const myDevice = devices[myDeviceId];
|
||||
|
||||
if (!myDevice) {
|
||||
return loadError;
|
||||
}
|
||||
|
||||
const otherDevices = devices.filter((device) => device.device_id !== myDeviceId);
|
||||
const otherDevices = Object.values(devices).filter((device) => device.device_id !== myDeviceId);
|
||||
otherDevices.sort(this.deviceCompare);
|
||||
|
||||
const verifiedDevices: IMyDevice[] = [];
|
||||
const unverifiedDevices: IMyDevice[] = [];
|
||||
const nonCryptoDevices: IMyDevice[] = [];
|
||||
const verifiedDevices: ExtendedDevice[] = [];
|
||||
const unverifiedDevices: ExtendedDevice[] = [];
|
||||
const nonCryptoDevices: ExtendedDevice[] = [];
|
||||
for (const device of otherDevices) {
|
||||
const verified = this.isDeviceVerified(device);
|
||||
const verified = device.isVerified;
|
||||
if (verified === true) {
|
||||
verifiedDevices.push(device);
|
||||
} else if (verified === false) {
|
||||
|
@ -266,7 +260,7 @@ export default class DevicesPanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
const section = (trustIcon: JSX.Element, title: string, deviceList: IMyDevice[]): JSX.Element => {
|
||||
const section = (trustIcon: JSX.Element, title: string, deviceList: ExtendedDevice[]): JSX.Element => {
|
||||
if (deviceList.length === 0) {
|
||||
return <React.Fragment />;
|
||||
}
|
||||
|
|
|
@ -50,24 +50,26 @@ const parseDeviceExtendedInformation = (matrixClient: MatrixClient, device: IMyD
|
|||
};
|
||||
};
|
||||
|
||||
const fetchDevicesWithVerification = async (matrixClient: MatrixClient): Promise<DevicesState["devices"]> => {
|
||||
/**
|
||||
* Fetch extended details of the user's own devices
|
||||
*
|
||||
* @param matrixClient - Matrix Client
|
||||
* @returns A dictionary mapping from device ID to ExtendedDevice
|
||||
*/
|
||||
export async function fetchExtendedDeviceInformation(matrixClient: MatrixClient): Promise<DevicesDictionary> {
|
||||
const { devices } = await matrixClient.getDevices();
|
||||
|
||||
const devicesDict = devices.reduce(
|
||||
(acc, device: IMyDevice) => ({
|
||||
...acc,
|
||||
[device.device_id]: {
|
||||
...device,
|
||||
isVerified: isDeviceVerified(matrixClient, device.device_id),
|
||||
...parseDeviceExtendedInformation(matrixClient, device),
|
||||
...parseUserAgent(device[UNSTABLE_MSC3852_LAST_SEEN_UA.name]),
|
||||
},
|
||||
}),
|
||||
{},
|
||||
);
|
||||
|
||||
const devicesDict: DevicesDictionary = {};
|
||||
for (const device of devices) {
|
||||
devicesDict[device.device_id] = {
|
||||
...device,
|
||||
isVerified: await isDeviceVerified(matrixClient, device.device_id),
|
||||
...parseDeviceExtendedInformation(matrixClient, device),
|
||||
...parseUserAgent(device[UNSTABLE_MSC3852_LAST_SEEN_UA.name]),
|
||||
};
|
||||
}
|
||||
return devicesDict;
|
||||
};
|
||||
}
|
||||
|
||||
export enum OwnDevicesError {
|
||||
Unsupported = "Unsupported",
|
||||
|
@ -112,7 +114,7 @@ export const useOwnDevices = (): DevicesState => {
|
|||
const refreshDevices = useCallback(async (): Promise<void> => {
|
||||
setIsLoadingDeviceList(true);
|
||||
try {
|
||||
const devices = await fetchDevicesWithVerification(matrixClient);
|
||||
const devices = await fetchExtendedDeviceInformation(matrixClient);
|
||||
setDevices(devices);
|
||||
|
||||
const { pushers } = await matrixClient.getPushers();
|
||||
|
|
|
@ -2256,7 +2256,6 @@
|
|||
"Room settings": "Room settings",
|
||||
"Trusted": "Trusted",
|
||||
"Not trusted": "Not trusted",
|
||||
"Unable to load session list": "Unable to load session list",
|
||||
"%(count)s verified sessions|other": "%(count)s verified sessions",
|
||||
"%(count)s verified sessions|one": "1 verified session",
|
||||
"Hide verified sessions": "Hide verified sessions",
|
||||
|
|
|
@ -109,14 +109,20 @@ export class SetupEncryptionStore extends EventEmitter {
|
|||
const dehydratedDevice = await cli.getDehydratedDevice();
|
||||
const ownUserId = cli.getUserId()!;
|
||||
const crossSigningInfo = cli.getStoredCrossSigningForUser(ownUserId);
|
||||
this.hasDevicesToVerifyAgainst = cli
|
||||
.getStoredDevicesForUser(ownUserId)
|
||||
.some(
|
||||
(device) =>
|
||||
device.getIdentityKey() &&
|
||||
(!dehydratedDevice || device.deviceId != dehydratedDevice.device_id) &&
|
||||
crossSigningInfo?.checkDeviceTrust(crossSigningInfo, device, false, true).isCrossSigningVerified(),
|
||||
);
|
||||
this.hasDevicesToVerifyAgainst = cli.getStoredDevicesForUser(ownUserId).some((device) => {
|
||||
if (!device.getIdentityKey() || (dehydratedDevice && device.deviceId == dehydratedDevice?.device_id)) {
|
||||
return false;
|
||||
}
|
||||
// check if the device is signed by the cross-signing key stored for our user. Note that this is
|
||||
// *different* to calling `cryptoApi.getDeviceVerificationStatus`, because even if we have stored
|
||||
// a cross-signing key for our user, we don't necessarily trust it yet (In legacy Crypto, we have not
|
||||
// yet imported it into `Crypto.crossSigningInfo`, which for maximal confusion is a different object to
|
||||
// `Crypto.getStoredCrossSigningForUser(ownUserId)`).
|
||||
//
|
||||
// TODO: figure out wtf to to here for rust-crypto
|
||||
const verificationStatus = crossSigningInfo?.checkDeviceTrust(crossSigningInfo, device, false, true);
|
||||
return !!verificationStatus?.isCrossSigningVerified();
|
||||
});
|
||||
|
||||
this.phase = Phase.Intro;
|
||||
this.emit("update");
|
||||
|
|
|
@ -48,7 +48,7 @@ export const showToast = async (deviceId: string): Promise<void> => {
|
|||
const device = await cli.getDevice(deviceId);
|
||||
const extendedDevice = {
|
||||
...device,
|
||||
isVerified: isDeviceVerified(cli, deviceId),
|
||||
isVerified: await isDeviceVerified(cli, deviceId),
|
||||
deviceType: DeviceType.Unknown,
|
||||
};
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import { MatrixClient } from "matrix-js-sdk/src/client";
|
|||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
|
||||
import DMRoomMap from "./DMRoomMap";
|
||||
import { asyncSome } from "./arrays";
|
||||
|
||||
export enum E2EStatus {
|
||||
Warning = "warning",
|
||||
|
@ -54,8 +55,9 @@ export async function shieldStatusForRoom(client: MatrixClient, room: Room): Pro
|
|||
const targets = includeUser ? [...verified, client.getUserId()!] : verified;
|
||||
for (const userId of targets) {
|
||||
const devices = client.getStoredDevicesForUser(userId);
|
||||
const anyDeviceNotVerified = devices.some(({ deviceId }) => {
|
||||
return !client.checkDeviceTrust(userId, deviceId).isVerified();
|
||||
const anyDeviceNotVerified = await asyncSome(devices, async ({ deviceId }) => {
|
||||
const verificationStatus = await client.getCrypto()?.getDeviceVerificationStatus(userId, deviceId);
|
||||
return !verificationStatus?.isVerified();
|
||||
});
|
||||
if (anyDeviceNotVerified) {
|
||||
return E2EStatus.Warning;
|
||||
|
|
|
@ -324,6 +324,16 @@ export async function asyncEvery<T>(values: T[], predicate: (value: T) => Promis
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Async version of Array.some.
|
||||
*/
|
||||
export async function asyncSome<T>(values: T[], predicate: (value: T) => Promise<boolean>): Promise<boolean> {
|
||||
for (const value of values) {
|
||||
if (await predicate(value)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function filterBoolean<T>(values: Array<T | null | undefined>): T[] {
|
||||
return values.filter(Boolean) as T[];
|
||||
}
|
||||
|
|
|
@ -25,10 +25,10 @@ import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
|||
* @returns `true` if the device has been correctly cross-signed. `false` if the device is unknown or not correctly
|
||||
* cross-signed. `null` if there was an error fetching the device info.
|
||||
*/
|
||||
export const isDeviceVerified = (client: MatrixClient, deviceId: string): boolean | null => {
|
||||
export const isDeviceVerified = async (client: MatrixClient, deviceId: string): Promise<boolean | null> => {
|
||||
try {
|
||||
const trustLevel = client.checkDeviceTrust(client.getSafeUserId(), deviceId);
|
||||
return trustLevel.isCrossSigningVerified();
|
||||
const trustLevel = await client.getCrypto()?.getDeviceVerificationStatus(client.getSafeUserId(), deviceId);
|
||||
return trustLevel?.crossSigningVerified ?? false;
|
||||
} catch (e) {
|
||||
console.error("Error getting device cross-signing info", e);
|
||||
return null;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue