diff --git a/src/background.ts b/src/background.ts index bb59a2f9..2b0447dc 100644 --- a/src/background.ts +++ b/src/background.ts @@ -119,7 +119,7 @@ async function getTotp(text: string, silent = false) { } } else { let uri = text.split("otpauth://")[1]; - let type = uri.substr(0, 4).toLowerCase(); + let type = uri.substr(0, 4).toLowerCase() as OTPType; uri = uri.substr(5); let label = uri.split("?")[0]; const parameterPart = uri.split("?")[1]; @@ -193,15 +193,15 @@ async function getTotp(text: string, silent = false) { if ( !/^[2-7a-z]+=*$/i.test(secret) && /^[0-9a-f]+$/i.test(secret) && - type === "totp" + type === OTPType.totp ) { - type = "hex"; + type = OTPType.hex; } else if ( !/^[2-7a-z]+=*$/i.test(secret) && /^[0-9a-f]+$/i.test(secret) && - type === "hotp" + type === OTPType.hotp ) { - type = "hhex"; + type = OTPType.hhex; } const entryData: { [hash: string]: RawOTPStorage } = {}; entryData[hash] = { diff --git a/src/components/Popup/BackupPage.vue b/src/components/Popup/BackupPage.vue index 8e718b46..ce797271 100644 --- a/src/components/Popup/BackupPage.vue +++ b/src/components/Popup/BackupPage.vue @@ -71,6 +71,7 @@ <script lang="ts"> import Vue from "vue"; import { isSafari } from "../../browser"; +import { OTPType } from "../../models/otp"; export default Vue.extend({ data: function () { @@ -212,10 +213,13 @@ function getOneLineOtpBackupFile(entryData: { [hash: string]: RawOTPStorage }) { ? otpStorage.issuer + ":" + (otpStorage.account || "") : otpStorage.account || ""; let type = ""; - if (otpStorage.type === "totp" || otpStorage.type === "hex") { - type = "totp"; - } else if (otpStorage.type === "hotp" || otpStorage.type === "hhex") { - type = "hotp"; + if (otpStorage.type === OTPType.totp || otpStorage.type === OTPType.hex) { + type = OTPType.totp; + } else if ( + otpStorage.type === OTPType.hotp || + otpStorage.type === OTPType.hhex + ) { + type = OTPType.hotp; } else { continue; } @@ -228,8 +232,8 @@ function getOneLineOtpBackupFile(entryData: { [hash: string]: RawOTPStorage }) { "?secret=" + otpStorage.secret + (otpStorage.issuer ? "&issuer=" + otpStorage.issuer : "") + - (type === "hotp" ? "&counter=" + otpStorage.counter : "") + - (type === "totp" && otpStorage.period + (type === OTPType.hotp ? "&counter=" + otpStorage.counter : "") + + (type === OTPType.totp && otpStorage.period ? "&period=" + otpStorage.period : "") + (otpStorage.digits ? "&digits=" + otpStorage.digits : "") + diff --git a/src/components/Popup/EntryComponent.vue b/src/components/Popup/EntryComponent.vue index 92099b5b..abd96418 100644 --- a/src/components/Popup/EntryComponent.vue +++ b/src/components/Popup/EntryComponent.vue @@ -264,10 +264,10 @@ function getQrUrl(entry: OTPEntry) { : entry.account; const type = entry.type === OTPType.hex - ? OTPType[OTPType.totp] + ? OTPType.totp : entry.type === OTPType.hhex - ? OTPType[OTPType.hotp] - : OTPType[entry.type]; + ? OTPType.hotp + : entry.type; const otpauth = "otpauth://" + type + diff --git a/src/definitions/module-interface.d.ts b/src/definitions/module-interface.d.ts index 49426631..0d8470ec 100644 --- a/src/definitions/module-interface.d.ts +++ b/src/definitions/module-interface.d.ts @@ -62,7 +62,7 @@ interface AccountsState { entries: OTPEntryInterface[]; defaultEncryption: string; encryption: Map<string, EncryptionInterface>; - OTPType: number; + OTPType: OTPType; shouldShowPassphrase: boolean; sectorStart: boolean; sectorOffset: number; diff --git a/src/definitions/otp.d.ts b/src/definitions/otp.d.ts index c55fb148..1ac0583f 100644 --- a/src/definitions/otp.d.ts +++ b/src/definitions/otp.d.ts @@ -1,5 +1,14 @@ +declare enum OTPType { + totp = "totp", + hotp = "hotp", + battle = "battle", + steam = "steam", + hex = "hex", + hhex = "hhex", +} + interface OTPEntryInterface { - type: number; // OTPType + type: OTPType; index: number; issuer: string; secret: string | null; @@ -42,7 +51,7 @@ interface RawOTPStorage { index: number; issuer?: string; secret: string; - type: string; + type: OTPType; counter?: number; period?: number; digits?: number; diff --git a/src/import.ts b/src/import.ts index 21bebdab..342debb5 100644 --- a/src/import.ts +++ b/src/import.ts @@ -211,7 +211,7 @@ export async function getEntryDataFromOTPAuthPerLine(importCode: string) { } let uri = item.split("otpauth://")[1]; - let type = uri.substr(0, 4).toLowerCase(); + let type = uri.substr(0, 4).toLowerCase() as OTPType; uri = uri.substr(5); let label = uri.split("?")[0]; const parameterPart = uri.split("?")[1]; @@ -282,15 +282,15 @@ export async function getEntryDataFromOTPAuthPerLine(importCode: string) { if ( !/^[2-7a-z]+=*$/i.test(secret) && /^[0-9a-f]+$/i.test(secret) && - type === "totp" + type === OTPType.totp ) { - type = "hex"; + type = OTPType.hex; } else if ( !/^[2-7a-z]+=*$/i.test(secret) && /^[0-9a-f]+$/i.test(secret) && - type === "hotp" + type === OTPType.hotp ) { - type = "hhex"; + type = OTPType.hhex; } exportData[hash] = { diff --git a/src/models/otp.ts b/src/models/otp.ts index cdfa38db..c0296abd 100644 --- a/src/models/otp.ts +++ b/src/models/otp.ts @@ -3,12 +3,12 @@ import { UserSettings } from "./settings"; import { EntryStorage } from "./storage"; export enum OTPType { - totp = 1, - hotp, - battle, - steam, - hex, - hhex, + totp = "totp", + hotp = "hotp", + battle = "battle", + steam = "steam", + hex = "hex", + hhex = "hhex", } export enum CodeState { @@ -117,7 +117,30 @@ export class OTPEntry implements OTPEntryInterface { this.secret = entry.secret; } - this.type = entry.type; + // We may have already had some error OTP type entries in the storage + // totp = 1 + // hotp = 2 + // battle = 3 + // steam = 4 + // hex = 5 + // hhex = 6 + + if ((entry.type as unknown) === 1) { + this.type = OTPType.totp; + } else if ((entry.type as unknown) === 2) { + this.type = OTPType.hotp; + } else if ((entry.type as unknown) === 3) { + this.type = OTPType.battle; + } else if ((entry.type as unknown) === 4) { + this.type = OTPType.steam; + } else if ((entry.type as unknown) === 5) { + this.type = OTPType.hex; + } else if ((entry.type as unknown) === 6) { + this.type = OTPType.hhex; + } else { + this.type = entry.type; + } + if (entry.issuer) { this.issuer = entry.issuer; } else { @@ -223,8 +246,31 @@ export class OTPEntry implements OTPEntryInterface { this.period = decryptedData.period || 30; this.pinned = decryptedData.pinned || false; this.secret = decryptedData.secret; - // @ts-expect-error need a better way to do this - this.type = OTPType[decryptedData.type] || OTPType.totp; + this.type = decryptedData.type || OTPType.totp; + + // We may have already had some error OTP type entries in the storage + // totp = 1 + // hotp = 2 + // battle = 3 + // steam = 4 + // hex = 5 + // hhex = 6 + + if ((decryptedData.type as unknown) === 1) { + this.type = OTPType.totp; + } else if ((decryptedData.type as unknown) === 2) { + this.type = OTPType.hotp; + } else if ((decryptedData.type as unknown) === 3) { + this.type = OTPType.battle; + } else if ((decryptedData.type as unknown) === 4) { + this.type = OTPType.steam; + } else if ((decryptedData.type as unknown) === 5) { + this.type = OTPType.hex; + } else if ((decryptedData.type as unknown) === 6) { + this.type = OTPType.hhex; + } else { + this.type = OTPType.totp; + } if (this.type !== OTPType.hotp && this.type !== OTPType.hhex) { this.generate(); diff --git a/src/models/storage.ts b/src/models/storage.ts index 4b3699fb..e0527973 100644 --- a/src/models/storage.ts +++ b/src/models/storage.ts @@ -222,7 +222,7 @@ export class EntryStorage { encrypted, hash: entry.hash, index: entry.index, - type: OTPType[entry.type], + type: entry.type, secret, }; @@ -392,10 +392,7 @@ export class EntryStorage { } // remove unnecessary fields - if ( - !(entry.type === OTPType[OTPType.hotp]) && - !(entry.type === OTPType[OTPType.hhex]) - ) { + if (!(entry.type === OTPType.hotp) && !(entry.type === OTPType.hhex)) { delete entry.counter; } @@ -478,7 +475,7 @@ export class EntryStorage { algorithm: OTPAlgorithm; pinned: boolean; } = { - type: (parseInt(data[hash].type) as OTPType) || OTPType[OTPType.totp], + type: data[hash].type || OTPType.totp, index: data[hash].index || 0, issuer: data[hash].issuer || "", account: data[hash].account || "", @@ -617,29 +614,53 @@ export class EntryStorage { } if (!entryData.type) { - entryData.type = OTPType[OTPType.totp]; + entryData.type = OTPType.totp; } let type: OTPType; switch (entryData.type) { - case "totp": - case "hotp": - case "battle": - case "steam": - case "hex": - case "hhex": - type = OTPType[entryData.type]; + case OTPType.totp: + case OTPType.hotp: + case OTPType.battle: + case OTPType.steam: + case OTPType.hex: + case OTPType.hhex: + type = entryData.type; break; default: // we need correct the type here // and save it - type = OTPType.totp; - entryData.type = OTPType[OTPType.totp]; + + // We may have already had some error OTP type entries in the storage + // totp = 1 + // hotp = 2 + // battle = 3 + // steam = 4 + // hex = 5 + // hhex = 6 + + if ((entryData.type as unknown) === 1) { + type = OTPType.totp; + } else if ((entryData.type as unknown) === 2) { + type = OTPType.hotp; + } else if ((entryData.type as unknown) === 3) { + type = OTPType.battle; + } else if ((entryData.type as unknown) === 4) { + type = OTPType.steam; + } else if ((entryData.type as unknown) === 5) { + type = OTPType.hex; + } else if ((entryData.type as unknown) === 6) { + type = OTPType.hhex; + } else { + type = OTPType.totp; + } + + entryData.type = type; } let period: number | undefined; if ( - entryData.type === OTPType[OTPType.totp] && + entryData.type === OTPType.totp && entryData.period && entryData.period > 0 ) {