feat: add snjs package

This commit is contained in:
Karol Sójko
2022-07-06 14:04:18 +02:00
parent 321a055bae
commit 0e40469e2f
296 changed files with 46109 additions and 187 deletions

View File

@@ -0,0 +1,81 @@
import { SNApiService } from '../Api/ApiService'
import { SettingsGateway } from './SettingsGateway'
import { SNSessionManager } from '../Session/SessionManager'
import {
CloudProvider,
EmailBackupFrequency,
SettingName,
SensitiveSettingName,
SubscriptionSettingName,
} from '@standardnotes/settings'
import { ExtensionsServerURL } from '@Lib/Hosts'
import { AbstractService, InternalEventBusInterface } from '@standardnotes/services'
import { SettingsClientInterface } from './SettingsClientInterface'
export class SNSettingsService extends AbstractService implements SettingsClientInterface {
private provider!: SettingsGateway
private frequencyOptionsLabels = {
[EmailBackupFrequency.Disabled]: 'No email backups',
[EmailBackupFrequency.Daily]: 'Daily',
[EmailBackupFrequency.Weekly]: 'Weekly',
}
private cloudProviderIntegrationUrlEndpoints = {
[CloudProvider.Dropbox]: 'dropbox',
[CloudProvider.Google]: 'gdrive',
[CloudProvider.OneDrive]: 'onedrive',
}
constructor(
private readonly sessionManager: SNSessionManager,
private readonly apiService: SNApiService,
protected override internalEventBus: InternalEventBusInterface,
) {
super(internalEventBus)
}
initializeFromDisk(): void {
this.provider = new SettingsGateway(this.apiService, this.sessionManager)
}
async listSettings() {
return this.provider.listSettings()
}
async getSetting(name: SettingName) {
return this.provider.getSetting(name)
}
async getSubscriptionSetting(name: SubscriptionSettingName) {
return this.provider.getSubscriptionSetting(name)
}
async updateSetting(name: SettingName, payload: string, sensitive = false) {
return this.provider.updateSetting(name, payload, sensitive)
}
async getDoesSensitiveSettingExist(name: SensitiveSettingName) {
return this.provider.getDoesSensitiveSettingExist(name)
}
async deleteSetting(name: SettingName) {
return this.provider.deleteSetting(name)
}
getEmailBackupFrequencyOptionLabel(frequency: EmailBackupFrequency): string {
return this.frequencyOptionsLabels[frequency]
}
getCloudProviderIntegrationUrl(cloudProviderName: CloudProvider, isDevEnvironment: boolean): string {
const { Dev, Prod } = ExtensionsServerURL
const extServerUrl = isDevEnvironment ? Dev : Prod
return `${extServerUrl}/${this.cloudProviderIntegrationUrlEndpoints[cloudProviderName]}?redirect_url=${extServerUrl}/components/cloudlink?`
}
override deinit(): void {
this.provider?.deinit()
;(this.provider as unknown) = undefined
;(this.sessionManager as unknown) = undefined
;(this.apiService as unknown) = undefined
}
}

View File

@@ -0,0 +1,16 @@
import { SettingName, SensitiveSettingName, EmailBackupFrequency } from '@standardnotes/settings'
import { SettingsList } from './SettingsList'
export interface SettingsClientInterface {
listSettings(): Promise<SettingsList>
getSetting(name: SettingName): Promise<string | undefined>
getDoesSensitiveSettingExist(name: SensitiveSettingName): Promise<boolean>
updateSetting(name: SettingName, payload: string, sensitive?: boolean): Promise<void>
deleteSetting(name: SettingName): Promise<void>
getEmailBackupFrequencyOptionLabel(frequency: EmailBackupFrequency): string
}

View File

