From 1a1572b58bc0a76020978ab51ad85cbac0766aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kl=C3=ADma?= Date: Mon, 25 Apr 2022 17:06:37 +0200 Subject: [PATCH] feat(message-system): target user by device fw revision and bl version (cherry picked from commit 2aa5f338ebd155472926f70034241e8a254d358a) --- docs/misc/message_system.md | 9 +- .../schema/config.schema.v1.json | 16 +- packages/suite/src/support/tests/setupJest.ts | 2 + .../utils/suite/__fixtures__/messageSystem.ts | 357 +++++++++++++++++- packages/suite/src/utils/suite/device.ts | 19 +- .../suite/src/utils/suite/messageSystem.ts | 39 +- 6 files changed, 434 insertions(+), 8 deletions(-) diff --git a/docs/misc/message_system.md b/docs/misc/message_system.md index e34106abacd..e55f7b3a49d 100644 --- a/docs/misc/message_system.md +++ b/docs/misc/message_system.md @@ -167,9 +167,16 @@ Structure of config, types and optionality of specific keys can be found in the { // Possible values: "1" or "T" "model": "1", - "firmware": "1.9.4", + /* + Beware + - firmware version in bootloader mode is unavailable on model 1 + - bootloader version is available only in bootloader mode + */ + "firmware": "2.4.1", + "bootloader": "2.0.4", // Possible values: "*", "bitcoin-only", and "regular" "variant": "bitcoin-only", + "firmwareRevision": "*", "vendor": "trezor.io" } ] diff --git a/packages/suite-data/src/message-system/schema/config.schema.v1.json b/packages/suite-data/src/message-system/schema/config.schema.v1.json index da6b9166a55..2d8d09406ec 100644 --- a/packages/suite-data/src/message-system/schema/config.schema.v1.json +++ b/packages/suite-data/src/message-system/schema/config.schema.v1.json @@ -158,16 +158,30 @@ "items": { "title": "Device", "type": "object", - "required": ["model", "firmware", "variant", "vendor"], + "required": [ + "model", + "firmwareRevision", + "firmware", + "bootloader", + "variant", + "vendor" + ], "properties": { "model": { "title": "Model", "type": "string", "enum": ["T", "1"] }, + "firmwareRevision": { + "title": "Firmware Revision", + "type": "string" + }, "firmware": { "$ref": "#/definitions/version" }, + "bootloader": { + "$ref": "#/definitions/version" + }, "variant": { "title": "Firmware Variant", "type": "string", diff --git a/packages/suite/src/support/tests/setupJest.ts b/packages/suite/src/support/tests/setupJest.ts index 3080f785591..d08b3a3826e 100644 --- a/packages/suite/src/support/tests/setupJest.ts +++ b/packages/suite/src/support/tests/setupJest.ts @@ -433,6 +433,8 @@ const getMessageSystemConfig = ( { model: 'T', firmware: '2.1.1', + bootloader: '*', + firmwareRevision: '*', variant: 'regular', vendor: 'trezor.io', }, diff --git a/packages/suite/src/utils/suite/__fixtures__/messageSystem.ts b/packages/suite/src/utils/suite/__fixtures__/messageSystem.ts index 90387bbbfa5..190f8a8bf6f 100644 --- a/packages/suite/src/utils/suite/__fixtures__/messageSystem.ts +++ b/packages/suite/src/utils/suite/__fixtures__/messageSystem.ts @@ -575,6 +575,8 @@ export const validateDeviceCompatibility = [ { model: 'T', firmware: '2.1.3', + bootloader: '*', + firmwareRevision: '*', variant: '*', vendor: 'trezor.io', }, @@ -599,12 +601,16 @@ export const validateDeviceCompatibility = [ { model: '1', firmware: ['1', '2'], + bootloader: '*', + firmwareRevision: '*', variant: 'bitcoin-only', vendor: 'trezor.io', }, { model: 'T', firmware: ['3.0'], + bootloader: '*', + firmwareRevision: '*', variant: 'regular', vendor: 'trezor.io', }, @@ -629,6 +635,8 @@ export const validateDeviceCompatibility = [ { model: 'T', firmware: '1', + bootloader: '*', + firmwareRevision: '*', variant: '*', vendor: 'trezor.io', }, @@ -653,6 +661,8 @@ export const validateDeviceCompatibility = [ { model: 'T', firmware: '1', + bootloader: '*', + firmwareRevision: '*', variant: 'regular', vendor: 'trezor.io', }, @@ -677,6 +687,8 @@ export const validateDeviceCompatibility = [ { model: 'T', firmware: '2', + bootloader: '*', + firmwareRevision: '*', variant: 'regular', vendor: 'trezor.io', }, @@ -717,6 +729,8 @@ export const validateDeviceCompatibility = [ { model: 'T', firmware: '2', + bootloader: '*', + firmwareRevision: '*', variant: 'regular', vendor: 'trezor.io', }, @@ -736,6 +750,8 @@ export const validateDeviceCompatibility = [ { model: '1', firmware: '1', + bootloader: '*', + firmwareRevision: '*', variant: '*', vendor: 'trezor.io', }, @@ -760,6 +776,8 @@ export const validateDeviceCompatibility = [ { model: '1', firmware: '1', + bootloader: '*', + firmwareRevision: '*', variant: 'regular', vendor: 'trezor.io', }, @@ -784,6 +802,8 @@ export const validateDeviceCompatibility = [ { model: '1', firmware: '1', + bootloader: '*', + firmwareRevision: '*', variant: 'bitcoin-only', vendor: 'trezor.io', }, @@ -808,6 +828,8 @@ export const validateDeviceCompatibility = [ { model: '1', firmware: '1', + bootloader: '*', + firmwareRevision: '*', variant: '*', vendor: '*', }, @@ -832,6 +854,8 @@ export const validateDeviceCompatibility = [ { model: '1', firmware: '1', + bootloader: '*', + firmwareRevision: '*', variant: '*', vendor: 'trezor.io', }, @@ -850,6 +874,276 @@ export const validateDeviceCompatibility = [ }, result: false, }, + { + description: 'validateDeviceCompatibility case 14', + deviceConditions: [ + { + model: '1', + firmware: '1', + bootloader: '*', + firmwareRevision: '*', + variant: '*', + vendor: '*', + }, + ], + device: { + features: { + ...getDeviceFeatures({ + vendor: 'trevor.io', + model: '1', + major_version: 1, + minor_version: 0, + patch_version: 2, + revision: 'fa8eha', + }), + }, + }, + result: true, + }, + { + description: 'validateDeviceCompatibility case 15', + deviceConditions: [ + { + model: '1', + firmware: '1', + bootloader: '*', + firmwareRevision: 'fa8eha', + variant: '*', + vendor: '*', + }, + ], + device: { + features: { + ...getDeviceFeatures({ + vendor: 'trevor.io', + model: '1', + major_version: 1, + minor_version: 0, + patch_version: 2, + revision: 'fa8eha', + }), + }, + }, + result: true, + }, + { + description: 'validateDeviceCompatibility case 16', + deviceConditions: [ + { + model: '1', + firmware: '1', + bootloader: '*', + firmwareRevision: 'abcdef', + variant: '*', + vendor: '*', + }, + ], + device: { + features: { + ...getDeviceFeatures({ + vendor: 'trevor.io', + model: '1', + major_version: 1, + minor_version: 0, + patch_version: 2, + revision: 'fa8eha', + }), + }, + }, + result: false, + }, + { + description: 'validateDeviceCompatibility case 17', + deviceConditions: [ + { + model: 'T', + firmware: '*', + bootloader: '2.0.4', + firmwareRevision: '*', + variant: '*', + vendor: 'trezor.io', + }, + ], + device: { + features: { + ...getDeviceFeatures({ + vendor: 'trezor.io', + model: 'T', + major_version: 2, + minor_version: 0, + patch_version: 4, + bootloader_mode: true, + }), + }, + }, + result: true, + }, + { + description: 'validateDeviceCompatibility case 18', + deviceConditions: [ + { + model: 'T', + firmware: '*', + bootloader: '2.0.4', + firmwareRevision: '*', + variant: '*', + vendor: '*', + }, + ], + device: { + features: { + ...getDeviceFeatures({ + vendor: '*', + model: 'T', + major_version: 2, + minor_version: 0, + patch_version: 3, + bootloader_mode: true, + }), + }, + }, + result: false, + }, + { + description: 'validateDeviceCompatibility case 19', + deviceConditions: [ + { + model: 'T', + firmware: '*', + bootloader: '2.0.4', + firmwareRevision: '*', + variant: '*', + vendor: '*', + }, + ], + device: { + features: { + ...getDeviceFeatures({ + vendor: '*', + model: 'T', + major_version: 2, + minor_version: 0, + patch_version: 4, + bootloader_mode: false, + }), + }, + }, + result: false, + }, + { + description: 'validateDeviceCompatibility case 20', + deviceConditions: [ + { + model: 'T', + firmware: '*', + bootloader: '2.0.4', + firmwareRevision: 'fa8e42', + variant: '*', + vendor: '*', + }, + ], + device: { + features: { + ...getDeviceFeatures({ + vendor: '*', + model: 'T', + major_version: 2, + minor_version: 0, + patch_version: 4, + revision: null, + bootloader_mode: false, + }), + }, + }, + result: false, + }, + { + description: 'validateDeviceCompatibility case 21', + deviceConditions: [ + { + model: 'T', + firmware: '2.4.5', + bootloader: '2.0.4', + firmwareRevision: '*', + variant: '*', + vendor: '*', + }, + ], + device: { + features: { + ...getDeviceFeatures({ + vendor: '*', + model: 'T', + major_version: 2, + minor_version: 0, + patch_version: 4, + fw_major: 2, + fw_minor: 4, + fw_patch: 5, + bootloader_mode: true, + }), + }, + }, + result: true, + }, + { + description: 'validateDeviceCompatibility case 22', + deviceConditions: [ + { + model: 'T', + firmware: '2.4.5', + bootloader: '2.0.4', + firmwareRevision: '*', + variant: '*', + vendor: '*', + }, + ], + device: { + features: { + ...getDeviceFeatures({ + vendor: '*', + model: 'T', + major_version: 2, + minor_version: 0, + patch_version: 4, + fw_major: 2, + fw_minor: 4, + fw_patch: 4, + bootloader_mode: true, + }), + }, + }, + result: false, + }, + { + description: 'validateDeviceCompatibility case 23', + deviceConditions: [ + { + model: 'T', + firmware: '2.4.5', + bootloader: '2.0.3', + firmwareRevision: '*', + variant: '*', + vendor: '*', + }, + ], + device: { + features: { + ...getDeviceFeatures({ + vendor: '*', + model: 'T', + major_version: 2, + minor_version: 0, + patch_version: 4, + fw_major: 2, + fw_minor: 4, + fw_patch: 5, + bootloader_mode: true, + }), + }, + }, + result: false, + }, ]; export const getValidMessages = [ @@ -1182,8 +1476,22 @@ export const getValidMessages = [ conditions: [ { devices: [ - { model: '1', firmware: '1.0.2', variant: '*', vendor: 'trezor.io' }, - { model: 'T', firmware: '2.1.1', variant: '*', vendor: 'trezor.io' }, + { + model: '1', + firmware: '1.0.2', + firmwareRevision: '*', + bootloader: '*', + variant: '*', + vendor: 'trezor.io', + }, + { + model: 'T', + firmware: '2.1.1', + firmwareRevision: '*', + bootloader: '*', + variant: '*', + vendor: 'trezor.io', + }, ], }, ], @@ -1209,6 +1517,8 @@ export const getValidMessages = [ { model: 'T', firmware: '2.2.1', + firmwareRevision: '*', + bootloader: '*', variant: '*', vendor: 'trezor.io', }, @@ -1237,6 +1547,8 @@ export const getValidMessages = [ { model: 'T', firmware: '2.1.1', + firmwareRevision: '*', + bootloader: '*', variant: 'bitcoin-only', vendor: 'trezor.io', }, @@ -1269,6 +1581,8 @@ export const getValidMessages = [ { model: 'T', firmware: '2.1.1', + firmwareRevision: '*', + bootloader: '*', variant: 'regular', vendor: 'trezor.io', }, @@ -1302,4 +1616,43 @@ export const getValidMessages = [ }, result: global.JestMocks.getMessageSystemConfig().actions.map(action => action.message), }, + { + description: 'getValidMessages case 20', + currentDate: '', + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', + osName: 'macos', + environment: '', + suiteVersion: '', + config: global.JestMocks.getMessageSystemConfig(undefined, undefined, { + conditions: [ + { + devices: [ + { + model: 'T', + firmware: '*', + firmwareRevision: 'fae8ac', + bootloader: '2.0.4', + variant: 'bitcoin-only', + vendor: 'trezor.io', + }, + ], + }, + ], + }), + options: { + settings: { tor: false, enabledNetworks: [] }, + device: { + ...global.JestMocks.getConnectDevice(undefined, { + capabilities: ['Capability_Bitcoin'], + revision: 'fae8ac', + bootloader_mode: true, + major_version: 2, + minor_version: 0, + patch_version: 4, + }), + }, + }, + result: [global.JestMocks.getMessageSystemConfig().actions[1].message], + }, ]; diff --git a/packages/suite/src/utils/suite/device.ts b/packages/suite/src/utils/suite/device.ts index 2c909a829a4..09d8e3ec340 100644 --- a/packages/suite/src/utils/suite/device.ts +++ b/packages/suite/src/utils/suite/device.ts @@ -130,18 +130,35 @@ export const isSelectedDevice = (selected?: TrezorDevice | Device, device?: Trez return selected.id === device.id; }; +export const isDeviceInBootloader = (device?: KnownDevice) => !!device?.features.bootloader_mode; + export const getDeviceModel = (device: TrezorDevice): 'T' | '1' => { const { features } = device; return features && features.major_version > 1 ? 'T' : '1'; }; +export const getFwRevision = (device?: KnownDevice) => device?.features.revision || ''; + +export const getBootloaderVersion = (device?: KnownDevice) => { + if (!device?.features) { + return ''; + } + const { features } = device; + + if (isDeviceInBootloader(device) && features.major_version) { + return `${features.major_version}.${features.minor_version}.${features.patch_version}`; + } + + return ''; +}; + export const getFwVersion = (device?: KnownDevice) => { if (!device?.features) { return ''; } const { features } = device; - if (features.bootloader_mode) { + if (isDeviceInBootloader(device)) { return features.fw_major ? `${features.fw_major}.${features.fw_minor}.${features.fw_patch}` : ''; diff --git a/packages/suite/src/utils/suite/messageSystem.ts b/packages/suite/src/utils/suite/messageSystem.ts index e27e351e1be..d73b58641f0 100644 --- a/packages/suite/src/utils/suite/messageSystem.ts +++ b/packages/suite/src/utils/suite/messageSystem.ts @@ -7,7 +7,13 @@ import { getOsName, getOsVersion, } from '@suite-utils/env'; -import { getDeviceModel, getFwVersion, isBitcoinOnly } from './device'; +import { + getBootloaderVersion, + getDeviceModel, + getFwRevision, + getFwVersion, + isBitcoinOnly, +} from './device'; import type { TransportInfo } from 'trezor-connect'; @@ -125,9 +131,36 @@ export const validateDeviceCompatibility = ( } const deviceFwVersion = getFwVersion(device); + const deviceBootloaderVersion = getBootloaderVersion(device); + const deviceFwRevision = getFwRevision(device); const deviceFwVariant = isBitcoinOnly(device) ? 'bitcoin-only' : 'regular'; - const model = getDeviceModel(device); - const { vendor } = device.features; + const deviceModel = getDeviceModel(device).toLowerCase(); + const deviceVendor = device.features.vendor.toLowerCase(); + + return deviceConditions.some(deviceCondition => { + const { + model: modelCondition, + vendor: vendorCondition, + firmwareRevision: firmwareRevisionCondition, + firmware: firmwareCondition, + bootloader: bootloaderCondition, + variant: variantCondition, + } = deviceCondition; + + return ( + modelCondition.toLowerCase() === deviceModel && + (vendorCondition.toLowerCase() === deviceVendor || vendorCondition === '*') && + (variantCondition.toLowerCase() === deviceFwVariant || variantCondition === '*') && + (firmwareRevisionCondition.toLowerCase() === deviceFwRevision.toLowerCase() || + firmwareRevisionCondition === '*') && + (semver.satisfies(deviceFwVersion, createVersionRange(firmwareCondition)!) || + firmwareCondition === '*') && + (semver.satisfies(deviceBootloaderVersion, createVersionRange(bootloaderCondition)!) || + bootloaderCondition === '*') + ); + }); +}; + export const validateEnvironmentCompatibility = ( environmentCondition: Environment, environment: EnvironmentType,