import { VaultSourceID } from "buttercup" ; import ms from "ms" ; import EventEmitter from "eventemitter3" ; import { getAsyncStorage } from "./storage" ; import { getAllSourceIDs , onVaultSourcesUpdated } from "./buttercup" ; import { cloneObject } from "../library/clone" ; export interface VaultConfiguration { autofill : boolean ; autoLockEnabled : boolean ; autoLockTime : number ; otpAlwaysAvailable : boolean ; } const STORAGE_PREFIX_VAULT_CONFIG = "config:source:" ; const __vaultConfigurations = { } ; let __emitter = null ; export function getEmitter ( ) { if ( ! __emitter ) { __emitter = new EventEmitter ( ) ; } return __emitter ; } function getInitialConfig ( ) { return { autofill : false , autoLockEnabled : true , autoLockTime : ms ( "15m" ) , otpAlwaysAvailable : false } ; } export function getVaultConfig ( sourceID ) { return __vaultConfigurations [ sourceID ] ?? null ; } export async function initialise ( ) { const storage = getAsyncStorage ( ) ; const allKeys = await storage . getAllKeys ( ) ; const configKeys = allKeys . filter ( key => key . indexOf ( STORAGE_PREFIX_VAULT_CONFIG ) === 0 ) ; let currentSources = getAllSourceIDs ( ) ; const oldKeys = configKeys . filter ( key => { const sourceID = key . replace ( STORAGE_PREFIX_VAULT_CONFIG , "" ) ; return currentSources . indexOf ( sourceID ) === - 1 ; } ) ; for ( const oldKey of oldKeys ) { await storage . removeKey ( oldKey ) ; } const updateFromVaultSources = async ( ) => { for ( const sourceID of currentSources ) { const storageKey = `${ STORAGE_PREFIX_VAULT_CONFIG }${ sourceID }` ; const hasConfig = configKeys . includes ( storageKey ) ; if ( hasConfig ) { const rawConfig = await storage . getValue ( storageKey ) ; __vaultConfigurations [ sourceID ] = mergeConfigurations ( getInitialConfig ( ) , JSON . parse ( rawConfig ) ) ; } else { const config = __vaultConfigurations [ sourceID ] = getInitialConfig ( ) ; await storage . setValue ( storageKey , JSON . stringify ( config ) ) ; } } } ; await updateFromVaultSources ( ) ; onVaultSourcesUpdated ( async ( ) => { currentSources = getAllSourceIDs ( ) ; await updateFromVaultSources ( ) ; } ) ; } function mergeConfigurations ( target , merge ) { const output = cloneObject ( target ) ; for ( const key in merge ) { output [ key ] = merge [ key ] ; } return output ; } export async function updateVaultConfig ( sourceID , config ) { const storage = getAsyncStorage ( ) ; const updatedConfig = __vaultConfigurations [ sourceID ] = mergeConfigurations ( getInitialConfig ( ) , config ) ; const storageKey = `${ STORAGE_PREFIX_VAULT_CONFIG }${ sourceID }` ; await storage . setValue ( storageKey , JSON . stringify ( updatedConfig ) ) ; const emitter = getEmitter ( ) ; emitter . emit ( "update" , sourceID ) ; emitter . emit ( `update:${ sourceID }` , updatedConfig ) ; }