feat: enable strictNullChecks

feat: enable `noImplicitAny`

chore: remove sync data access

fix loading package data for affected dependencies

chore: properly get alt marketplace data

update patchdb client to allow for emit on undefined values
This commit is contained in:
waterplea
2022-05-26 18:20:31 +03:00
committed by Lucy C
parent 948fb795f2
commit 0390954a85
99 changed files with 674 additions and 535 deletions

View File

@@ -1,6 +1,10 @@
import { Component, Input, ViewChild } from '@angular/core'
import { IonInput, ModalController } from '@ionic/angular'
import { DiskInfo, CifsBackupTarget, DiskBackupTarget } from 'src/app/services/api/api.service'
import {
DiskInfo,
CifsBackupTarget,
DiskBackupTarget,
} from 'src/app/services/api/api.service'
import * as argon2 from '@start9labs/argon2'
@Component({
@@ -21,26 +25,27 @@ export class PasswordPage {
passwordVer = ''
unmasked2 = false
constructor (
private modalController: ModalController,
) { }
constructor(private modalController: ModalController) {}
ngAfterViewInit () {
ngAfterViewInit() {
setTimeout(() => this.elem.setFocus(), 400)
}
async verifyPw () {
if (!this.target || !this.target['embassy-os']) this.pwError = 'No recovery target' // unreachable
async verifyPw() {
if (!this.target || !this.target['embassy-os'])
this.pwError = 'No recovery target' // unreachable
try {
argon2.verify(this.target['embassy-os']['password-hash'], this.password)
const passwordHash = this.target['embassy-os']?.['password-hash'] || ''
argon2.verify(passwordHash, this.password)
this.modalController.dismiss({ password: this.password }, 'success')
} catch (e) {
this.pwError = 'Incorrect password provided'
}
}
async submitPw () {
async submitPw() {
this.validate()
if (this.password !== this.passwordVer) {
this.verError = '*passwords do not match'
@@ -50,8 +55,8 @@ export class PasswordPage {
this.modalController.dismiss({ password: this.password }, 'success')
}
validate () {
if (!!this.target) return this.pwError = ''
validate() {
if (!!this.target) return (this.pwError = '')
if (this.passwordVer) {
this.checkVer()
@@ -64,11 +69,12 @@ export class PasswordPage {
}
}
checkVer () {
this.verError = this.password !== this.passwordVer ? 'Passwords do not match' : ''
checkVer() {
this.verError =
this.password !== this.passwordVer ? 'Passwords do not match' : ''
}
cancel () {
cancel() {
this.modalController.dismiss()
}
}

View File

@@ -16,19 +16,19 @@ export class ProdKeyModal {
productKey = ''
unmasked = false
constructor (
constructor(
private readonly modalController: ModalController,
private readonly apiService: ApiService,
private readonly loadingCtrl: LoadingController,
private readonly httpService: HttpService,
) { }
) {}
ngAfterViewInit () {
ngAfterViewInit() {
setTimeout(() => this.elem.setFocus(), 400)
}
async verifyProductKey () {
if (!this.productKey) return
async verifyProductKey() {
if (!this.productKey || !this.target.logicalname) return
const loader = await this.loadingCtrl.create({
message: 'Verifying Product Key',
@@ -48,7 +48,7 @@ export class ProdKeyModal {
}
}
cancel () {
cancel() {
this.modalController.dismiss()
}
}

View File

@@ -68,8 +68,8 @@ export class RecoverPage {
'embassy-os': p['embassy-os'],
}
this.mappedDrives.push({
hasValidBackup: p['embassy-os']?.full,
is02x: drive['embassy-os']?.version.startsWith('0.2'),
hasValidBackup: !!p['embassy-os']?.full,
is02x: !!drive['embassy-os']?.version.startsWith('0.2'),
drive,
})
})
@@ -111,7 +111,8 @@ export class RecoverPage {
{
text: 'Use Drive',
handler: async () => {
await this.importDrive(importableDrive.guid)
if (importableDrive.guid)
await this.importDrive(importableDrive.guid)
},
},
],
@@ -148,11 +149,14 @@ export class RecoverPage {
}
async select(target: DiskBackupTarget) {
const is02x = target['embassy-os'].version.startsWith('0.2')
const is02x = target['embassy-os']?.version.startsWith('0.2')
const { logicalname } = target
if (!logicalname) return
if (this.stateService.hasProductKey) {
if (is02x) {
this.selectRecoverySource(target.logicalname)
this.selectRecoverySource(logicalname)
} else {
const modal = await this.modalController.create({
component: PasswordPage,
@@ -160,8 +164,8 @@ export class RecoverPage {
cssClass: 'alertlike-modal',
})
modal.onDidDismiss().then(res => {
if (res.data && res.data.password) {
this.selectRecoverySource(target.logicalname, res.data.password)
if (res.data?.password) {
this.selectRecoverySource(logicalname, res.data.password)
}
})
await modal.present()
@@ -188,8 +192,8 @@ export class RecoverPage {
cssClass: 'alertlike-modal',
})
modal.onDidDismiss().then(res => {
if (res.data && res.data.productKey) {
this.selectRecoverySource(target.logicalname)
if (res.data?.productKey) {
this.selectRecoverySource(logicalname)
}
})
await modal.present()

View File

@@ -24,7 +24,7 @@ export class SuccessPage {
await this.stateService.completeEmbassy()
document
.getElementById('install-cert')
.setAttribute(
?.setAttribute(
'href',
'data:application/x-x509-ca-cert;base64,' +
encodeURIComponent(this.stateService.cert),
@@ -56,20 +56,24 @@ export class SuccessPage {
}
installCert() {
document.getElementById('install-cert').click()
document.getElementById('install-cert')?.click()
}
download() {
document.getElementById('tor-addr').innerHTML = this.stateService.torAddress
document.getElementById('lan-addr').innerHTML = this.stateService.lanAddress
const torAddress = document.getElementById('tor-addr')
const lanAddress = document.getElementById('lan-addr')
if (torAddress) torAddress.innerHTML = this.stateService.torAddress
if (lanAddress) lanAddress.innerHTML = this.stateService.lanAddress
document
.getElementById('cert')
.setAttribute(
?.setAttribute(
'href',
'data:application/x-x509-ca-cert;base64,' +
encodeURIComponent(this.stateService.cert),
)
let html = document.getElementById('downloadable').innerHTML
let html = document.getElementById('downloadable')?.innerHTML || ''
const filename = 'embassy-info.html'
const elem = document.createElement('a')

View File

@@ -15,7 +15,7 @@ import { HttpError, RpcError } from '@start9labs/shared'
})
export class HttpService {
fullUrl: string
productKey: string
productKey?: string
constructor(private readonly http: HttpClient) {
const port = window.location.port
@@ -43,6 +43,8 @@ export class HttpService {
}
if (isRpcSuccess(res)) return res.result
throw new Error('Unknown RPC response')
}
async encryptedHttpRequest<T>(httpOpts: {
@@ -53,7 +55,7 @@ export class HttpService {
const url = urlIsRelative ? this.fullUrl + httpOpts.url : httpOpts.url
const encryptedBody = await AES_CTR.encryptPbkdf2(
this.productKey,
this.productKey || '',
encodeUtf8(JSON.stringify(httpOpts.body)),
)
const options = {
@@ -74,7 +76,7 @@ export class HttpService {
.toPromise()
.then(res =>
AES_CTR.decryptPbkdf2(
this.productKey,
this.productKey || '',
(res as any).body as ArrayBuffer,
),
)
@@ -206,7 +208,7 @@ type AES_CTR = {
secretKey: string,
messageBuffer: Uint8Array,
) => Promise<Uint8Array>
decryptPbkdf2: (secretKey, arr: ArrayBuffer) => Promise<string>
decryptPbkdf2: (secretKey: string, arr: ArrayBuffer) => Promise<string>
}
export const AES_CTR: AES_CTR = {
@@ -243,8 +245,10 @@ export const AES_CTR: AES_CTR = {
export const encode16 = (buffer: Uint8Array) =>
buffer.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '')
export const decode16 = hexString =>
new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)))
export const decode16 = (hexString: string) =>
new Uint8Array(
hexString.match(/.{1,2}/g)?.map(byte => parseInt(byte, 16)) || [],
)
export function encodeUtf8(str: string): Uint8Array {
const encoder = new TextEncoder()

View File

@@ -43,7 +43,7 @@ export class LiveApiService extends ApiService {
)
}
async set02XDrive(logicalname) {
async set02XDrive(logicalname: string) {
return this.http.rpcRequest<void>(
{
method: 'setup.recovery.v2.set',
@@ -124,7 +124,7 @@ export class LiveApiService extends ApiService {
}
function isCifsSource(
source: CifsRecoverySource | DiskRecoverySource | undefined,
source: CifsRecoverySource | DiskRecoverySource | null,
): source is CifsRecoverySource {
return !!(source as CifsRecoverySource)?.hostname
}

View File

@@ -18,7 +18,7 @@ export class StateService {
embassyLoaded = false
recoverySource: CifsRecoverySource | DiskRecoverySource
recoveryPassword: string
recoveryPassword?: string
dataTransferProgress: {
bytesTransferred: number