import { SettingName } from '@standardnotes/settings' import { SNSettingsService } from '../Settings' import { PureCryptoInterface } from '@standardnotes/sncrypto-common' import { SNFeaturesService } from '../Features/FeaturesService' import { AbstractService, InternalEventBusInterface, SignInStrings } from '@standardnotes/services' export class SNMfaService extends AbstractService { constructor( private settingsService: SNSettingsService, private crypto: PureCryptoInterface, private featuresService: SNFeaturesService, protected override internalEventBus: InternalEventBusInterface, ) { super(internalEventBus) } private async saveMfaSetting(secret: string): Promise { return await this.settingsService.updateSetting(SettingName.MfaSecret, secret, true) } async isMfaActivated(): Promise { const mfaSetting = await this.settingsService.getDoesSensitiveSettingExist(SettingName.MfaSecret) return mfaSetting != false } async generateMfaSecret(): Promise { return this.crypto.generateOtpSecret() } async getOtpToken(secret: string): Promise { return this.crypto.totpToken(secret, Date.now(), 6, 30) } async enableMfa(secret: string, otpToken: string): Promise { const otpTokenValid = otpToken != undefined && otpToken === (await this.getOtpToken(secret)) if (!otpTokenValid) { throw new Error(SignInStrings.IncorrectMfa) } return this.saveMfaSetting(secret) } async disableMfa(): Promise { return await this.settingsService.deleteSetting(SettingName.MfaSecret) } override deinit(): void { ;(this.settingsService as unknown) = undefined ;(this.crypto as unknown) = undefined ;(this.featuresService as unknown) = undefined super.deinit() } }