diff --git a/page/index.js b/page/index.js index b62bbd5..ac87bd0 100644 --- a/page/index.js +++ b/page/index.js @@ -15,8 +15,8 @@ Page( app._options.globalData.TOTPS = x this.initPage(); }) - .catch((x) => { - app._options.globalData.TOTPS = localStorage.getItem('TOTPs') + .catch(() => { + app._options.globalData.TOTPS = localStorage.getItem('TOTPs') ?? [] this.initPage() }) }, diff --git a/setting/index.js b/setting/index.js index 9e92d84..9400ed2 100644 --- a/setting/index.js +++ b/setting/index.js @@ -1,10 +1,31 @@ +import { getTOTPByLink } from './utils/queryParser.js' + let _props = null; AppSettingsPage({ build(props) { _props = props; - const storage = props.settingsStorage.getItem("TOTPs"); - const totpEntrys = GetTOTPList(storage); + const storage = props.settingsStorage.getItem("TOTPs") + const totpEntrys = GetTOTPList(storage) + const createButton = TextInput({ + placeholder: "otpauth://", + label: "Add new OTP Link", + onChange: (changes) => { + storage.push(getTOTPByLink(changes)) + updateStorage(storage) + }, + labelStyle: { + backgroundColor: "#14213D", + display: "flex", + alignItems: "center", + justifyContent: "center", + margin: "10px", + flexGrow: 1, + fontSize: "20px", + color: "#FFFFFF", + borderRadius: "5px" + } + }); var body = Section( { @@ -34,7 +55,8 @@ AppSettingsPage({ "TOTPS:" ) ), - ...totpEntrys + ...totpEntrys, + createButton ] ); return body; @@ -47,8 +69,12 @@ function GetTOTPList(storage){ storage.forEach((element) => { const elementId = counter; const textInput = TextInput({ - placeholder: "otplink", + placeholder: "otpauth://", label: "Change OTP link", + onChange: (changes) => { + storage[elementId] = getTOTPByLink(changes) + updateStorage(storage) + }, labelStyle: { backgroundColor: "#14213D", textAlign: "center", @@ -75,7 +101,7 @@ function GetTOTPList(storage){ ); const delButton = Button( { - onClick: (el) => { + onClick: () => { storage = storage.filter(x => storage.indexOf(x) != elementId) updateStorage(storage) }, diff --git a/setting/utils/queryParser.js b/setting/utils/queryParser.js new file mode 100644 index 0000000..f016b32 --- /dev/null +++ b/setting/utils/queryParser.js @@ -0,0 +1,36 @@ +import { TOTP } from "../../lib/totp-quickjs"; + +const otpScheme = "otpauth:/"; + +export function getTOTPByLink(link){ + let args = link.split("/", otpScheme.length) + let type = args[2] //Returns 'hotp' or 'totp' + let issuer = args[3].split(':')[0]?.split('?')[0] //Returns issuer + let client = args[3].split(':')[1]?.split('?')[0] ?? args[3].split(':')[0]?.split('?')[0] //Returns client + let secret = args[3].split('secret=')[1]?.split('&')[0] //Returns secret + let period = args[3].split('period=')[1]?.split('&')[0] //Returns period + let digits = args[3].split('digits=')[1]?.split('&')[0] //Returns digits + let algorithm = args[3].split('algorithm=')[1]?.split('&')[0] //Returns algorithm + + if(type.toLowerCase() != 'totp') + return Error("Type is not valid, requires 'TOTP'") + + if(secret === undefined) + return Error("Secret not defined") + + issuer = issuer.replace("%20", " ") + client = client.replace("%20", " ") + + return new TOTP(secret, issuer, client, digits, period, 0, getHashType(algorithm)) +} + +function getHashType(algorithm){ + if(algorithm == "SHA1") + return "SHA-1" + if(algorithm == "SHA256") + return "SHA-256" + if(algorithm == "SHA512") + return "SHA-512" + else + return null +}