chore(web): put sign-in email notifications setting under paywall (#2249)
* chore: upgrade setting names to value objects * chore(web): put sign-in email notifications setting under paywall * chore: fix using setting name value objects in mocha tests * chore: fix wording on email notifications titles
This commit is contained in:
@@ -8,7 +8,9 @@ export class GetRecoveryCodes implements UseCaseInterface<string> {
|
||||
constructor(private authClient: AuthClientInterface, private settingsClient: SettingsClientInterface) {}
|
||||
|
||||
async execute(): Promise<Result<string>> {
|
||||
const existingRecoveryCodes = await this.settingsClient.getSetting(SettingName.RecoveryCodes)
|
||||
const existingRecoveryCodes = await this.settingsClient.getSetting(
|
||||
SettingName.create(SettingName.NAMES.RecoveryCodes).getValue(),
|
||||
)
|
||||
if (existingRecoveryCodes !== undefined) {
|
||||
return Result.ok(existingRecoveryCodes)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { FeatureDescription } from '@standardnotes/features'
|
||||
import { joinPaths } from '@standardnotes/utils'
|
||||
import { SettingName, SubscriptionSettingName } from '@standardnotes/settings'
|
||||
import {
|
||||
AbstractService,
|
||||
ApiServiceInterface,
|
||||
@@ -568,31 +567,25 @@ export class SNApiService
|
||||
})
|
||||
}
|
||||
|
||||
async getSetting(userUuid: UuidString, settingName: SettingName): Promise<HttpResponse<GetSettingResponse>> {
|
||||
async getSetting(userUuid: UuidString, settingName: string): Promise<HttpResponse<GetSettingResponse>> {
|
||||
return await this.tokenRefreshableRequest<GetSettingResponse>({
|
||||
verb: HttpVerb.Get,
|
||||
url: joinPaths(this.host, Paths.v1.setting(userUuid, settingName.toLowerCase() as SettingName)),
|
||||
url: joinPaths(this.host, Paths.v1.setting(userUuid, settingName.toLowerCase())),
|
||||
authentication: this.getSessionAccessToken(),
|
||||
fallbackErrorMessage: API_MESSAGE_FAILED_GET_SETTINGS,
|
||||
})
|
||||
}
|
||||
|
||||
async getSubscriptionSetting(
|
||||
userUuid: UuidString,
|
||||
settingName: SubscriptionSettingName,
|
||||
): Promise<HttpResponse<GetSettingResponse>> {
|
||||
async getSubscriptionSetting(userUuid: UuidString, settingName: string): Promise<HttpResponse<GetSettingResponse>> {
|
||||
return await this.tokenRefreshableRequest<GetSettingResponse>({
|
||||
verb: HttpVerb.Get,
|
||||
url: joinPaths(
|
||||
this.host,
|
||||
Paths.v1.subscriptionSetting(userUuid, settingName.toLowerCase() as SubscriptionSettingName),
|
||||
),
|
||||
url: joinPaths(this.host, Paths.v1.subscriptionSetting(userUuid, settingName.toLowerCase())),
|
||||
authentication: this.getSessionAccessToken(),
|
||||
fallbackErrorMessage: API_MESSAGE_FAILED_GET_SETTINGS,
|
||||
})
|
||||
}
|
||||
|
||||
async deleteSetting(userUuid: UuidString, settingName: SettingName): Promise<HttpResponse<DeleteSettingResponse>> {
|
||||
async deleteSetting(userUuid: UuidString, settingName: string): Promise<HttpResponse<DeleteSettingResponse>> {
|
||||
return this.tokenRefreshableRequest<DeleteSettingResponse>({
|
||||
verb: HttpVerb.Delete,
|
||||
url: joinPaths(this.host, Paths.v1.setting(userUuid, settingName)),
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { SettingName, SubscriptionSettingName } from '@standardnotes/settings'
|
||||
|
||||
const FilesPaths = {
|
||||
closeUploadSession: '/v1/files/upload/close-session',
|
||||
createFileValetToken: '/v1/files/valet-tokens',
|
||||
@@ -31,8 +29,8 @@ const ItemsPaths = {
|
||||
|
||||
const SettingsPaths = {
|
||||
settings: (userUuid: string) => `/v1/users/${userUuid}/settings`,
|
||||
setting: (userUuid: string, settingName: SettingName) => `/v1/users/${userUuid}/settings/${settingName}`,
|
||||
subscriptionSetting: (userUuid: string, settingName: SubscriptionSettingName) =>
|
||||
setting: (userUuid: string, settingName: string) => `/v1/users/${userUuid}/settings/${settingName}`,
|
||||
subscriptionSetting: (userUuid: string, settingName: string) =>
|
||||
`/v1/users/${userUuid}/subscription-settings/${settingName}`,
|
||||
}
|
||||
|
||||
|
||||
@@ -725,7 +725,7 @@ describe('featuresService', () => {
|
||||
|
||||
const featuresService = createService()
|
||||
await featuresService.migrateFeatureRepoToUserSetting([extensionRepoItem])
|
||||
expect(settingsService.updateSetting).toHaveBeenCalledWith(SettingName.ExtensionKey, extensionKey, true)
|
||||
expect(settingsService.updateSetting).toHaveBeenCalledWith(SettingName.create(SettingName.NAMES.ExtensionKey).getValue(), extensionKey, true)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -341,7 +341,11 @@ export class SNFeaturesService
|
||||
const userKeyMatch = repoUrl.match(/\w{32,64}/)
|
||||
if (userKeyMatch && userKeyMatch.length > 0) {
|
||||
const userKey = userKeyMatch[0]
|
||||
await this.settingsService.updateSetting(SettingName.ExtensionKey, userKey, true)
|
||||
await this.settingsService.updateSetting(
|
||||
SettingName.create(SettingName.NAMES.ExtensionKey).getValue(),
|
||||
userKey,
|
||||
true,
|
||||
)
|
||||
await this.itemManager.changeFeatureRepo(item, (m) => {
|
||||
m.migratedToUserSetting = true
|
||||
})
|
||||
|
||||
@@ -108,7 +108,9 @@ export class ListedService extends AbstractService implements ListedClientInterf
|
||||
}
|
||||
|
||||
private async getSettingsBasedListedAccounts(): Promise<ListedAccount[]> {
|
||||
const response = await this.settingsService.getSetting(SettingName.ListedAuthorSecrets)
|
||||
const response = await this.settingsService.getSetting(
|
||||
SettingName.create(SettingName.NAMES.ListedAuthorSecrets).getValue(),
|
||||
)
|
||||
if (!response) {
|
||||
return []
|
||||
}
|
||||
|
||||
@@ -16,11 +16,17 @@ export class SNMfaService extends AbstractService {
|
||||
}
|
||||
|
||||
private async saveMfaSetting(secret: string): Promise<void> {
|
||||
return await this.settingsService.updateSetting(SettingName.MfaSecret, secret, true)
|
||||
return await this.settingsService.updateSetting(
|
||||
SettingName.create(SettingName.NAMES.MfaSecret).getValue(),
|
||||
secret,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
async isMfaActivated(): Promise<boolean> {
|
||||
const mfaSetting = await this.settingsService.getDoesSensitiveSettingExist(SettingName.MfaSecret)
|
||||
const mfaSetting = await this.settingsService.getDoesSensitiveSettingExist(
|
||||
SettingName.create(SettingName.NAMES.MfaSecret).getValue(),
|
||||
)
|
||||
return mfaSetting != false
|
||||
}
|
||||
|
||||
@@ -43,7 +49,7 @@ export class SNMfaService extends AbstractService {
|
||||
}
|
||||
|
||||
async disableMfa(): Promise<void> {
|
||||
return await this.settingsService.deleteSetting(SettingName.MfaSecret)
|
||||
return await this.settingsService.deleteSetting(SettingName.create(SettingName.NAMES.MfaSecret).getValue())
|
||||
}
|
||||
|
||||
override deinit(): void {
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import { SNApiService } from '../Api/ApiService'
|
||||
import { SettingsGateway } from './SettingsGateway'
|
||||
import { SNSessionManager } from '../Session/SessionManager'
|
||||
import {
|
||||
CloudProvider,
|
||||
EmailBackupFrequency,
|
||||
SettingName,
|
||||
SensitiveSettingName,
|
||||
SubscriptionSettingName,
|
||||
} from '@standardnotes/settings'
|
||||
import { CloudProvider, EmailBackupFrequency, SettingName } from '@standardnotes/settings'
|
||||
import { ExtensionsServerURL } from '@Lib/Hosts'
|
||||
import { AbstractService, InternalEventBusInterface } from '@standardnotes/services'
|
||||
import { SettingsClientInterface } from './SettingsClientInterface'
|
||||
@@ -46,7 +40,7 @@ export class SNSettingsService extends AbstractService implements SettingsClient
|
||||
return this.provider.getSetting(name)
|
||||
}
|
||||
|
||||
async getSubscriptionSetting(name: SubscriptionSettingName) {
|
||||
async getSubscriptionSetting(name: SettingName) {
|
||||
return this.provider.getSubscriptionSetting(name)
|
||||
}
|
||||
|
||||
@@ -54,7 +48,7 @@ export class SNSettingsService extends AbstractService implements SettingsClient
|
||||
return this.provider.updateSetting(name, payload, sensitive)
|
||||
}
|
||||
|
||||
async getDoesSensitiveSettingExist(name: SensitiveSettingName) {
|
||||
async getDoesSensitiveSettingExist(name: SettingName) {
|
||||
return this.provider.getDoesSensitiveSettingExist(name)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SettingName, SensitiveSettingName, EmailBackupFrequency } from '@standardnotes/settings'
|
||||
import { SettingName, EmailBackupFrequency } from '@standardnotes/settings'
|
||||
import { SettingsList } from './SettingsList'
|
||||
|
||||
export interface SettingsClientInterface {
|
||||
@@ -6,7 +6,7 @@ export interface SettingsClientInterface {
|
||||
|
||||
getSetting(name: SettingName): Promise<string | undefined>
|
||||
|
||||
getDoesSensitiveSettingExist(name: SensitiveSettingName): Promise<boolean>
|
||||
getDoesSensitiveSettingExist(name: SettingName): Promise<boolean>
|
||||
|
||||
updateSetting(name: SettingName, payload: string, sensitive?: boolean): Promise<void>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { SettingsList } from './SettingsList'
|
||||
import { SettingName, SensitiveSettingName, SubscriptionSettingName } from '@standardnotes/settings'
|
||||
import { SettingName } from '@standardnotes/settings'
|
||||
import { API_MESSAGE_INVALID_SESSION } from '@standardnotes/services'
|
||||
import { HttpStatusCode, isErrorResponse, User } from '@standardnotes/responses'
|
||||
import { SettingsServerInterface } from './SettingsServerInterface'
|
||||
@@ -46,7 +46,7 @@ export class SettingsGateway {
|
||||
}
|
||||
|
||||
async getSetting(name: SettingName): Promise<string | undefined> {
|
||||
const response = await this.settingsApi.getSetting(this.userUuid, name)
|
||||
const response = await this.settingsApi.getSetting(this.userUuid, name.value)
|
||||
|
||||
if (response.status === HttpStatusCode.BadRequest) {
|
||||
return undefined
|
||||
@@ -59,8 +59,12 @@ export class SettingsGateway {
|
||||
return response?.data?.setting?.value ?? undefined
|
||||
}
|
||||
|
||||
async getSubscriptionSetting(name: SubscriptionSettingName): Promise<string | undefined> {
|
||||
const response = await this.settingsApi.getSubscriptionSetting(this.userUuid, name)
|
||||
async getSubscriptionSetting(name: SettingName): Promise<string | undefined> {
|
||||
if (!name.isASubscriptionSetting()) {
|
||||
throw new Error(`Setting ${name.value} is not a subscription setting`)
|
||||
}
|
||||
|
||||
const response = await this.settingsApi.getSubscriptionSetting(this.userUuid, name.value)
|
||||
|
||||
if (response.status === HttpStatusCode.BadRequest) {
|
||||
return undefined
|
||||
@@ -73,8 +77,12 @@ export class SettingsGateway {
|
||||
return response?.data?.setting?.value ?? undefined
|
||||
}
|
||||
|
||||
async getDoesSensitiveSettingExist(name: SensitiveSettingName): Promise<boolean> {
|
||||
const response = await this.settingsApi.getSetting(this.userUuid, name)
|
||||
async getDoesSensitiveSettingExist(name: SettingName): Promise<boolean> {
|
||||
if (!name.isSensitive()) {
|
||||
throw new Error(`Setting ${name.value} is not sensitive`)
|
||||
}
|
||||
|
||||
const response = await this.settingsApi.getSetting(this.userUuid, name.value)
|
||||
|
||||
if (response.status === HttpStatusCode.BadRequest) {
|
||||
return false
|
||||
@@ -88,14 +96,14 @@ export class SettingsGateway {
|
||||
}
|
||||
|
||||
async updateSetting(name: SettingName, payload: string, sensitive: boolean): Promise<void> {
|
||||
const response = await this.settingsApi.updateSetting(this.userUuid, name, payload, sensitive)
|
||||
const response = await this.settingsApi.updateSetting(this.userUuid, name.value, payload, sensitive)
|
||||
if (isErrorResponse(response)) {
|
||||
throw new Error(response.data?.error.message)
|
||||
}
|
||||
}
|
||||
|
||||
async deleteSetting(name: SettingName): Promise<void> {
|
||||
const response = await this.settingsApi.deleteSetting(this.userUuid, name)
|
||||
const response = await this.settingsApi.deleteSetting(this.userUuid, name.value)
|
||||
if (isErrorResponse(response)) {
|
||||
throw new Error(response.data?.error.message)
|
||||
}
|
||||
|
||||
@@ -28,16 +28,16 @@ type SettingType =
|
||||
| OneDriveBackupFrequency
|
||||
|
||||
export class SettingsList {
|
||||
private map: Partial<Record<SettingName, SettingData>> = {}
|
||||
private map: Partial<Record<string, SettingData>> = {}
|
||||
|
||||
constructor(settings: SettingData[]) {
|
||||
for (const setting of settings) {
|
||||
this.map[setting.name as SettingName] = setting
|
||||
this.map[setting.name] = setting
|
||||
}
|
||||
}
|
||||
|
||||
getSettingValue<T = SettingType, D = SettingType>(setting: SettingName, defaultValue: D): T {
|
||||
const settingData = this.map[setting]
|
||||
getSettingValue<T = SettingType, D = SettingType>(settingName: SettingName, defaultValue: D): T {
|
||||
const settingData = this.map[settingName.value]
|
||||
return (settingData?.value as unknown as T) || (defaultValue as unknown as T)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user