feat: add "multi file auth state" implementation

1. add multi file auth state since it's far more efficient than single state
2. deprecate single file auth state (please don't use it anymore)
This commit is contained in:
Adhiraj Singh
2022-05-22 21:21:35 +05:30
parent a8e209705a
commit 06437e182d
7 changed files with 177 additions and 88 deletions

View File

@@ -1,10 +1,9 @@
import { Boom } from '@hapi/boom'
import { randomBytes } from 'crypto'
import type { Logger } from 'pino'
import { proto } from '../../WAProto'
import type { AuthenticationCreds, AuthenticationState, SignalDataSet, SignalDataTypeMap, SignalKeyStore, SignalKeyStoreWithTransaction, TransactionCapabilityOptions } from '../Types'
import type { AuthenticationCreds, SignalDataSet, SignalDataTypeMap, SignalKeyStore, SignalKeyStoreWithTransaction, TransactionCapabilityOptions } from '../Types'
import { Curve, signedKeyPair } from './crypto'
import { BufferJSON, delay, generateRegistrationId } from './generics'
import { delay, generateRegistrationId } from './generics'
/**
* Adds DB like transaction capability (https://en.wikipedia.org/wiki/Database_transaction) to the SignalKeyStore,
@@ -126,79 +125,4 @@ export const initAuthCreds = (): AuthenticationCreds => {
unarchiveChats: false
}
}
}
// useless key map only there to maintain backwards compatibility
// do not use in your own systems please
const KEY_MAP: { [T in keyof SignalDataTypeMap]: string } = {
'pre-key': 'preKeys',
'session': 'sessions',
'sender-key': 'senderKeys',
'app-state-sync-key': 'appStateSyncKeys',
'app-state-sync-version': 'appStateVersions',
'sender-key-memory': 'senderKeyMemory'
}
/** stores the full authentication state in a single JSON file */
export const useSingleFileAuthState = (filename: string, logger?: Logger): { state: AuthenticationState, saveState: () => void } => {
// require fs here so that in case "fs" is not available -- the app does not crash
const { readFileSync, writeFileSync, existsSync } = require('fs')
let creds: AuthenticationCreds
let keys: any = { }
// save the authentication state to a file
const saveState = () => {
logger && logger.trace('saving auth state')
writeFileSync(
filename,
// BufferJSON replacer utility saves buffers nicely
JSON.stringify({ creds, keys }, BufferJSON.replacer, 2)
)
}
if(existsSync(filename)) {
const result = JSON.parse(
readFileSync(filename, { encoding: 'utf-8' }),
BufferJSON.reviver
)
creds = result.creds
keys = result.keys
} else {
creds = initAuthCreds()
keys = { }
}
return {
state: {
creds,
keys: {
get: (type, ids) => {
const key = KEY_MAP[type]
return ids.reduce(
(dict, id) => {
let value = keys[key]?.[id]
if(value) {
if(type === 'app-state-sync-key') {
value = proto.AppStateSyncKeyData.fromObject(value)
}
dict[id] = value
}
return dict
}, { }
)
},
set: (data) => {
for(const _key in data) {
const key = KEY_MAP[_key as keyof SignalDataTypeMap]
keys[key] = keys[key] || { }
Object.assign(keys[key], data[_key])
}
saveState()
}
}
},
saveState
}
}