Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

persist successful auth for 60 secs #323

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 48 additions & 4 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AfterViewInit, Component } from '@angular/core'
import { StatusBar, Style } from '@capacitor/status-bar'

import { Platform } from '@ionic/angular'
import { AlertController, Platform } from '@ionic/angular'
import { TranslateService } from '@ngx-translate/core'

import {
Expand All @@ -17,12 +17,19 @@ import { BehaviorSubject } from 'rxjs'
styleUrls: ['app.component.scss'],
})
export class AppComponent implements AfterViewInit {
// authentication is valid for 60 seconds
private static authenticationValidTime = 60

// this is only used on android
activeAuthentication = new BehaviorSubject(false)
lastSuccessfulAuthentication = new BehaviorSubject(-1)

private authenticationAlert?: HTMLIonAlertElement = undefined

constructor(
private platform: Platform,
private translateService: TranslateService
private translateService: TranslateService,
private alertController: AlertController
) {
// init translation with browser-language (== device-language)
this.translateService.addLangs(['en', 'de'])
Expand All @@ -44,6 +51,10 @@ export class AppComponent implements AfterViewInit {
})
}

get timestamp(): number {
return new Date().getTime() / 1000
}

async ngAfterViewInit() {
await StatusBar.show()
await StatusBar.setStyle({ style: Style.Light }) // there is no dark mode (yet)
Expand All @@ -52,6 +63,9 @@ export class AppComponent implements AfterViewInit {
}

async authenticate() {
if (!this.needsAuthentication()) {
return
}
this.activeAuthentication.next(true)

let isAuthenticated = false
Expand All @@ -63,6 +77,7 @@ export class AppComponent implements AfterViewInit {
allowDeviceCredential: true,
})
isAuthenticated = true
this.lastSuccessfulAuthentication.next(this.timestamp)
} catch (e) {
const { message, code } = e as BiometryError

Expand All @@ -73,11 +88,40 @@ export class AppComponent implements AfterViewInit {
]

if (noCredentialsError.includes(code)) {
alert(this.translateService.instant('pinLock.noAuthMessage'))
this.showAlert(this.translateService.instant('pinLock.noAuthMessage'))
} else {
alert(message)
this.showAlert(message)
}
}
}
}

private async showAlert(message: string) {
if (this.authenticationAlert !== undefined) {
return
}

this.authenticationAlert = await this.alertController.create({
message,
buttons: [
{
text: this.translateService.instant('general.ok'),
handler: () => {
this.authenticationAlert?.dismiss()
this.authenticationAlert = undefined
},
},
],
backdropDismiss: false,
})
await this.authenticationAlert?.present()
}

