Feature/setup migrate (#1841)

* add migrate component

* finish out migrate page and adjust recover options

* fix typo

* rename migrate -> transfer, adjust copy and typos, update transfer component logic

* add alert for old drive data when transferring

* comments for clarity

* auto adjust swiper slide height

* cleanup uneeded imports from transfer module

* pr feedback suggestions

* remove 02x from setup wiz

* clean up copy/styling for recover flow

* add support for migrating from old drive

* add RecoverySource lifted type

Co-authored-by: Matt Hill <matthewonthemoon@gmail.com>
Co-authored-by: Aiden McClelland <me@drbonez.dev>
This commit is contained in:
Lucy C
2022-11-01 09:00:25 -06:00
committed by Aiden McClelland
parent 1d151d8fa6
commit 74af03408f
25 changed files with 502 additions and 695 deletions

View File

@@ -5,7 +5,6 @@ export abstract class ApiService {
abstract getStatus(): Promise<GetStatusRes> // setup.status
abstract getPubKey(): Promise<void> // setup.get-pubkey
abstract getDrives(): Promise<DiskListResponse> // setup.disk.list
abstract set02XDrive(logicalname: string): Promise<void> // setup.recovery.v2.set
abstract getRecoveryStatus(): Promise<RecoveryStatusRes> // setup.recovery.status
abstract verifyCifs(cifs: CifsRecoverySource): Promise<EmbassyOSRecoveryInfo> // setup.cifs.verify
abstract importDrive(importInfo: ImportDriveReq): Promise<SetupEmbassyRes> // setup.attach
@@ -39,7 +38,7 @@ export type ImportDriveReq = {
export type SetupEmbassyReq = {
'embassy-logicalname': string
'embassy-password': Encrypted
'recovery-source': CifsRecoverySource | DiskRecoverySource | null
'recovery-source': RecoverySource | null
'recovery-password': Encrypted | null
}
@@ -81,6 +80,17 @@ export type DiskRecoverySource = {
logicalname: string // partition logicalname
}
export type BackupRecoverySource = {
type: 'backup'
target: CifsRecoverySource | DiskRecoverySource
}
export type RecoverySource = BackupRecoverySource | DiskMigrateSource
export type DiskMigrateSource = {
type: 'migrate'
guid: string
}
export type CifsRecoverySource = {
type: 'cifs'
hostname: string
@@ -95,7 +105,7 @@ export type DiskInfo = {
model: string | null
partitions: PartitionInfo[]
capacity: number
guid: string | null // cant back up if guid exists
guid: string | null // cant back up if guid exists, but needed if migrating
}
export type RecoveryStatusRes = {

View File

@@ -10,6 +10,7 @@ import {
ApiService,
CifsRecoverySource,
DiskListResponse,
DiskMigrateSource,
DiskRecoverySource,
EmbassyOSRecoveryInfo,
GetStatusRes,
@@ -58,13 +59,6 @@ export class LiveApiService extends ApiService {
})
}
async set02XDrive(logicalname: string) {
return this.rpcRequest<void>({
method: 'setup.recovery.v2.set',
params: { logicalname },
})
}
async getRecoveryStatus() {
return this.rpcRequest<RecoveryStatusRes>({
method: 'setup.recovery.status',
@@ -93,10 +87,12 @@ export class LiveApiService extends ApiService {
}
async setupEmbassy(setupInfo: SetupEmbassyReq) {
if (isCifsSource(setupInfo['recovery-source'])) {
setupInfo['recovery-source'].path = setupInfo[
'recovery-source'
].path.replace('/\\/g', '/')
if (setupInfo['recovery-source']?.type === 'backup') {
if (isCifsSource(setupInfo['recovery-source'].target)) {
setupInfo['recovery-source'].target.path = setupInfo[
'recovery-source'
].target.path.replace('/\\/g', '/')
}
}
const res = await this.rpcRequest<SetupEmbassyRes>({

View File

@@ -54,7 +54,30 @@ export class MockApiService extends ApiService {
'embassy-os': {
version: '0.2.17',
full: true,
'password-hash': null,
'password-hash':
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
'wrapped-key': null,
},
},
],
capacity: 123456789123,
guid: 'uuid-uuid-uuid-uuid',
},
{
logicalname: 'dcba',
vendor: 'Samsung',
model: 'T5',
partitions: [
{
logicalname: 'pbcba',
label: null,
capacity: 73264762332,
used: null,
'embassy-os': {
version: '0.3.1',
full: true,
'password-hash':
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
'wrapped-key': null,
},
},
@@ -65,11 +88,6 @@ export class MockApiService extends ApiService {
]
}
async set02XDrive() {
await pauseFor(1000)
return
}
async getRecoveryStatus() {
tries = Math.min(tries + 1, 4)
return {
@@ -134,105 +152,3 @@ const setupRes = {
'lan-address': 'https://embassy-abcdefgh.local',
'root-ca': encodeBase64(rootCA),
}
const disks = [
{
vendor: 'Samsung',
model: 'SATA',
logicalname: '/dev/sda',
guid: 'theguid',
partitions: [
{
logicalname: 'sda1',
label: 'label 1',
capacity: 100000,
used: 200.1255312,
'embassy-os': null,
},
{
logicalname: 'sda2',
label: 'label 2',
capacity: 50000,
used: 200.1255312,
'embassy-os': null,
},
],
capacity: 150000,
},
{
vendor: 'Samsung',
model: null,
logicalname: 'dev/sdb',
partitions: [],
capacity: 34359738369,
guid: null,
},
{
vendor: 'Crucial',
model: 'MX500',
logicalname: 'dev/sdc',
guid: null,
partitions: [
{
logicalname: 'sdc1',
label: 'label 1',
capacity: 0,
used: null,
'embassy-os': {
version: '0.3.3',
full: true,
'password-hash': 'asdfasdfasdf',
'wrapped-key': '',
},
},
{
logicalname: 'sdc1MOCKTESTER',
label: 'label 1',
capacity: 0,
used: null,
'embassy-os': {
version: '0.3.6',
full: true,
// password is 'asdfasdf'
'password-hash':
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
'wrapped-key': '',
},
},
{
logicalname: 'sdc1',
label: 'label 1',
capacity: 0,
used: null,
'embassy-os': {
version: '0.3.3',
full: false,
'password-hash': 'asdfasdfasdf',
'wrapped-key': '',
},
},
],
capacity: 100000,
},
{
vendor: 'Sandisk',
model: null,
logicalname: '/dev/sdd',
guid: null,
partitions: [
{
logicalname: 'sdd1',
label: null,
capacity: 10000,
used: null,
'embassy-os': {
version: '0.2.7',
full: true,
'password-hash': 'asdfasdfasdf',
'wrapped-key': '',
},
},
],
capacity: 10000,
},
]

View File

@@ -1,10 +1,6 @@
import { Injectable } from '@angular/core'
import { BehaviorSubject } from 'rxjs'
import {
ApiService,
CifsRecoverySource,
DiskRecoverySource,
} from './api/api.service'
import { ApiService, RecoverySource } from './api/api.service'
import { pauseFor, ErrorToastService } from '@start9labs/shared'
@Injectable({
@@ -14,7 +10,7 @@ export class StateService {
polling = false
embassyLoaded = false
recoverySource?: CifsRecoverySource | DiskRecoverySource
recoverySource?: RecoverySource
recoveryPassword?: string
dataTransferProgress?: {