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

Device manager - display client information in device details (PSG-682) #9315

Merged
merged 17 commits into from
Oct 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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