private needsAuthentication(): boolean {
const authTime = this.lastSuccessfulAuthentication.value
return (
authTime < 0 ||
this.timestamp - authTime > AppComponent.authenticationValidTime
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import {
ModalController,
PopoverController,
ToastController,
Platform,
ActionSheetController,
} from '@ionic/angular'
import { TranslateService } from '@ngx-translate/core'
import { TrajectoryMeta, TrajectoryType } from 'src/app/model/trajectory'
Expand All @@ -26,13 +24,11 @@ export class TrajectoryCardPopoverPage implements OnInit {
@Input() trajectory: TrajectoryMeta

constructor(
private platform: Platform,
private modalController: ModalController,
private popoverController: PopoverController,
private alertController: AlertController,
private loadingController: LoadingController,
private toastController: ToastController,
private actionSheetController: ActionSheetController,
private locationService: LocationService,
private trajectoryImportExportService: TrajectoryImportExportService,
private translateService: TranslateService,
Expand All @@ -49,18 +45,14 @@ export class TrajectoryCardPopoverPage implements OnInit {
e.stopPropagation()
this.popoverController.dismiss()

if (this.platform.is('android')) {
await this.presentExportActionSheet()
} else {
await this.showLoadingDialog(
this.translateService.instant('trajectory.export.loadingDialogMessage')
)
await this.trajectoryImportExportService
.exportTrajectoryViaShareDialog(this.trajectory)
.then(async (result) => {
await this.handleExportResult(result)
})
}
await this.showLoadingDialog(
this.translateService.instant('trajectory.export.loadingDialogMessage')
)
await this.trajectoryImportExportService
.exportTrajectoryViaShareDialog(this.trajectory)
.then(async (result) => {
await this.handleExportResult(result)
})
}

async deleteTrajectory(e: Event) {
Expand Down Expand Up @@ -116,52 +108,6 @@ export class TrajectoryCardPopoverPage implements OnInit {
await alert.present()
}

private async presentExportActionSheet() {
const actionSheet = await this.actionSheetController.create({
header: this.translateService.instant('trajectory.export.alertHeader'),
buttons: [
{
text: this.translateService.instant('trajectory.export.saveMessage'),
icon: 'save-outline',
handler: async () => {
await this.showLoadingDialog(
this.translateService.instant(
'trajectory.export.loadingDialogMessage'
)
)
await this.trajectoryImportExportService
.exportTrajectoryToDownloads(this.trajectory)
.then(async (result) => {
await this.handleExportResult(result)
})
},
},
{
text: this.translateService.instant('general.share'),
icon: 'share-social-outline',
handler: async () => {
await this.showLoadingDialog(
this.translateService.instant(
'trajectory.export.loadingDialogMessage'
)
)
await this.trajectoryImportExportService
.exportTrajectoryViaShareDialog(this.trajectory)
.then(async (result) => {
await this.handleExportResult(result)
})
},
},
{
text: this.translateService.instant('general.cancel'),
icon: 'close',
role: 'cancel',
},
],
})
await actionSheet.present()
}

private async handleExportResult(result: TrajectoryExportResult) {
await this.hideLoadingDialog()
if (result.success) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
} from '../../model/trajectory'
import { TrajectoryService } from '../../shared-services/trajectory/trajectory.service'
import { v4 as uuid } from 'uuid'
import { Platform } from '@ionic/angular'
import { HttpClient } from '@angular/common/http'
import { SqliteService } from '../db/sqlite.service'

Expand Down Expand Up @@ -44,7 +43,6 @@ export class TrajectoryImportExportService extends TrajectoryService {
constructor(
http: HttpClient,
db: SqliteService,
private platform: Platform,
private translateService: TranslateService
) {
super(http, db)
Expand Down Expand Up @@ -181,10 +179,6 @@ export class TrajectoryImportExportService extends TrajectoryService {
encoding: Encoding.UTF8,
})

if (this.platform.is('android')) {
// await Share.requestPermissions()
}

// share file
await Share.share({
title: this.translateService.instant('trajectory.export.alertHeader'),
Expand All @@ -210,36 +204,6 @@ export class TrajectoryImportExportService extends TrajectoryService {
}
}

/**
* This is android-only.
*
* @param t trajectory to export
*/
async exportTrajectoryToDownloads(
trajectoryMeta: TrajectoryMeta
): Promise<TrajectoryExportResult> {
const trajectoryFile = await this.createTrajectoryExportFileFromMeta(
trajectoryMeta,
false
)
try {
await Filesystem.writeFile({
path: `Download/${trajectoryFile.filename}.json`,
data: trajectoryFile.trajectory,
directory: Directory.ExternalStorage,
encoding: Encoding.UTF8,
})
return { success: true, errorMessage: null }
} catch (e) {
return {
success: false,
errorMessage: this.translateService.instant(
'trajectory.export.errorMessage'
),
}
}
}

/**
* Translates trajectory from model class {@linkcode TrajectoryMeta}
* into JSON-format specified by {@linkcode TrajectoryJSON}
Expand Down
1 change: 1 addition & 0 deletions src/assets/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"yes": "Ja",
"save": "Speichern",
"discard": "Verwerfen",
"ok": "OK",
"exampleTrajectoryName": "Münster"
},
"diary": {
Expand Down
1 change: 1 addition & 0 deletions src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"yes": "Yes",
"save": "Save",
"discard": "Discard",
"ok": "OK",
"exampleTrajectoryName": "Münster"
},
"diary": {
Expand Down