Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Device manager - display client information in device details (PSG-68…
Browse files Browse the repository at this point in the history
…2) (#9315)

* record device client inforamtion events on app start

* matrix-client-information -> matrix_client_information

* fix types

* remove another unused export

* add docs link

* display device client information in device details

* update snapshots

* integration-ish test client information in metadata

* tests

* fix tests

* export helper

* DeviceClientInformation type
  • Loading branch information
Kerry authored Oct 4, 2022
1 parent c7a3209 commit 16c3efe
Show file tree
Hide file tree
Showing 11 changed files with 210 additions and 109 deletions.
27 changes: 23 additions & 4 deletions src/components/views/settings/devices/DeviceDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ import Spinner from '../../elements/Spinner';
import ToggleSwitch from '../../elements/ToggleSwitch';
import { DeviceDetailHeading } from './DeviceDetailHeading';
import { DeviceVerificationStatusCard } from './DeviceVerificationStatusCard';
import { DeviceWithVerification } from './types';
import { ExtendedDevice } from './types';

interface Props {
device: DeviceWithVerification;
device: ExtendedDevice;
pusher?: IPusher | undefined;
localNotificationSettings?: LocalNotificationSettings | undefined;
isSigningOut: boolean;
Expand All @@ -41,6 +41,7 @@ interface Props {
}

interface MetadataTable {
id: string;
heading?: string;
values: { label: string, value?: string | React.ReactNode }[];
}
Expand All @@ -58,6 +59,7 @@ const DeviceDetails: React.FC<Props> = ({
}) => {
const metadata: MetadataTable[] = [
{
id: 'session',
values: [
{ label: _t('Session ID'), value: device.device_id },
{
Expand All @@ -67,12 +69,28 @@ const DeviceDetails: React.FC<Props> = ({
],
},
{
id: 'application',
heading: _t('Application'),
values: [
{ label: _t('Name'), value: device.clientName },
{ label: _t('Version'), value: device.clientVersion },
{ label: _t('URL'), value: device.url },
],
},
{
id: 'device',
heading: _t('Device'),
values: [
{ label: _t('IP address'), value: device.last_seen_ip },
],
},
];
].map(section =>
// filter out falsy values
({ ...section, values: section.values.filter(row => !!row.value) }))
.filter(section =>
// then filter out sections with no values
section.values.length,
);

const showPushNotificationSection = !!pusher || !!localNotificationSettings;

Expand Down Expand Up @@ -101,9 +119,10 @@ const DeviceDetails: React.FC<Props> = ({
</section>
<section className='mx_DeviceDetails_section'>
<p className='mx_DeviceDetails_sectionHeading'>{ _t('Session details') }</p>
{ metadata.map(({ heading, values }, index) => <table
{ metadata.map(({ heading, values, id }, index) => <table
className='mx_DeviceDetails_metadataTable'
key={index}
data-testid={`device-detail-metadata-${id}`}
>
{ heading &&
<thead>
Expand Down
8 changes: 7 additions & 1 deletion src/components/views/settings/devices/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ limitations under the License.
import { IMyDevice } from "matrix-js-sdk/src/matrix";

export type DeviceWithVerification = IMyDevice & { isVerified: boolean | null };
export type DevicesDictionary = Record<DeviceWithVerification['device_id'], DeviceWithVerification>;
export type ExtendedDeviceInfo = {
clientName?: string;
clientVersion?: string;
url?: string;
};
export type ExtendedDevice = DeviceWithVerification & ExtendedDeviceInfo;
export type DevicesDictionary = Record<DeviceWithVerification['device_id'], ExtendedDevice>;

export enum DeviceSecurityVariation {
Verified = 'Verified',
Expand Down
14 changes: 13 additions & 1 deletion src/components/views/settings/devices/useOwnDevices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ import { LocalNotificationSettings } from "matrix-js-sdk/src/@types/local_notifi

import MatrixClientContext from "../../../../contexts/MatrixClientContext";
import { _t } from "../../../../languageHandler";
import { DevicesDictionary, DeviceWithVerification } from "./types";
import { getDeviceClientInformation } from "../../../../utils/device/clientInformation";
import { DevicesDictionary, DeviceWithVerification, ExtendedDeviceInfo } from "./types";
import { useEventEmitter } from "../../../../hooks/useEventEmitter";

const isDeviceVerified = (
Expand Down Expand Up @@ -62,6 +63,16 @@ const isDeviceVerified = (
}
};

const parseDeviceExtendedInformation = (matrixClient: MatrixClient, device: IMyDevice): ExtendedDeviceInfo => {
const { name, version, url } = getDeviceClientInformation(matrixClient, device.device_id);

return {
clientName: name,
clientVersion: version,
url,
};
};

const fetchDevicesWithVerification = async (
matrixClient: MatrixClient,
userId: string,
Expand All @@ -75,6 +86,7 @@ const fetchDevicesWithVerification = async (
[device.device_id]: {
...device,
isVerified: isDeviceVerified(matrixClient, crossSigningInfo, device),
...parseDeviceExtendedInformation(matrixClient, device),
},
}), {});

Expand Down
3 changes: 3 additions & 0 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1717,6 +1717,9 @@
"Please be aware that session names are also visible to people you communicate with": "Please be aware that session names are also visible to people you communicate with",
"Session ID": "Session ID",
"Last activity": "Last activity",
"Application": "Application",
"Version": "Version",
"URL": "URL",
"Device": "Device",
"IP address": "IP address",
"Session details": "Session details",
Expand Down
28 changes: 27 additions & 1 deletion src/utils/device/clientInformation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ import { MatrixClient } from "matrix-js-sdk/src/client";
import BasePlatform from "../../BasePlatform";
import { IConfigOptions } from "../../IConfigOptions";

export type DeviceClientInformation = {
name?: string;
version?: string;
url?: string;
};

const formatUrl = (): string | undefined => {
// don't record url for electron clients
if (window.electron) {
Expand All @@ -34,7 +40,7 @@ const formatUrl = (): string | undefined => {
].join("");
};

const getClientInformationEventType = (deviceId: string): string =>
export const getClientInformationEventType = (deviceId: string): string =>
`io.element.matrix_client_information.${deviceId}`;

/**
Expand All @@ -58,3 +64,23 @@ export const recordClientInformation = async (
url,
});
};

const sanitizeContentString = (value: unknown): string | undefined =>
value && typeof value === 'string' ? value : undefined;

export const getDeviceClientInformation = (matrixClient: MatrixClient, deviceId: string): DeviceClientInformation => {
const event = matrixClient.getAccountData(getClientInformationEventType(deviceId));

if (!event) {
return {};
}

const { name, version, url } = event.getContent();

return {
name: sanitizeContentString(name),
version: sanitizeContentString(version),
url: sanitizeContentString(url),
};
};

2 changes: 1 addition & 1 deletion test/DeviceListener-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ import { isSecretStorageBeingAccessed } from "../src/SecurityManager";
import dis from "../src/dispatcher/dispatcher";
import { Action } from "../src/dispatcher/actions";
import SettingsStore from "../src/settings/SettingsStore";
import { mockPlatformPeg } from "./test-utils";
import { SettingLevel } from "../src/settings/SettingLevel";
import { mockPlatformPeg } from "./test-utils";

// don't litter test console with logs
jest.mock("matrix-js-sdk/src/logger");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ describe('<DeviceDetails />', () => {
display_name: 'My Device',
last_seen_ip: '123.456.789',
last_seen_ts: now - 60000000,
clientName: 'Element Web',
};
const { container } = render(getComponent({ device }));
expect(container).toMatchSnapshot();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ HTMLCollection [
</p>
<table
class="mx_DeviceDetails_metadataTable"
data-testid="device-detail-metadata-session"
>
<tbody>
<tr>
Expand All @@ -90,39 +91,6 @@ HTMLCollection [
alices_device
</td>
</tr>
<tr>
<td
class="mxDeviceDetails_metadataLabel"
>
Last activity
</td>
<td
class="mxDeviceDetails_metadataValue"
/>
</tr>
</tbody>
</table>
<table
class="mx_DeviceDetails_metadataTable"
>
<thead>
<tr>
<th>
Device
</th>
</tr>
</thead>
<tbody>
<tr>
<td
class="mxDeviceDetails_metadataLabel"
>
IP address
</td>
<td
class="mxDeviceDetails_metadataValue"
/>
</tr>
</tbody>
</table>
</section>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ exports[`<DeviceDetails /> renders a verified device 1`] = `
</p>
<table
class="mx_DeviceDetails_metadataTable"
data-testid="device-detail-metadata-session"
>
<tbody>
<tr>
Expand All @@ -78,39 +79,6 @@ exports[`<DeviceDetails /> renders a verified device 1`] = `
my-device
</td>
</tr>
<tr>
<td
class="mxDeviceDetails_metadataLabel"
>
Last activity
</td>
<td
class="mxDeviceDetails_metadataValue"
/>
</tr>
</tbody>
</table>
<table
class="mx_DeviceDetails_metadataTable"
>
<thead>
<tr>
<th>
Device
</th>
</tr>
</thead>
<tbody>
<tr>
<td
class="mxDeviceDetails_metadataLabel"
>
IP address
</td>
<td
class="mxDeviceDetails_metadataValue"
/>
</tr>
</tbody>
</table>
</section>
Expand Down Expand Up @@ -198,6 +166,7 @@ exports[`<DeviceDetails /> renders device with metadata 1`] = `
</p>
<table
class="mx_DeviceDetails_metadataTable"
data-testid="device-detail-metadata-session"
>
<tbody>
<tr>
Expand Down Expand Up @@ -228,6 +197,33 @@ exports[`<DeviceDetails /> renders device with metadata 1`] = `
</table>
<table
class="mx_DeviceDetails_metadataTable"
data-testid="device-detail-metadata-application"
>
<thead>
<tr>
<th>
Application
</th>
</tr>
</thead>
<tbody>
<tr>
<td
class="mxDeviceDetails_metadataLabel"
>
Name
</td>
<td
class="mxDeviceDetails_metadataValue"
>
Element Web
</td>
</tr>
</tbody>
</table>
<table
class="mx_DeviceDetails_metadataTable"
data-testid="device-detail-metadata-device"
>
<thead>
<tr>
Expand Down Expand Up @@ -336,6 +332,7 @@ exports[`<DeviceDetails /> renders device without metadata 1`] = `
</p>
<table
class="mx_DeviceDetails_metadataTable"
data-testid="device-detail-metadata-session"
>
<tbody>
<tr>
Expand All @@ -350,39 +347,6 @@ exports[`<DeviceDetails /> renders device without metadata 1`] = `
my-device
</td>
</tr>
<tr>
<td
class="mxDeviceDetails_metadataLabel"
>
Last activity
</td>
<td
class="mxDeviceDetails_metadataValue"
/>
</tr>
</tbody>
</table>
<table
class="mx_DeviceDetails_metadataTable"
>
<thead>
<tr>
<th>
Device
</th>
</tr>
</thead>
<tbody>
<tr>
<td
class="mxDeviceDetails_metadataLabel"
>
IP address
</td>
<td
class="mxDeviceDetails_metadataValue"
/>
</tr>
</tbody>
</table>
</section>
Expand Down
Loading

0 comments on commit 16c3efe

Please sign in to comment.