Reset password through setup wizard (#1490)

* closes FE portion of  #1470

* remove accidental commit of local script

* add reset password option (#1560)

* fix error code for incorrect password and clarify codes with comments

Co-authored-by: Matt Hill <matthill@Matt-M1.local>
Co-authored-by: Lucy Cifferello <12953208+elvece@users.noreply.github.com>
Co-authored-by: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com>
This commit is contained in:
Matt Hill
2022-06-20 16:48:32 -06:00
committed by GitHub
parent 1f5e6dbff6
commit d2195411a6
14 changed files with 380 additions and 224 deletions

View File

@@ -32,7 +32,7 @@ export class RecoverPage {
private readonly loadingCtrl: LoadingController,
private readonly errorToastService: ErrorToastService,
public readonly stateService: StateService,
) {}
) { }
async ngOnInit() {
await this.getDrives()
@@ -99,8 +99,7 @@ export class RecoverPage {
const alert = await this.alertCtrl.create({
header: 'Embassy Data Drive Detected',
message: new IonicSafeString(
`${importableDrive.vendor || 'Unknown Vendor'} - ${
importableDrive.model || 'Unknown Model'
`${importableDrive.vendor || 'Unknown Vendor'} - ${importableDrive.model || 'Unknown Model'
} contains Embassy data. To use this drive and its data <i>as-is</i>, click "Use Drive". This will complete the setup process.<br /><br /><b>Important</b>. If you are trying to restore from backup or update from 0.2.x, DO NOT click "Use Drive". Instead, click "Cancel" and follow instructions.`,
),
buttons: [
@@ -111,8 +110,16 @@ export class RecoverPage {
{
text: 'Use Drive',
handler: async () => {
if (importableDrive.guid)
await this.importDrive(importableDrive.guid)
const modal = await this.modalController.create({
component: PasswordPage,
componentProps: { storageDrive: importableDrive },
})
modal.onDidDismiss().then(res => {
if (res.data && res.data.password) {
this.importDrive(importableDrive.guid!, res.data.password)
}
})
await modal.present()
},
},
],
@@ -201,13 +208,13 @@ export class RecoverPage {
}
}
private async importDrive(guid: string) {
private async importDrive(guid: string, password: string) {
const loader = await this.loadingCtrl.create({
message: 'Importing Drive',
})
await loader.present()
try {
await this.stateService.importDrive(guid)
await this.stateService.importDrive(guid, password)
await this.navCtrl.navigateForward(`/success`)
} catch (e: any) {
this.errorToastService.present(e)

View File

@@ -8,7 +8,7 @@ export abstract class ApiService {
// encrypted
abstract verifyCifs(cifs: CifsRecoverySource): Promise<EmbassyOSRecoveryInfo> // setup.cifs.verify
abstract verifyProductKey(): Promise<void> // echo - throws error if invalid
abstract importDrive(guid: string): Promise<SetupEmbassyRes> // setup.execute
abstract importDrive(importInfo: ImportDriveReq): Promise<SetupEmbassyRes> // setup.attach
abstract setupEmbassy(setupInfo: SetupEmbassyReq): Promise<SetupEmbassyRes> // setup.execute
abstract setupComplete(): Promise<SetupEmbassyRes> // setup.complete
}
@@ -18,6 +18,11 @@ export interface GetStatusRes {
migrating: boolean
}
export interface ImportDriveReq {
guid: string
'embassy-password': string
}
export interface SetupEmbassyReq {
'embassy-logicalname': string
'embassy-password': string

View File

@@ -2,11 +2,11 @@ import { Injectable } from '@angular/core'
import {
ApiService,
CifsRecoverySource,
DiskInfo,
DiskListResponse,
DiskRecoverySource,
EmbassyOSRecoveryInfo,
GetStatusRes,
ImportDriveReq,
RecoveryStatusRes,
SetupEmbassyReq,
SetupEmbassyRes,
@@ -80,10 +80,10 @@ export class LiveApiService extends ApiService {
})
}
async importDrive(guid: string) {
async importDrive(params: ImportDriveReq) {
const res = await this.http.rpcRequest<SetupEmbassyRes>({
method: 'setup.attach',
params: { guid },
params: params as any,
})
return {

View File

@@ -1,6 +1,11 @@
import { Injectable } from '@angular/core'
import { pauseFor } from '@start9labs/shared'
import { ApiService, CifsRecoverySource, SetupEmbassyReq } from './api.service'
import {
ApiService,
CifsRecoverySource,
ImportDriveReq,
SetupEmbassyReq,
} from './api.service'
let tries = 0
@@ -84,7 +89,7 @@ export class MockApiService extends ApiService {
return
}
async importDrive(guid: string) {
async importDrive(params: ImportDriveReq) {
await pauseFor(3000)
return setupRes
}

View File

@@ -69,8 +69,11 @@ export class StateService {
setTimeout(() => this.pollDataTransferProgress(), 0) // prevent call stack from growing
}
async importDrive(guid: string): Promise<void> {
const ret = await this.apiService.importDrive(guid)
async importDrive(guid: string, password: string): Promise<void> {
const ret = await this.apiService.importDrive({
guid,
'embassy-password': password,
})
this.torAddress = ret['tor-address']
this.lanAddress = ret['lan-address']
this.cert = ret['root-ca']

View File

@@ -50,7 +50,8 @@ export class LoginPage {
.setVerified()
.then(() => this.router.navigate([''], { replaceUrl: true }))
} catch (e: any) {
this.error = e.code === 34 ? 'Invalid Password' : e.message
// code 7 is for incorrect password
this.error = e.code === 7 ? 'Invalid Password' : e.message
} finally {
this.loader.dismiss()
}

View File

@@ -35,6 +35,7 @@ export class HttpService {
const res = await this.httpRequest<RPCResponse<T>>(httpOpts)
if (isRpcError(res)) {
// code 34 is authorization error ie. invalid session
if (res.error.code === 34) this.auth.setUnverified()
throw new RpcError(res.error)
}