@@ -0,0 +1,110 @@
import { SettingsList } from './SettingsList'
import { SettingName, SensitiveSettingName, SubscriptionSettingName } from '@standardnotes/settings'
import * as messages from '../Api/Messages'
import { StatusCode, User } from '@standardnotes/responses'
import { SettingsServerInterface } from './SettingsServerInterface'
/**
* SettingsGateway coordinates communication with the API service
* wrapping the userUuid provision for simpler consumption
*/
export class SettingsGateway {
constructor(
private readonly settingsApi: SettingsServerInterface,
private readonly userProvider: { getUser: () => User | undefined },
) {}
isReadyForModification(): boolean {
return this.getUser() != undefined
}
private getUser() {
return this.userProvider.getUser()
}
private get userUuid() {
const user = this.getUser()
if (user == undefined || user.uuid == undefined) {
throw new Error(messages.API_MESSAGE_INVALID_SESSION)
}
return user.uuid
}
async listSettings() {
const { error, data } = await this.settingsApi.listSettings(this.userUuid)
if (error != undefined) {
throw new Error(error.message)
}
if (data == undefined || data.settings == undefined) {
return new SettingsList([])
}
const settings: SettingsList = new SettingsList(data.settings)
return settings
}
async getSetting(name: SettingName): Promise<string | undefined> {
const response = await this.settingsApi.getSetting(this.userUuid, name)
// Backend responds with 400 when setting doesn't exist
if (response.status === StatusCode.HttpBadRequest) {
return undefined
}
if (response.error != undefined) {
throw new Error(response.error.message)
}
return response?.data?.setting?.value ?? undefined
}
async getSubscriptionSetting(name: SubscriptionSettingName): Promise<string | undefined> {
const response = await this.settingsApi.getSubscriptionSetting(this.userUuid, name)
if (response.status === StatusCode.HttpBadRequest) {
return undefined
}
if (response.error != undefined) {
throw new Error(response.error.message)
}
return response?.data?.setting?.value ?? undefined
}
async getDoesSensitiveSettingExist(name: SensitiveSettingName): Promise<boolean> {
const response = await this.settingsApi.getSetting(this.userUuid, name)
// Backend responds with 400 when setting doesn't exist
if (response.status === StatusCode.HttpBadRequest) {
return false
}
if (response.error != undefined) {
throw new Error(response.error.message)
}
return response.data?.success ?? false
}
async updateSetting(name: SettingName, payload: string, sensitive: boolean): Promise<void> {
const { error } = await this.settingsApi.updateSetting(this.userUuid, name, payload, sensitive)
if (error != undefined) {
throw new Error(error.message)
}
}
async deleteSetting(name: SettingName): Promise<void> {
const { error } = await this.settingsApi.deleteSetting(this.userUuid, name)
if (error != undefined) {
throw new Error(error.message)
}
}
deinit() {
;(this.settingsApi as unknown) = undefined
;(this.userProvider as unknown) = undefined
}
}

View File

@@ -0,0 +1,41 @@
import { SettingData } from '@standardnotes/responses'
import {
OneDriveBackupFrequency,
MuteSignInEmailsOption,
MuteFailedCloudBackupsEmailsOption,
MuteFailedBackupsEmailsOption,
CloudProvider,
DropboxBackupFrequency,
EmailBackupFrequency,
GoogleDriveBackupFrequency,
ListedAuthorSecretsData,
LogSessionUserAgentOption,
SettingName,
} from '@standardnotes/settings'
type SettingType =
| CloudProvider
| DropboxBackupFrequency
| EmailBackupFrequency
| GoogleDriveBackupFrequency
| ListedAuthorSecretsData
| LogSessionUserAgentOption
| MuteFailedBackupsEmailsOption
| MuteFailedCloudBackupsEmailsOption
| MuteSignInEmailsOption
| OneDriveBackupFrequency
export class SettingsList {
private map: Partial<Record<SettingName, SettingData>> = {}
constructor(settings: SettingData[]) {
for (const setting of settings) {
this.map[setting.name as SettingName] = setting
}
}
getSettingValue<T = SettingType, D = SettingType>(setting: SettingName, defaultValue: D): T {
const settingData = this.map[setting]
return (settingData?.value as unknown as T) || (defaultValue as unknown as T)
}
}

View File

@@ -0,0 +1,24 @@
import {
DeleteSettingResponse,
GetSettingResponse,
ListSettingsResponse,
UpdateSettingResponse,
} from '@standardnotes/responses'
import { UuidString } from '@Lib/Types/UuidString'
export interface SettingsServerInterface {
listSettings(userUuid: UuidString): Promise<ListSettingsResponse>
updateSetting(
userUuid: UuidString,
settingName: string,
settingValue: string,
sensitive: boolean,
): Promise<UpdateSettingResponse>
getSetting(userUuid: UuidString, settingName: string): Promise<GetSettingResponse>
getSubscriptionSetting(userUuid: UuidString, settingName: string): Promise<GetSettingResponse>
deleteSetting(userUuid: UuidString, settingName: string): Promise<DeleteSettingResponse>
}

View File

@@ -0,0 +1 @@
export * from './SNSettingsService'