auto check for update on init

This commit is contained in:
Matt Hill
2021-01-15 16:35:39 -07:00
committed by Aiden McClelland
parent 792a5cc429
commit 0c7eae7333
6 changed files with 109 additions and 23 deletions

View File

@@ -13,16 +13,16 @@
<ion-content class="ion-padding">
<div>
<h3>Overview</h3>
<h2>Overview</h2>
<p>
0.2.8 is a small but important update designed to enhance awareness around potential pitfalls of using certain services.
It introduces warnings for installing, uninstalling, backing up, and restoring backups of stateful services such as LND or c-lightning.
This release also draws a distinction between services that can be launched inside the browser and those that are designed to run in the background.
0.2.8 also draws a distinction between services that can be launched inside the browser and those that are designed to run in the background.
</p>
</div>
<div style="margin-top: 30px">
<h3 style="color: var(--ion-color-danger)">Critical Information - Read Carefully</h3>
<h5 style="color: var(--ion-color-danger)">Critical - Read Carefully</h5>
<p>
If you have LND or c-lightning installed, it is critical that you update them to the latest version.
An oversight in Start9s USB backups system has created a situation where restoring a LND or c-lightning backup can result in permanent loss of channel funds.

View File

@@ -106,6 +106,7 @@ export class ServerModel {
ssh: [],
notifications: [],
welcomeAck: true,
autoCheckUpdates: true,
})
}
}
@@ -124,6 +125,7 @@ export interface S9Server {
ssh: SSHFingerprint[]
notifications: S9Notification[]
welcomeAck: boolean
autoCheckUpdates: boolean
}
export interface S9Notification {

View File

@@ -18,6 +18,7 @@ export interface ApiServer {
ssh: SSHFingerprint[]
serverId: string
welcomeAck: boolean
autoCheckUpdates: boolean
}
/** APPS **/

View File

@@ -28,7 +28,7 @@ export abstract class ApiService {
abstract getServerMetrics (): Promise<ReqRes.GetServerMetricsRes>
abstract getNotifications (page: number, perPage: number): Promise<S9Notification[]>
abstract deleteNotification (id: string): Promise<Unit>
abstract updateAgent (thing: any): Promise<Unit>
abstract updateAgent (version: any): Promise<Unit>
abstract acknowledgeOSWelcome (version: string): Promise<Unit>
abstract getAvailableApps (): Promise<AppAvailablePreview[]>
abstract getAvailableApp (appId: string): Promise<AppAvailableFull>

View File

@@ -12,6 +12,7 @@ import { mockApiAppAvailableFull, mockApiAppAvailableVersionInfo, mockApiAppInst
@Injectable()
export class MockApiService extends ApiService {
welcomeAck = false
constructor (
private readonly appModel: AppModel,
private readonly serverModel: ServerModel,
@@ -34,7 +35,10 @@ export class MockApiService extends ApiService {
async getServer (): Promise<ApiServer> {
const res = await mockGetServer()
return { ...res, welcomeAck: this.welcomeAck }
return {
...res,
welcomeAck: this.welcomeAck,
}
}
async ejectExternalDisk (): Promise<Unit> {
@@ -402,9 +406,11 @@ const mockApiServer: () => ReqRes.GetServerRes = () => ({
serverId: 'start9-mockxyzab',
name: 'Embassy:12345678',
versionInstalled: '0.2.8',
versionLatest: '0.2.9',
status: ServerStatus.RUNNING,
alternativeRegistryUrl: 'beta-registry.start9labs.com',
welcomeAck: true,
autoCheckUpdates: true,
specs: {
'Tor Address': 'nfsnjkcnaskjnlkasnfahj7dh23fdnieqwjdnhjewbfijendiueqwbd.onion',
'CPU': 'Broadcom BCM2711, Quad core Cortex-A72 (ARM v8) 64-bit SoC @ 1.5GHz',

View File

@@ -1,26 +1,35 @@
import { Injectable } from '@angular/core'
import { ConfigService } from 'src/app/services/config.service'
import { ToastController, NavController, ModalController } from '@ionic/angular'
import { ServerModel, S9Server } from '../models/server-model'
import { ToastController, NavController, ModalController, AlertController } from '@ionic/angular'
import { ServerModel, S9Server, ServerStatus } from '../models/server-model'
import { OSWelcomePage } from '../modals/os-welcome/os-welcome.page'
import { ApiService } from './api/api.service'
import { Emver } from './emver.service'
import { LoaderService } from './loader.service'
@Injectable({
providedIn: 'root',
})
export class SyncNotifier {
displayedWelcomeMessage = false
checkedForUpdates = false
constructor (
private readonly config: ConfigService,
private readonly toastCtrl: ToastController,
private readonly modalCtrl: ModalController,
private readonly alertCtrl: AlertController,
private readonly navCtrl: NavController,
private readonly serverModel: ServerModel,
private readonly apiService: ApiService,
private readonly loader: LoaderService,
private readonly emver: Emver,
) { }
async handleSpecial (server: Readonly<S9Server>): Promise<void> {
this.handleNotifications(server)
this.handleOSWelcome(server)
if (!this.displayedWelcomeMessage) this.handleUpdateCheck(server)
}
private async handleNotifications (server: Readonly<S9Server>) {
@@ -59,26 +68,94 @@ export class SyncNotifier {
this.serverModel.update(updates)
}
osWelcomeOpen = false
private async handleOSWelcome (server: Readonly<S9Server>) {
if (server.welcomeAck || server.versionInstalled !== this.config.version || this.osWelcomeOpen) return
if (server.welcomeAck || server.versionInstalled !== this.config.version || this.displayedWelcomeMessage) return
this.osWelcomeOpen = true
const [modal, _] = await Promise.all([
this.modalCtrl.create({
backdropDismiss: false,
component: OSWelcomePage,
presentingElement: await this.modalCtrl.getTop(),
componentProps: {
version: server.versionInstalled,
},
}),
this.apiService.acknowledgeOSWelcome(this.config.version),
])
this.displayedWelcomeMessage = true
modal.onWillDismiss().then(() => {
this.osWelcomeOpen = false
const modal = await this.modalCtrl.create({
backdropDismiss: false,
component: OSWelcomePage,
presentingElement: await this.modalCtrl.getTop(),
componentProps: {
version: server.versionInstalled,
},
})
modal.onDidDismiss().then(() => {
this.apiService.acknowledgeOSWelcome(this.config.version)
this.handleUpdateCheck(server)
})
await modal.present()
}
private async handleUpdateCheck (server: Readonly<S9Server>) {
if (!server.autoCheckUpdates || this.checkedForUpdates) return
this.checkedForUpdates = true
if (server.versionLatest && this.emver.compare(server.versionInstalled, server.versionLatest) === -1) {
return this.presentAlertNewOS(server.versionLatest)
}
try {
const availableApps = await this.apiService.getAvailableApps()
if (!!availableApps.find(app => this.emver.compare(app.versionInstalled, app.versionLatest) === -1)) {
return this.presentAlertNewApps()
}
} catch {
this.checkedForUpdates = false
}
}
private async presentAlertNewApps () {
const alert = await this.alertCtrl.create({
backdropDismiss: true,
header: 'Updates Available!',
message: 'New service updates are availbale in the Marketplace.',
buttons: [
{
text: 'Cancel',
role: 'cancel'
},
{
text: 'View in Marketplace',
handler: () => {
return this.navCtrl.navigateForward('/services/marketplace')
}
}
]
})
await alert.present()
}
private async presentAlertNewOS (versionLatest: string) {
const alert = await this.alertCtrl.create({
backdropDismiss: true,
header: 'New EmbassyOS Version!',
message: `Update to EmbassyOS, version ${versionLatest}?`,
buttons: [
{
text: 'Not now',
role: 'cancel'
},
{
text: 'Update',
handler: () => {
return this.updateEmbassyOS(versionLatest)
}
}
]
})
await alert.present()
}
private async updateEmbassyOS (versionLatest: string) {
this.loader
.displayDuringAsync(async () => {
await this.apiService.updateAgent(versionLatest)
this.serverModel.update({ status: ServerStatus.UPDATING })
})
.catch(e => alert(e))
}
}