import { ipcMain } from "electron" ; import forceFocus from "forcefocus" ; import { WindowMain } from "./window.main" ; import { BiometricMain } from "jslib-common/abstractions/biometric.main" ; import { I18nService } from "jslib-common/abstractions/i18n.service" ; import { LogService } from "jslib-common/abstractions/log.service" ; import { StateService } from "jslib-common/abstractions/state.service" ; export default class BiometricWindowsMain implements BiometricMain { isError : boolean = false ; private windowsSecurityCredentialsUiModule : any ; constructor ( private i18nservice , private windowMain , private stateService , private logService ) { } async init ( ) { this . windowsSecurityCredentialsUiModule = this . getWindowsSecurityCredentialsUiModule ( ) ; let supportsBiometric = false ; try { supportsBiometric = await this . supportsBiometric ( ) ; } catch { this . isError = true ; } await this . stateService . setEnableBiometric ( supportsBiometric ) ; await this . stateService . setBiometricText ( "unlockWithWindowsHello" ) ; await this . stateService . setNoAutoPromptBiometricsText ( "noAutoPromptWindowsHello" ) ; ipcMain . on ( "biometric" , async ( event , message ) => { event . returnValue = await this . authenticateBiometric ( ) ; } ) ; } async supportsBiometric ( ) { const availability = await this . checkAvailabilityAsync ( ) ; return this . getAllowedAvailabilities ( ) . includes ( availability ) ; } async authenticateBiometric ( ) { const module = this . getWindowsSecurityCredentialsUiModule ( ) ; if ( module == null ) { return false ; } const verification = await this . requestVerificationAsync ( this . i18nservice . t ( "windowsHelloConsentMessage" ) ) ; return verification === module . UserConsentVerificationResult . verified ; } getWindowsSecurityCredentialsUiModule ( ) { try { if ( this . windowsSecurityCredentialsUiModule == null && this . getWindowsMajorVersion ( ) >= 10 ) { this . windowsSecurityCredentialsUiModule = require ( "@nodert-win10-rs4/windows.security.credentials.ui" ) ; } return this . windowsSecurityCredentialsUiModule ; } catch { this . isError = true ; } return null ; } async checkAvailabilityAsync ( ) { const module = this . getWindowsSecurityCredentialsUiModule ( ) ; if ( module != null ) { return new Promise ( ( resolve , reject ) => { try { module . UserConsentVerifier . checkAvailabilityAsync ( ( error , result ) => { if ( error ) { return resolve ( null ) ; } return resolve ( result ) ; } ) ; } catch { this . isError = true ; return resolve ( null ) ; } } ) ; } return Promise . resolve ( null ) ; } async requestVerificationAsync ( message ) { const module = this . getWindowsSecurityCredentialsUiModule ( ) ; if ( module != null ) { return new Promise ( ( resolve , reject ) => { try { module . UserConsentVerifier . requestVerificationAsync ( message , ( error , result ) => { if ( error ) { return resolve ( null ) ; } return resolve ( result ) ; } ) ; forceFocus . focusWindow ( this . windowMain . win ) ; } catch ( error ) { this . isError = true ; return reject ( error ) ; } } ) ; } return Promise . resolve ( null ) ; } getAllowedAvailabilities ( ) { try { const module = this . getWindowsSecurityCredentialsUiModule ( ) ; if ( module != null ) { return [ module . UserConsentVerifierAvailability . available , module . UserConsentVerifierAvailability . deviceBusy , ] ; } } catch { } return [ ] ; } getWindowsMajorVersion ( ) { if ( process . platform !== "win32" ) { return - 1 ; } try { const version = require ( "os" ) . release ( ) ; return Number . parseInt ( version . split ( "." ) [ 0 ] , 10 ) ; } catch { this . logService . error ( "Unable to resolve windows major version number" ) ; } return - 1 ; } }