mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-04-02 05:23:14 +00:00
chore: enable strict mode (#1569)
* chore: enable strict mode * refactor: remove sync data access from PatchDbService * launchable even when no LAN url Co-authored-by: Matt Hill <matthewonthemoon@gmail.com>
This commit is contained in:
@@ -1,24 +1,33 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>
|
||||
{{ !!storageDrive ? 'Set Password' : 'Unlock Drive' }}
|
||||
{{ storageDrive ? 'Set Password' : 'Unlock Drive' }}
|
||||
</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<div style="padding: 8px 24px;">
|
||||
<div style="padding-bottom: 16px;">
|
||||
<ng-container *ngIf="!!storageDrive">
|
||||
<p>Choose a password for your Embassy. <i>Make it good. Write it down.</i></p>
|
||||
<p style="color: var(--ion-color-warning);">Losing your password can result in total loss of data.</p>
|
||||
</ng-container>
|
||||
<p *ngIf="!storageDrive">Enter the password that was used to encrypt this drive.</p>
|
||||
<div style="padding: 8px 24px">
|
||||
<div style="padding-bottom: 16px">
|
||||
<ng-template #choose>
|
||||
<p>
|
||||
Choose a password for your Embassy.
|
||||
<i>Make it good. Write it down.</i>
|
||||
</p>
|
||||
<p style="color: var(--ion-color-warning)">
|
||||
Losing your password can result in total loss of data.
|
||||
</p>
|
||||
</ng-template>
|
||||
<p *ngIf="!storageDrive else choose">
|
||||
Enter the password that was used to encrypt this drive.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form (ngSubmit)="!!storageDrive ? submitPw() : verifyPw()">
|
||||
<form (ngSubmit)="storageDrive ? submitPw() : verifyPw()">
|
||||
<p>Password</p>
|
||||
<ion-item [class]="pwError ? 'error-border' : password && !!storageDrive ? 'success-border' : ''">
|
||||
<ion-item
|
||||
[class]="pwError ? 'error-border' : password && storageDrive ? 'success-border' : ''"
|
||||
>
|
||||
<ion-input
|
||||
#focusInput
|
||||
[(ngModel)]="password"
|
||||
@@ -29,15 +38,23 @@
|
||||
maxlength="64"
|
||||
></ion-input>
|
||||
<ion-button fill="clear" color="light" (click)="unmasked1 = !unmasked1">
|
||||
<ion-icon slot="icon-only" [name]="unmasked1 ? 'eye-off-outline' : 'eye-outline'" size="small"></ion-icon>
|
||||
<ion-icon
|
||||
slot="icon-only"
|
||||
[name]="unmasked1 ? 'eye-off-outline' : 'eye-outline'"
|
||||
size="small"
|
||||
></ion-icon>
|
||||
</ion-button>
|
||||
</ion-item>
|
||||
<div style="height: 16px;">
|
||||
<p style="color: var(--ion-color-danger); font-size: x-small;">{{ pwError }}</p>
|
||||
<div style="height: 16px">
|
||||
<p style="color: var(--ion-color-danger); font-size: x-small">
|
||||
{{ pwError }}
|
||||
</p>
|
||||
</div>
|
||||
<ng-container *ngIf="!!storageDrive">
|
||||
<ng-container *ngIf="storageDrive">
|
||||
<p>Confirm Password</p>
|
||||
<ion-item [class]="verError ? 'error-border' : passwordVer ? 'success-border' : ''">
|
||||
<ion-item
|
||||
[class]="verError ? 'error-border' : passwordVer ? 'success-border' : ''"
|
||||
>
|
||||
<ion-input
|
||||
[(ngModel)]="passwordVer"
|
||||
[ngModelOptions]="{'standalone': true}"
|
||||
@@ -46,12 +63,22 @@
|
||||
maxlength="64"
|
||||
placeholder="Retype Password"
|
||||
></ion-input>
|
||||
<ion-button fill="clear" color="light" (click)="unmasked2 = !unmasked2">
|
||||
<ion-icon slot="icon-only" [name]="unmasked2 ? 'eye-off-outline' : 'eye-outline'" size="small"></ion-icon>
|
||||
<ion-button
|
||||
fill="clear"
|
||||
color="light"
|
||||
(click)="unmasked2 = !unmasked2"
|
||||
>
|
||||
<ion-icon
|
||||
slot="icon-only"
|
||||
[name]="unmasked2 ? 'eye-off-outline' : 'eye-outline'"
|
||||
size="small"
|
||||
></ion-icon>
|
||||
</ion-button>
|
||||
</ion-item>
|
||||
<div style="height: 16px;">
|
||||
<p style="color: var(--ion-color-danger); font-size: x-small;">{{ verError }}</p>
|
||||
<div style="height: 16px">
|
||||
<p style="color: var(--ion-color-danger); font-size: x-small">
|
||||
{{ verError }}
|
||||
</p>
|
||||
</div>
|
||||
</ng-container>
|
||||
<input type="submit" style="display: none" />
|
||||
@@ -61,12 +88,24 @@
|
||||
|
||||
<ion-footer>
|
||||
<ion-toolbar>
|
||||
<ion-button class="ion-padding-end" slot="end" color="dark" fill="clear" (click)="cancel()">
|
||||
<ion-button
|
||||
class="ion-padding-end"
|
||||
slot="end"
|
||||
color="dark"
|
||||
fill="clear"
|
||||
(click)="cancel()"
|
||||
>
|
||||
Cancel
|
||||
</ion-button>
|
||||
<ion-button class="ion-padding-end" slot="end" color="dark" fill="clear" strong="true" (click)="!!storageDrive ? submitPw() : verifyPw()">
|
||||
{{ !!storageDrive ? 'Finish' : 'Unlock' }}
|
||||
<ion-button
|
||||
class="ion-padding-end"
|
||||
slot="end"
|
||||
color="dark"
|
||||
fill="clear"
|
||||
strong="true"
|
||||
(click)="storageDrive ? submitPw() : verifyPw()"
|
||||
>
|
||||
{{ storageDrive ? 'Finish' : 'Unlock' }}
|
||||
</ion-button>
|
||||
</ion-toolbar>
|
||||
</ion-footer>
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ import * as argon2 from '@start9labs/argon2'
|
||||
styleUrls: ['password.page.scss'],
|
||||
})
|
||||
export class PasswordPage {
|
||||
@ViewChild('focusInput') elem: IonInput
|
||||
@Input() target: CifsBackupTarget | DiskBackupTarget
|
||||
@Input() storageDrive: DiskInfo
|
||||
@ViewChild('focusInput') elem?: IonInput
|
||||
@Input() target?: CifsBackupTarget | DiskBackupTarget
|
||||
@Input() storageDrive?: DiskInfo
|
||||
|
||||
pwError = ''
|
||||
password = ''
|
||||
@@ -28,7 +28,7 @@ export class PasswordPage {
|
||||
constructor(private modalController: ModalController) {}
|
||||
|
||||
ngAfterViewInit() {
|
||||
setTimeout(() => this.elem.setFocus(), 400)
|
||||
setTimeout(() => this.elem?.setFocus(), 400)
|
||||
}
|
||||
|
||||
async verifyPw() {
|
||||
@@ -36,7 +36,7 @@ export class PasswordPage {
|
||||
this.pwError = 'No recovery target' // unreachable
|
||||
|
||||
try {
|
||||
const passwordHash = this.target['embassy-os']?.['password-hash'] || ''
|
||||
const passwordHash = this.target!['embassy-os']?.['password-hash'] || ''
|
||||
|
||||
argon2.verify(passwordHash, this.password)
|
||||
this.modalController.dismiss({ password: this.password }, 'success')
|
||||
|
||||
@@ -9,8 +9,8 @@ import { HttpService } from 'src/app/services/api/http.service'
|
||||
styleUrls: ['prod-key-modal.page.scss'],
|
||||
})
|
||||
export class ProdKeyModal {
|
||||
@ViewChild('focusInput') elem: IonInput
|
||||
@Input() target: DiskBackupTarget
|
||||
@ViewChild('focusInput') elem?: IonInput
|
||||
@Input() target!: DiskBackupTarget
|
||||
|
||||
error = ''
|
||||
productKey = ''
|
||||
@@ -24,7 +24,7 @@ export class ProdKeyModal {
|
||||
) {}
|
||||
|
||||
ngAfterViewInit() {
|
||||
setTimeout(() => this.elem.setFocus(), 400)
|
||||
setTimeout(() => this.elem?.setFocus(), 400)
|
||||
}
|
||||
|
||||
async verifyProductKey() {
|
||||
|
||||
@@ -10,24 +10,24 @@ import { StateService } from 'src/app/services/state.service'
|
||||
styleUrls: ['product-key.page.scss'],
|
||||
})
|
||||
export class ProductKeyPage {
|
||||
@ViewChild('focusInput') elem: IonInput
|
||||
productKey: string
|
||||
error: string
|
||||
@ViewChild('focusInput') elem?: IonInput
|
||||
productKey = ''
|
||||
error = ''
|
||||
|
||||
constructor (
|
||||
constructor(
|
||||
private readonly navCtrl: NavController,
|
||||
private readonly stateService: StateService,
|
||||
private readonly apiService: ApiService,
|
||||
private readonly loadingCtrl: LoadingController,
|
||||
private readonly httpService: HttpService,
|
||||
) { }
|
||||
) {}
|
||||
|
||||
ionViewDidEnter () {
|
||||
setTimeout(() => this.elem.setFocus(), 400)
|
||||
ionViewDidEnter() {
|
||||
setTimeout(() => this.elem?.setFocus(), 400)
|
||||
}
|
||||
|
||||
async submit () {
|
||||
if (!this.productKey) return this.error = 'Must enter product key'
|
||||
async submit() {
|
||||
if (!this.productKey) return (this.error = 'Must enter product key')
|
||||
|
||||
const loader = await this.loadingCtrl.create({
|
||||
message: 'Verifying Product Key',
|
||||
@@ -50,4 +50,3 @@ export class ProductKeyPage {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ export class RecoverPage {
|
||||
private readonly alertCtrl: AlertController,
|
||||
private readonly loadingCtrl: LoadingController,
|
||||
private readonly errorToastService: ErrorToastService,
|
||||
public readonly stateService: StateService,
|
||||
private readonly stateService: StateService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -243,8 +243,8 @@ export class RecoverPage {
|
||||
styleUrls: ['./recover.page.scss'],
|
||||
})
|
||||
export class DriveStatusComponent {
|
||||
@Input() hasValidBackup: boolean
|
||||
@Input() is02x: boolean
|
||||
@Input() hasValidBackup!: boolean
|
||||
@Input() is02x!: boolean
|
||||
}
|
||||
|
||||
interface MappedDisk {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<ion-card-content>
|
||||
<br />
|
||||
<ng-template
|
||||
[ngIf]="stateService.recoverySource && stateService.recoverySource.type === 'disk'"
|
||||
[ngIf]="recoverySource && recoverySource.type === 'disk'"
|
||||
>
|
||||
<h2>You can now safely unplug your backup drive.</h2>
|
||||
</ng-template>
|
||||
@@ -53,15 +53,13 @@
|
||||
<ion-item lines="none" color="dark">
|
||||
<ion-label class="ion-text-wrap">
|
||||
<code
|
||||
><ion-text color="light"
|
||||
>{{ stateService.torAddress }}</ion-text
|
||||
></code
|
||||
><ion-text color="light">{{ torAddress }}</ion-text></code
|
||||
>
|
||||
</ion-label>
|
||||
<ion-button
|
||||
color="light"
|
||||
fill="clear"
|
||||
(click)="copy(stateService.torAddress)"
|
||||
(click)="copy(torAddress)"
|
||||
>
|
||||
<ion-icon slot="icon-only" name="copy-outline"></ion-icon>
|
||||
</ion-button>
|
||||
@@ -133,15 +131,13 @@
|
||||
<ion-item lines="none" color="dark">
|
||||
<ion-label class="ion-text-wrap">
|
||||
<code
|
||||
><ion-text color="light"
|
||||
>{{ stateService.lanAddress }}</ion-text
|
||||
></code
|
||||
><ion-text color="light">{{ lanAddress }}</ion-text></code
|
||||
>
|
||||
</ion-label>
|
||||
<ion-button
|
||||
color="light"
|
||||
fill="clear"
|
||||
(click)="copy(stateService.lanAddress)"
|
||||
(click)="copy(lanAddress)"
|
||||
>
|
||||
<ion-icon slot="icon-only" name="copy-outline"></ion-icon>
|
||||
</ion-button>
|
||||
|
||||
@@ -16,9 +16,21 @@ export class SuccessPage {
|
||||
constructor(
|
||||
private readonly toastCtrl: ToastController,
|
||||
private readonly errCtrl: ErrorToastService,
|
||||
public readonly stateService: StateService,
|
||||
private readonly stateService: StateService,
|
||||
) {}
|
||||
|
||||
get recoverySource() {
|
||||
return this.stateService.recoverySource
|
||||
}
|
||||
|
||||
get torAddress() {
|
||||
return this.stateService.torAddress
|
||||
}
|
||||
|
||||
get lanAddress() {
|
||||
return this.stateService.lanAddress
|
||||
}
|
||||
|
||||
async ngAfterViewInit() {
|
||||
try {
|
||||
await this.stateService.completeEmbassy()
|
||||
|
||||
@@ -11,26 +11,26 @@ import { pauseFor, ErrorToastService } from '@start9labs/shared'
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class StateService {
|
||||
hasProductKey: boolean
|
||||
isMigrating: boolean
|
||||
hasProductKey = false
|
||||
isMigrating = false
|
||||
|
||||
polling = false
|
||||
embassyLoaded = false
|
||||
|
||||
recoverySource: CifsRecoverySource | DiskRecoverySource
|
||||
recoverySource?: CifsRecoverySource | DiskRecoverySource
|
||||
recoveryPassword?: string
|
||||
|
||||
dataTransferProgress: {
|
||||
dataTransferProgress?: {
|
||||
bytesTransferred: number
|
||||
totalBytes: number
|
||||
complete: boolean
|
||||
} | null
|
||||
}
|
||||
dataProgress = 0
|
||||
dataCompletionSubject = new BehaviorSubject(false)
|
||||
|
||||
torAddress: string
|
||||
lanAddress: string
|
||||
cert: string
|
||||
torAddress = ''
|
||||
lanAddress = ''
|
||||
cert = ''
|
||||
|
||||
constructor(
|
||||
private readonly apiService: ApiService,
|
||||
|
||||
Reference in New Issue
Block a user