Jeremy Kahn 94a4b2fb2e
refactor(services): Standardize services and lib organization ()
* refactor(Notification): use instance methods
* refactor(Audio): move to lib layer
* refactor(EncryptionService): rename instance to encryption
* refactor(ConnectionTest): move to lib
* refactor(FileTransfer): move to lib
* refactor(PeerRoom): move to lib
* refactor(sleep): move to lib
* refactor(type-guards): move to lib
* refactor(SerializationService): use standard instance name
* refactor(SettingsService): use standard instance name
2024-01-28 20:46:59 -06:00

82 lines
2.2 KiB
TypeScript

import { saveAs } from 'file-saver'
import { UserSettings } from 'models/settings'
import { encryption } from 'services/Encryption'
import {
isSerializedUserSettings,
serialization,
} from 'services/Serialization/Serialization'
class InvalidFileError extends Error {
message = 'InvalidFileError: File could not be imported'
}
const encryptionTestTarget = 'chitchatter'
export class SettingsService {
exportSettings = async (userSettings: UserSettings) => {
const serializedUserSettings = await serialization.serializeUserSettings(
userSettings
)
const blob = new Blob([JSON.stringify(serializedUserSettings)], {
type: 'application/json;charset=utf-8',
})
saveAs(blob, `chitchatter-profile-${userSettings.userId}.json`)
}
importSettings = async (file: File) => {
const fileReader = new FileReader()
const promise = new Promise<UserSettings>((resolve, reject) => {
fileReader.addEventListener('loadend', async evt => {
try {
const fileReaderResult = evt.target?.result
if (typeof fileReaderResult !== 'string') {
throw new Error()
}
const parsedFileResult = JSON.parse(fileReaderResult)
if (!isSerializedUserSettings(parsedFileResult)) {
throw new Error()
}
const deserializedUserSettings =
await serialization.deserializeUserSettings(parsedFileResult)
const encryptedString = await encryption.encryptString(
deserializedUserSettings.publicKey,
encryptionTestTarget
)
const decryptedString = await encryption.decryptString(
deserializedUserSettings.privateKey,
encryptedString
)
// NOTE: This determines whether the public and private keys match
// and are compatible with Chitchatter.
if (decryptedString !== encryptionTestTarget) {
throw new Error()
}
resolve(deserializedUserSettings)
} catch (e) {
const err = new InvalidFileError()
console.error(err)
reject(err)
}
})
fileReader.readAsText(file.slice())
})
return promise
}
}
export const settings = new SettingsService()