diff --git a/src/commands/getIsGenuine.js b/src/commands/getIsGenuine.js index c0b66b8b..c34f4693 100644 --- a/src/commands/getIsGenuine.js +++ b/src/commands/getIsGenuine.js @@ -6,11 +6,19 @@ import { fromPromise } from 'rxjs/observable/fromPromise' import getIsGenuine from 'helpers/devices/getIsGenuine' import { withDevice } from 'helpers/deviceAccess' -type Input = * // FIXME ! +type Input = { + devicePath: string, + targetId: string | number, + version: string, +} type Result = string -const cmd: Command = createCommand('getIsGenuine', ({ devicePath, targetId }) => - fromPromise(withDevice(devicePath)(transport => getIsGenuine(transport, { targetId }))), +const cmd: Command = createCommand( + 'getIsGenuine', + ({ devicePath, targetId, version }) => + fromPromise( + withDevice(devicePath)(transport => getIsGenuine(transport, { targetId, version })), + ), ) export default cmd diff --git a/src/commands/installMcu.js b/src/commands/installMcu.js index fcc70eb3..7e49ea16 100644 --- a/src/commands/installMcu.js +++ b/src/commands/installMcu.js @@ -9,14 +9,15 @@ import installMcu from 'helpers/firmware/installMcu' type Input = { devicePath: string, targetId: string | number, + version: string, } type Result = * -const cmd: Command = createCommand('installMcu', ({ devicePath, targetId }) => - fromPromise( - withDevice(devicePath)(transport => installMcu(transport, { targetId, version: '1.5' })), - ), +const cmd: Command = createCommand( + 'installMcu', + ({ devicePath, targetId, version }) => + fromPromise(withDevice(devicePath)(transport => installMcu(transport, { targetId, version }))), ) export default cmd diff --git a/src/commands/installOsuFirmware.js b/src/commands/installOsuFirmware.js index 416badf0..02767210 100644 --- a/src/commands/installOsuFirmware.js +++ b/src/commands/installOsuFirmware.js @@ -6,17 +6,22 @@ import { fromPromise } from 'rxjs/observable/fromPromise' import { withDevice } from 'helpers/deviceAccess' import installOsuFirmware from 'helpers/firmware/installOsuFirmware' +import type { LedgerScriptParams } from 'helpers/common' + type Input = { devicePath: string, - firmware: Object, + targetId: string | number, + firmware: LedgerScriptParams, } type Result = * const cmd: Command = createCommand( 'installOsuFirmware', - ({ devicePath, firmware }) => - fromPromise(withDevice(devicePath)(transport => installOsuFirmware(transport, firmware))), + ({ devicePath, firmware, targetId }) => + fromPromise( + withDevice(devicePath)(transport => installOsuFirmware(transport, targetId, firmware)), + ), ) export default cmd diff --git a/src/components/ManagerPage/AppsList.js b/src/components/ManagerPage/AppsList.js index 2333f396..ee87e6a6 100644 --- a/src/components/ManagerPage/AppsList.js +++ b/src/components/ManagerPage/AppsList.js @@ -175,8 +175,8 @@ class AppsList extends PureComponent { } renderList() { - const { appsList } = this.state - return appsList.length > 0 ? ( + const { appsList, status } = this.state + return status === 'idle' ? ( {items => ( diff --git a/src/components/ManagerPage/FirmwareUpdate.js b/src/components/ManagerPage/FirmwareUpdate.js index c71c75e4..a9ab1e2f 100644 --- a/src/components/ManagerPage/FirmwareUpdate.js +++ b/src/components/ManagerPage/FirmwareUpdate.js @@ -10,6 +10,8 @@ import logger from 'logger' import type { Device, T } from 'types/common' +import type { LedgerScriptParams } from 'helpers/common' + import getLatestFirmwareForDevice from 'commands/getLatestFirmwareForDevice' import installOsuFirmware from 'commands/installOsuFirmware' @@ -23,11 +25,6 @@ import UpdateFirmwareButton from './UpdateFirmwareButton' let CACHED_LATEST_FIRMWARE = null -type FirmwareInfos = { - name: string, - notes: string, -} - type DeviceInfos = { targetId: number | string, version: string, @@ -40,7 +37,7 @@ type Props = { } type State = { - latestFirmware: ?FirmwareInfos, + latestFirmware: ?LedgerScriptParams, } class FirmwareUpdate extends PureComponent { @@ -84,12 +81,13 @@ class FirmwareUpdate extends PureComponent { installFirmware = async () => { try { const { latestFirmware } = this.state + const { infos } = this.props invariant(latestFirmware, 'did not find a new firmware or firmware is not set') const { device: { path: devicePath }, } = this.props const { success } = await installOsuFirmware - .send({ devicePath, firmware: latestFirmware }) + .send({ devicePath, firmware: latestFirmware, targetId: infos.targetId }) .toPromise() if (success) { this.fetchLatestFirmware() diff --git a/src/components/ManagerPage/FlashMcu.js b/src/components/ManagerPage/FlashMcu.js index a9cd2d5a..5edeacd4 100644 --- a/src/components/ManagerPage/FlashMcu.js +++ b/src/components/ManagerPage/FlashMcu.js @@ -25,23 +25,30 @@ class FlashMcu extends PureComponent { flashing: false, } - componentDidMount() { - this.flasMCU() - } - - flasMCU = async () => { + flashMCU = async () => { const { device, deviceInfo } = this.props const { flashing } = this.state if (!flashing) { - this.setState(state => ({ ...state, flashing: true })) - await installMcu.send({ devicePath: device.path, targetId: deviceInfo.targetId }).toPromise() - this.setState(state => ({ ...state, flashing: false })) + this.setState({ flashing: true }) + await installMcu + .send({ + devicePath: device.path, + targetId: deviceInfo.targetId, + version: deviceInfo.version, + }) + .toPromise() + this.setState({ flashing: false }) } } render() { - return
Flashing MCU
+ return ( +
+

Flashing MCU

+ +
+ ) } } diff --git a/src/components/Workflow/EnsureGenuine.js b/src/components/Workflow/EnsureGenuine.js index 42cb971d..a1890480 100644 --- a/src/components/Workflow/EnsureGenuine.js +++ b/src/components/Workflow/EnsureGenuine.js @@ -61,7 +61,7 @@ class EnsureGenuine extends PureComponent { this._checking = true try { const res = await getIsGenuine - .send({ devicePath: device.path, targetId: infos.targetId }) + .send({ devicePath: device.path, targetId: infos.targetId, version: infos.version }) .pipe(timeout(GENUINE_TIMEOUT)) .toPromise() if (this._unmounting) return diff --git a/src/helpers/apps/listApps.js b/src/helpers/apps/listApps.js index 7683158c..21f9ec03 100644 --- a/src/helpers/apps/listApps.js +++ b/src/helpers/apps/listApps.js @@ -10,13 +10,14 @@ export default async (targetId: string | number, version: string) => { const provider = 1 const deviceData = await getDeviceVersion(targetId) const firmwareData = await getCurrentFirmware({ deviceId: deviceData.id, version }) - const { - data: { application_versions }, - } = await axios.post(APPLICATIONS_BY_DEVICE, { + const params = { provider, current_se_firmware_final_version: firmwareData.id, device_version: deviceData.id, - }) + } + const { + data: { application_versions }, + } = await axios.post(APPLICATIONS_BY_DEVICE, params) return application_versions.length > 0 ? application_versions : [] } catch (err) { const error = Error(err.message) diff --git a/src/helpers/devices/getIsGenuine.js b/src/helpers/devices/getIsGenuine.js index 7cf140fc..4fa98804 100644 --- a/src/helpers/devices/getIsGenuine.js +++ b/src/helpers/devices/getIsGenuine.js @@ -1,15 +1,24 @@ // @flow -import qs from 'qs' import type Transport from '@ledgerhq/hw-transport' import { SKIP_GENUINE } from 'config/constants' import { WS_GENUINE } from 'helpers/urls' import { createDeviceSocket } from 'helpers/socket' +import getCurrentFirmware from './getCurrentFirmware' +import getDeviceVersion from './getDeviceVersion' export default async ( transport: Transport<*>, - params: { targetId: string | number }, + app: { targetId: string | number, version: string }, ): Promise => { + const { targetId, version } = app + const device = await getDeviceVersion(app.targetId) + const firmware = await getCurrentFirmware({ deviceId: device.id, version }) + const params = { + targetId, + version, + perso: firmware.perso, + } const url = WS_GENUINE(params) return SKIP_GENUINE ? new Promise(resolve => setTimeout(() => resolve('0000'), 1000)) diff --git a/src/helpers/devices/getNextMCU.js b/src/helpers/devices/getNextMCU.js new file mode 100644 index 00000000..fc246abe --- /dev/null +++ b/src/helpers/devices/getNextMCU.js @@ -0,0 +1,26 @@ +// @flow +import axios from 'axios' + +import { GET_NEXT_MCU } from 'helpers/urls' +import createCustomErrorClass from 'helpers/createCustomErrorClass' + +const LatestMCUInstalledError = createCustomErrorClass('LatestMCUInstalledError') + +export default async (bootloaderVersion: string): Promise<*> => { + try { + const { data } = await axios.post(GET_NEXT_MCU, { + bootloader_version: bootloaderVersion, + }) + + // FIXME: nextVersion will not be able to "default" when Error + // handling is standardize on the API side + if (data === 'default' || !data.name) { + throw new LatestMCUInstalledError('there is no next mcu version to install') + } + return data + } catch (err) { + const error = Error(err.message) + error.stack = err.stack + throw err + } +} diff --git a/src/helpers/firmware/installMcu.js b/src/helpers/firmware/installMcu.js index 56fe5448..0c0ceb62 100644 --- a/src/helpers/firmware/installMcu.js +++ b/src/helpers/firmware/installMcu.js @@ -1,16 +1,23 @@ // @flow -import qs from 'qs' import type Transport from '@ledgerhq/hw-transport' -import { MANAGER_API_BASE } from 'config/constants' +import { WS_MCU } from 'helpers/urls' import { createDeviceSocket } from 'helpers/socket' +import getNextMCU from 'helpers/devices/getNextMCU' type Result = Promise<*> export default async ( transport: Transport<*>, - params: { targetId: string | number, version: string }, + args: { targetId: string | number, version: string }, ): Result => { - const url = `${MANAGER_API_BASE}/mcu?${qs.stringify(params)}` + const { version } = args + const nextVersion = await getNextMCU(version) + + const params = { + targetId: args.targetId, + version: nextVersion.name, + } + const url = WS_MCU(params) return createDeviceSocket(transport, url).toPromise() } diff --git a/src/helpers/firmware/installOsuFirmware.js b/src/helpers/firmware/installOsuFirmware.js index 227ff103..5c8b95ff 100644 --- a/src/helpers/firmware/installOsuFirmware.js +++ b/src/helpers/firmware/installOsuFirmware.js @@ -4,13 +4,22 @@ import type Transport from '@ledgerhq/hw-transport' import { WS_INSTALL } from 'helpers/urls' import { createDeviceSocket } from 'helpers/socket' -type Input = Object +import type { LedgerScriptParams } from 'helpers/common' type Result = Promise<{ success: boolean, error?: any }> -export default async (transport: Transport<*>, firmware: Input): Result => { +export default async ( + transport: Transport<*>, + targetId: string | number, + firmware: LedgerScriptParams, +): Result => { try { - const url = WS_INSTALL(firmware) + const params = { + targetId, + ...firmware, + firmwareKey: firmware.firmware_key, + } + const url = WS_INSTALL(params) await createDeviceSocket(transport, url).toPromise() return { success: true } } catch (err) { diff --git a/src/helpers/urls.js b/src/helpers/urls.js index ea240e6f..a8bc82fb 100644 --- a/src/helpers/urls.js +++ b/src/helpers/urls.js @@ -11,11 +11,17 @@ const managerUrlbuilder = urlBuilder(MANAGER_API_BASE) const wsURLBuilder = (endpoint: string) => (params?: Object) => `${BASE_SOCKET_URL_SECURE}/${endpoint}${params ? `?${qs.stringify(params)}` : ''}` +// const wsURLBuilderProxy = (endpoint: string) => (params?: Object) => +// `ws://manager.ledger.fr:3501/${endpoint}${params ? `?${qs.stringify(params)}` : ''}` + export const GET_DEVICE_VERSION: string = managerUrlbuilder('get_device_version') export const APPLICATIONS_BY_DEVICE: string = managerUrlbuilder('get_apps') export const GET_CURRENT_FIRMWARE: string = managerUrlbuilder('get_firmware_version') export const GET_LATEST_FIRMWARE: string = managerUrlbuilder('get_latest_firmware') +export const GET_NEXT_MCU: string = managerUrlbuilder('mcu_versions_bootloader') export const WS_INSTALL: (arg: LedgerScriptParams) => string = wsURLBuilder('install') export const WS_GENUINE: (arg: { targetId: string | number }) => string = wsURLBuilder('genuine') -export const WS_MCU: (arg: LedgerScriptParams) => string = wsURLBuilder('genuine') +export const WS_MCU: (arg: { targetId: string | number, version: string }) => string = wsURLBuilder( + 'mcu', +) diff --git a/static/i18n/en/errors.yml b/static/i18n/en/errors.yml index 2d542878..108a9402 100644 --- a/static/i18n/en/errors.yml +++ b/static/i18n/en/errors.yml @@ -19,3 +19,4 @@ WebsocketConnectionFailed: Failed to establish a socket connection DeviceSocketFail: Device socket failure DeviceSocketNoBulkStatus: Device socket failure (bulk) DeviceSocketNoHandler: Device socket failure (handler {{query}}) +LatestMCUInstalledError: The latest MCU is already installed on the Device