refactor: application dependency management (#2363)

This commit is contained in:
Mo
2023-07-23 15:54:31 -05:00
committed by GitHub
parent e698b1c990
commit a77535456c
299 changed files with 7415 additions and 4890 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,147 @@
export const TYPES = {
// System
DeviceInterface: Symbol.for('DeviceInterface'),
AlertService: Symbol.for('AlertService'),
Crypto: Symbol.for('Crypto'),
// Services
InternalEventBus: Symbol.for('InternalEventBus'),
PayloadManager: Symbol.for('PayloadManager'),
ItemManager: Symbol.for('ItemManager'),
MutatorService: Symbol.for('MutatorService'),
DiskStorageService: Symbol.for('DiskStorageService'),
UserEventService: Symbol.for('UserEventService'),
InMemoryStore: Symbol.for('InMemoryStore'),
KeySystemKeyManager: Symbol.for('KeySystemKeyManager'),
EncryptionService: Symbol.for('EncryptionService'),
ChallengeService: Symbol.for('ChallengeService'),
DeprecatedHttpService: Symbol.for('DeprecatedHttpService'),
HttpService: Symbol.for('HttpService'),
LegacyApiService: Symbol.for('LegacyApiService'),
UserServer: Symbol.for('UserServer'),
UserRequestServer: Symbol.for('UserRequestServer'),
UserApiService: Symbol.for('UserApiService'),
SubscriptionServer: Symbol.for('SubscriptionServer'),
SubscriptionApiService: Symbol.for('SubscriptionApiService'),
WebSocketServer: Symbol.for('WebSocketServer'),
WebSocketApiService: Symbol.for('WebSocketApiService'),
WebSocketsService: Symbol.for('WebSocketsService'),
SessionManager: Symbol.for('SessionManager'),
SubscriptionManager: Symbol.for('SubscriptionManager'),
HistoryManager: Symbol.for('HistoryManager'),
SyncService: Symbol.for('SyncService'),
ProtectionService: Symbol.for('ProtectionService'),
UserService: Symbol.for('UserService'),
KeyRecoveryService: Symbol.for('KeyRecoveryService'),
SingletonManager: Symbol.for('SingletonManager'),
PreferencesService: Symbol.for('PreferencesService'),
SettingsService: Symbol.for('SettingsService'),
FeaturesService: Symbol.for('FeaturesService'),
ComponentManager: Symbol.for('ComponentManager'),
MfaService: Symbol.for('MfaService'),
StatusService: Symbol.for('StatusService'),
MigrationService: Symbol.for('MigrationService'),
FileService: Symbol.for('FileService'),
IntegrityService: Symbol.for('IntegrityService'),
ListedService: Symbol.for('ListedService'),
ActionsService: Symbol.for('ActionsService'),
AuthenticatorApiService: Symbol.for('AuthenticatorApiService'),
AuthenticatorManager: Symbol.for('AuthenticatorManager'),
AuthApiService: Symbol.for('AuthApiService'),
AuthManager: Symbol.for('AuthManager'),
RevisionApiService: Symbol.for('RevisionApiService'),
RevisionManager: Symbol.for('RevisionManager'),
ContactService: Symbol.for('ContactService'),
VaultService: Symbol.for('VaultService'),
SharedVaultService: Symbol.for('SharedVaultService'),
AsymmetricMessageService: Symbol.for('AsymmetricMessageService'),
SelfContactManager: Symbol.for('SelfContactManager'),
EncryptionOperators: Symbol.for('EncryptionOperators'),
RootKeyManager: Symbol.for('RootKeyManager'),
ItemsEncryptionService: Symbol.for('ItemsEncryptionService'),
// Servers
RevisionServer: Symbol.for('RevisionServer'),
AuthenticatorServer: Symbol.for('AuthenticatorServer'),
AuthServer: Symbol.for('AuthServer'),
SharedVaultInvitesServer: Symbol.for('SharedVaultInvitesServer'),
SharedVaultServer: Symbol.for('SharedVaultServer'),
SharedVaultUsersServer: Symbol.for('SharedVaultUsersServer'),
AsymmetricMessageServer: Symbol.for('AsymmetricMessageServer'),
// Desktop Services
FilesBackupService: Symbol.for('FilesBackupService'),
HomeServerService: Symbol.for('HomeServerService'),
// Usecases
SignInWithRecoveryCodes: Symbol.for('SignInWithRecoveryCodes'),
GetRecoveryCodes: Symbol.for('GetRecoveryCodes'),
AddAuthenticator: Symbol.for('AddAuthenticator'),
ListAuthenticators: Symbol.for('ListAuthenticators'),
DeleteAuthenticator: Symbol.for('DeleteAuthenticator'),
GetAuthenticatorAuthenticationOptions: Symbol.for('GetAuthenticatorAuthenticationOptions'),
GetAuthenticatorAuthenticationResponse: Symbol.for('GetAuthenticatorAuthenticationResponse'),
ListRevisions: Symbol.for('ListRevisions'),
GetRevision: Symbol.for('GetRevision'),
DeleteRevision: Symbol.for('DeleteRevision'),
ImportDataUseCase: Symbol.for('ImportDataUseCase'),
RemoveItemsLocally: Symbol.for('RemoveItemsLocally'),
FindContact: Symbol.for('FindContact'),
GetAllContacts: Symbol.for('GetAllContacts'),
CreateOrEditContact: Symbol.for('CreateOrEditContact'),
EditContact: Symbol.for('EditContact'),
ValidateItemSigner: Symbol.for('ValidateItemSigner'),
GetVault: Symbol.for('GetVault'),
ChangeVaultKeyOptions: Symbol.for('ChangeVaultKeyOptions'),
MoveItemsToVault: Symbol.for('MoveItemsToVault'),
CreateVault: Symbol.for('CreateVault'),
RemoveItemFromVault: Symbol.for('RemoveItemFromVault'),
DeleteVault: Symbol.for('DeleteVault'),
RotateVaultKey: Symbol.for('RotateVaultKey'),
CreateSharedVault: Symbol.for('CreateSharedVault'),
HandleKeyPairChange: Symbol.for('HandleKeyPairChange'),
NotifyVaultUsersOfKeyRotation: Symbol.for('NotifyVaultUsersOfKeyRotation'),
SendVaultDataChangedMessage: Symbol.for('SendVaultDataChangedMessage'),
SendVaultKeyChangedMessage: Symbol.for('SendVaultKeyChangedMessage'),
GetTrustedPayload: Symbol.for('GetTrustedPayload'),
GetUntrustedPayload: Symbol.for('GetUntrustedPayload'),
GetVaultContacts: Symbol.for('GetVaultContacts'),
AcceptVaultInvite: Symbol.for('AcceptVaultInvite'),
InviteToVault: Symbol.for('InviteToVault'),
LeaveVault: Symbol.for('LeaveVault'),
DeleteThirdPartyVault: Symbol.for('DeleteThirdPartyVault'),
ShareContactWithVault: Symbol.for('ShareContactWithVault'),
ConvertToSharedVault: Symbol.for('ConvertToSharedVault'),
DeleteSharedVault: Symbol.for('DeleteSharedVault'),
RemoveVaultMember: Symbol.for('RemoveVaultMember'),
GetVaultUsers: Symbol.for('GetSharedVaultUsers'),
ResendAllMessages: Symbol.for('ResendAllMessages'),
ReuploadAllInvites: Symbol.for('ReuploadAllInvites'),
ReuploadInvite: Symbol.for('ReuploadInvite'),
GetInboundMessages: Symbol.for('GetInboundMessages'),
GetOutboundMessages: Symbol.for('GetOutboundMessages'),
HandleRootKeyChangedMessage: Symbol.for('HandleRootKeyChangedMessage'),
ProcessAcceptedVaultInvite: Symbol.for('ProcessAcceptedVaultInvite'),
ResendMessage: Symbol.for('ResendMessage'),
SendMessage: Symbol.for('SendMessage'),
SendOwnContactChangeMessage: Symbol.for('SendOwnContactChangeMessage'),
DecryptMessage: Symbol.for('DecryptMessage'),
DecryptOwnMessage: Symbol.for('DecryptOwnMessage'),
EncryptMessage: Symbol.for('EncryptMessage'),
GetMessageAdditionalData: Symbol.for('GetMessageAdditionalData'),
SendVaultInvite: Symbol.for('SendVaultInvite'),
ReplaceContactData: Symbol.for('ReplaceContactData'),
CreateNewDefaultItemsKey: Symbol.for('CreateNewDefaultItemsKey'),
CreateNewItemsKeyWithRollback: Symbol.for('CreateNewItemsKeyWithRollback'),
FindDefaultItemsKey: Symbol.for('FindDefaultItemsKey'),
DecryptErroredTypeAPayloads: Symbol.for('DecryptErroredTypeAPayloads'),
DecryptTypeAPayload: Symbol.for('DecryptTypeAPayload'),
DecryptTypeAPayloadWithKeyLookup: Symbol.for('DecryptTypeAPayloadWithKeyLookup'),
EncryptTypeAPayload: Symbol.for('EncryptTypeAPayload'),
EncryptTypeAPayloadWithKeyLookup: Symbol.for('EncryptTypeAPayloadWithKeyLookup'),
DecryptBackupFile: Symbol.for('DecryptBackupFile'),
// Mappers
SessionStorageMapper: Symbol.for('SessionStorageMapper'),
LegacySessionStorageMapper: Symbol.for('LegacySessionStorageMapper'),
}

View File

@@ -0,0 +1,14 @@
export function isDeinitable(service: unknown): service is { deinit(): void } {
if (!service) {
throw new Error('Service is undefined')
}
return typeof (service as { deinit(): void }).deinit === 'function'
}
export function canBlockDeinit(service: unknown): service is { blockDeinit(): Promise<void> } {
if (!service) {
throw new Error('Service is undefined')
}
return typeof (service as { blockDeinit(): Promise<void> }).blockDeinit === 'function'
}

View File

@@ -1,6 +1,5 @@
import { EncryptedPayloadInterface, HistoryEntry } from '@standardnotes/models'
import { EncryptionProviderInterface } from '@standardnotes/encryption'
import { RevisionClientInterface } from '@standardnotes/services'
import { EncryptionProviderInterface, RevisionClientInterface } from '@standardnotes/services'
jest.mock('@standardnotes/models', () => {
const original = jest.requireActual('@standardnotes/models')
@@ -32,11 +31,13 @@ describe('GetRevision', () => {
enc_item_key: 'foobar',
auth_hash: 'foobar',
created_at: '2021-01-01T00:00:00.000Z',
updated_at: '2021-01-01T00:00:00.000Z'
updated_at: '2021-01-01T00:00:00.000Z',
} as jest.Mocked<Revision>)
encryptionService = {} as jest.Mocked<EncryptionProviderInterface>
encryptionService.getEmbeddedPayloadAuthenticatedData = jest.fn().mockReturnValue({ u: '00000000-0000-0000-0000-000000000000' })
encryptionService.getEmbeddedPayloadAuthenticatedData = jest
.fn()
.mockReturnValue({ u: '00000000-0000-0000-0000-000000000000' })
const encryptedPayload = {
content: 'foobar',
} as jest.Mocked<EncryptedPayloadInterface>

View File

@@ -1,5 +1,5 @@
import { ServerItemResponse } from '@standardnotes/responses'
import { RevisionClientInterface } from '@standardnotes/services'
import { EncryptionProviderInterface, RevisionClientInterface } from '@standardnotes/services'
import { Result, UseCaseInterface, Uuid } from '@standardnotes/domain-core'
import {
EncryptedPayload,
@@ -9,7 +9,6 @@ import {
NoteContent,
PayloadTimestampDefaults,
} from '@standardnotes/models'
import { EncryptionProviderInterface } from '@standardnotes/encryption'
import { GetRevisionDTO } from './GetRevisionDTO'

View File

@@ -1,10 +1,10 @@
import {
AuthClientInterface,
EncryptionProviderInterface,
InternalEventBusInterface,
KeyValueStoreInterface,
SessionsClientInterface,
} from '@standardnotes/services'
import { EncryptionProviderInterface } from '@standardnotes/encryption'
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { AnyKeyParamsContent } from '@standardnotes/common'
import { DecryptedPayloadInterface, RootKeyContent, RootKeyInterface } from '@standardnotes/models'
@@ -20,14 +20,8 @@ describe('SignInWithRecoveryCodes', () => {
let sessionManager: SessionsClientInterface
let internalEventBus: InternalEventBusInterface
const createUseCase = () => new SignInWithRecoveryCodes(
authManager,
encryptionService,
inMemoryStore,
crypto,
sessionManager,
internalEventBus,
)
const createUseCase = () =>
new SignInWithRecoveryCodes(authManager, encryptionService, inMemoryStore, crypto, sessionManager, internalEventBus)
beforeEach(() => {
authManager = {} as jest.Mocked<AuthClientInterface>
@@ -54,12 +48,7 @@ describe('SignInWithRecoveryCodes', () => {
encryptionService.hasAccount = jest.fn()
encryptionService.computeRootKey = jest.fn().mockReturnValue(rootKey)
encryptionService.platformSupportsKeyDerivation = jest.fn().mockReturnValue(true)
encryptionService.supportedVersions = jest.fn().mockReturnValue([
'001',
'002',
'003',
'004',
])
encryptionService.supportedVersions = jest.fn().mockReturnValue(['001', '002', '003', '004'])
encryptionService.isVersionNewerThanLibraryVersion = jest.fn()
inMemoryStore = {} as jest.Mocked<KeyValueStoreInterface<string>>
@@ -82,7 +71,11 @@ describe('SignInWithRecoveryCodes', () => {
encryptionService.hasAccount = jest.fn().mockReturnValue(true)
const useCase = createUseCase()
const result = await useCase.execute({ recoveryCodes: 'recovery-codes', password: 'foobar', username: 'test@test.te' })
const result = await useCase.execute({
recoveryCodes: 'recovery-codes',
password: 'foobar',
username: 'test@test.te',
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toEqual('Tried to sign in when an account already exists.')
@@ -92,7 +85,11 @@ describe('SignInWithRecoveryCodes', () => {
authManager.recoveryKeyParams = jest.fn().mockReturnValue(false)
const useCase = createUseCase()
const result = await useCase.execute({ recoveryCodes: 'recovery-codes', password: 'foobar', username: 'test@test.te' })
const result = await useCase.execute({
recoveryCodes: 'recovery-codes',
password: 'foobar',
username: 'test@test.te',
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toEqual('Could not retrieve recovery key params')
@@ -102,10 +99,16 @@ describe('SignInWithRecoveryCodes', () => {
encryptionService.platformSupportsKeyDerivation = jest.fn().mockReturnValue(false)
const useCase = createUseCase()
const result = await useCase.execute({ recoveryCodes: 'recovery-codes', password: 'foobar', username: 'test@test.te' })
const result = await useCase.execute({
recoveryCodes: 'recovery-codes',
password: 'foobar',
username: 'test@test.te',
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toEqual('Your account was created on a platform with higher security capabilities than this browser supports. If we attempted to generate your login keys here, it would take hours. Please use a browser with more up to date security capabilities, like Google Chrome or Firefox, to log in.')
expect(result.getError()).toEqual(
'Your account was created on a platform with higher security capabilities than this browser supports. If we attempted to generate your login keys here, it would take hours. Please use a browser with more up to date security capabilities, like Google Chrome or Firefox, to log in.',
)
})
it('should fail if key params has unsupported version', async () => {
@@ -123,10 +126,16 @@ describe('SignInWithRecoveryCodes', () => {
encryptionService.platformSupportsKeyDerivation = jest.fn().mockReturnValue(false)
const useCase = createUseCase()
const result = await useCase.execute({ recoveryCodes: 'recovery-codes', password: 'foobar', username: 'test@test.te' })
const result = await useCase.execute({
recoveryCodes: 'recovery-codes',
password: 'foobar',
username: 'test@test.te',
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toEqual('This version of the application does not support your newer account type. Please upgrade to the latest version of Standard Notes to sign in.')
expect(result.getError()).toEqual(
'This version of the application does not support your newer account type. Please upgrade to the latest version of Standard Notes to sign in.',
)
})
it('should fail if key params has expired version', async () => {
@@ -144,17 +153,27 @@ describe('SignInWithRecoveryCodes', () => {
encryptionService.platformSupportsKeyDerivation = jest.fn().mockReturnValue(false)
const useCase = createUseCase()
const result = await useCase.execute({ recoveryCodes: 'recovery-codes', password: 'foobar', username: 'test@test.te' })
const result = await useCase.execute({
recoveryCodes: 'recovery-codes',
password: 'foobar',
username: 'test@test.te',
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toEqual('The protocol version associated with your account is outdated and no longer supported by this application. Please visit standardnotes.com/help/security for more information.')
expect(result.getError()).toEqual(
'The protocol version associated with your account is outdated and no longer supported by this application. Please visit standardnotes.com/help/security for more information.',
)
})
it('should fail if the sign in with recovery code fails', async () => {
authManager.signInWithRecoveryCodes = jest.fn().mockReturnValue(false)
const useCase = createUseCase()
const result = await useCase.execute({ recoveryCodes: 'recovery-codes', password: 'foobar', username: 'test@test.te' })
const result = await useCase.execute({
recoveryCodes: 'recovery-codes',
password: 'foobar',
username: 'test@test.te',
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toEqual('Could not sign in with recovery code')
@@ -168,11 +187,15 @@ describe('SignInWithRecoveryCodes', () => {
uuid: '1-2-3',
email: 'test@test.te',
protocolVersion: '004',
}
},
})
const useCase = createUseCase()
const result = await useCase.execute({ recoveryCodes: 'recovery-codes', password: 'foobar', username: 'test@test.te' })
const result = await useCase.execute({
recoveryCodes: 'recovery-codes',
password: 'foobar',
username: 'test@test.te',
})
expect(result.isFailed()).toBe(false)
})

View File

@@ -4,6 +4,7 @@ import {
AccountEvent,
AuthClientInterface,
EXPIRED_PROTOCOL_VERSION,
EncryptionProviderInterface,
InternalEventBusInterface,
InternalEventPublishStrategy,
KeyValueStoreInterface,
@@ -12,7 +13,7 @@ import {
UNSUPPORTED_KEY_DERIVATION,
UNSUPPORTED_PROTOCOL_VERSION,
} from '@standardnotes/services'
import { CreateAnyKeyParams, EncryptionProviderInterface, SNRootKey } from '@standardnotes/encryption'
import { CreateAnyKeyParams, SNRootKey } from '@standardnotes/encryption'
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { SignInWithRecoveryCodesDTO } from './SignInWithRecoveryCodesDTO'

View File

@@ -7,10 +7,10 @@ import {
MutatorClientInterface,
PreferenceServiceInterface,
} from '@standardnotes/services'
import { SNSessionManager } from '../Services/Session/SessionManager'
import { SessionManager } from '../Services/Session/SessionManager'
import { ApplicationIdentifier } from '@standardnotes/common'
import { ItemManager } from '@Lib/Services/Items/ItemManager'
import { ChallengeService, SNSingletonManager, SNFeaturesService, DiskStorageService } from '@Lib/Services'
import { ChallengeService, SingletonManager, FeaturesService, DiskStorageService } from '@Lib/Services'
import { LegacySession, MapperInterface } from '@standardnotes/domain-core'
export type MigrationServices = {
@@ -18,12 +18,12 @@ export type MigrationServices = {
deviceInterface: DeviceInterface
storageService: DiskStorageService
challengeService: ChallengeService
sessionManager: SNSessionManager
sessionManager: SessionManager
backups?: BackupServiceInterface
itemManager: ItemManager
mutator: MutatorClientInterface
singletonManager: SNSingletonManager
featuresService: SNFeaturesService
singletonManager: SingletonManager
featuresService: FeaturesService
preferences: PreferenceServiceInterface
environment: Environment
platform: Platform

View File

@@ -1,7 +1,6 @@
import { removeFromArray } from '@standardnotes/utils'
import { SNRootKey } from '@standardnotes/encryption'
import { ChallengeService } from '../Challenge'
import { ListedService } from '../Listed/ListedService'
import { ActionResponse, DeprecatedHttpResponse } from '@standardnotes/responses'
import { ItemManager } from '@Lib/Services/Items/ItemManager'
import {
@@ -21,8 +20,6 @@ import {
TransferPayload,
ItemContent,
} from '@standardnotes/models'
import { SNSyncService } from '../Sync/SyncService'
import { PayloadManager } from '../Payloads/PayloadManager'
import { DeprecatedHttpService } from '../Api/DeprecatedHttpService'
import {
AbstractService,
@@ -53,20 +50,17 @@ type PayloadRequestHandler = (uuid: string) => TransferPayload | undefined
* `post`: sends an item's data to a remote service. This is used for example by Listed
* to allow publishing a note to a user's blog.
*/
export class SNActionsService extends AbstractService {
export class ActionsService extends AbstractService {
private previousPasswords: string[] = []
private payloadRequestHandlers: PayloadRequestHandler[] = []
constructor(
private itemManager: ItemManager,
private alertService: AlertService,
public deviceInterface: DeviceInterface,
private device: DeviceInterface,
private httpService: DeprecatedHttpService,
private payloadManager: PayloadManager,
private encryptionService: EncryptionService,
private syncService: SNSyncService,
private challengeService: ChallengeService,
private listedService: ListedService,
protected override internalEventBus: InternalEventBusInterface,
) {
super(internalEventBus)
@@ -76,13 +70,10 @@ export class SNActionsService extends AbstractService {
public override deinit(): void {
;(this.itemManager as unknown) = undefined
;(this.alertService as unknown) = undefined
;(this.deviceInterface as unknown) = undefined
;(this.device as unknown) = undefined
;(this.httpService as unknown) = undefined
;(this.payloadManager as unknown) = undefined
;(this.listedService as unknown) = undefined
;(this.challengeService as unknown) = undefined
;(this.encryptionService as unknown) = undefined
;(this.syncService as unknown) = undefined
this.payloadRequestHandlers.length = 0
this.previousPasswords.length = 0
super.deinit()
@@ -323,7 +314,7 @@ export class SNActionsService extends AbstractService {
}
private handleShowAction(action: Action) {
void this.deviceInterface.openUrl(action.url)
void this.device.openUrl(action.url)
return {} as ActionResponse
}

View File

@@ -1,7 +1,7 @@
import { joinPaths } from '@standardnotes/utils'
import {
AbstractService,
ApiServiceInterface,
LegacyApiServiceInterface,
InternalEventBusInterface,
IntegrityApiInterface,
ItemsServerInterface,
@@ -86,10 +86,10 @@ const V0_API_VERSION = '20200115'
type InvalidSessionObserver = (revoked: boolean) => void
export class SNApiService
export class LegacyApiService
extends AbstractService<ApiServiceEvent, ApiServiceEventData>
implements
ApiServiceInterface,
LegacyApiServiceInterface,
FilesApiInterface,
IntegrityApiInterface,
ItemsServerInterface,

View File

@@ -2,7 +2,7 @@ import { InternalEventBusInterface } from '@standardnotes/services'
import { WebSocketApiServiceInterface } from '@standardnotes/api'
import { StorageKey, DiskStorageService } from '@Lib/index'
import { SNWebSocketsService } from './WebsocketsService'
import { WebSocketsService } from './WebsocketsService'
describe('webSocketsService', () => {
const webSocketUrl = ''
@@ -12,7 +12,7 @@ describe('webSocketsService', () => {
let internalEventBus: InternalEventBusInterface
const createService = () => {
return new SNWebSocketsService(storageService, webSocketUrl, webSocketApiService, internalEventBus)
return new WebSocketsService(storageService, webSocketUrl, webSocketApiService, internalEventBus)
}
beforeEach(() => {

View File

@@ -9,7 +9,7 @@ import {
import { WebSocketApiServiceInterface } from '@standardnotes/api'
import { WebSocketsServiceEvent } from './WebSocketsServiceEvent'
export class SNWebSocketsService extends AbstractService<WebSocketsServiceEvent, UserRolesChangedEvent> {
export class WebSocketsService extends AbstractService<WebSocketsServiceEvent, UserRolesChangedEvent> {
private webSocket?: WebSocket
constructor(

View File

@@ -158,7 +158,7 @@ export class ChallengeService extends AbstractService implements ChallengeServic
return { wrappingKey }
}
public isPasscodeLocked() {
public isPasscodeLocked(): Promise<boolean> {
return this.encryptionService.isPasscodeLocked()
}
@@ -260,7 +260,7 @@ export class ChallengeService extends AbstractService implements ChallengeServic
delete this.challengeOperations[challenge.id]
}
public cancelChallenge(challenge: Challenge) {
public cancelChallenge(challenge: Challenge): void {
const operation = this.challengeOperations[challenge.id]
operation.cancel()
@@ -274,7 +274,7 @@ export class ChallengeService extends AbstractService implements ChallengeServic
this.deleteChallengeOperation(operation)
}
public async submitValuesForChallenge(challenge: Challenge, values: ChallengeValue[]) {
public async submitValuesForChallenge(challenge: Challenge, values: ChallengeValue[]): Promise<void> {
if (values.length === 0) {
throw Error('Attempting to submit 0 values for challenge')
}

View File

@@ -10,14 +10,14 @@ import {
PreferenceServiceInterface,
} from '@standardnotes/services'
import { ItemManager } from '@Lib/Services/Items/ItemManager'
import { SNFeaturesService } from '@Lib/Services/Features/FeaturesService'
import { FeaturesService } from '@Lib/Services/Features/FeaturesService'
import { SNComponentManager } from './ComponentManager'
import { SNSyncService } from '../Sync/SyncService'
import { SyncService } from '../Sync/SyncService'
describe('featuresService', () => {
let items: ItemManagerInterface
let mutator: MutatorClientInterface
let features: SNFeaturesService
let features: FeaturesService
let alerts: AlertService
let sync: SyncServiceInterface
let prefs: PreferenceServiceInterface
@@ -47,7 +47,7 @@ describe('featuresService', () => {
attachEvent: jest.fn(),
} as unknown as Window & typeof globalThis
sync = {} as jest.Mocked<SNSyncService>
sync = {} as jest.Mocked<SyncService>
sync.sync = jest.fn()
items = {} as jest.Mocked<ItemManager>
@@ -61,7 +61,7 @@ describe('featuresService', () => {
mutator.changeItem = jest.fn()
mutator.changeFeatureRepo = jest.fn()
features = {} as jest.Mocked<SNFeaturesService>
features = {} as jest.Mocked<FeaturesService>
prefs = {} as jest.Mocked<SNPreferencesService>
prefs.addEventObserver = jest.fn()

View File

@@ -1,4 +1,4 @@
import { SNFeaturesService } from '@Lib/Services/Features/FeaturesService'
import { FeaturesService } from '@Lib/Services/Features/FeaturesService'
import { ContentType } from '@standardnotes/domain-core'
import {
ActionObserver,
@@ -94,7 +94,7 @@ export class SNComponentManager
private items: ItemManagerInterface,
private mutator: MutatorClientInterface,
private sync: SyncServiceInterface,
private features: SNFeaturesService,
private features: FeaturesService,
private preferences: PreferenceServiceInterface,
protected alerts: AlertService,
private environment: Environment,

View File

@@ -11,7 +11,7 @@ import {
ItemManagerInterface,
SyncServiceInterface,
} from '@standardnotes/services'
import { SNFeaturesService } from '@Lib/Services'
import { FeaturesService } from '@Lib/Services'
import {
ActionObserver,
ComponentEventObserver,
@@ -100,7 +100,7 @@ export class ComponentViewer implements ComponentViewerInterface {
sync: SyncServiceInterface
alerts: AlertService
preferences: PreferenceServiceInterface
features: SNFeaturesService
features: FeaturesService
},
private options: {
item: ComponentViewerItem

View File

@@ -1,15 +1,15 @@
import { ItemInterface, SNFeatureRepo } from '@standardnotes/models'
import { SNSyncService } from '../Sync/SyncService'
import { SyncService } from '../Sync/SyncService'
import { SettingName } from '@standardnotes/settings'
import { SNFeaturesService } from '@Lib/Services/Features'
import { FeaturesService } from '@Lib/Services/Features'
import { RoleName, ContentType } from '@standardnotes/domain-core'
import { FeatureIdentifier, GetFeatures } from '@standardnotes/features'
import { SNWebSocketsService } from '../Api/WebsocketsService'
import { SNSettingsService } from '../Settings'
import { WebSocketsService } from '../Api/WebsocketsService'
import { SettingsService } from '../Settings'
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
import {
AlertService,
ApiServiceInterface,
LegacyApiServiceInterface,
FeaturesEvent,
FeatureStatus,
InternalEventBusInterface,
@@ -23,7 +23,7 @@ import {
UserClientInterface,
UserService,
} from '@standardnotes/services'
import { SNApiService, SNSessionManager } from '../Api'
import { LegacyApiService, SessionManager } from '../Api'
import { ItemManager } from '../Items'
import { DiskStorageService } from '../Storage/DiskStorageService'
import { SettingsClientInterface } from '../Settings/SettingsClientInterface'
@@ -33,8 +33,8 @@ describe('FeaturesService', () => {
let itemManager: ItemManagerInterface
let mutator: MutatorClientInterface
let subscriptions: SubscriptionManagerInterface
let apiService: ApiServiceInterface
let webSocketsService: SNWebSocketsService
let apiService: LegacyApiServiceInterface
let webSocketsService: WebSocketsService
let settingsService: SettingsClientInterface
let userService: UserClientInterface
let syncService: SyncServiceInterface
@@ -46,7 +46,7 @@ describe('FeaturesService', () => {
let internalEventBus: InternalEventBusInterface
const createService = () => {
return new SNFeaturesService(
return new FeaturesService(
storageService,
itemManager,
mutator,
@@ -72,7 +72,7 @@ describe('FeaturesService', () => {
storageService.setValue = jest.fn()
storageService.getValue = jest.fn()
apiService = {} as jest.Mocked<SNApiService>
apiService = {} as jest.Mocked<LegacyApiService>
apiService.addEventObserver = jest.fn()
apiService.isThirdPartyHostUsed = jest.fn().mockReturnValue(false)
@@ -92,23 +92,23 @@ describe('FeaturesService', () => {
subscriptions.getOnlineSubscription = jest.fn()
subscriptions.addEventObserver = jest.fn()
webSocketsService = {} as jest.Mocked<SNWebSocketsService>
webSocketsService = {} as jest.Mocked<WebSocketsService>
webSocketsService.addEventObserver = jest.fn()
settingsService = {} as jest.Mocked<SNSettingsService>
settingsService = {} as jest.Mocked<SettingsService>
settingsService.updateSetting = jest.fn()
userService = {} as jest.Mocked<UserService>
userService.addEventObserver = jest.fn()
syncService = {} as jest.Mocked<SNSyncService>
syncService = {} as jest.Mocked<SyncService>
syncService.sync = jest.fn()
alertService = {} as jest.Mocked<AlertService>
alertService.confirm = jest.fn().mockReturnValue(true)
alertService.alert = jest.fn()
sessionManager = {} as jest.Mocked<SNSessionManager>
sessionManager = {} as jest.Mocked<SessionManager>
sessionManager.isSignedIntoFirstPartyServer = jest.fn()
sessionManager.getUser = jest.fn()

View File

@@ -4,7 +4,7 @@ import { ClientDisplayableError } from '@standardnotes/responses'
import { RoleName, ContentType } from '@standardnotes/domain-core'
import { PROD_OFFLINE_FEATURES_URL } from '../../Hosts'
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { SNWebSocketsService } from '../Api/WebsocketsService'
import { WebSocketsService } from '../Api/WebsocketsService'
import { WebSocketsServiceEvent } from '../Api/WebSocketsServiceEvent'
import { TRUSTED_CUSTOM_EXTENSIONS_HOSTS, TRUSTED_FEATURE_HOSTS } from '@Lib/Hosts'
import { UserRolesChangedEvent } from '@standardnotes/domain-events'
@@ -39,7 +39,7 @@ import {
StorageKey,
MutatorClientInterface,
StorageServiceInterface,
ApiServiceInterface,
LegacyApiServiceInterface,
ItemManagerInterface,
SyncServiceInterface,
SessionsClientInterface,
@@ -47,6 +47,8 @@ import {
SubscriptionManagerInterface,
AccountEvent,
SubscriptionManagerEvent,
ApplicationEvent,
ApplicationStageChangedEventPayload,
} from '@standardnotes/services'
import { DownloadRemoteThirdPartyFeatureUseCase } from './UseCase/DownloadRemoteThirdPartyFeature'
@@ -56,7 +58,7 @@ import { SettingsClientInterface } from '../Settings/SettingsClientInterface'
type GetOfflineSubscriptionDetailsResponse = OfflineSubscriptionEntitlements | ClientDisplayableError
export class SNFeaturesService
export class FeaturesService
extends AbstractService<FeaturesEvent>
implements FeaturesClientInterface, InternalEventHandlerInterface
{
@@ -71,8 +73,8 @@ export class SNFeaturesService
private items: ItemManagerInterface,
private mutator: MutatorClientInterface,
private subscriptions: SubscriptionManagerInterface,
private api: ApiServiceInterface,
sockets: SNWebSocketsService,
private api: LegacyApiServiceInterface,
sockets: WebSocketsService,
private settings: SettingsClientInterface,
private user: UserClientInterface,
private sync: SyncServiceInterface,
@@ -152,20 +154,19 @@ export class SNFeaturesService
const { userRoles } = event.payload as MetaReceivedData
void this.updateOnlineRolesWithNewValues(userRoles.map((role) => role.name))
}
}
override async handleApplicationStage(stage: ApplicationStage): Promise<void> {
if (stage === ApplicationStage.FullSyncCompleted_13) {
if (!this.hasFirstPartyOnlineSubscription()) {
const offlineRepo = this.getOfflineRepo()
if (event.type === ApplicationEvent.ApplicationStageChanged) {
const stage = (event.payload as ApplicationStageChangedEventPayload).stage
if (stage === ApplicationStage.FullSyncCompleted_13) {
if (!this.hasFirstPartyOnlineSubscription()) {
const offlineRepo = this.getOfflineRepo()
if (offlineRepo) {
void this.downloadOfflineRoles(offlineRepo)
if (offlineRepo) {
void this.downloadOfflineRoles(offlineRepo)
}
}
}
}
return super.handleApplicationStage(stage)
}
public enableExperimentalFeature(identifier: FeatureIdentifier): void {

View File

@@ -9,13 +9,17 @@ import {
import {
AlertService,
API_MESSAGE_FAILED_DOWNLOADING_EXTENSION,
ApiServiceInterface,
LegacyApiServiceInterface,
ItemManagerInterface,
} from '@standardnotes/services'
import { isString } from '@standardnotes/utils'
export class DownloadRemoteThirdPartyFeatureUseCase {
constructor(private api: ApiServiceInterface, private items: ItemManagerInterface, private alerts: AlertService) {}
constructor(
private api: LegacyApiServiceInterface,
private items: ItemManagerInterface,
private alerts: AlertService,
) {}
async execute(url: string): Promise<ComponentInterface | undefined> {
const response = await this.api.downloadFeatureUrl(url)

View File

@@ -30,7 +30,7 @@ const LargeEntryDeltaThreshold = 25
* 2. Remote server history. Entries are automatically added by the server and must be
* retrieved per item via an API call.
*/
export class SNHistoryManager extends AbstractService implements HistoryServiceInterface {
export class HistoryManager extends AbstractService implements HistoryServiceInterface {
private removeChangeObserver: () => void
/**

View File

@@ -1,9 +1,13 @@
import { ItemsKeyInterface } from '@standardnotes/models'
import { dateSorted } from '@standardnotes/utils'
import { SNRootKeyParams, EncryptionProviderInterface } from '@standardnotes/encryption'
import { SNRootKeyParams } from '@standardnotes/encryption'
import { DecryptionQueueItem, KeyRecoveryOperationResult } from './Types'
import { serverKeyParamsAreSafe } from './Utils'
import { ChallengeServiceInterface, DecryptItemsKeyByPromptingUser } from '@standardnotes/services'
import {
ChallengeServiceInterface,
DecryptItemsKeyByPromptingUser,
EncryptionProviderInterface,
} from '@standardnotes/services'
import { ItemManager } from '../Items'
import { ContentType } from '@standardnotes/domain-core'

View File

@@ -11,11 +11,11 @@ import {
getIncrementedDirtyIndex,
ContentTypeUsesRootKeyEncryption,
} from '@standardnotes/models'
import { SNSyncService } from '../Sync/SyncService'
import { SyncService } from '../Sync/SyncService'
import { DiskStorageService } from '../Storage/DiskStorageService'
import { PayloadManager } from '../Payloads/PayloadManager'
import { ChallengeService } from '../Challenge'
import { SNApiService } from '@Lib/Services/Api/ApiService'
import { LegacyApiService } from '@Lib/Services/Api/ApiService'
import { ItemManager } from '../Items/ItemManager'
import { removeFromArray, Uuids } from '@standardnotes/utils'
import { ClientDisplayableError, isErrorResponse } from '@standardnotes/responses'
@@ -33,6 +33,10 @@ import {
EncryptionService,
Challenge,
UserService,
InternalEventHandlerInterface,
InternalEventInterface,
ApplicationEvent,
ApplicationStageChangedEventPayload,
} from '@standardnotes/services'
import {
UndecryptableItemsStorage,
@@ -79,7 +83,10 @@ import { ContentType } from '@standardnotes/domain-core'
* but our current copy is not, we will ignore the incoming value until we can properly
* decrypt it.
*/
export class SNKeyRecoveryService extends AbstractService<KeyRecoveryEvent, DecryptedPayloadInterface[]> {
export class KeyRecoveryService
extends AbstractService<KeyRecoveryEvent, DecryptedPayloadInterface[]>
implements InternalEventHandlerInterface
{
private removeItemObserver: () => void
private decryptionQueue: DecryptionQueueItem[] = []
private isProcessingQueue = false
@@ -87,12 +94,12 @@ export class SNKeyRecoveryService extends AbstractService<KeyRecoveryEvent, Decr
constructor(
private itemManager: ItemManager,
private payloadManager: PayloadManager,
private apiService: SNApiService,
private apiService: LegacyApiService,
private encryptionService: EncryptionService,
private challengeService: ChallengeService,
private alertService: AlertService,
private storageService: DiskStorageService,
private syncService: SNSyncService,
private sync: SyncService,
private userService: UserService,
protected override internalEventBus: InternalEventBusInterface,
) {
@@ -126,7 +133,7 @@ export class SNKeyRecoveryService extends AbstractService<KeyRecoveryEvent, Decr
;(this.challengeService as unknown) = undefined
;(this.alertService as unknown) = undefined
;(this.storageService as unknown) = undefined
;(this.syncService as unknown) = undefined
;(this.sync as unknown) = undefined
;(this.userService as unknown) = undefined
this.removeItemObserver()
@@ -135,11 +142,12 @@ export class SNKeyRecoveryService extends AbstractService<KeyRecoveryEvent, Decr
super.deinit()
}
// eslint-disable-next-line @typescript-eslint/require-await
override async handleApplicationStage(stage: ApplicationStage): Promise<void> {
void super.handleApplicationStage(stage)
if (stage === ApplicationStage.LoadedDatabase_12) {
void this.processPersistedUndecryptables()
async handleEvent(event: InternalEventInterface): Promise<void> {
if (event.type === ApplicationEvent.ApplicationStageChanged) {
const stage = (event.payload as ApplicationStageChangedEventPayload).stage
if (stage === ApplicationStage.LoadedDatabase_12) {
void this.processPersistedUndecryptables()
}
}
}
@@ -383,8 +391,8 @@ export class SNKeyRecoveryService extends AbstractService<KeyRecoveryEvent, Decr
await this.potentiallyPerformFallbackSignInToUpdateOutdatedLocalRootKey(serverParams)
}
if (this.syncService.isOutOfSync()) {
void this.syncService.sync({ checkIntegrity: true })
if (this.sync.isOutOfSync()) {
void this.sync.sync({ checkIntegrity: true })
}
}
@@ -500,7 +508,7 @@ export class SNKeyRecoveryService extends AbstractService<KeyRecoveryEvent, Decr
}
if (decryptedMatching.some((p) => p.dirty)) {
await this.syncService.sync()
await this.sync.sync()
}
await this.notifyEvent(KeyRecoveryEvent.KeysRecovered, decryptedMatching)

View File

@@ -1,27 +1,31 @@
import { SyncClientInterface } from './../Sync/SyncClientInterface'
import { isString, lastElement, sleep } from '@standardnotes/utils'
import { UuidString } from '@Lib/Types/UuidString'
import { ItemManager } from '@Lib/Services/Items/ItemManager'
import { DeprecatedHttpService } from '../Api/DeprecatedHttpService'
import { SettingName } from '@standardnotes/settings'
import { SNSettingsService } from '../Settings/SNSettingsService'
import { SettingsService } from '../Settings/SNSettingsService'
import { ListedClientInterface } from './ListedClientInterface'
import { SNApiService } from '../Api/ApiService'
import { LegacyApiService } from '../Api/ApiService'
import { isErrorResponse, ListedAccount, ListedAccountInfo, ListedAccountInfoResponse } from '@standardnotes/responses'
import { NoteMutator, SNActionsExtension, SNNote } from '@standardnotes/models'
import { AbstractService, InternalEventBusInterface, MutatorClientInterface } from '@standardnotes/services'
import {
AbstractService,
InternalEventBusInterface,
MutatorClientInterface,
SyncServiceInterface,
} from '@standardnotes/services'
import { SNProtectionService } from '../Protection'
import { ContentType } from '@standardnotes/domain-core'
export class ListedService extends AbstractService implements ListedClientInterface {
constructor(
private apiService: SNApiService,
private apiService: LegacyApiService,
private itemManager: ItemManager,
private settingsService: SNSettingsService,
private settingsService: SettingsService,
private httpSerivce: DeprecatedHttpService,
private protectionService: SNProtectionService,
private mutator: MutatorClientInterface,
private sync: SyncClientInterface,
private sync: SyncServiceInterface,
protected override internalEventBus: InternalEventBusInterface,
) {
super(internalEventBus)

View File

@@ -1,15 +1,15 @@
import { SettingName } from '@standardnotes/settings'
import { SNSettingsService } from '../Settings'
import { SettingsService } from '../Settings'
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { SNFeaturesService } from '../Features/FeaturesService'
import { FeaturesService } from '../Features/FeaturesService'
import { AbstractService, InternalEventBusInterface, SignInStrings } from '@standardnotes/services'
export class SNMfaService extends AbstractService {
constructor(
private settingsService: SNSettingsService,
private settingsService: SettingsService,
private crypto: PureCryptoInterface,
private featuresService: SNFeaturesService,
private featuresService: FeaturesService,
protected override internalEventBus: InternalEventBusInterface,
) {
super(internalEventBus)

View File

@@ -10,6 +10,9 @@ import {
ApplicationStage,
AbstractService,
DiagnosticInfo,
InternalEventHandlerInterface,
InternalEventInterface,
ApplicationStageChangedEventPayload,
} from '@standardnotes/services'
import { SnjsVersion, isRightVersionGreaterThanLeft } from '../../Version'
import { SNLog } from '@Lib/Log'
@@ -23,7 +26,7 @@ import { MigrationClasses } from '@Lib/Migrations/Versions'
* first launches, and also other steps after the application is unlocked, or after the
* first sync completes. Migrations live under /migrations and inherit from the base Migration class.
*/
export class SNMigrationService extends AbstractService {
export class MigrationService extends AbstractService implements InternalEventHandlerInterface {
private activeMigrations?: Migration[]
private baseMigration!: BaseMigration
@@ -44,7 +47,7 @@ export class SNMigrationService extends AbstractService {
public async initialize(): Promise<void> {
await this.runBaseMigrationPreRun()
const requiredMigrations = SNMigrationService.getRequiredMigrations(await this.getStoredSnjsVersion())
const requiredMigrations = MigrationService.getRequiredMigrations(await this.getStoredSnjsVersion())
this.activeMigrations = this.instantiateMigrationClasses(requiredMigrations)
@@ -70,13 +73,11 @@ export class SNMigrationService extends AbstractService {
await this.baseMigration.preRun()
}
/**
* Application instances will call this function directly when they arrive
* at a certain migratory state.
*/
public override async handleApplicationStage(stage: ApplicationStage): Promise<void> {
await super.handleApplicationStage(stage)
await this.handleStage(stage)
async handleEvent(event: InternalEventInterface): Promise<void> {
if (event.type === ApplicationEvent.ApplicationStageChanged) {
const stage = (event.payload as ApplicationStageChangedEventPayload).stage
await this.handleStage(stage)
}
}
/**
@@ -89,7 +90,7 @@ export class SNMigrationService extends AbstractService {
}
public async hasPendingMigrations(): Promise<boolean> {
const requiredMigrations = SNMigrationService.getRequiredMigrations(await this.getStoredSnjsVersion())
const requiredMigrations = MigrationService.getRequiredMigrations(await this.getStoredSnjsVersion())
return requiredMigrations.length > 0 || (await this.baseMigration.needsKeychainRepair())
}

View File

@@ -1,7 +1,7 @@
import { SNUserPrefs, PrefKey, PrefValue, UserPrefsMutator, ItemContent, FillItemContent } from '@standardnotes/models'
import { ItemManager } from '../Items/ItemManager'
import { SNSingletonManager } from '../Singleton/SingletonManager'
import { SNSyncService } from '../Sync/SyncService'
import { SingletonManager } from '../Singleton/SingletonManager'
import { SyncService } from '../Sync/SyncService'
import {
AbstractService,
InternalEventBusInterface,
@@ -10,12 +10,16 @@ import {
PreferenceServiceInterface,
PreferencesServiceEvent,
MutatorClientInterface,
InternalEventHandlerInterface,
InternalEventInterface,
ApplicationEvent,
ApplicationStageChangedEventPayload,
} from '@standardnotes/services'
import { ContentType } from '@standardnotes/domain-core'
export class SNPreferencesService
extends AbstractService<PreferencesServiceEvent>
implements PreferenceServiceInterface
implements PreferenceServiceInterface, InternalEventHandlerInterface
{
private shouldReload = true
private reloading = false
@@ -24,10 +28,10 @@ export class SNPreferencesService
private removeSyncObserver?: () => void
constructor(
private singletons: SNSingletonManager,
private singletons: SingletonManager,
items: ItemManager,
private mutator: MutatorClientInterface,
private sync: SNSyncService,
private sync: SyncService,
protected override internalEventBus: InternalEventBusInterface,
) {
super(internalEventBus)
@@ -52,18 +56,19 @@ export class SNPreferencesService
super.deinit()
}
public override async handleApplicationStage(stage: ApplicationStage): Promise<void> {
await super.handleApplicationStage(stage)
async handleEvent(event: InternalEventInterface): Promise<void> {
if (event.type === ApplicationEvent.ApplicationStageChanged) {
const stage = (event.payload as ApplicationStageChangedEventPayload).stage
if (stage === ApplicationStage.LoadedDatabase_12) {
/** Try to read preferences singleton from storage */
this.preferences = this.singletons.findSingleton<SNUserPrefs>(
ContentType.TYPES.UserPrefs,
SNUserPrefs.singletonPredicate,
)
if (stage === ApplicationStage.LoadedDatabase_12) {
/** Try to read preferences singleton from storage */
this.preferences = this.singletons.findSingleton<SNUserPrefs>(
ContentType.TYPES.UserPrefs,
SNUserPrefs.singletonPredicate,
)
if (this.preferences) {
void this.notifyEvent(PreferencesServiceEvent.PreferencesChanged)
if (this.preferences) {
void this.notifyEvent(PreferencesServiceEvent.PreferencesChanged)
}
}
}
}

View File

@@ -25,6 +25,10 @@ import {
TimingDisplayOption,
ProtectionsClientInterface,
MutatorClientInterface,
InternalEventHandlerInterface,
InternalEventInterface,
ApplicationEvent,
ApplicationStageChangedEventPayload,
} from '@standardnotes/services'
import { ContentType } from '@standardnotes/domain-core'
@@ -70,7 +74,10 @@ export const ProtectionSessionDurations = [
* like viewing a protected note, as well as managing how long that
* authentication should be valid for.
*/
export class SNProtectionService extends AbstractService<ProtectionEvent> implements ProtectionsClientInterface {
export class SNProtectionService
extends AbstractService<ProtectionEvent>
implements ProtectionsClientInterface, InternalEventHandlerInterface
{
private sessionExpiryTimeout = -1
private mobilePasscodeTiming: MobileUnlockTiming | undefined = MobileUnlockTiming.OnQuit
private mobileBiometricsTiming: MobileUnlockTiming | undefined = MobileUnlockTiming.OnQuit
@@ -93,13 +100,15 @@ export class SNProtectionService extends AbstractService<ProtectionEvent> implem
super.deinit()
}
override handleApplicationStage(stage: ApplicationStage): Promise<void> {
if (stage === ApplicationStage.LoadedDatabase_12) {
this.updateSessionExpiryTimer(this.getSessionExpiryDate())
this.mobilePasscodeTiming = this.getMobilePasscodeTiming()
this.mobileBiometricsTiming = this.getMobileBiometricsTiming()
async handleEvent(event: InternalEventInterface): Promise<void> {
if (event.type === ApplicationEvent.ApplicationStageChanged) {
const stage = (event.payload as ApplicationStageChangedEventPayload).stage
if (stage === ApplicationStage.LoadedDatabase_12) {
this.updateSessionExpiryTimer(this.getSessionExpiryDate())
this.mobilePasscodeTiming = this.getMobilePasscodeTiming()
this.mobileBiometricsTiming = this.getMobileBiometricsTiming()
}
}
return Promise.resolve()
}
public hasProtectionSources(): boolean {

View File

@@ -30,7 +30,7 @@ import {
InternalFeatureService,
InternalFeature,
} from '@standardnotes/services'
import { Base64String, PkcKeyPair } from '@standardnotes/sncrypto-common'
import { Base64String, PkcKeyPair, PureCryptoInterface } from '@standardnotes/sncrypto-common'
import {
SessionBody,
ErrorTag,
@@ -52,9 +52,9 @@ import * as Common from '@standardnotes/common'
import { RawStorageValue } from './Sessions/Types'
import { ShareToken } from './ShareToken'
import { SNApiService } from '../Api/ApiService'
import { LegacyApiService } from '../Api/ApiService'
import { DiskStorageService } from '../Storage/DiskStorageService'
import { SNWebSocketsService } from '../Api/WebsocketsService'
import { WebSocketsService } from '../Api/WebsocketsService'
import { Strings } from '@Lib/Strings'
import { UuidString } from '@Lib/Types/UuidString'
import { ChallengeResponse, ChallengeService } from '../Challenge'
@@ -78,7 +78,7 @@ const cleanedEmailString = (email: string) => {
* server credentials, such as the session token. It also exposes methods for registering
* for a new account, signing into an existing one, or changing an account password.
*/
export class SNSessionManager
export class SessionManager
extends AbstractService<SessionEvent>
implements SessionsClientInterface, InternalEventHandlerInterface
{
@@ -87,13 +87,14 @@ export class SNSessionManager
private session?: Session | LegacySession
constructor(
private diskStorageService: DiskStorageService,
private apiService: SNApiService,
private storage: DiskStorageService,
private apiService: LegacyApiService,
private userApiService: UserApiServiceInterface,
private alertService: AlertService,
private encryptionService: EncryptionService,
private crypto: PureCryptoInterface,
private challengeService: ChallengeService,
private webSocketsService: SNWebSocketsService,
private webSocketsService: WebSocketsService,
private httpService: HttpServiceInterface,
private sessionStorageMapper: MapperInterface<Session, Record<string, unknown>>,
private legacySessionStorageMapper: MapperInterface<LegacySession, Record<string, unknown>>,
@@ -118,7 +119,7 @@ export class SNSessionManager
override deinit(): void {
;(this.encryptionService as unknown) = undefined
;(this.diskStorageService as unknown) = undefined
;(this.storage as unknown) = undefined
;(this.apiService as unknown) = undefined
;(this.alertService as unknown) = undefined
;(this.challengeService as unknown) = undefined
@@ -141,17 +142,17 @@ export class SNSessionManager
this.apiService.setUser(user)
}
async initializeFromDisk() {
this.memoizeUser(this.diskStorageService.getValue(StorageKey.User))
async initializeFromDisk(): Promise<void> {
this.memoizeUser(this.storage.getValue(StorageKey.User))
if (!this.user) {
const legacyUuidLookup = this.diskStorageService.getValue<string>(StorageKey.LegacyUuid)
const legacyUuidLookup = this.storage.getValue<string>(StorageKey.LegacyUuid)
if (legacyUuidLookup) {
this.memoizeUser({ uuid: legacyUuidLookup, email: legacyUuidLookup })
}
}
const rawSession = this.diskStorageService.getValue<RawStorageValue>(StorageKey.Session)
const rawSession = this.storage.getValue<RawStorageValue>(StorageKey.Session)
if (rawSession) {
try {
const session =
@@ -286,7 +287,7 @@ export class SNSessionManager
email,
password,
false,
this.diskStorageService.isEphemeralSession(),
this.storage.isEphemeralSession(),
currentKeyParams?.version,
)
if (isErrorResponse(response)) {
@@ -630,10 +631,17 @@ export class SNSessionManager
if (!isErrorResponse(rawResponse)) {
if (InternalFeatureService.get().isFeatureEnabled(InternalFeature.Vaults)) {
const eventData: UserKeyPairChangedEventData = {
oldKeyPair,
oldSigningKeyPair,
newKeyPair: parameters.newRootKey.encryptionKeyPair,
newSigningKeyPair: parameters.newRootKey.signingKeyPair,
previous:
oldKeyPair && oldSigningKeyPair
? {
encryption: oldKeyPair,
signing: oldSigningKeyPair,
}
: undefined,
current: {
encryption: parameters.newRootKey.encryptionKeyPair,
signing: parameters.newRootKey.signingKeyPair,
},
}
void this.notifyEvent(SessionEvent.UserKeyPairChanged, eventData)
@@ -692,7 +700,7 @@ export class SNSessionManager
}
private decodeDemoShareToken(token: Base64String): ShareToken {
const jsonString = this.encryptionService.crypto.base64Decode(token)
const jsonString = this.crypto.base64Decode(token)
return JSON.parse(jsonString)
}
@@ -712,7 +720,7 @@ export class SNSessionManager
await this.encryptionService.setRootKey(rootKey, wrappingKey)
this.memoizeUser(user)
this.diskStorageService.setValue(StorageKey.User, user)
this.storage.setValue(StorageKey.User, user)
void this.apiService.setHost(host)
this.httpService.setHost(host)

View File

@@ -1,11 +1,11 @@
import { SNApiService } from '../Api/ApiService'
import { LegacyApiService } from '../Api/ApiService'
import { SettingsGateway } from './SettingsGateway'
import { SNSessionManager } from '../Session/SessionManager'
import { SessionManager } from '../Session/SessionManager'
import { EmailBackupFrequency, SettingName } from '@standardnotes/settings'
import { AbstractService, InternalEventBusInterface } from '@standardnotes/services'
import { SettingsClientInterface } from './SettingsClientInterface'
export class SNSettingsService extends AbstractService implements SettingsClientInterface {
export class SettingsService extends AbstractService implements SettingsClientInterface {
private provider!: SettingsGateway
private frequencyOptionsLabels = {
[EmailBackupFrequency.Disabled]: 'No email backups',
@@ -14,8 +14,8 @@ export class SNSettingsService extends AbstractService implements SettingsClient
}
constructor(
private readonly sessionManager: SNSessionManager,
private readonly apiService: SNApiService,
private readonly sessionManager: SessionManager,
private readonly apiService: LegacyApiService,
protected override internalEventBus: InternalEventBusInterface,
) {
super(internalEventBus)

View File

@@ -12,7 +12,7 @@ import {
Predicate,
} from '@standardnotes/models'
import { arrayByRemovingFromIndex, extendArray, UuidGenerator } from '@standardnotes/utils'
import { SNSyncService } from '../Sync/SyncService'
import { SyncService } from '../Sync/SyncService'
import {
AbstractService,
InternalEventBusInterface,
@@ -33,7 +33,7 @@ import { ContentType } from '@standardnotes/domain-core'
* 2. Items can override isSingleton, singletonPredicate, and strategyWhenConflictingWithItem (optional)
* to automatically gain singleton resolution.
*/
export class SNSingletonManager extends AbstractService implements SingletonManagerInterface {
export class SingletonManager extends AbstractService implements SingletonManagerInterface {
private resolveQueue: DecryptedItemInterface[] = []
private removeItemObserver!: () => void
@@ -43,7 +43,7 @@ export class SNSingletonManager extends AbstractService implements SingletonMana
private itemManager: ItemManager,
private mutator: MutatorClientInterface,
private payloadManager: PayloadManager,
private syncService: SNSyncService,
private sync: SyncService,
protected override internalEventBus: InternalEventBusInterface,
) {
super(internalEventBus)
@@ -51,7 +51,7 @@ export class SNSingletonManager extends AbstractService implements SingletonMana
}
public override deinit(): void {
;(this.syncService as unknown) = undefined
;(this.sync as unknown) = undefined
;(this.mutator as unknown) = undefined
;(this.itemManager as unknown) = undefined
;(this.payloadManager as unknown) = undefined
@@ -93,7 +93,7 @@ export class SNSingletonManager extends AbstractService implements SingletonMana
}
})
this.removeSyncObserver = this.syncService.addEventObserver(async (eventName) => {
this.removeSyncObserver = this.sync.addEventObserver(async (eventName) => {
if (
eventName === SyncEvent.DownloadFirstSyncCompleted ||
eventName === SyncEvent.SyncCompletedWithAllItemsUploaded
@@ -142,7 +142,7 @@ export class SNSingletonManager extends AbstractService implements SingletonMana
* of a download-first request.
*/
if (handled.length > 0 && eventSource === SyncEvent.SyncCompletedWithAllItemsUploaded) {
await this.syncService?.sync({ sourceDescription: 'Resolve singletons for items' })
await this.sync?.sync({ sourceDescription: 'Resolve singletons for items' })
}
}
@@ -182,7 +182,7 @@ export class SNSingletonManager extends AbstractService implements SingletonMana
}
/** Item not found, safe to create after full sync has completed */
if (!this.syncService.getLastSyncDate()) {
if (!this.sync.getLastSyncDate()) {
/**
* Add a temporary observer in case of long-running sync request, where
* the item we're looking for ends up resolving early or in the middle.
@@ -199,7 +199,7 @@ export class SNSingletonManager extends AbstractService implements SingletonMana
}
})
await this.syncService.sync({ sourceDescription: 'Find or create singleton, before any sync has completed' })
await this.sync.sync({ sourceDescription: 'Find or create singleton, before any sync has completed' })
removeObserver()
@@ -233,7 +233,7 @@ export class SNSingletonManager extends AbstractService implements SingletonMana
const item = await this.mutator.emitItemFromPayload(dirtyPayload, PayloadEmitSource.LocalInserted)
void this.syncService.sync({ sourceDescription: 'After find or create singleton' })
void this.sync.sync({ sourceDescription: 'After find or create singleton' })
return item as T
}
@@ -248,7 +248,7 @@ export class SNSingletonManager extends AbstractService implements SingletonMana
}
/** Item not found, safe to create after full sync has completed */
if (!this.syncService.getLastSyncDate()) {
if (!this.sync.getLastSyncDate()) {
/**
* Add a temporary observer in case of long-running sync request, where
* the item we're looking for ends up resolving early or in the middle.
@@ -265,7 +265,7 @@ export class SNSingletonManager extends AbstractService implements SingletonMana
}
})
await this.syncService.sync({ sourceDescription: 'Find or create singleton, before any sync has completed' })
await this.sync.sync({ sourceDescription: 'Find or create singleton, before any sync has completed' })
removeObserver()
@@ -292,7 +292,7 @@ export class SNSingletonManager extends AbstractService implements SingletonMana
const item = await this.mutator.emitItemFromPayload(dirtyPayload, PayloadEmitSource.LocalInserted)
void this.syncService.sync({ sourceDescription: 'After find or create singleton' })
void this.sync.sync({ sourceDescription: 'After find or create singleton' })
return item as T
}

View File

@@ -1,8 +1,33 @@
import { Copy, extendArray, UuidGenerator, Uuids } from '@standardnotes/utils'
import { SNLog } from '../../Log'
import { isErrorDecryptingParameters, SNRootKey } from '@standardnotes/encryption'
import * as Encryption from '@standardnotes/encryption'
import * as Services from '@standardnotes/services'
import {
KeyedDecryptionSplit,
KeyedEncryptionSplit,
SplitPayloadsByEncryptionType,
CreateEncryptionSplitWithKeyLookup,
isErrorDecryptingParameters,
SNRootKey,
} from '@standardnotes/encryption'
import {
AbstractService,
StorageServiceInterface,
InternalEventHandlerInterface,
StoragePersistencePolicies,
StorageValuesObject,
DeviceInterface,
InternalEventBusInterface,
InternalEventInterface,
ApplicationEvent,
ApplicationStageChangedEventPayload,
ApplicationStage,
ValueModesKeys,
StorageValueModes,
namespacedKey,
RawStorageKey,
WrappedStorageValue,
ValuesObjectRecord,
EncryptionProviderInterface,
} from '@standardnotes/services'
import {
CreateDecryptedLocalStorageContextPayload,
CreateDeletedLocalStorageContextPayload,
@@ -31,25 +56,28 @@ import { ContentType } from '@standardnotes/domain-core'
* decrypt the persisted key/values, and also a method to determine whether a particular
* key can decrypt wrapped storage.
*/
export class DiskStorageService extends Services.AbstractService implements Services.StorageServiceInterface {
private encryptionProvider!: Encryption.EncryptionProviderInterface
export class DiskStorageService
extends AbstractService
implements StorageServiceInterface, InternalEventHandlerInterface
{
private encryptionProvider!: EncryptionProviderInterface
private storagePersistable = false
private persistencePolicy!: Services.StoragePersistencePolicies
private persistencePolicy!: StoragePersistencePolicies
private needsPersist = false
private currentPersistPromise?: Promise<Services.StorageValuesObject>
private currentPersistPromise?: Promise<StorageValuesObject>
private values!: Services.StorageValuesObject
private values!: StorageValuesObject
constructor(
private deviceInterface: Services.DeviceInterface,
private deviceInterface: DeviceInterface,
private identifier: string,
protected override internalEventBus: Services.InternalEventBusInterface,
protected override internalEventBus: InternalEventBusInterface,
) {
super(internalEventBus)
void this.setPersistencePolicy(Services.StoragePersistencePolicies.Default)
void this.setPersistencePolicy(StoragePersistencePolicies.Default)
}
public provideEncryptionProvider(provider: Encryption.EncryptionProviderInterface): void {
public provideEncryptionProvider(provider: EncryptionProviderInterface): void {
this.encryptionProvider = provider
}
@@ -60,21 +88,22 @@ export class DiskStorageService extends Services.AbstractService implements Serv
super.deinit()
}
override async handleApplicationStage(stage: Services.ApplicationStage) {
await super.handleApplicationStage(stage)
if (stage === Services.ApplicationStage.Launched_10) {
this.storagePersistable = true
if (this.needsPersist) {
void this.persistValuesToDisk()
async handleEvent(event: InternalEventInterface): Promise<void> {
if (event.type === ApplicationEvent.ApplicationStageChanged) {
const stage = (event.payload as ApplicationStageChangedEventPayload).stage
if (stage === ApplicationStage.Launched_10) {
this.storagePersistable = true
if (this.needsPersist) {
void this.persistValuesToDisk()
}
}
}
}
public async setPersistencePolicy(persistencePolicy: Services.StoragePersistencePolicies) {
public async setPersistencePolicy(persistencePolicy: StoragePersistencePolicies) {
this.persistencePolicy = persistencePolicy
if (this.persistencePolicy === Services.StoragePersistencePolicies.Ephemeral) {
if (this.persistencePolicy === StoragePersistencePolicies.Ephemeral) {
await this.deviceInterface.clearNamespacedKeychainValue(this.identifier)
await this.deviceInterface.removeAllDatabaseEntries(this.identifier)
await this.deviceInterface.removeRawStorageValuesForIdentifier(this.identifier)
@@ -82,42 +111,42 @@ export class DiskStorageService extends Services.AbstractService implements Serv
}
}
public isEphemeralSession() {
return this.persistencePolicy === Services.StoragePersistencePolicies.Ephemeral
public isEphemeralSession(): boolean {
return this.persistencePolicy === StoragePersistencePolicies.Ephemeral
}
public async initializeFromDisk() {
public async initializeFromDisk(): Promise<void> {
const value = await this.deviceInterface.getRawStorageValue(this.getPersistenceKey())
const values = value ? JSON.parse(value as string) : undefined
await this.setInitialValues(values)
}
private async setInitialValues(values?: Services.StorageValuesObject) {
private async setInitialValues(values?: StorageValuesObject) {
const sureValues = values || this.defaultValuesObject()
if (!sureValues[Services.ValueModesKeys.Unwrapped]) {
sureValues[Services.ValueModesKeys.Unwrapped] = {}
if (!sureValues[ValueModesKeys.Unwrapped]) {
sureValues[ValueModesKeys.Unwrapped] = {}
}
this.values = sureValues
if (!this.isStorageWrapped()) {
this.values[Services.ValueModesKeys.Unwrapped] = {
...(this.values[Services.ValueModesKeys.Wrapped].content as object),
...this.values[Services.ValueModesKeys.Unwrapped],
this.values[ValueModesKeys.Unwrapped] = {
...(this.values[ValueModesKeys.Wrapped].content as object),
...this.values[ValueModesKeys.Unwrapped],
}
}
}
public isStorageWrapped(): boolean {
const wrappedValue = this.values[Services.ValueModesKeys.Wrapped]
const wrappedValue = this.values[ValueModesKeys.Wrapped]
return wrappedValue != undefined && isEncryptedLocalStoragePayload(wrappedValue)
}
public async canDecryptWithKey(key: SNRootKey): Promise<boolean> {
const wrappedValue = this.values[Services.ValueModesKeys.Wrapped]
const wrappedValue = this.values[ValueModesKeys.Wrapped]
if (!isEncryptedLocalStoragePayload(wrappedValue)) {
throw Error('Attempting to decrypt non decrypted storage value')
@@ -143,7 +172,7 @@ export class DiskStorageService extends Services.AbstractService implements Serv
content_type: ContentType.TYPES.EncryptedStorage,
})
const split: Encryption.KeyedDecryptionSplit = key
const split: KeyedDecryptionSplit = key
? {
usesRootKey: {
items: [payload],
@@ -161,8 +190,8 @@ export class DiskStorageService extends Services.AbstractService implements Serv
return decryptedPayload
}
public async decryptStorage() {
const wrappedValue = this.values[Services.ValueModesKeys.Wrapped]
public async decryptStorage(): Promise<void> {
const wrappedValue = this.values[ValueModesKeys.Wrapped]
if (!isEncryptedLocalStoragePayload(wrappedValue)) {
throw Error('Attempting to decrypt already decrypted storage')
@@ -174,7 +203,7 @@ export class DiskStorageService extends Services.AbstractService implements Serv
throw SNLog.error(Error('Unable to decrypt storage.'))
}
this.values[Services.ValueModesKeys.Unwrapped] = Copy(decryptedPayload.content)
this.values[ValueModesKeys.Unwrapped] = Copy(decryptedPayload.content)
}
/** @todo This function should be debounced. */
@@ -184,7 +213,7 @@ export class DiskStorageService extends Services.AbstractService implements Serv
return
}
if (this.persistencePolicy === Services.StoragePersistencePolicies.Ephemeral) {
if (this.persistencePolicy === StoragePersistencePolicies.Ephemeral) {
return
}
@@ -195,18 +224,18 @@ export class DiskStorageService extends Services.AbstractService implements Serv
const values = await this.immediatelyPersistValuesToDisk()
/** Save the persisted value so we have access to it in memory (for unit tests afawk) */
this.values[Services.ValueModesKeys.Wrapped] = values[Services.ValueModesKeys.Wrapped]
this.values[ValueModesKeys.Wrapped] = values[ValueModesKeys.Wrapped]
}
public async awaitPersist(): Promise<void> {
await this.currentPersistPromise
}
private async immediatelyPersistValuesToDisk(): Promise<Services.StorageValuesObject> {
private async immediatelyPersistValuesToDisk(): Promise<StorageValuesObject> {
this.currentPersistPromise = this.executeCriticalFunction(async () => {
const values = await this.generatePersistableValues()
const persistencePolicySuddenlyChanged = this.persistencePolicy === Services.StoragePersistencePolicies.Ephemeral
const persistencePolicySuddenlyChanged = this.persistencePolicy === StoragePersistencePolicies.Ephemeral
if (persistencePolicySuddenlyChanged) {
return values
}
@@ -224,10 +253,10 @@ export class DiskStorageService extends Services.AbstractService implements Serv
* either as a plain object, or an encrypted item.
*/
private async generatePersistableValues() {
const rawContent = <Partial<Services.StorageValuesObject>>Copy(this.values)
const rawContent = <Partial<StorageValuesObject>>Copy(this.values)
const valuesToWrap = rawContent[Services.ValueModesKeys.Unwrapped]
rawContent[Services.ValueModesKeys.Unwrapped] = undefined
const valuesToWrap = rawContent[ValueModesKeys.Unwrapped]
rawContent[ValueModesKeys.Unwrapped] = undefined
const payload = new DecryptedPayload({
uuid: UuidGenerator.GenerateUuid(),
@@ -237,7 +266,7 @@ export class DiskStorageService extends Services.AbstractService implements Serv
})
if (this.encryptionProvider.hasRootKeyEncryptionSource()) {
const split: Encryption.KeyedEncryptionSplit = {
const split: KeyedEncryptionSplit = {
usesRootKeyWithKeyLookup: {
items: [payload],
},
@@ -245,31 +274,27 @@ export class DiskStorageService extends Services.AbstractService implements Serv
const encryptedPayload = await this.encryptionProvider.encryptSplitSingle(split)
rawContent[Services.ValueModesKeys.Wrapped] = CreateEncryptedLocalStorageContextPayload(encryptedPayload)
rawContent[ValueModesKeys.Wrapped] = CreateEncryptedLocalStorageContextPayload(encryptedPayload)
} else {
rawContent[Services.ValueModesKeys.Wrapped] = CreateDecryptedLocalStorageContextPayload(payload)
rawContent[ValueModesKeys.Wrapped] = CreateDecryptedLocalStorageContextPayload(payload)
}
return rawContent as Services.StorageValuesObject
return rawContent as StorageValuesObject
}
public setValue<T>(key: string, value: T, mode = Services.StorageValueModes.Default): void {
public setValue<T>(key: string, value: T, mode = StorageValueModes.Default): void {
this.setValueWithNoPersist(key, value, mode)
void this.persistValuesToDisk()
}
public async setValueAndAwaitPersist(
key: string,
value: unknown,
mode = Services.StorageValueModes.Default,
): Promise<void> {
public async setValueAndAwaitPersist(key: string, value: unknown, mode = StorageValueModes.Default): Promise<void> {
this.setValueWithNoPersist(key, value, mode)
await this.persistValuesToDisk()
}
private setValueWithNoPersist(key: string, value: unknown, mode = Services.StorageValueModes.Default): void {
private setValueWithNoPersist(key: string, value: unknown, mode = StorageValueModes.Default): void {
if (!this.values) {
throw Error(`Attempting to set storage key ${key} before loading local storage.`)
}
@@ -279,7 +304,7 @@ export class DiskStorageService extends Services.AbstractService implements Serv
domainStorage[key] = value
}
public getValue<T>(key: string, mode = Services.StorageValueModes.Default, defaultValue?: T): T {
public getValue<T>(key: string, mode = StorageValueModes.Default, defaultValue?: T): T {
if (!this.values) {
throw Error(`Attempting to get storage key ${key} before loading local storage.`)
}
@@ -293,7 +318,7 @@ export class DiskStorageService extends Services.AbstractService implements Serv
return value != undefined ? (value as T) : (defaultValue as T)
}
public getAllKeys(mode = Services.StorageValueModes.Default): string[] {
public getAllKeys(mode = StorageValueModes.Default): string[] {
if (!this.values) {
throw Error('Attempting to get all keys before loading local storage.')
}
@@ -301,7 +326,7 @@ export class DiskStorageService extends Services.AbstractService implements Serv
return Object.keys(this.values[this.domainKeyForMode(mode)])
}
public async removeValue(key: string, mode = Services.StorageValueModes.Default): Promise<void> {
public async removeValue(key: string, mode = StorageValueModes.Default): Promise<void> {
if (!this.values) {
throw Error(`Attempting to remove storage key ${key} before loading local storage.`)
}
@@ -318,34 +343,34 @@ export class DiskStorageService extends Services.AbstractService implements Serv
* Default persistence key. Platforms can override as needed.
*/
private getPersistenceKey() {
return Services.namespacedKey(this.identifier, Services.RawStorageKey.StorageObject)
return namespacedKey(this.identifier, RawStorageKey.StorageObject)
}
private defaultValuesObject(
wrapped?: Services.WrappedStorageValue,
unwrapped?: Services.ValuesObjectRecord,
nonwrapped?: Services.ValuesObjectRecord,
wrapped?: WrappedStorageValue,
unwrapped?: ValuesObjectRecord,
nonwrapped?: ValuesObjectRecord,
) {
return DiskStorageService.DefaultValuesObject(wrapped, unwrapped, nonwrapped)
}
public static DefaultValuesObject(
wrapped: Services.WrappedStorageValue = {} as Services.WrappedStorageValue,
unwrapped: Services.ValuesObjectRecord = {},
nonwrapped: Services.ValuesObjectRecord = {},
wrapped: WrappedStorageValue = {} as WrappedStorageValue,
unwrapped: ValuesObjectRecord = {},
nonwrapped: ValuesObjectRecord = {},
) {
return {
[Services.ValueModesKeys.Wrapped]: wrapped,
[Services.ValueModesKeys.Unwrapped]: unwrapped,
[Services.ValueModesKeys.Nonwrapped]: nonwrapped,
} as Services.StorageValuesObject
[ValueModesKeys.Wrapped]: wrapped,
[ValueModesKeys.Unwrapped]: unwrapped,
[ValueModesKeys.Nonwrapped]: nonwrapped,
} as StorageValuesObject
}
private domainKeyForMode(mode: Services.StorageValueModes) {
if (mode === Services.StorageValueModes.Default) {
return Services.ValueModesKeys.Unwrapped
} else if (mode === Services.StorageValueModes.Nonwrapped) {
return Services.ValueModesKeys.Nonwrapped
private domainKeyForMode(mode: StorageValueModes) {
if (mode === StorageValueModes.Default) {
return ValueModesKeys.Unwrapped
} else if (mode === StorageValueModes.Nonwrapped) {
return ValueModesKeys.Nonwrapped
} else {
throw Error('Invalid mode')
}
@@ -368,7 +393,7 @@ export class DiskStorageService extends Services.AbstractService implements Serv
}
public async savePayloads(payloads: FullyFormedPayloadInterface[]): Promise<void> {
if (this.persistencePolicy === Services.StoragePersistencePolicies.Ephemeral) {
if (this.persistencePolicy === StoragePersistencePolicies.Ephemeral) {
return
}
@@ -380,7 +405,7 @@ export class DiskStorageService extends Services.AbstractService implements Serv
const unencryptable: DecryptedPayloadInterface[] = []
const { rootKeyEncryption, keySystemRootKeyEncryption, itemsKeyEncryption } =
Encryption.SplitPayloadsByEncryptionType(decrypted)
SplitPayloadsByEncryptionType(decrypted)
if (itemsKeyEncryption) {
extendArray(encryptable, itemsKeyEncryption)
@@ -402,9 +427,9 @@ export class DiskStorageService extends Services.AbstractService implements Serv
await this.deletePayloads(discardable)
}
const encryptableSplit = Encryption.SplitPayloadsByEncryptionType(encryptable)
const encryptableSplit = SplitPayloadsByEncryptionType(encryptable)
const keyLookupSplit = Encryption.CreateEncryptionSplitWithKeyLookup(encryptableSplit)
const keyLookupSplit = CreateEncryptionSplitWithKeyLookup(encryptableSplit)
const encryptedResults = await this.encryptionProvider.encryptSplit(keyLookupSplit)
@@ -449,9 +474,7 @@ export class DiskStorageService extends Services.AbstractService implements Serv
await this.clearValues()
await this.clearAllPayloads()
await this.deviceInterface.removeRawStorageValue(
Services.namespacedKey(this.identifier, Services.RawStorageKey.SnjsVersion),
)
await this.deviceInterface.removeRawStorageValue(namespacedKey(this.identifier, RawStorageKey.SnjsVersion))
await this.deviceInterface.removeRawStorageValue(this.getPersistenceKey())
})

View File

@@ -2,7 +2,7 @@ import { ServerSyncPushContextualPayload } from '@standardnotes/models'
import { arrayByDifference, nonSecureRandomIdentifier, subtractFromArray } from '@standardnotes/utils'
import { ServerSyncResponse } from '@Lib/Services/Sync/Account/Response'
import { ResponseSignalReceiver, SyncSignal } from '@Lib/Services/Sync/Signals'
import { SNApiService } from '../../Api/ApiService'
import { LegacyApiService } from '../../Api/ApiService'
export const SyncUpDownLimit = 150
@@ -23,7 +23,7 @@ export class AccountSyncOperation {
constructor(
public readonly payloads: ServerSyncPushContextualPayload[],
private receiver: ResponseSignalReceiver<ServerSyncResponse>,
private apiService: SNApiService,
private apiService: LegacyApiService,
public readonly options: {
syncToken?: string
paginationToken?: string

View File

@@ -1,14 +0,0 @@
import { SyncOpStatus } from './SyncOpStatus'
import { AbstractService, SyncEvent, SyncOptions } from '@standardnotes/services'
export interface SyncClientInterface extends AbstractService<SyncEvent> {
setLaunchPriorityUuids(launchPriorityUuids: string[]): void
sync(options?: Partial<SyncOptions>): Promise<unknown>
isOutOfSync(): boolean
getLastSyncDate(): Date | undefined
getSyncStatus(): SyncOpStatus
lockSyncing(): void
unlockSyncing(): void
completedOnlineDownloadFirstSync: boolean
}

View File

@@ -1,125 +0,0 @@
import { SyncEvent, SyncEventReceiver } from '@standardnotes/services'
const HEALTHY_SYNC_DURATION_THRESHOLD_S = 5
const TIMING_MONITOR_POLL_FREQUENCY_MS = 500
export class SyncOpStatus {
error?: any
private interval: any
private receiver: SyncEventReceiver
private completedUpload = 0
private totalUpload = 0
private downloaded = 0
private databaseLoadCurrent = 0
private databaseLoadTotal = 0
private databaseLoadDone = false
private syncing = false
private syncStart!: Date
private timingMonitor?: any
constructor(interval: any, receiver: SyncEventReceiver) {
this.interval = interval
this.receiver = receiver
}
public deinit() {
this.stopTimingMonitor()
}
public setUploadStatus(completed: number, total: number) {
this.completedUpload = completed
this.totalUpload = total
this.receiver(SyncEvent.StatusChanged)
}
public setDownloadStatus(downloaded: number) {
this.downloaded += downloaded
this.receiver(SyncEvent.StatusChanged)
}
public setDatabaseLoadStatus(current: number, total: number, done: boolean) {
this.databaseLoadCurrent = current
this.databaseLoadTotal = total
this.databaseLoadDone = done
if (done) {
this.receiver(SyncEvent.LocalDataLoaded)
} else {
this.receiver(SyncEvent.LocalDataIncrementalLoad)
}
}
public getStats() {
return {
uploadCompletionCount: this.completedUpload,
uploadTotalCount: this.totalUpload,
downloadCount: this.downloaded,
localDataDone: this.databaseLoadDone,
localDataCurrent: this.databaseLoadCurrent,
localDataTotal: this.databaseLoadTotal,
}
}
public setDidBegin() {
this.syncing = true
this.syncStart = new Date()
}
public setDidEnd() {
this.syncing = false
}
get syncInProgress() {
return this.syncing === true
}
get secondsSinceSyncStart() {
return (new Date().getTime() - this.syncStart.getTime()) / 1000
}
/**
* Notifies receiver if current sync request is taking too long to complete.
*/
startTimingMonitor(): void {
if (this.timingMonitor) {
this.stopTimingMonitor()
}
this.timingMonitor = this.interval(() => {
if (this.secondsSinceSyncStart > HEALTHY_SYNC_DURATION_THRESHOLD_S) {
this.receiver(SyncEvent.SyncTakingTooLong)
this.stopTimingMonitor()
}
}, TIMING_MONITOR_POLL_FREQUENCY_MS)
}
stopTimingMonitor(): void {
if (Object.prototype.hasOwnProperty.call(this.interval, 'cancel')) {
this.interval.cancel(this.timingMonitor)
} else {
clearInterval(this.timingMonitor)
}
this.timingMonitor = null
}
hasError(): boolean {
return !!this.error
}
setError(error: any): void {
this.error = error
}
clearError() {
this.error = null
}
reset() {
this.downloaded = 0
this.completedUpload = 0
this.totalUpload = 0
this.syncing = false
this.error = null
this.stopTimingMonitor()
this.receiver(SyncEvent.StatusChanged)
}
}

View File

@@ -13,14 +13,12 @@ import {
import { ItemManager } from '@Lib/Services/Items/ItemManager'
import { OfflineSyncOperation } from '@Lib/Services/Sync/Offline/Operation'
import { PayloadManager } from '../Payloads/PayloadManager'
import { SNApiService } from '../Api/ApiService'
import { SNHistoryManager } from '../History/HistoryManager'
import { LegacyApiService } from '../Api/ApiService'
import { HistoryManager } from '../History/HistoryManager'
import { SNLog } from '@Lib/Log'
import { SNSessionManager } from '../Session/SessionManager'
import { SessionManager } from '../Session/SessionManager'
import { DiskStorageService } from '../Storage/DiskStorageService'
import { SyncClientInterface } from './SyncClientInterface'
import { SyncPromise } from './Types'
import { SyncOpStatus } from '@Lib/Services/Sync/SyncOpStatus'
import { ServerSyncResponse } from '@Lib/Services/Sync/Account/Response'
import { ServerSyncResponseResolver } from '@Lib/Services/Sync/Account/ResponseResolver'
import { SyncSignal, SyncStats } from '@Lib/Services/Sync/Signals'
@@ -84,6 +82,7 @@ import {
SyncEventReceivedRemoteSharedVaultsData,
SyncEventReceivedUserEventsData,
SyncEventReceivedAsymmetricMessagesData,
SyncOpStatus,
} from '@standardnotes/services'
import { OfflineSyncResponse } from './Offline/Response'
import {
@@ -121,9 +120,9 @@ const ContentTypeLocalLoadPriorty = [
* After each sync request, any changes made or retrieved are also persisted locally.
* The sync service largely does not perform any task unless it is called upon.
*/
export class SNSyncService
export class SyncService
extends AbstractService<SyncEvent>
implements SyncServiceInterface, InternalEventHandlerInterface, SyncClientInterface
implements SyncServiceInterface, InternalEventHandlerInterface
{
private dirtyIndexAtLastPresyncSave?: number
private lastSyncDate?: Date
@@ -152,12 +151,12 @@ export class SNSyncService
constructor(
private itemManager: ItemManager,
private sessionManager: SNSessionManager,
private sessionManager: SessionManager,
private encryptionService: EncryptionService,
private storageService: DiskStorageService,
private payloadManager: PayloadManager,
private apiService: SNApiService,
private historyService: SNHistoryManager,
private apiService: LegacyApiService,
private historyService: HistoryManager,
private device: DeviceInterface,
private identifier: string,
private readonly options: ApplicationSyncOptions,
@@ -968,25 +967,25 @@ export class SNSyncService
const historyMap = this.historyService.getHistoryMapCopy()
if (response.userEvents) {
if (response.userEvents && response.userEvents.length > 0) {
await this.notifyEventSync(SyncEvent.ReceivedUserEvents, response.userEvents as SyncEventReceivedUserEventsData)
}
if (response.asymmetricMessages) {
if (response.asymmetricMessages && response.asymmetricMessages.length > 0) {
await this.notifyEventSync(
SyncEvent.ReceivedAsymmetricMessages,
response.asymmetricMessages as SyncEventReceivedAsymmetricMessagesData,
)
}
if (response.vaults) {
if (response.vaults && response.vaults.length > 0) {
await this.notifyEventSync(
SyncEvent.ReceivedRemoteSharedVaults,
response.vaults as SyncEventReceivedRemoteSharedVaultsData,
)
}
if (response.vaultInvites) {
if (response.vaultInvites && response.vaultInvites.length > 0) {
await this.notifyEventSync(
SyncEvent.ReceivedSharedVaultInvites,
response.vaultInvites as SyncEventReceivedSharedVaultInvitesData,

View File

@@ -1,7 +1,5 @@
export * from './SyncService'
export * from './Types'
export * from './SyncOpStatus'
export * from './SyncClientInterface'
export * from './Account/Operation'
export * from './Account/ResponseResolver'
export * from './Offline/Operation'

View File

@@ -1,4 +1,5 @@
export * from './Application'
export * from './Application/Dependencies/Types'
export * from './ApplicationGroup'
export * from './Client'
export * from './Domain'

View File

@@ -31,7 +31,7 @@ describe('001 protocol operations', () => {
})
it('cost minimum', () => {
expect(application.encryptionService.costMinimumForVersion('001')).to.equal(3000)
expect(application.encryption.costMinimumForVersion('001')).to.equal(3000)
})
it('generates valid keys for registration', async () => {
@@ -46,7 +46,7 @@ describe('001 protocol operations', () => {
it('generates valid keys from existing params and decrypts', async () => {
const password = 'password'
const keyParams = await application.encryptionService.createKeyParams({
const keyParams = await application.encryption.createKeyParams({
pw_func: 'pbkdf2',
pw_alg: 'sha512',
pw_key_size: 512,
@@ -67,7 +67,7 @@ describe('001 protocol operations', () => {
'sVuHmG0XAp1PRDE8r8XqFXijjP8Pqdwal9YFRrXK4hKLt1yyq8MwQU+1Z95Tz/b7ajYdidwFE0iDwd8Iu8281VtJsQ4yhh2tJiAzBy6newyHfhA5nH93yZ3iXRJaG87bgNQE9lsXzTV/OHAvqMuQtw/QVSWI3Qy1Pyu1Tn72q7FPKKhRRkzEEZ+Ax0BA1fHg',
uuid: '54001a6f-7c22-4b34-8316-fadf9b1fc255',
})
const decrypted = await application.encryptionService.decryptSplitSingle({
const decrypted = await application.encryption.decryptSplitSingle({
usesRootKey: {
items: [payload],
key: key,

View File

@@ -30,7 +30,7 @@ describe('002 protocol operations', () => {
})
it('cost minimum', () => {
expect(application.encryptionService.costMinimumForVersion('002')).to.equal(3000)
expect(application.encryption.costMinimumForVersion('002')).to.equal(3000)
})
it('generates valid keys for registration', async () => {
@@ -46,7 +46,7 @@ describe('002 protocol operations', () => {
it('generates valid keys from existing params and decrypts', async () => {
const password = 'password'
const keyParams = await application.encryptionService.createKeyParams({
const keyParams = await application.encryption.createKeyParams({
pw_salt: '8d381ef44cdeab1489194f87066b747b46053a833ee24956e846e7b40440f5f4',
pw_cost: 101000,
version: '002',
@@ -64,7 +64,7 @@ describe('002 protocol operations', () => {
'002:24a8e8f7728bbe06605d8209d87ad338d3d15ef81154bb64d3967c77daa01333:959b042a-3892-461e-8c50-477c10c7c40a:f1d294388742dca34f6f266a01483a4e:VdlEDyjhZ35GbJDg8ruSZv3Tp6WtMME3T5LLvcBYLHIMhrMi0RlPK83lK6F0aEaZvY82pZ0ntU+XpAX7JMSEdKdPXsACML7WeFrqKb3z2qHnA7NxgnIC0yVT/Z2mRrvlY3NNrUPGwJbfRcvfS7FVyw87MemT9CSubMZRviXvXETx82t7rsgjV/AIwOOeWhFi',
uuid: '959b042a-3892-461e-8c50-477c10c7c40a',
})
const decrypted = await application.encryptionService.decryptSplitSingle({
const decrypted = await application.encryption.decryptSplitSingle({
usesRootKey: {
items: [payload],
key: key,

View File

@@ -39,7 +39,7 @@ describe('003 protocol operations', () => {
it('cost minimum should throw', () => {
expect(() => {
sharedApplication.encryptionService.costMinimumForVersion('003')
sharedApplication.encryption.costMinimumForVersion('003')
}).to.throw('Cost minimums only apply to versions <= 002')
})
@@ -59,7 +59,7 @@ describe('003 protocol operations', () => {
it('computes proper keys for sign in', async () => {
const identifier = 'foo@bar.com'
const password = 'very_secure'
const keyParams = sharedApplication.encryptionService.createKeyParams({
const keyParams = sharedApplication.encryption.createKeyParams({
pw_nonce: 'baaec0131d677cf993381367eb082fe377cefe70118c1699cb9b38f0bc850e7b',
identifier: identifier,
version: '003',
@@ -73,7 +73,7 @@ describe('003 protocol operations', () => {
it('can decrypt item generated with web version 3.3.6', async () => {
const identifier = 'demo@standardnotes.org'
const password = 'password'
const keyParams = sharedApplication.encryptionService.createKeyParams({
const keyParams = sharedApplication.encryption.createKeyParams({
pw_nonce: '31107837b44d86179140b7c602a55d694243e2e9ced0c4c914ac21ad90215055',
identifier: identifier,
version: '003',

View File

@@ -25,16 +25,12 @@ describe('004 protocol operations', function () {
it('cost minimum should throw', function () {
expect(function () {
application.encryptionService.costMinimumForVersion('004')
application.encryption.costMinimumForVersion('004')
}).to.throw('Cost minimums only apply to versions <= 002')
})
it('generates valid keys for registration', async function () {
const key = await application.encryptionService.createRootKey(
_identifier,
_password,
KeyParamsOrigination.Registration,
)
const key = await application.encryption.createRootKey(_identifier, _password, KeyParamsOrigination.Registration)
expect(key.masterKey).to.be.ok
@@ -51,7 +47,7 @@ describe('004 protocol operations', function () {
it('computes proper keys for sign in', async function () {
const identifier = 'foo@bar.com'
const password = 'very_secure'
const keyParams = application.encryptionService.createKeyParams({
const keyParams = application.encryption.createKeyParams({
pw_nonce: 'baaec0131d677cf993381367eb082fe377cefe70118c1699cb9b38f0bc850e7b',
identifier: identifier,
version: '004',
@@ -64,7 +60,7 @@ describe('004 protocol operations', function () {
it('generates random key', async function () {
const length = 96
const key = await application.encryptionService.crypto.generateRandomKey(length)
const key = await application.encryption.crypto.generateRandomKey(length)
expect(key.length).to.equal(length / 4)
})
@@ -78,7 +74,7 @@ describe('004 protocol operations', function () {
}),
})
const operator = application.encryptionService.operators.operatorForVersion(ProtocolVersion.V004)
const operator = application.dependencies.get(TYPES.EncryptionOperators).operatorForVersion(ProtocolVersion.V004)
const encrypted = await operator.generateEncryptedParameters(payload, rootKey)
const decrypted = await operator.generateDecryptedParameters(encrypted, rootKey)
@@ -97,7 +93,7 @@ describe('004 protocol operations', function () {
}),
})
const operator = application.encryptionService.operators.operatorForVersion(ProtocolVersion.V004)
const operator = application.dependencies.get(TYPES.EncryptionOperators).operatorForVersion(ProtocolVersion.V004)
const encrypted = await operator.generateEncryptedParameters(payload, rootKey)
const decrypted = await operator.generateDecryptedParameters(
@@ -112,7 +108,7 @@ describe('004 protocol operations', function () {
})
it('generates existing keys for key params', async function () {
const key = await application.encryptionService.computeRootKey(_password, rootKeyParams)
const key = await application.encryption.computeRootKey(_password, rootKeyParams)
expect(key.compare(rootKey)).to.be.true
})

View File

@@ -55,4 +55,4 @@ export const BaseTests = [
'session.test.js',
'subscriptions.test.js',
'recovery.test.js',
];
]

View File

@@ -5,6 +5,8 @@ export const VaultTests = [
'vaults/contacts.test.js',
'vaults/crypto.test.js',
'vaults/asymmetric-messages.test.js',
'vaults/keypair-change.test.js',
'vaults/signatures.test.js',
'vaults/shared_vaults.test.js',
'vaults/invites.test.js',
'vaults/items.test.js',

View File

@@ -14,8 +14,8 @@ describe('actions service', () => {
localStorage.clear()
this.application = await Factory.createInitAppWithFakeCrypto()
this.itemManager = this.application.itemManager
this.actionsManager = this.application.actionsManager
this.itemManager = this.application.items
this.actionsManager = this.application.actions
this.email = UuidGenerator.GenerateUuid()
this.password = UuidGenerator.GenerateUuid()
@@ -25,7 +25,7 @@ describe('actions service', () => {
password: this.password,
})
const rootKey = await this.application.encryptionService.createRootKey(
const rootKey = await this.application.encryption.createRootKey(
this.email,
this.password,
KeyParamsOrigination.Registration,
@@ -117,7 +117,7 @@ describe('actions service', () => {
})
const encryptedPayload = CreateEncryptedServerSyncPushPayload(
await this.application.encryptionService.encryptSplitSingle({
await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [payload],
},
@@ -170,7 +170,10 @@ describe('actions service', () => {
})
// Extension item
const extensionItem = await this.application.mutator.createItem(ContentType.TYPES.ActionsExtension, this.actionsExtension)
const extensionItem = await this.application.mutator.createItem(
ContentType.TYPES.ActionsExtension,
this.actionsExtension,
)
this.extensionItemUuid = extensionItem.uuid
})
@@ -308,8 +311,8 @@ describe('actions service', () => {
})
beforeEach(async function () {
this.actionsManager.deviceInterface.openUrl = (url) => url
this.deviceInterfaceOpenUrl = sandbox.spy(this.actionsManager.deviceInterface, 'openUrl')
this.actionsManager.device.openUrl = (url) => url
this.deviceInterfaceOpenUrl = sandbox.spy(this.actionsManager.device, 'openUrl')
})
this.afterEach(async function () {
@@ -359,14 +362,14 @@ describe('actions service', () => {
const response = await this.actionsManager.runAction(this.encryptedPostAction, this.noteItem)
expect(response.items[0].enc_item_key).to.satisfy((string) => {
return string.startsWith(this.application.encryptionService.getLatestVersion())
return string.startsWith(this.application.encryption.getLatestVersion())
})
expect(response.items[0].uuid).to.eq(this.noteItem.uuid)
expect(response.items[0].auth_hash).to.not.be.ok
expect(response.items[0].content_type).to.be.ok
expect(response.items[0].created_at).to.be.ok
expect(response.items[0].content).to.satisfy((string) => {
return string.startsWith(this.application.encryptionService.getLatestVersion())
return string.startsWith(this.application.encryption.getLatestVersion())
})
})

View File

@@ -24,12 +24,12 @@ describe('application instances', () => {
const context2 = await Factory.createAppContext({ identifier: 'app2' })
await Promise.all([context1.launch(), context2.launch()])
expect(context1.application.payloadManager).to.equal(context1.application.payloadManager)
expect(context1.application.payloadManager).to.not.equal(context2.application.payloadManager)
expect(context1.application.payloads).to.equal(context1.application.payloads)
expect(context1.application.payloads).to.not.equal(context2.application.payloads)
await Factory.createMappedNote(context1.application)
expect(context1.application.itemManager.items.length).length.to.equal(BaseItemCounts.DefaultItems + 1)
expect(context2.application.itemManager.items.length).to.equal(BaseItemCounts.DefaultItems)
expect(context1.application.items.items.length).length.to.equal(BaseItemCounts.DefaultItems + 1)
expect(context2.application.items.items.length).to.equal(BaseItemCounts.DefaultItems)
await context1.deinit()
await context2.deinit()
@@ -40,16 +40,16 @@ describe('application instances', () => {
const app2 = await Factory.createAndInitializeApplication('app2')
await Factory.createMappedNote(app1)
await app1.syncService.sync(syncOptions)
await app1.sync.sync(syncOptions)
expect((await app1.diskStorageService.getAllRawPayloads()).length).length.to.equal(BaseItemCounts.DefaultItems + 1)
expect((await app2.diskStorageService.getAllRawPayloads()).length).length.to.equal(BaseItemCounts.DefaultItems)
expect((await app1.storage.getAllRawPayloads()).length).length.to.equal(BaseItemCounts.DefaultItems + 1)
expect((await app2.storage.getAllRawPayloads()).length).length.to.equal(BaseItemCounts.DefaultItems)
await Factory.createMappedNote(app2)
await app2.syncService.sync(syncOptions)
await app2.sync.sync(syncOptions)
expect((await app1.diskStorageService.getAllRawPayloads()).length).length.to.equal(BaseItemCounts.DefaultItems + 1)
expect((await app2.diskStorageService.getAllRawPayloads()).length).length.to.equal(BaseItemCounts.DefaultItems + 1)
expect((await app1.storage.getAllRawPayloads()).length).length.to.equal(BaseItemCounts.DefaultItems + 1)
expect((await app2.storage.getAllRawPayloads()).length).length.to.equal(BaseItemCounts.DefaultItems + 1)
await Factory.safeDeinit(app1)
await Factory.safeDeinit(app2)
})
@@ -58,7 +58,7 @@ describe('application instances', () => {
/** This test will always succeed but should be observed for console exceptions */
const app = await Factory.createAndInitializeApplication('app')
/** Don't await */
app.diskStorageService.persistValuesToDisk()
app.storage.persistValuesToDisk()
await app.prepareForDeinit()
await Factory.safeDeinit(app)
})
@@ -101,13 +101,13 @@ describe('application instances', () => {
const app = await Factory.createAndInitializeApplication('app')
/** Don't await */
const MaximumWaitTime = 0.5
app.diskStorageService.executeCriticalFunction(async () => {
app.storage.executeCriticalFunction(async () => {
/** If we sleep less than the maximum, locking should occur safely.
* If we sleep more than the maximum, locking should occur with exception on
* app deinit. */
await Factory.sleep(MaximumWaitTime - 0.05)
/** Access any deviceInterface function */
app.diskStorageService.deviceInterface.getAllDatabaseEntries(app.identifier)
app.device.getAllDatabaseEntries(app.identifier)
})
await app.lock()
})

View File

@@ -48,7 +48,7 @@ describe('auth fringe cases', () => {
console.warn("Expecting errors 'Unable to find operator for version undefined'")
const restartedApplication = await Factory.restartApplication(context.application)
const refreshedNote = restartedApplication.payloadManager.findOne(note.uuid)
const refreshedNote = restartedApplication.payloads.findOne(note.uuid)
expect(refreshedNote.errorDecrypting).to.equal(true)
await Factory.safeDeinit(restartedApplication)
@@ -67,9 +67,9 @@ describe('auth fringe cases', () => {
)
await restartedApplication.signIn(context.email, context.password, undefined, undefined, undefined, awaitSync)
const refreshedNote = restartedApplication.itemManager.findItem(note.uuid)
const refreshedNote = restartedApplication.items.findItem(note.uuid)
expect(isDecryptedItem(refreshedNote)).to.equal(true)
expect(restartedApplication.itemManager.getDisplayableNotes().length).to.equal(1)
expect(restartedApplication.items.getDisplayableNotes().length).to.equal(1)
await Factory.safeDeinit(restartedApplication)
}).timeout(10000)
})
@@ -97,15 +97,13 @@ describe('auth fringe cases', () => {
/** Sign in and merge local data */
await newApplication.signIn(context.email, context.password, undefined, undefined, true, true)
expect(newApplication.itemManager.getDisplayableNotes().length).to.equal(2)
expect(newApplication.items.getDisplayableNotes().length).to.equal(2)
expect(
newApplication.itemManager.getDisplayableNotes().find((n) => n.uuid === firstVersionOfNote.uuid).text,
).to.equal(staleText)
expect(newApplication.items.getDisplayableNotes().find((n) => n.uuid === firstVersionOfNote.uuid).text).to.equal(
staleText,
)
const conflictedCopy = newApplication.itemManager
.getDisplayableNotes()
.find((n) => n.uuid !== firstVersionOfNote.uuid)
const conflictedCopy = newApplication.items.getDisplayableNotes().find((n) => n.uuid !== firstVersionOfNote.uuid)
expect(conflictedCopy.text).to.equal(serverText)
expect(conflictedCopy.duplicate_of).to.equal(firstVersionOfNote.uuid)
await Factory.safeDeinit(newApplication)

View File

@@ -31,7 +31,7 @@ describe('basic auth', function () {
it('successfully register new account', async function () {
const response = await this.application.register(this.email, this.password)
expect(response).to.be.ok
expect(await this.application.encryptionService.getRootKey()).to.be.ok
expect(await this.application.encryption.getRootKey()).to.be.ok
})
it('fails register new account with short password', async function () {
@@ -49,18 +49,18 @@ describe('basic auth', function () {
'For your security, please choose a longer password or, ideally, a passphrase, and try again.',
)
expect(await this.application.encryptionService.getRootKey()).to.not.be.ok
expect(await this.application.encryption.getRootKey()).to.not.be.ok
})
it('successfully signs out of account', async function () {
await this.application.register(this.email, this.password)
expect(await this.application.encryptionService.getRootKey()).to.be.ok
expect(await this.application.encryption.getRootKey()).to.be.ok
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
expect(await this.application.encryptionService.getRootKey()).to.not.be.ok
expect(this.application.encryptionService.rootKeyManager.getKeyMode()).to.equal(KeyMode.RootKeyNone)
expect(await this.application.encryption.getRootKey()).to.not.be.ok
expect(this.application.encryption.rootKeyManager.getKeyMode()).to.equal(KeyMode.RootKeyNone)
})
it('successfully signs in to registered account', async function () {
@@ -69,7 +69,7 @@ describe('basic auth', function () {
const response = await this.application.signIn(this.email, this.password, undefined, undefined, undefined, true)
expect(response).to.be.ok
expect(response.data.error).to.not.be.ok
expect(await this.application.encryptionService.getRootKey()).to.be.ok
expect(await this.application.encryption.getRootKey()).to.be.ok
}).timeout(20000)
it('cannot sign while already signed in', async function () {
@@ -79,7 +79,7 @@ describe('basic auth', function () {
const response = await this.application.signIn(this.email, this.password, undefined, undefined, undefined, true)
expect(response).to.be.ok
expect(response.data.error).to.not.be.ok
expect(await this.application.encryptionService.getRootKey()).to.be.ok
expect(await this.application.encryption.getRootKey()).to.be.ok
let error
try {
@@ -99,7 +99,7 @@ describe('basic auth', function () {
error = e
}
expect(error).to.be.ok
expect(await this.application.encryptionService.getRootKey()).to.be.ok
expect(await this.application.encryption.getRootKey()).to.be.ok
}).timeout(20000)
it('cannot perform two sign-ins at the same time', async function () {
@@ -111,7 +111,7 @@ describe('basic auth', function () {
const response = await this.application.signIn(this.email, this.password, undefined, undefined, undefined, true)
expect(response).to.be.ok
expect(response.data.error).to.not.be.ok
expect(await this.application.encryptionService.getRootKey()).to.be.ok
expect(await this.application.encryption.getRootKey()).to.be.ok
})(),
(async () => {
/** Make sure the first function runs first */
@@ -134,7 +134,7 @@ describe('basic auth', function () {
const response = await this.application.register(this.email, this.password)
expect(response).to.be.ok
expect(response.error).to.not.be.ok
expect(await this.application.encryptionService.getRootKey()).to.be.ok
expect(await this.application.encryption.getRootKey()).to.be.ok
})(),
(async () => {
/** Make sure the first function runs first */
@@ -185,7 +185,7 @@ describe('basic auth', function () {
*/
await this.application.register(uppercase, this.password)
const response = await this.application.sessionManager.retrieveKeyParams(lowercase)
const response = await this.application.sessions.retrieveKeyParams(lowercase)
const keyParams = response.keyParams
expect(keyParams.identifier).to.equal(lowercase)
expect(keyParams.identifier).to.not.equal(uppercase)
@@ -204,7 +204,7 @@ describe('basic auth', function () {
const response = await this.application.signIn(uppercase, this.password, undefined, undefined, undefined, true)
expect(response).to.be.ok
expect(response.data.error).to.not.be.ok
expect(await this.application.encryptionService.getRootKey()).to.be.ok
expect(await this.application.encryption.getRootKey()).to.be.ok
}).timeout(20000)
it('can sign into account regardless of whitespace', async function () {
@@ -220,7 +220,7 @@ describe('basic auth', function () {
const response = await this.application.signIn(withspace, this.password, undefined, undefined, undefined, true)
expect(response).to.be.ok
expect(response.data.error).to.not.be.ok
expect(await this.application.encryptionService.getRootKey()).to.be.ok
expect(await this.application.encryption.getRootKey()).to.be.ok
}).timeout(20000)
it('fails login with wrong password', async function () {
@@ -229,7 +229,7 @@ describe('basic auth', function () {
const response = await this.application.signIn(this.email, 'wrongpassword', undefined, undefined, undefined, true)
expect(response).to.be.ok
expect(response.data.error).to.be.ok
expect(await this.application.encryptionService.getRootKey()).to.not.be.ok
expect(await this.application.encryption.getRootKey()).to.not.be.ok
}).timeout(20000)
it('fails to change to short password', async function () {
@@ -255,7 +255,7 @@ describe('basic auth', function () {
let outOfSync = true
let didCompletePostDownloadFirstSync = false
let didCompleteDownloadFirstSync = false
this.application.syncService.addEventObserver((eventName) => {
this.application.sync.addEventObserver((eventName) => {
if (eventName === SyncEvent.DownloadFirstSyncCompleted) {
didCompleteDownloadFirstSync = true
}
@@ -265,7 +265,7 @@ describe('basic auth', function () {
if (!didCompletePostDownloadFirstSync && eventName === SyncEvent.PaginatedSyncRequestCompleted) {
didCompletePostDownloadFirstSync = true
/** Should be in sync */
outOfSync = this.application.syncService.isOutOfSync()
outOfSync = this.application.sync.isOutOfSync()
}
})
@@ -289,9 +289,9 @@ describe('basic auth', function () {
this.expectedItemCount += noteCount
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
const newPassword = 'newpassword'
const response = await this.application.changePassword(this.password, newPassword)
@@ -299,18 +299,18 @@ describe('basic auth', function () {
/** New items key */
this.expectedItemCount++
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
expect(response.error).to.not.be.ok
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.payloadManager.invalidPayloads.length).to.equal(0)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
expect(this.application.payloads.invalidPayloads.length).to.equal(0)
await this.application.syncService.markAllItemsAsNeedingSyncAndPersist()
await this.application.syncService.sync(syncOptions)
await this.application.sync.markAllItemsAsNeedingSyncAndPersist()
await this.application.sync.sync(syncOptions)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
const note = this.application.itemManager.getDisplayableNotes()[0]
const note = this.application.items.getDisplayableNotes()[0]
/**
* Create conflict for a note. First modify the item without saving so that
@@ -339,10 +339,10 @@ describe('basic auth', function () {
expect(signinResponse).to.be.ok
expect(signinResponse.data.error).to.not.be.ok
expect(await this.application.encryptionService.getRootKey()).to.be.ok
expect(await this.application.encryption.getRootKey()).to.be.ok
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.payloadManager.invalidPayloads.length).to.equal(0)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
expect(this.application.payloads.invalidPayloads.length).to.equal(0)
}
it('successfully changes password', changePassword).timeout(40000)
@@ -383,7 +383,7 @@ describe('basic auth', function () {
const noteCount = 10
await Factory.createManyMappedNotes(this.application, noteCount)
this.expectedItemCount += noteCount
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
const numTimesToChangePw = 3
let newPassword = Factory.randomString()
@@ -398,16 +398,16 @@ describe('basic auth', function () {
currentPassword = newPassword
newPassword = Factory.randomString()
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.payloadManager.invalidPayloads.length).to.equal(0)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
expect(this.application.payloads.invalidPayloads.length).to.equal(0)
await this.application.syncService.markAllItemsAsNeedingSyncAndPersist()
await this.application.syncService.sync(syncOptions)
await this.application.sync.markAllItemsAsNeedingSyncAndPersist()
await this.application.sync.sync(syncOptions)
this.application = await this.context.signout()
expect(this.application.itemManager.items.length).to.equal(BaseItemCounts.DefaultItems)
expect(this.application.payloadManager.invalidPayloads.length).to.equal(0)
expect(this.application.items.items.length).to.equal(BaseItemCounts.DefaultItems)
expect(this.application.payloads.invalidPayloads.length).to.equal(0)
/** Should login with new password */
const signinResponse = await this.application.signIn(
@@ -421,7 +421,7 @@ describe('basic auth', function () {
expect(signinResponse).to.be.ok
expect(signinResponse.data.error).to.not.be.ok
expect(await this.application.encryptionService.getRootKey()).to.be.ok
expect(await this.application.encryption.getRootKey()).to.be.ok
}
}).timeout(80000)
@@ -432,7 +432,7 @@ describe('basic auth', function () {
password: this.password,
})
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
const performSignIn = sinon.spy(this.application.sessionManager, 'performSignIn')
const performSignIn = sinon.spy(this.application.sessions, 'performSignIn')
await this.application.signIn(this.email, 'wrong password', undefined, undefined, undefined, true)
expect(performSignIn.callCount).to.equal(1)
})
@@ -441,8 +441,8 @@ describe('basic auth', function () {
/** Should delete the new items key locally without marking it as deleted so that it doesn't sync */
await this.context.register()
const originalImpl = this.application.encryptionService.getSureDefaultItemsKey
this.application.encryptionService.getSureDefaultItemsKey = () => {
const originalImpl = this.application.encryption.getSureDefaultItemsKey
this.application.encryption.getSureDefaultItemsKey = () => {
return {
neverSynced: true,
}
@@ -454,7 +454,7 @@ describe('basic auth', function () {
await this.context.changePassword('new-password')
this.application.encryptionService.getSureDefaultItemsKey = originalImpl
this.application.encryption.getSureDefaultItemsKey = originalImpl
expect(mutatorSpy.callCount).to.equal(0)
expect(removeItemsSpy.callCount).to.equal(1)
@@ -518,8 +518,8 @@ describe('basic auth', function () {
const _response = await this.application.deleteAccount()
sinon.spy(snApp.challengeService, 'sendChallenge')
const spyCall = snApp.challengeService.sendChallenge.getCall(0)
sinon.spy(snApp.challenges, 'sendChallenge')
const spyCall = snApp.challenges.sendChallenge.getCall(0)
const challenge = spyCall.firstArg
expect(challenge.prompts).to.have.lengthOf(2)
expect(challenge.prompts[0].validation).to.equal(ChallengeValidation.AccountPassword)

View File

@@ -27,10 +27,10 @@ describe('backups', function () {
it('backup file should have a version number', async function () {
let data = await this.application.createDecryptedBackupFile()
expect(data.version).to.equal(this.application.encryptionService.getLatestVersion())
expect(data.version).to.equal(this.application.encryption.getLatestVersion())
await this.application.addPasscode('passcode')
data = await this.application.createEncryptedBackupFileForAutomatedDesktopBackups()
expect(data.version).to.equal(this.application.encryptionService.getLatestVersion())
expect(data.version).to.equal(this.application.encryption.getLatestVersion())
})
it('no passcode + no account backup file should have correct number of items', async function () {
@@ -143,7 +143,7 @@ describe('backups', function () {
const note = await Factory.createSyncedNote(this.application)
const encrypted = await this.application.encryptionService.encryptSplitSingle({
const encrypted = await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [note.payload],
},
@@ -153,9 +153,9 @@ describe('backups', function () {
errorDecrypting: true,
})
await this.application.payloadManager.emitPayload(errored)
await this.application.payloads.emitPayload(errored)
const erroredItem = this.application.itemManager.findAnyItem(errored.uuid)
const erroredItem = this.application.items.findAnyItem(errored.uuid)
expect(erroredItem.errorDecrypting).to.equal(true)

View File

@@ -18,11 +18,11 @@ describe('device authentication', function () {
const application = await Factory.createAndInitializeApplication(namespace)
const passcode = 'foobar'
const wrongPasscode = 'barfoo'
expect(await application.protectionService.createLaunchChallenge()).to.not.be.ok
expect(await application.protections.createLaunchChallenge()).to.not.be.ok
await application.addPasscode(passcode)
expect(await application.hasPasscode()).to.equal(true)
expect(await application.protectionService.createLaunchChallenge()).to.be.ok
expect(application.encryptionService.rootKeyManager.getKeyMode()).to.equal(KeyMode.WrapperOnly)
expect(await application.protections.createLaunchChallenge()).to.be.ok
expect(application.encryption.rootKeyManager.getKeyMode()).to.equal(KeyMode.WrapperOnly)
await Factory.safeDeinit(application)
/** Recreate application and initialize */
@@ -49,10 +49,10 @@ describe('device authentication', function () {
tmpApplication.submitValuesForChallenge(challenge, initialValues)
}
await tmpApplication.prepareForLaunch({ receiveChallenge })
expect(await tmpApplication.encryptionService.getRootKey()).to.not.be.ok
expect(await tmpApplication.encryption.getRootKey()).to.not.be.ok
await tmpApplication.launch(true)
expect(await tmpApplication.encryptionService.getRootKey()).to.be.ok
expect(tmpApplication.encryptionService.rootKeyManager.getKeyMode()).to.equal(KeyMode.WrapperOnly)
expect(await tmpApplication.encryption.getRootKey()).to.be.ok
expect(tmpApplication.encryption.rootKeyManager.getKeyMode()).to.equal(KeyMode.WrapperOnly)
await Factory.safeDeinit(tmpApplication)
}).timeout(10000)
@@ -64,8 +64,8 @@ describe('device authentication', function () {
await application.addPasscode(passcode)
await application.protections.enableBiometrics()
expect(await application.hasPasscode()).to.equal(true)
expect((await application.protectionService.createLaunchChallenge()).prompts.length).to.equal(2)
expect(application.encryptionService.rootKeyManager.getKeyMode()).to.equal(KeyMode.WrapperOnly)
expect((await application.protections.createLaunchChallenge()).prompts.length).to.equal(2)
expect(application.encryption.rootKeyManager.getKeyMode()).to.equal(KeyMode.WrapperOnly)
await Factory.safeDeinit(application)
/** Recreate application and initialize */
@@ -98,11 +98,11 @@ describe('device authentication', function () {
}
await tmpApplication.prepareForLaunch({ receiveChallenge })
expect(await tmpApplication.encryptionService.getRootKey()).to.not.be.ok
expect((await tmpApplication.protectionService.createLaunchChallenge()).prompts.length).to.equal(2)
expect(await tmpApplication.encryption.getRootKey()).to.not.be.ok
expect((await tmpApplication.protections.createLaunchChallenge()).prompts.length).to.equal(2)
await tmpApplication.launch(true)
expect(await tmpApplication.encryptionService.getRootKey()).to.be.ok
expect(tmpApplication.encryptionService.rootKeyManager.getKeyMode()).to.equal(KeyMode.WrapperOnly)
expect(await tmpApplication.encryption.getRootKey()).to.be.ok
expect(tmpApplication.encryption.rootKeyManager.getKeyMode()).to.equal(KeyMode.WrapperOnly)
await Factory.safeDeinit(tmpApplication)
}).timeout(Factory.TwentySecondTimeout)
@@ -118,12 +118,12 @@ describe('device authentication', function () {
})
const sampleStorageKey = 'foo'
const sampleStorageValue = 'bar'
await application.diskStorageService.setValue(sampleStorageKey, sampleStorageValue)
expect(application.encryptionService.rootKeyManager.getKeyMode()).to.equal(KeyMode.RootKeyOnly)
await application.storage.setValue(sampleStorageKey, sampleStorageValue)
expect(application.encryption.rootKeyManager.getKeyMode()).to.equal(KeyMode.RootKeyOnly)
const passcode = 'foobar'
Factory.handlePasswordChallenges(application, password)
await application.addPasscode(passcode)
expect(application.encryptionService.rootKeyManager.getKeyMode()).to.equal(KeyMode.RootKeyPlusWrapper)
expect(application.encryption.rootKeyManager.getKeyMode()).to.equal(KeyMode.RootKeyPlusWrapper)
expect(await application.hasPasscode()).to.equal(true)
await Factory.safeDeinit(application)
@@ -154,11 +154,11 @@ describe('device authentication', function () {
await tmpApplication.prepareForLaunch({
receiveChallenge: receiveChallenge,
})
expect(await tmpApplication.encryptionService.getRootKey()).to.not.be.ok
expect(await tmpApplication.encryption.getRootKey()).to.not.be.ok
await tmpApplication.launch(true)
expect(await tmpApplication.diskStorageService.getValue(sampleStorageKey)).to.equal(sampleStorageValue)
expect(await tmpApplication.encryptionService.getRootKey()).to.be.ok
expect(tmpApplication.encryptionService.rootKeyManager.getKeyMode()).to.equal(KeyMode.RootKeyPlusWrapper)
expect(await tmpApplication.storage.getValue(sampleStorageKey)).to.equal(sampleStorageValue)
expect(await tmpApplication.encryption.getRootKey()).to.be.ok
expect(tmpApplication.encryption.rootKeyManager.getKeyMode()).to.equal(KeyMode.RootKeyPlusWrapper)
await Factory.safeDeinit(tmpApplication)
}).timeout(Factory.TwentySecondTimeout)
})

View File

@@ -32,8 +32,8 @@ describe('features', () => {
describe('new user roles received on api response meta', () => {
it('should save roles and features', async () => {
expect(application.featuresService.onlineRoles).to.have.lengthOf(1)
expect(application.featuresService.onlineRoles[0]).to.equal('CORE_USER')
expect(application.features.onlineRoles).to.have.lengthOf(1)
expect(application.features.onlineRoles[0]).to.equal('CORE_USER')
const storedRoles = await application.getValue(StorageKey.UserRoles)
@@ -44,7 +44,7 @@ describe('features', () => {
describe('extension repo items observer', () => {
it('should migrate to user setting when extension repo is added', async () => {
sinon.stub(application.apiService, 'isThirdPartyHostUsed').callsFake(() => {
sinon.stub(application.legacyApi, 'isThirdPartyHostUsed').callsFake(() => {
return false
})
@@ -57,7 +57,7 @@ describe('features', () => {
const extensionKey = UuidGenerator.GenerateUuid().split('-').join('')
const promise = new Promise((resolve) => {
sinon.stub(application.featuresService, 'migrateFeatureRepoToUserSetting').callsFake(resolve)
sinon.stub(application.features, 'migrateFeatureRepoToUserSetting').callsFake(resolve)
})
await application.mutator.createItem(
@@ -71,14 +71,14 @@ describe('features', () => {
})
it('signing into account with ext repo should migrate it', async () => {
sinon.stub(application.apiService, 'isThirdPartyHostUsed').callsFake(() => {
sinon.stub(application.legacyApi, 'isThirdPartyHostUsed').callsFake(() => {
return false
})
/** Attach an ExtensionRepo object to an account, but prevent it from being migrated.
* Then sign out, sign back in, and ensure the item is migrated. */
/** Prevent migration from running */
sinon
.stub(application.featuresService, 'migrateFeatureRepoToUserSetting')
.stub(application.features, 'migrateFeatureRepoToUserSetting')
// eslint-disable-next-line @typescript-eslint/no-empty-function
.callsFake(() => {})
const extensionKey = UuidGenerator.GenerateUuid().split('-').join('')
@@ -93,11 +93,11 @@ describe('features', () => {
application = await Factory.signOutApplicationAndReturnNew(application)
sinon.restore()
sinon.stub(application.apiService, 'isThirdPartyHostUsed').callsFake(() => {
sinon.stub(application.legacyApi, 'isThirdPartyHostUsed').callsFake(() => {
return false
})
const promise = new Promise((resolve) => {
sinon.stub(application.featuresService, 'migrateFeatureRepoToUserSetting').callsFake(resolve)
sinon.stub(application.features, 'migrateFeatureRepoToUserSetting').callsFake(resolve)
})
await Factory.loginToApplication({
application,
@@ -109,7 +109,7 @@ describe('features', () => {
it('having an ext repo with no account, then signing into account, should migrate it', async () => {
application = await Factory.signOutApplicationAndReturnNew(application)
sinon.stub(application.apiService, 'isThirdPartyHostUsed').callsFake(() => {
sinon.stub(application.legacyApi, 'isThirdPartyHostUsed').callsFake(() => {
return false
})
const extensionKey = UuidGenerator.GenerateUuid().split('-').join('')
@@ -123,7 +123,7 @@ describe('features', () => {
await application.sync.sync()
const promise = new Promise((resolve) => {
sinon.stub(application.featuresService, 'migrateFeatureRepoToUserSetting').callsFake(resolve)
sinon.stub(application.features, 'migrateFeatureRepoToUserSetting').callsFake(resolve)
})
await Factory.loginToApplication({
application,
@@ -134,7 +134,7 @@ describe('features', () => {
})
it.skip('migrated ext repo should have property indicating it was migrated', async () => {
sinon.stub(application.apiService, 'isThirdPartyHostUsed').callsFake(() => {
sinon.stub(application.legacyApi, 'isThirdPartyHostUsed').callsFake(() => {
return false
})
expect(await application.settings.getDoesSensitiveSettingExist(SettingName.ExtensionKey)).to.equal(false)
@@ -171,7 +171,7 @@ describe('features', () => {
)
await application.sync.sync()
const repo = application.featuresService.getOfflineRepo()
const repo = application.features.getOfflineRepo()
expect(repo.migratedToOfflineEntitlements).to.equal(true)
expect(repo.offlineFeaturesUrl).to.equal('https://api.standardnotes.com/v1/offline/features')
expect(repo.offlineKey).to.equal(extensionKey)

View File

@@ -12,7 +12,6 @@ describe('files', function () {
let context
let fileService
let itemManager
let subscriptionId = 1001
beforeEach(function () {
localStorage.clear()
@@ -28,8 +27,8 @@ describe('files', function () {
await context.launch()
application = context.application
fileService = context.application.fileService
itemManager = context.application.itemManager
fileService = context.application.files
itemManager = context.application.items
await Factory.registerUserToApplication({
application: context.application,
@@ -51,7 +50,7 @@ describe('files', function () {
await setup({ fakeCrypto: true, subscription: true })
const remoteIdentifier = Utils.generateUuid()
const token = await application.apiService.createUserFileValetToken(remoteIdentifier, ValetTokenOperation.Write)
const token = await application.legacyApi.createUserFileValetToken(remoteIdentifier, ValetTokenOperation.Write)
expect(token.length).to.be.above(0)
})
@@ -60,7 +59,7 @@ describe('files', function () {
await setup({ fakeCrypto: true, subscription: false })
const remoteIdentifier = Utils.generateUuid()
const tokenOrError = await application.apiService.createUserFileValetToken(
const tokenOrError = await application.legacyApi.createUserFileValetToken(
remoteIdentifier,
ValetTokenOperation.Write,
)
@@ -79,7 +78,7 @@ describe('files', function () {
})
const remoteIdentifier = Utils.generateUuid()
const tokenOrError = await application.apiService.createUserFileValetToken(
const tokenOrError = await application.legacyApi.createUserFileValetToken(
remoteIdentifier,
ValetTokenOperation.Write,
)
@@ -90,19 +89,19 @@ describe('files', function () {
it('creating two upload sessions successively should succeed', async function () {
await setup({ fakeCrypto: true, subscription: true })
const firstToken = await application.apiService.createUserFileValetToken(
const firstToken = await application.legacyApi.createUserFileValetToken(
Utils.generateUuid(),
ValetTokenOperation.Write,
)
const firstSession = await application.apiService.startUploadSession(firstToken, 'user')
const firstSession = await application.legacyApi.startUploadSession(firstToken, 'user')
expect(firstSession.uploadId).to.be.ok
const secondToken = await application.apiService.createUserFileValetToken(
const secondToken = await application.legacyApi.createUserFileValetToken(
Utils.generateUuid(),
ValetTokenOperation.Write,
)
const secondSession = await application.apiService.startUploadSession(secondToken, 'user')
const secondSession = await application.legacyApi.startUploadSession(secondToken, 'user')
expect(secondSession.uploadId).to.be.ok
})

View File

@@ -24,10 +24,10 @@ describe('history manager', () => {
describe('session', function () {
beforeEach(async function () {
this.application = await Factory.createInitAppWithFakeCrypto()
this.historyManager = this.application.historyManager
this.payloadManager = this.application.payloadManager
this.history = this.application.dependencies.get(TYPES.HistoryManager)
this.payloadManager = this.application.payloads
/** Automatically optimize after every revision by setting this to 0 */
this.historyManager.itemRevisionThreshold = 0
this.history.itemRevisionThreshold = 0
})
afterEach(async function () {
@@ -52,11 +52,11 @@ describe('history manager', () => {
it('create basic history entries 1', async function () {
const item = await Factory.createSyncedNote(this.application)
expect(this.historyManager.sessionHistoryForItem(item).length).to.equal(0)
expect(this.history.sessionHistoryForItem(item).length).to.equal(0)
/** Sync with same contents, should not create new entry */
await Factory.markDirtyAndSyncItem(this.application, item)
expect(this.historyManager.sessionHistoryForItem(item).length).to.equal(0)
expect(this.history.sessionHistoryForItem(item).length).to.equal(0)
/** Sync with different contents, should create new entry */
await this.application.changeAndSaveItem(
@@ -68,7 +68,7 @@ describe('history manager', () => {
undefined,
syncOptions,
)
expect(this.historyManager.sessionHistoryForItem(item).length).to.equal(1)
expect(this.history.sessionHistoryForItem(item).length).to.equal(1)
})
it('first change should create revision with previous value', async function () {
@@ -78,7 +78,7 @@ describe('history manager', () => {
/** Simulate loading new application session */
const context = await Factory.createAppContext({ identifier })
await context.launch()
expect(context.application.historyManager.sessionHistoryForItem(item).length).to.equal(0)
expect(context.history.sessionHistoryForItem(item).length).to.equal(0)
await context.application.changeAndSaveItem(
item,
(mutator) => {
@@ -88,7 +88,7 @@ describe('history manager', () => {
undefined,
syncOptions,
)
const entries = context.application.historyManager.sessionHistoryForItem(item)
const entries = context.history.sessionHistoryForItem(item)
expect(entries.length).to.equal(1)
expect(entries[0].payload.content.title).to.equal(item.content.title)
await context.deinit()
@@ -101,7 +101,7 @@ describe('history manager', () => {
references: [],
})
await context.application.mutator.insertItem(item)
expect(context.application.historyManager.sessionHistoryForItem(item).length).to.equal(0)
expect(context.history.sessionHistoryForItem(item).length).to.equal(0)
await context.application.changeAndSaveItem(
item,
@@ -112,7 +112,7 @@ describe('history manager', () => {
undefined,
syncOptions,
)
expect(context.application.historyManager.sessionHistoryForItem(item).length).to.equal(0)
expect(context.history.sessionHistoryForItem(item).length).to.equal(0)
await context.deinit()
})
@@ -123,14 +123,14 @@ describe('history manager', () => {
* won't here because it's the first change, which we want to keep.
*/
await setTextAndSync(this.application, item, item.content.text + '1')
expect(this.historyManager.sessionHistoryForItem(item).length).to.equal(1)
expect(this.history.sessionHistoryForItem(item).length).to.equal(1)
/**
* Changing it by one character should keep this entry,
* since it's now the last (and will keep the first)
*/
item = await setTextAndSync(this.application, item, item.content.text + '2')
expect(this.historyManager.sessionHistoryForItem(item).length).to.equal(2)
expect(this.history.sessionHistoryForItem(item).length).to.equal(2)
/**
* Change it over the largeCharacterChange threshold. It should keep this
* revision, but now remove the previous revision, since it's no longer
@@ -141,29 +141,29 @@ describe('history manager', () => {
item,
item.content.text + Factory.randomString(largeCharacterChange + 1),
)
expect(this.historyManager.sessionHistoryForItem(item).length).to.equal(2)
expect(this.history.sessionHistoryForItem(item).length).to.equal(2)
item = await setTextAndSync(
this.application,
item,
item.content.text + Factory.randomString(largeCharacterChange + 1),
)
expect(this.historyManager.sessionHistoryForItem(item).length).to.equal(2)
expect(this.history.sessionHistoryForItem(item).length).to.equal(2)
/** Delete over threshold text. */
item = await setTextAndSync(
this.application,
item,
deleteCharsFromString(item.content.text, largeCharacterChange + 1),
)
expect(this.historyManager.sessionHistoryForItem(item).length).to.equal(3)
expect(this.history.sessionHistoryForItem(item).length).to.equal(3)
/**
* Delete just 1 character. It should now retain the previous revision, as well as the
* one previous to that.
*/
item = await setTextAndSync(this.application, item, deleteCharsFromString(item.content.text, 1))
expect(this.historyManager.sessionHistoryForItem(item).length).to.equal(4)
expect(this.history.sessionHistoryForItem(item).length).to.equal(4)
item = await setTextAndSync(this.application, item, deleteCharsFromString(item.content.text, 1))
expect(this.historyManager.sessionHistoryForItem(item).length).to.equal(5)
expect(this.history.sessionHistoryForItem(item).length).to.equal(5)
})
it('should keep the entry right before a large deletion, regardless of its delta', async function () {
@@ -174,25 +174,25 @@ describe('history manager', () => {
)
let item = await this.application.mutator.emitItemFromPayload(payload, PayloadEmitSource.LocalChanged)
await this.application.mutator.setItemDirty(item)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
/** It should keep the first and last by default */
item = await setTextAndSync(this.application, item, item.content.text)
item = await setTextAndSync(this.application, item, item.content.text + Factory.randomString(1))
expect(this.historyManager.sessionHistoryForItem(item).length).to.equal(2)
expect(this.history.sessionHistoryForItem(item).length).to.equal(2)
item = await setTextAndSync(
this.application,
item,
deleteCharsFromString(item.content.text, largeCharacterChange + 1),
)
expect(this.historyManager.sessionHistoryForItem(item).length).to.equal(2)
expect(this.history.sessionHistoryForItem(item).length).to.equal(2)
item = await setTextAndSync(this.application, item, item.content.text + Factory.randomString(1))
expect(this.historyManager.sessionHistoryForItem(item).length).to.equal(3)
expect(this.history.sessionHistoryForItem(item).length).to.equal(3)
item = await setTextAndSync(
this.application,
item,
item.content.text + Factory.randomString(largeCharacterChange + 1),
)
expect(this.historyManager.sessionHistoryForItem(item).length).to.equal(4)
expect(this.history.sessionHistoryForItem(item).length).to.equal(4)
})
it('entries should be ordered from newest to oldest', async function () {
@@ -205,7 +205,7 @@ describe('history manager', () => {
let item = await this.application.mutator.emitItemFromPayload(payload, PayloadEmitSource.LocalChanged)
await this.application.mutator.setItemDirty(item)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
item = await setTextAndSync(this.application, item, item.content.text + Factory.randomString(1))
@@ -224,10 +224,10 @@ describe('history manager', () => {
)
/** First entry should be the latest revision. */
const latestRevision = this.historyManager.sessionHistoryForItem(item)[0]
const latestRevision = this.history.sessionHistoryForItem(item)[0]
/** Last entry should be the initial revision. */
const initialRevision =
this.historyManager.sessionHistoryForItem(item)[this.historyManager.sessionHistoryForItem(item).length - 1]
this.history.sessionHistoryForItem(item)[this.history.sessionHistoryForItem(item).length - 1]
expect(latestRevision).to.not.equal(initialRevision)
@@ -252,7 +252,7 @@ describe('history manager', () => {
undefined,
syncOptions,
)
const historyItem = this.historyManager.sessionHistoryForItem(item)[0]
const historyItem = this.history.sessionHistoryForItem(item)[0]
expect(historyItem.previewTitle()).to.equal(historyItem.payload.created_at.toLocaleString())
})
})
@@ -262,8 +262,8 @@ describe('history manager', () => {
beforeEach(async function () {
this.application = await Factory.createInitAppWithFakeCrypto()
this.historyManager = this.application.historyManager
this.payloadManager = this.application.payloadManager
this.history = this.application.dependencies.get(TYPES.HistoryManager)
this.payloadManager = this.application.payloads
this.email = UuidGenerator.GenerateUuid()
this.password = UuidGenerator.GenerateUuid()
await Factory.registerUserToApplication({
@@ -280,10 +280,10 @@ describe('history manager', () => {
it('response from server should be failed if not signed in', async function () {
await this.application.user.signOut()
this.application = await Factory.createInitAppWithFakeCrypto()
this.historyManager = this.application.historyManager
this.payloadManager = this.application.payloadManager
this.history = this.application.dependencies.get(TYPES.HistoryManager)
this.payloadManager = this.application.payloads
const item = await Factory.createSyncedNote(this.application)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
const itemHistoryOrError = await this.application.listRevisions.execute({ itemUuid: item.uuid })
expect(itemHistoryOrError.isFailed()).to.equal(true)
@@ -355,7 +355,7 @@ describe('history manager', () => {
expect(payloadFromServer.uuid).to.eq(item.payload.uuid)
expect(payloadFromServer.content).to.eql(item.payload.content)
item = this.application.itemManager.findItem(item.uuid)
item = this.application.items.findItem(item.uuid)
expect(payloadFromServer.content).to.not.eql(item.payload.content)
})

View File

@@ -37,21 +37,21 @@ describe('key recovery service', function () {
await context.register()
const randomRootKey = await application.encryptionService.createRootKey(
const randomRootKey = await application.encryption.createRootKey(
unassociatedIdentifier,
unassociatedPassword,
KeyParamsOrigination.Registration,
)
const randomItemsKey = await application.encryptionService.operators.defaultOperator().createItemsKey()
const randomItemsKey = await context.operators.defaultOperator().createItemsKey()
const encrypted = await application.encryptionService.encryptSplitSingle({
const encrypted = await application.encryption.encryptSplitSingle({
usesRootKey: {
items: [randomItemsKey.payload],
key: randomRootKey,
},
})
const errored = await application.encryptionService.decryptSplitSingle({
const errored = await application.encryption.decryptSplitSingle({
usesRootKeyWithKeyLookup: {
items: [encrypted],
},
@@ -59,13 +59,13 @@ describe('key recovery service', function () {
expect(errored.errorDecrypting).to.equal(true)
await application.payloadManager.emitPayload(errored, PayloadEmitSource.LocalInserted)
await application.payloads.emitPayload(errored, PayloadEmitSource.LocalInserted)
await context.resolveWhenKeyRecovered(errored.uuid)
expect(application.items.findItem(errored.uuid).errorDecrypting).to.not.be.ok
expect(application.syncService.isOutOfSync()).to.equal(false)
expect(application.sync.isOutOfSync()).to.equal(false)
await context.deinit()
})
@@ -89,37 +89,37 @@ describe('key recovery service', function () {
})
await context.register()
const randomRootKey = await application.encryptionService.createRootKey(
const randomRootKey = await application.encryption.createRootKey(
unassociatedIdentifier,
unassociatedPassword,
KeyParamsOrigination.Registration,
)
const randomItemsKey = await application.encryptionService.operators.defaultOperator().createItemsKey()
const randomItemsKey = await context.operators.defaultOperator().createItemsKey()
await application.payloadManager.emitPayload(
await application.payloads.emitPayload(
randomItemsKey.payload.copy({ dirty: true, dirtyIndex: getIncrementedDirtyIndex() }),
PayloadEmitSource.LocalInserted,
)
await context.sync()
const originalSyncTime = application.payloadManager.findOne(randomItemsKey.uuid).lastSyncEnd.getTime()
const originalSyncTime = application.payloads.findOne(randomItemsKey.uuid).lastSyncEnd.getTime()
const encrypted = await application.encryptionService.encryptSplitSingle({
const encrypted = await application.encryption.encryptSplitSingle({
usesRootKey: {
items: [randomItemsKey.payload],
key: randomRootKey,
},
})
const errored = await application.encryptionService.decryptSplitSingle({
const errored = await application.encryption.decryptSplitSingle({
usesRootKeyWithKeyLookup: {
items: [encrypted],
},
})
await application.payloadManager.emitPayload(errored, PayloadEmitSource.LocalInserted)
await application.payloads.emitPayload(errored, PayloadEmitSource.LocalInserted)
const recoveryPromise = context.resolveWhenKeyRecovered(errored.uuid)
@@ -127,7 +127,7 @@ describe('key recovery service', function () {
await recoveryPromise
expect(application.payloadManager.findOne(errored.uuid).lastSyncEnd.getTime()).to.be.above(originalSyncTime)
expect(application.payloads.findOne(errored.uuid).lastSyncEnd.getTime()).to.be.above(originalSyncTime)
await context.deinit()
})
@@ -214,15 +214,15 @@ describe('key recovery service', function () {
})
/** Create items key associated with a random root key */
const randomRootKey = await application.encryptionService.createRootKey(
const randomRootKey = await application.encryption.createRootKey(
unassociatedIdentifier,
unassociatedPassword,
KeyParamsOrigination.Registration,
)
const randomItemsKey = await application.encryptionService.operators.defaultOperator().createItemsKey()
const randomItemsKey2 = await application.encryptionService.operators.defaultOperator().createItemsKey()
const randomItemsKey = await context.operators.defaultOperator().createItemsKey()
const randomItemsKey2 = await context.operators.defaultOperator().createItemsKey()
const encrypted = await application.encryptionService.encryptSplit({
const encrypted = await application.encryption.encryptSplit({
usesRootKey: {
items: [randomItemsKey.payload, randomItemsKey2.payload],
key: randomRootKey,
@@ -230,13 +230,13 @@ describe('key recovery service', function () {
})
/** Attempt decryption and insert into rotation in errored state */
const decrypted = await application.encryptionService.decryptSplit({
const decrypted = await application.encryption.decryptSplit({
usesRootKeyWithKeyLookup: {
items: encrypted,
},
})
await application.payloadManager.emitPayloads(decrypted, PayloadEmitSource.LocalInserted)
await application.payloads.emitPayloads(decrypted, PayloadEmitSource.LocalInserted)
/** Wait and allow recovery wizard to complete */
await Factory.sleep(1.5)
@@ -247,7 +247,7 @@ describe('key recovery service', function () {
expect(totalPromptCount).to.equal(1)
expect(application.syncService.isOutOfSync()).to.equal(false)
expect(application.sync.isOutOfSync()).to.equal(false)
await context.deinit()
})
@@ -289,19 +289,19 @@ describe('key recovery service', function () {
/** Same previously errored key should now no longer be errored, */
expect(contextA.application.items.getAnyItems(ContentType.TYPES.ItemsKey).length).to.equal(2)
for (const key of contextA.application.itemManager.getDisplayableItemsKeys()) {
for (const key of contextA.application.items.getDisplayableItemsKeys()) {
expect(key.errorDecrypting).to.not.be.ok
}
const aKey = await contextA.application.encryptionService.getRootKey()
const bKey = await contextB.application.encryptionService.getRootKey()
const aKey = await contextA.application.encryption.getRootKey()
const bKey = await contextB.application.encryption.getRootKey()
expect(aKey.compare(bKey)).to.equal(true)
expect(contextA.application.items.findItem(note.uuid).errorDecrypting).to.not.be.ok
expect(contextB.application.items.findItem(note.uuid).errorDecrypting).to.not.be.ok
expect(contextA.application.syncService.isOutOfSync()).to.equal(false)
expect(contextB.application.syncService.isOutOfSync()).to.equal(false)
expect(contextA.application.sync.isOutOfSync()).to.equal(false)
expect(contextB.application.sync.isOutOfSync()).to.equal(false)
await contextA.deinit()
await contextB.deinit()
@@ -341,7 +341,7 @@ describe('key recovery service', function () {
/** We expect the item in appA to be errored at this point, but we do not want it to recover */
await appA.sync.sync()
expect(appA.payloadManager.findOne(note.uuid).waitingForKey).to.equal(true)
expect(appA.payloads.findOne(note.uuid).waitingForKey).to.equal(true)
console.warn('Expecting exceptions below as we destroy app during key recovery')
await Factory.safeDeinit(appA)
@@ -351,8 +351,8 @@ describe('key recovery service', function () {
await recreatedAppA.prepareForLaunch({ receiveChallenge: () => {} })
await recreatedAppA.launch(true)
expect(recreatedAppA.payloadManager.findOne(note.uuid).errorDecrypting).to.equal(true)
expect(recreatedAppA.payloadManager.findOne(note.uuid).waitingForKey).to.equal(true)
expect(recreatedAppA.payloads.findOne(note.uuid).errorDecrypting).to.equal(true)
expect(recreatedAppA.payloads.findOne(note.uuid).waitingForKey).to.equal(true)
await Factory.safeDeinit(recreatedAppA)
})
@@ -379,7 +379,7 @@ describe('key recovery service', function () {
await application.launch(true)
await context.register()
const correctRootKey = await application.encryptionService.getRootKey()
const correctRootKey = await application.encryption.getRootKey()
/**
* 1. Change our root key locally so that its keys params doesn't match the server's
@@ -390,19 +390,19 @@ describe('key recovery service', function () {
const unassociatedIdentifier = 'foorand'
/** Create items key associated with a random root key */
const randomRootKey = await application.encryptionService.createRootKey(
const randomRootKey = await application.encryption.createRootKey(
unassociatedIdentifier,
unassociatedPassword,
KeyParamsOrigination.Registration,
)
const signInFunction = sinon.spy(application.keyRecoveryService, 'performServerSignIn')
const signInFunction = sinon.spy(context.keyRecovery, 'performServerSignIn')
await application.encryptionService.setRootKey(randomRootKey)
await application.encryption.setRootKey(randomRootKey)
const correctItemsKey = await application.encryptionService.operators.defaultOperator().createItemsKey()
const correctItemsKey = await context.operators.defaultOperator().createItemsKey()
const encrypted = await application.encryptionService.encryptSplitSingle({
const encrypted = await application.encryption.encryptSplitSingle({
usesRootKey: {
items: [correctItemsKey.payload],
key: randomRootKey,
@@ -414,7 +414,7 @@ describe('key recovery service', function () {
context.resolveWhenKeyRecovered(correctItemsKey.uuid),
])
await application.payloadManager.emitPayload(
await application.payloads.emitPayload(
encrypted.copy({
errorDecrypting: true,
dirty: true,
@@ -428,14 +428,14 @@ describe('key recovery service', function () {
expect(signInFunction.callCount).to.equal(1)
const clientRootKey = await application.encryptionService.getRootKey()
const clientRootKey = await application.encryption.getRootKey()
expect(clientRootKey.compare(correctRootKey)).to.equal(true)
const decryptedKey = application.items.findItem(correctItemsKey.uuid)
expect(decryptedKey).to.be.ok
expect(decryptedKey.content.itemsKey).to.equal(correctItemsKey.content.itemsKey)
expect(application.syncService.isOutOfSync()).to.equal(false)
expect(application.sync.isOutOfSync()).to.equal(false)
await context.deinit()
})
@@ -448,8 +448,8 @@ describe('key recovery service', function () {
await context.register()
/** Create and emit errored encrypted items key payload */
const itemsKey = await application.encryptionService.getSureDefaultItemsKey()
const encrypted = await application.encryptionService.encryptSplitSingle({
const itemsKey = await application.encryption.getSureDefaultItemsKey()
const encrypted = await application.encryption.encryptSplitSingle({
usesRootKeyWithKeyLookup: {
items: [itemsKey.payload],
},
@@ -474,7 +474,7 @@ describe('key recovery service', function () {
/** The timestamp of our current key should be updated however so we do not enter out of sync state */
expect(currentItemsKey.serverUpdatedAt.getTime()).to.equal(newUpdated.getTime())
expect(application.syncService.isOutOfSync()).to.equal(false)
expect(application.sync.isOutOfSync()).to.equal(false)
await context.deinit()
})
@@ -485,8 +485,8 @@ describe('key recovery service', function () {
await context.launch()
await context.register()
const itemsKey = await application.encryptionService.getSureDefaultItemsKey()
const encrypted = await application.encryptionService.encryptSplitSingle({
const itemsKey = await application.encryption.getSureDefaultItemsKey()
const encrypted = await application.encryption.encryptSplitSingle({
usesRootKeyWithKeyLookup: {
items: [itemsKey.payload],
},
@@ -498,7 +498,7 @@ describe('key recovery service', function () {
updated_at: newUpdated,
})
await application.payloadManager.emitDeltaEmit({
await application.payloads.emitDeltaEmit({
emits: [],
ignored: [errored],
source: PayloadEmitSource.RemoteRetrieved,
@@ -511,7 +511,7 @@ describe('key recovery service', function () {
expect(latestItemsKey.errorDecrypting).to.not.be.ok
expect(latestItemsKey.itemsKey).to.equal(itemsKey.itemsKey)
expect(latestItemsKey.serverUpdatedAt.getTime()).to.equal(newUpdated.getTime())
expect(application.syncService.isOutOfSync()).to.equal(false)
expect(application.sync.isOutOfSync()).to.equal(false)
await context.deinit()
})
@@ -524,8 +524,8 @@ describe('key recovery service', function () {
await context.register()
/** Create and emit errored encrypted items key payload */
const itemsKey = await application.encryptionService.getSureDefaultItemsKey()
const encrypted = await application.encryptionService.encryptSplitSingle({
const itemsKey = await application.encryption.getSureDefaultItemsKey()
const encrypted = await application.encryption.encryptSplitSingle({
usesRootKeyWithKeyLookup: {
items: [itemsKey.payload],
},
@@ -533,7 +533,7 @@ describe('key recovery service', function () {
context.disableKeyRecovery()
await application.payloadManager.emitDeltaEmit({
await application.payloads.emitDeltaEmit({
emits: [],
ignored: [
encrypted.copy({
@@ -548,7 +548,7 @@ describe('key recovery service', function () {
await Factory.sleep(0.1)
expect(application.syncService.isOutOfSync()).to.equal(false)
expect(application.sync.isOutOfSync()).to.equal(false)
await context.deinit()
@@ -589,17 +589,17 @@ describe('key recovery service', function () {
})
/** Create items key associated with a random root key */
const randomRootKey = await application.encryptionService.createRootKey(
const randomRootKey = await application.encryption.createRootKey(
unassociatedIdentifier,
unassociatedPassword,
KeyParamsOrigination.Registration,
ProtocolVersion.V003,
)
const randomItemsKey = await application.encryptionService.operators
const randomItemsKey = await context.operators
.operatorForVersion(ProtocolVersion.V003)
.createItemsKey()
const encrypted = await application.encryptionService.encryptSplitSingle({
const encrypted = await application.encryption.encryptSplitSingle({
usesRootKey: {
items: [randomItemsKey.payload],
key: randomRootKey,
@@ -607,7 +607,7 @@ describe('key recovery service', function () {
})
/** Attempt decryption and insert into rotation in errored state */
const decrypted = await application.encryptionService.decryptSplitSingle({
const decrypted = await application.encryption.decryptSplitSingle({
usesRootKeyWithKeyLookup: {
items: [encrypted],
},
@@ -616,7 +616,7 @@ describe('key recovery service', function () {
expect(decrypted.errorDecrypting).to.equal(true)
/** Insert into rotation */
await application.payloadManager.emitPayload(decrypted, PayloadEmitSource.LocalInserted)
await application.payloads.emitPayload(decrypted, PayloadEmitSource.LocalInserted)
/** Wait and allow recovery wizard to complete */
await Factory.sleep(0.3)
@@ -624,7 +624,7 @@ describe('key recovery service', function () {
/** Should be decrypted now */
expect(application.items.findItem(encrypted.uuid).errorDecrypting).to.not.be.ok
expect(application.syncService.isOutOfSync()).to.equal(false)
expect(application.sync.isOutOfSync()).to.equal(false)
await context.deinit()
})
@@ -653,9 +653,9 @@ describe('key recovery service', function () {
contextA.password = newPassword
await appB.sync.sync()
const newDefaultKey = appB.encryptionService.getSureDefaultItemsKey()
const newDefaultKey = appB.encryption.getSureDefaultItemsKey()
const encrypted = await appB.encryptionService.encryptSplitSingle({
const encrypted = await appB.encryption.encryptSplitSingle({
usesRootKeyWithKeyLookup: {
items: [newDefaultKey.payload],
},
@@ -663,28 +663,26 @@ describe('key recovery service', function () {
/** Insert foreign items key into appA, which shouldn't be able to decrypt it yet */
const appA = contextA.application
await appA.payloadManager.emitPayload(
await appA.payloads.emitPayload(
encrypted.copy({
errorDecrypting: true,
}),
PayloadEmitSource.LocalInserted,
)
await Factory.awaitFunctionInvokation(appA.keyRecoveryService, 'handleDecryptionOfAllKeysMatchingCorrectRootKey')
await Factory.awaitFunctionInvokation(contextA.keyRecovery, 'handleDecryptionOfAllKeysMatchingCorrectRootKey')
/** Stored version of items key should use new root key */
const stored = (await appA.deviceInterface.getAllDatabaseEntries(appA.identifier)).find(
const stored = (await appA.device.getAllDatabaseEntries(appA.identifier)).find(
(payload) => payload.uuid === newDefaultKey.uuid,
)
const storedParams = await appA.encryptionService.getKeyEmbeddedKeyParamsFromItemsKey(new EncryptedPayload(stored))
const storedParams = await appA.encryption.getKeyEmbeddedKeyParamsFromItemsKey(new EncryptedPayload(stored))
const correctStored = (await appB.deviceInterface.getAllDatabaseEntries(appB.identifier)).find(
const correctStored = (await appB.device.getAllDatabaseEntries(appB.identifier)).find(
(payload) => payload.uuid === newDefaultKey.uuid,
)
const correctParams = await appB.encryptionService.getKeyEmbeddedKeyParamsFromItemsKey(
new EncryptedPayload(correctStored),
)
const correctParams = await appB.encryption.getKeyEmbeddedKeyParamsFromItemsKey(new EncryptedPayload(correctStored))
expect(storedParams).to.eql(correctParams)

View File

@@ -29,7 +29,7 @@ describe('keys', function () {
})
it('should not have root key by default', async function () {
expect(await this.application.encryptionService.getRootKey()).to.not.be.ok
expect(await this.application.encryption.getRootKey()).to.not.be.ok
})
it('validates content types requiring root encryption', function () {
@@ -43,7 +43,7 @@ describe('keys', function () {
/** Items key available by default */
const payload = Factory.createNotePayload()
const processedPayload = CreateEncryptedLocalStorageContextPayload(
await this.application.encryptionService.encryptSplitSingle({
await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [payload],
},
@@ -54,44 +54,44 @@ describe('keys', function () {
it('has root key and one items key after registering user', async function () {
await Factory.registerUserToApplication({ application: this.application })
expect(this.application.encryptionService.getRootKey()).to.be.ok
expect(this.application.itemManager.getDisplayableItemsKeys().length).to.equal(1)
expect(this.application.encryption.getRootKey()).to.be.ok
expect(this.application.items.getDisplayableItemsKeys().length).to.equal(1)
})
it('changing root key with passcode should re-wrap root key', async function () {
const email = 'foo'
const password = 'bar'
const key = await this.application.encryptionService.createRootKey(email, password, KeyParamsOrigination.Registration)
await this.application.encryptionService.setRootKey(key)
const key = await this.application.encryption.createRootKey(email, password, KeyParamsOrigination.Registration)
await this.application.encryption.setRootKey(key)
Factory.handlePasswordChallenges(this.application, password)
await this.application.addPasscode(password)
/** We should be able to decrypt wrapped root key with passcode */
const wrappingKeyParams = await this.application.encryptionService.rootKeyManager.getRootKeyWrapperKeyParams()
const wrappingKey = await this.application.encryptionService.computeRootKey(password, wrappingKeyParams)
await this.application.encryptionService.unwrapRootKey(wrappingKey).catch((error) => {
const wrappingKeyParams = await this.application.encryption.rootKeyManager.getRootKeyWrapperKeyParams()
const wrappingKey = await this.application.encryption.computeRootKey(password, wrappingKeyParams)
await this.application.encryption.unwrapRootKey(wrappingKey).catch((error) => {
expect(error).to.not.be.ok
})
const newPassword = 'bar'
const newKey = await this.application.encryptionService.createRootKey(
const newKey = await this.application.encryption.createRootKey(
email,
newPassword,
KeyParamsOrigination.Registration,
)
await this.application.encryptionService.setRootKey(newKey, wrappingKey)
await this.application.encryptionService.unwrapRootKey(wrappingKey).catch((error) => {
await this.application.encryption.setRootKey(newKey, wrappingKey)
await this.application.encryption.unwrapRootKey(wrappingKey).catch((error) => {
expect(error).to.not.be.ok
})
})
it('items key should be encrypted with root key', async function () {
await Factory.registerUserToApplication({ application: this.application })
const itemsKey = await this.application.encryptionService.getSureDefaultItemsKey()
const rootKey = await this.application.encryptionService.getRootKey()
const itemsKey = await this.application.encryption.getSureDefaultItemsKey()
const rootKey = await this.application.encryption.getRootKey()
/** Encrypt items key */
const encryptedPayload = await this.application.encryptionService.encryptSplitSingle({
const encryptedPayload = await this.application.encryption.encryptSplitSingle({
usesRootKey: {
items: [itemsKey.payloadRepresentation()],
key: rootKey,
@@ -102,7 +102,7 @@ describe('keys', function () {
expect(encryptedPayload.items_key_id).to.not.be.ok
/** Attempt to decrypt with root key. Should succeed. */
const decryptedPayload = await this.application.encryptionService.decryptSplitSingle({
const decryptedPayload = await this.application.encryption.decryptSplitSingle({
usesRootKey: {
items: [encryptedPayload],
key: rootKey,
@@ -114,7 +114,7 @@ describe('keys', function () {
})
it('should create random items key if no account and no passcode', async function () {
const itemsKeys = this.application.itemManager.getDisplayableItemsKeys()
const itemsKeys = this.application.items.getDisplayableItemsKeys()
expect(itemsKeys.length).to.equal(1)
const notePayload = Factory.createNotePayload()
@@ -122,55 +122,55 @@ describe('keys', function () {
dirty: true,
dirtyIndex: getIncrementedDirtyIndex(),
})
await this.application.payloadManager.emitPayload(dirtied, PayloadEmitSource.LocalChanged)
await this.application.payloads.emitPayload(dirtied, PayloadEmitSource.LocalChanged)
await this.application.sync.sync()
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
const rawNotePayload = rawPayloads.find((r) => r.content_type === ContentType.TYPES.Note)
expect(typeof rawNotePayload.content).to.equal('string')
})
it('should keep offline created items key upon registration', async function () {
expect(this.application.itemManager.getDisplayableItemsKeys().length).to.equal(1)
const originalItemsKey = this.application.itemManager.getDisplayableItemsKeys()[0]
expect(this.application.items.getDisplayableItemsKeys().length).to.equal(1)
const originalItemsKey = this.application.items.getDisplayableItemsKeys()[0]
await this.application.register(this.email, this.password)
expect(this.application.itemManager.getDisplayableItemsKeys().length).to.equal(1)
const newestItemsKey = this.application.itemManager.getDisplayableItemsKeys()[0]
expect(this.application.items.getDisplayableItemsKeys().length).to.equal(1)
const newestItemsKey = this.application.items.getDisplayableItemsKeys()[0]
expect(newestItemsKey.uuid).to.equal(originalItemsKey.uuid)
})
it('should use items key for encryption of note', async function () {
const notePayload = Factory.createNotePayload()
const keyToUse = await this.application.encryptionService.itemsEncryption.keyToUseForItemEncryption(notePayload)
const keyToUse = await this.application.encryption.itemsEncryption.keyToUseForItemEncryption(notePayload)
expect(keyToUse.content_type).to.equal(ContentType.TYPES.ItemsKey)
})
it('encrypting an item should associate an items key to it', async function () {
const note = Factory.createNotePayload()
const encryptedPayload = await this.application.encryptionService.encryptSplitSingle({
const encryptedPayload = await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [note],
},
})
const itemsKey = this.application.encryptionService.itemsKeyForEncryptedPayload(encryptedPayload)
const itemsKey = this.application.encryption.itemsKeyForEncryptedPayload(encryptedPayload)
expect(itemsKey).to.be.ok
})
it('decrypt encrypted item with associated key', async function () {
const note = Factory.createNotePayload()
const title = note.content.title
const encryptedPayload = await this.application.encryptionService.encryptSplitSingle({
const encryptedPayload = await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [note],
},
})
const itemsKey = this.application.encryptionService.itemsKeyForEncryptedPayload(encryptedPayload)
const itemsKey = this.application.encryption.itemsKeyForEncryptedPayload(encryptedPayload)
expect(itemsKey).to.be.ok
const decryptedPayload = await this.application.encryptionService.decryptSplitSingle({
const decryptedPayload = await this.application.encryption.decryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [encryptedPayload],
},
@@ -182,17 +182,17 @@ describe('keys', function () {
it('decrypts items waiting for keys', async function () {
const notePayload = Factory.createNotePayload()
const title = notePayload.content.title
const encryptedPayload = await this.application.encryptionService.encryptSplitSingle({
const encryptedPayload = await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [notePayload],
},
})
const itemsKey = this.application.encryptionService.itemsKeyForEncryptedPayload(encryptedPayload)
const itemsKey = this.application.encryption.itemsKeyForEncryptedPayload(encryptedPayload)
await this.application.itemManager.removeItemLocally(itemsKey)
await this.application.items.removeItemLocally(itemsKey)
const erroredPayload = await this.application.encryptionService.decryptSplitSingle({
const erroredPayload = await this.application.encryption.decryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [encryptedPayload],
},
@@ -200,7 +200,7 @@ describe('keys', function () {
await this.application.mutator.emitItemsFromPayloads([erroredPayload], PayloadEmitSource.LocalChanged)
const note = this.application.itemManager.findAnyItem(notePayload.uuid)
const note = this.application.items.findAnyItem(notePayload.uuid)
expect(note.errorDecrypting).to.equal(true)
expect(note.waitingForKey).to.equal(true)
@@ -213,7 +213,7 @@ describe('keys', function () {
*/
await Factory.sleep(0.2)
const updatedNote = this.application.itemManager.findItem(note.uuid)
const updatedNote = this.application.items.findItem(note.uuid)
expect(updatedNote.errorDecrypting).to.not.be.ok
expect(updatedNote.waitingForKey).to.not.be.ok
@@ -223,7 +223,7 @@ describe('keys', function () {
it('attempting to emit errored items key for which there exists a non errored master copy should ignore it', async function () {
await Factory.registerUserToApplication({ application: this.application })
const itemsKey = await this.application.encryptionService.getSureDefaultItemsKey()
const itemsKey = await this.application.encryption.getSureDefaultItemsKey()
expect(itemsKey.errorDecrypting).to.not.be.ok
@@ -239,9 +239,9 @@ describe('keys', function () {
},
})
await this.application.syncService.handleSuccessServerResponse({ payloadsSavedOrSaving: [], options: {} }, response)
await this.application.sync.handleSuccessServerResponse({ payloadsSavedOrSaving: [], options: {} }, response)
const refreshedKey = this.application.payloadManager.findOne(itemsKey.uuid)
const refreshedKey = this.application.payloads.findOne(itemsKey.uuid)
expect(refreshedKey.errorDecrypting).to.not.be.ok
expect(refreshedKey.content.itemsKey).to.be.ok
@@ -250,19 +250,19 @@ describe('keys', function () {
it('generating export params with logged in account should produce encrypted payload', async function () {
await Factory.registerUserToApplication({ application: this.application })
const payload = Factory.createNotePayload()
const encryptedPayload = await this.application.encryptionService.encryptSplitSingle({
const encryptedPayload = await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [payload],
},
})
expect(typeof encryptedPayload.content).to.equal('string')
expect(encryptedPayload.content.substring(0, 3)).to.equal(this.application.encryptionService.getLatestVersion())
expect(encryptedPayload.content.substring(0, 3)).to.equal(this.application.encryption.getLatestVersion())
})
it('When setting passcode, should encrypt items keys', async function () {
await this.application.addPasscode('foo')
const itemsKey = this.application.itemManager.getDisplayableItemsKeys()[0]
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const itemsKey = this.application.items.getDisplayableItemsKeys()[0]
const rawPayloads = await this.application.storage.getAllRawPayloads()
const itemsKeyRawPayload = rawPayloads.find((p) => p.uuid === itemsKey.uuid)
const itemsKeyPayload = new EncryptedPayload(itemsKeyRawPayload)
expect(itemsKeyPayload.enc_item_key).to.be.ok
@@ -270,13 +270,13 @@ describe('keys', function () {
it('items key encrypted payload should contain root key params', async function () {
await this.application.addPasscode('foo')
const itemsKey = this.application.itemManager.getDisplayableItemsKeys()[0]
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const itemsKey = this.application.items.getDisplayableItemsKeys()[0]
const rawPayloads = await this.application.storage.getAllRawPayloads()
const itemsKeyRawPayload = rawPayloads.find((p) => p.uuid === itemsKey.uuid)
const itemsKeyPayload = new EncryptedPayload(itemsKeyRawPayload)
const authenticatedData = this.context.encryption.getEmbeddedPayloadAuthenticatedData(itemsKeyPayload)
const rootKeyParams = await this.application.encryptionService.getRootKeyParams()
const rootKeyParams = await this.application.encryption.getRootKeyParams()
expect(authenticatedData.kp).to.be.ok
expect(authenticatedData.kp).to.eql(rootKeyParams.getPortableValue())
@@ -286,8 +286,8 @@ describe('keys', function () {
it('correctly validates local passcode', async function () {
const passcode = 'foo'
await this.application.addPasscode('foo')
expect((await this.application.encryptionService.validatePasscode('wrong')).valid).to.equal(false)
expect((await this.application.encryptionService.validatePasscode(passcode)).valid).to.equal(true)
expect((await this.application.encryption.validatePasscode('wrong')).valid).to.equal(false)
expect((await this.application.encryption.validatePasscode(passcode)).valid).to.equal(true)
})
it('signing into 003 account should delete latest offline items key and create 003 items key', async function () {
@@ -296,8 +296,8 @@ describe('keys', function () {
* Upon signing into an 003 account, the application should delete any neverSynced items keys,
* and create a new default items key that is the default for a given protocol version.
*/
const defaultItemsKey = await this.application.encryptionService.getSureDefaultItemsKey()
const latestVersion = this.application.encryptionService.getLatestVersion()
const defaultItemsKey = await this.application.encryption.getSureDefaultItemsKey()
const latestVersion = this.application.encryption.getLatestVersion()
expect(defaultItemsKey.keyVersion).to.equal(latestVersion)
/** Register with 003 version */
@@ -308,11 +308,11 @@ describe('keys', function () {
version: ProtocolVersion.V003,
})
const itemsKeys = this.application.itemManager.getDisplayableItemsKeys()
const itemsKeys = this.application.items.getDisplayableItemsKeys()
expect(itemsKeys.length).to.equal(1)
const newestItemsKey = itemsKeys[0]
expect(newestItemsKey.keyVersion).to.equal(ProtocolVersion.V003)
const rootKey = await this.application.encryptionService.getRootKey()
const rootKey = await this.application.encryption.getRootKey()
expect(newestItemsKey.itemsKey).to.equal(rootKey.masterKey)
expect(newestItemsKey.dataAuthenticationKey).to.equal(rootKey.dataAuthenticationKey)
})
@@ -326,33 +326,33 @@ describe('keys', function () {
version: ProtocolVersion.V003,
})
expect(this.application.payloadManager.invalidPayloads.length).to.equal(0)
expect(this.application.itemManager.getDisplayableItemsKeys().length).to.equal(1)
expect(this.application.itemManager.getDisplayableItemsKeys()[0].dirty).to.equal(false)
expect(this.application.payloads.invalidPayloads.length).to.equal(0)
expect(this.application.items.getDisplayableItemsKeys().length).to.equal(1)
expect(this.application.items.getDisplayableItemsKeys()[0].dirty).to.equal(false)
/** Sign out and back in */
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
await this.application.signIn(this.email, this.password, undefined, undefined, undefined, true)
expect(this.application.itemManager.getDisplayableItemsKeys().length).to.equal(1)
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(10)
expect(this.application.payloadManager.invalidPayloads.length).to.equal(0)
expect(this.application.items.getDisplayableItemsKeys().length).to.equal(1)
expect(this.application.items.getDisplayableNotes().length).to.equal(10)
expect(this.application.payloads.invalidPayloads.length).to.equal(0)
})
it('When root key changes, all items keys must be re-encrypted', async function () {
const passcode = 'foo'
await this.application.addPasscode(passcode)
await Factory.createSyncedNote(this.application)
const itemsKeys = this.application.itemManager.getDisplayableItemsKeys()
const itemsKeys = this.application.items.getDisplayableItemsKeys()
expect(itemsKeys.length).to.equal(1)
const originalItemsKey = itemsKeys[0]
const originalRootKey = await this.application.encryptionService.getRootKey()
const originalRootKey = await this.application.encryption.getRootKey()
/** Expect that we can decrypt raw payload with current root key */
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
const itemsKeyRawPayload = rawPayloads.find((p) => p.uuid === originalItemsKey.uuid)
const itemsKeyPayload = new EncryptedPayload(itemsKeyRawPayload)
const decrypted = await this.application.encryptionService.decryptSplitSingle({
const decrypted = await this.application.encryption.decryptSplitSingle({
usesRootKey: {
items: [itemsKeyPayload],
key: originalRootKey,
@@ -366,7 +366,7 @@ describe('keys', function () {
Factory.handlePasswordChallenges(this.application, passcode)
await this.application.changePasscode('bar')
const newRootKey = await this.application.encryptionService.getRootKey()
const newRootKey = await this.application.encryption.getRootKey()
expect(newRootKey).to.not.equal(originalRootKey)
expect(newRootKey.masterKey).to.not.equal(originalRootKey.masterKey)
@@ -374,12 +374,12 @@ describe('keys', function () {
* Expect that originalRootKey can no longer decrypt originalItemsKey
* as items key has been re-encrypted with new root key
*/
const rawPayloads2 = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads2 = await this.application.storage.getAllRawPayloads()
const itemsKeyRawPayload2 = rawPayloads2.find((p) => p.uuid === originalItemsKey.uuid)
expect(itemsKeyRawPayload2.content).to.not.equal(itemsKeyRawPayload.content)
const itemsKeyPayload2 = new EncryptedPayload(itemsKeyRawPayload2)
const decrypted2 = await this.application.encryptionService.decryptSplitSingle({
const decrypted2 = await this.application.encryption.decryptSplitSingle({
usesRootKey: {
items: [itemsKeyPayload2],
key: originalRootKey,
@@ -388,7 +388,7 @@ describe('keys', function () {
expect(decrypted2.errorDecrypting).to.equal(true)
/** Should be able to decrypt with new root key */
const decrypted3 = await this.application.encryptionService.decryptSplitSingle({
const decrypted3 = await this.application.encryption.decryptSplitSingle({
usesRootKey: {
items: [itemsKeyPayload2],
key: newRootKey,
@@ -403,19 +403,19 @@ describe('keys', function () {
email: this.email,
password: this.password,
})
const itemsKeys = this.application.itemManager.getDisplayableItemsKeys()
const itemsKeys = this.application.items.getDisplayableItemsKeys()
expect(itemsKeys.length).to.equal(1)
const defaultItemsKey = await this.application.encryptionService.getSureDefaultItemsKey()
const defaultItemsKey = await this.application.encryption.getSureDefaultItemsKey()
const result = await this.application.changePassword(this.password, 'foobarfoo')
expect(result.error).to.not.be.ok
expect(this.application.itemManager.getDisplayableItemsKeys().length).to.equal(2)
const newDefaultItemsKey = await this.application.encryptionService.getSureDefaultItemsKey()
expect(this.application.items.getDisplayableItemsKeys().length).to.equal(2)
const newDefaultItemsKey = await this.application.encryption.getSureDefaultItemsKey()
expect(newDefaultItemsKey.uuid).to.not.equal(defaultItemsKey.uuid)
const note = await Factory.createSyncedNote(this.application)
const payload = await this.application.encryptionService.encryptSplitSingle({
const payload = await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [note.payload],
},
@@ -430,20 +430,20 @@ describe('keys', function () {
email: email,
password: password,
})
const itemsKeys = application.itemManager.getDisplayableItemsKeys()
const itemsKeys = application.items.getDisplayableItemsKeys()
expect(itemsKeys.length).to.equal(1)
const defaultItemsKey = application.encryptionService.getSureDefaultItemsKey()
const defaultItemsKey = application.encryption.getSureDefaultItemsKey()
const newEmail = UuidGenerator.GenerateUuid()
const result = await application.changeEmail(newEmail, password)
expect(result.error).to.not.be.ok
expect(application.itemManager.getDisplayableItemsKeys().length).to.equal(2)
const newDefaultItemsKey = application.encryptionService.getSureDefaultItemsKey()
expect(application.items.getDisplayableItemsKeys().length).to.equal(2)
const newDefaultItemsKey = application.encryption.getSureDefaultItemsKey()
expect(newDefaultItemsKey.uuid).to.not.equal(defaultItemsKey.uuid)
const note = await Factory.createSyncedNote(application)
const payload = await application.encryptionService.encryptSplitSingle({
const payload = await application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [note.payload],
},
@@ -480,34 +480,28 @@ describe('keys', function () {
it('loading the keychain root key should also load its key params', async function () {
await Factory.registerUserToApplication({ application: this.application })
const rootKey = await this.application.encryptionService.rootKeyManager.getRootKeyFromKeychain()
const rootKey = await this.application.encryption.rootKeyManager.getRootKeyFromKeychain()
expect(rootKey.keyParams).to.be.ok
})
it('key params should be persisted separately and not as part of root key', async function () {
await Factory.registerUserToApplication({ application: this.application })
const rawKey = await this.application.deviceInterface.getNamespacedKeychainValue(this.application.identifier)
const rawKey = await this.application.device.getNamespacedKeychainValue(this.application.identifier)
expect(rawKey.keyParams).to.not.be.ok
const rawKeyParams = await this.application.diskStorageService.getValue(
StorageKey.RootKeyParams,
StorageValueModes.Nonwrapped,
)
const rawKeyParams = await this.application.storage.getValue(StorageKey.RootKeyParams, StorageValueModes.Nonwrapped)
expect(rawKeyParams).to.be.ok
})
it('persisted key params should exactly equal in memory rootKey.keyParams', async function () {
await Factory.registerUserToApplication({ application: this.application })
const rootKey = await this.application.encryptionService.getRootKey()
const rawKeyParams = await this.application.diskStorageService.getValue(
StorageKey.RootKeyParams,
StorageValueModes.Nonwrapped,
)
const rootKey = await this.application.encryption.getRootKey()
const rawKeyParams = await this.application.storage.getValue(StorageKey.RootKeyParams, StorageValueModes.Nonwrapped)
expect(rootKey.keyParams.content).to.eql(rawKeyParams)
})
it('key params should have expected values', async function () {
await Factory.registerUserToApplication({ application: this.application })
const keyParamsObject = await this.application.encryptionService.getRootKeyParams()
const keyParamsObject = await this.application.encryption.getRootKeyParams()
const keyParams = keyParamsObject.content
expect(keyParams.identifier).to.be.ok
expect(keyParams.pw_nonce).to.be.ok
@@ -533,7 +527,7 @@ describe('keys', function () {
email,
password,
})
const keyParamsObject = await this.application.encryptionService.getRootKeyParams()
const keyParamsObject = await this.application.encryption.getRootKeyParams()
const keyParams = keyParamsObject.content
expect(keyParams.created).to.be.ok
@@ -551,7 +545,7 @@ describe('keys', function () {
password: this.password,
version: ProtocolVersion.V003,
})
const keyParamsObject = await this.application.encryptionService.getRootKeyParams()
const keyParamsObject = await this.application.encryption.getRootKeyParams()
const keyParams = keyParamsObject.content
expect(keyParams.created).to.be.ok
@@ -566,12 +560,12 @@ describe('keys', function () {
password: this.password,
version: ProtocolVersion.V003,
})
expect(await this.application.encryptionService.getEncryptionDisplayName()).to.equal('AES-256')
expect(await this.application.encryption.getEncryptionDisplayName()).to.equal('AES-256')
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
/** Register with 004 account */
await this.application.register(this.email + 'new', this.password)
expect(await this.application.encryptionService.getEncryptionDisplayName()).to.equal('XChaCha20-Poly1305')
expect(await this.application.encryption.getEncryptionDisplayName()).to.equal('XChaCha20-Poly1305')
})
it('when launching app with no keychain but data, should present account recovery challenge', async function () {
@@ -587,7 +581,7 @@ describe('keys', function () {
password: this.password,
})
/** Simulate empty keychain */
await this.application.deviceInterface.clearRawKeychainValue()
await this.application.device.clearRawKeychainValue()
const recreatedApp = await Factory.createApplicationWithFakeCrypto(id)
let totalChallenges = 0
@@ -599,7 +593,7 @@ describe('keys', function () {
await recreatedApp.prepareForLaunch({ receiveChallenge })
await recreatedApp.launch(true)
expect(recreatedApp.encryptionService.getRootKey()).to.be.ok
expect(recreatedApp.encryption.getRootKey()).to.be.ok
expect(totalChallenges).to.equal(expectedChallenges)
await Factory.safeDeinit(recreatedApp)
})
@@ -630,7 +624,7 @@ describe('keys', function () {
const newPassword = Utils.generateUuid()
await contextA.application.userService.changeCredentials({
await contextA.application.user.changeCredentials({
currentPassword: password,
newPassword: newPassword,
origination: KeyParamsOrigination.PasswordChange,
@@ -639,8 +633,8 @@ describe('keys', function () {
await contextB.syncWithIntegrityCheck()
await contextA.syncWithIntegrityCheck()
const clientAUndecryptables = contextA.application.keyRecoveryService.getUndecryptables()
const clientBUndecryptables = contextB.application.keyRecoveryService.getUndecryptables()
const clientAUndecryptables = contextA.keyRecovery.getUndecryptables()
const clientBUndecryptables = contextB.keyRecovery.getUndecryptables()
expect(Object.keys(clientBUndecryptables).length).to.equal(1)
expect(Object.keys(clientAUndecryptables).length).to.equal(0)
@@ -684,13 +678,13 @@ describe('keys', function () {
/** Change password through session manager directly instead of application,
* as not to create any items key (to simulate 003 client behavior) */
const currentRootKey = await oldClient.encryptionService.computeRootKey(
const currentRootKey = await oldClient.encryption.computeRootKey(
this.password,
await oldClient.encryptionService.getRootKeyParams(),
await oldClient.encryption.getRootKeyParams(),
)
const operator = oldClient.encryptionService.operators.operatorForVersion(ProtocolVersion.V003)
const operator = this.context.operators.operatorForVersion(ProtocolVersion.V003)
const newRootKey = await operator.createRootKey(this.email, this.password)
Object.defineProperty(oldClient.apiService, 'apiVersion', {
Object.defineProperty(oldClient.legacyApi, 'apiVersion', {
get: function () {
return '20190520'
},
@@ -701,7 +695,7 @@ describe('keys', function () {
*/
await newClient.signIn(this.email, this.password)
await oldClient.sessionManager.changeCredentials({
await oldClient.sessions.changeCredentials({
currentServerPassword: currentRootKey.serverPassword,
newRootKey,
})
@@ -711,7 +705,7 @@ describe('keys', function () {
await Factory.sleep(1)
/** Expect a new items key to be created based on the new root key */
expect(newClient.itemManager.getDisplayableItemsKeys().length).to.equal(2)
expect(newClient.items.getDisplayableItemsKeys().length).to.equal(2)
await Factory.safeDeinit(newClient)
await Factory.safeDeinit(oldClient)
@@ -734,11 +728,11 @@ describe('keys', function () {
/** Change password through session manager directly instead of application,
* as not to create any items key (to simulate 003 client behavior) */
const currentRootKey = await this.application.encryptionService.computeRootKey(
const currentRootKey = await this.application.encryption.computeRootKey(
this.password,
await this.application.encryptionService.getRootKeyParams(),
await this.application.encryption.getRootKeyParams(),
)
const operator = this.application.encryptionService.operators.operatorForVersion(ProtocolVersion.V003)
const operator = this.context.operators.operatorForVersion(ProtocolVersion.V003)
const newRootKeyTemplate = await operator.createRootKey(this.email, this.password)
const newRootKey = CreateNewRootKey({
...newRootKeyTemplate.content,
@@ -748,7 +742,7 @@ describe('keys', function () {
},
})
Object.defineProperty(this.application.apiService, 'apiVersion', {
Object.defineProperty(this.application.legacyApi, 'apiVersion', {
get: function () {
return '20190520'
},
@@ -757,25 +751,25 @@ describe('keys', function () {
/** Renew session to prevent timeouts */
this.application = await Factory.signOutAndBackIn(this.application, this.email, this.password)
await this.application.sessionManager.changeCredentials({
await this.application.sessions.changeCredentials({
currentServerPassword: currentRootKey.serverPassword,
newRootKey,
})
await this.application.encryptionService.reencryptApplicableItemsAfterUserRootKeyChange()
await this.application.encryption.reencryptApplicableItemsAfterUserRootKeyChange()
/** Note: this may result in a deadlock if features_service syncs and results in an error */
await this.application.sync.sync({ awaitAll: true })
/** Relaunch application and expect new items key to be created */
const identifier = this.application.identifier
/** Set to pre 2.0.15 version so migration runs */
await this.application.deviceInterface.setRawStorageValue(`${identifier}-snjs_version`, '2.0.14')
await this.application.device.setRawStorageValue(`${identifier}-snjs_version`, '2.0.14')
await Factory.safeDeinit(this.application)
const refreshedApp = await Factory.createApplicationWithFakeCrypto(identifier)
await Factory.initializeApplication(refreshedApp)
/** Expect a new items key to be created based on the new root key */
expect(refreshedApp.itemManager.getDisplayableItemsKeys().length).to.equal(2)
expect(refreshedApp.items.getDisplayableItemsKeys().length).to.equal(2)
await Factory.safeDeinit(refreshedApp)
})
})
@@ -793,8 +787,8 @@ describe('keys', function () {
await this.context.sync()
await promise
await this.application.itemManager.removeAllItemsFromMemory()
expect(this.application.encryptionService.getSureDefaultItemsKey()).to.not.be.ok
await this.application.items.removeAllItemsFromMemory()
expect(this.application.encryption.getSureDefaultItemsKey()).to.not.be.ok
const protocol003 = new SNProtocolOperator003(new SNWebCrypto())
const key = await protocol003.createItemsKey()
@@ -810,19 +804,19 @@ describe('keys', function () {
}),
)
const defaultKey = this.application.encryptionService.getSureDefaultItemsKey()
const defaultKey = this.application.encryption.getSureDefaultItemsKey()
expect(defaultKey.keyVersion).to.equal(ProtocolVersion.V003)
expect(defaultKey.uuid).to.equal(key.uuid)
await Factory.registerUserToApplication({ application: this.application })
const notePayload = Factory.createNotePayload()
expect(await this.application.encryptionService.itemsEncryption.keyToUseForItemEncryption(notePayload)).to.be.ok
expect(await this.application.encryption.itemsEncryption.keyToUseForItemEncryption(notePayload)).to.be.ok
})
it('having unsynced items keys should resync them upon download first sync completion', async function () {
await Factory.registerUserToApplication({ application: this.application })
const itemsKey = this.application.itemManager.getDisplayableItemsKeys()[0]
const itemsKey = this.application.items.getDisplayableItemsKeys()[0]
await this.application.mutator.emitItemFromPayload(
itemsKey.payload.copy({
dirty: false,
@@ -830,7 +824,7 @@ describe('keys', function () {
deleted: false,
}),
)
await this.application.syncService.sync({
await this.application.sync.sync({
mode: SyncMode.DownloadFirst,
})
const updatedKey = this.application.items.findItem(itemsKey.uuid)
@@ -840,7 +834,7 @@ describe('keys', function () {
it('having key while offline then signing into account with key should only have 1 default items key', async function () {
const otherClient = await Factory.createInitAppWithFakeCrypto()
/** Invert order of keys */
otherClient.itemManager.itemsKeyDisplayController.setDisplayOptions({ sortBy: 'dsc' })
otherClient.items.itemsKeyDisplayController.setDisplayOptions({ sortBy: 'dsc' })
/** On client A, create account and note */
await Factory.registerUserToApplication({
application: this.application,
@@ -856,12 +850,12 @@ describe('keys', function () {
email: this.email,
password: this.password,
})
const defaultKeys = otherClient.encryptionService.itemsEncryption.getItemsKeys().filter((key) => {
const defaultKeys = otherClient.encryption.itemsEncryption.getItemsKeys().filter((key) => {
return key.isDefault
})
expect(defaultKeys.length).to.equal(1)
const rawPayloads = await otherClient.diskStorageService.getAllRawPayloads()
const rawPayloads = await otherClient.storage.getAllRawPayloads()
const notePayload = rawPayloads.find((p) => p.content_type === ContentType.TYPES.Note)
expect(notePayload.items_key_id).to.equal(itemsKey.uuid)

View File

@@ -26,17 +26,16 @@ export class AppContext {
}
enableLogging() {
const syncService = this.application.syncService
const payloadManager = this.application.payloadManager
const payloadManager = this.application.payloads
syncService.getServiceName = () => {
this.application.sync.getServiceName = () => {
return `${this.identifier}—SyncService`
}
payloadManager.getServiceName = () => {
return `${this.identifier}-PayloadManager`
}
syncService.loggingEnabled = true
this.application.sync.loggingEnabled = true
payloadManager.loggingEnabled = true
}
@@ -51,7 +50,7 @@ export class AppContext {
}
get vaults() {
return this.application.vaultService
return this.application.vaults
}
get sessions() {
@@ -67,31 +66,51 @@ export class AppContext {
}
get payloads() {
return this.application.payloadManager
return this.application.payloads
}
get encryption() {
return this.application.encryptionService
return this.application.encryption
}
get keyRecovery() {
return this.application.dependencies.get(TYPES.KeyRecoveryService)
}
get singletons() {
return this.application.dependencies.get(TYPES.SingletonManager)
}
get history() {
return this.application.dependencies.get(TYPES.HistoryManager)
}
get subscriptions() {
return this.application.dependencies.get(TYPES.SubscriptionManager)
}
get contacts() {
return this.application.contactService
return this.application.contacts
}
get sharedVaults() {
return this.application.sharedVaultService
return this.application.sharedVaults
}
get files() {
return this.application.fileService
return this.application.files
}
get keys() {
return this.application.keySystemKeyManager
return this.application.dependencies.get(TYPES.KeySystemKeyManager)
}
get operators() {
return this.application.dependencies.get(TYPES.EncryptionOperators)
}
get asymmetric() {
return this.application.asymmetricMessageService
return this.application.asymmetric
}
get publicKey() {
@@ -115,20 +134,20 @@ export class AppContext {
}
disableIntegrityAutoHeal() {
this.application.syncService.emitOutOfSyncRemotePayloads = () => {
this.application.sync.emitOutOfSyncRemotePayloads = () => {
console.warn('Integrity self-healing is disabled for this test')
}
}
disableKeyRecovery() {
this.application.keyRecoveryService.beginKeyRecovery = () => {
this.keyRecovery.beginKeyRecovery = () => {
console.warn('Key recovery is disabled for this test')
}
}
handleChallenge = (challenge) => {
if (this.ignoringChallenges) {
this.application.challengeService.cancelChallenge(challenge)
this.application.challenges.cancelChallenge(challenge)
return
}
@@ -178,15 +197,12 @@ export class AppContext {
},
})
return this.application.syncService.handleSuccessServerResponse(
{ payloadsSavedOrSaving: [], options: {} },
response,
)
return this.application.sync.handleSuccessServerResponse({ payloadsSavedOrSaving: [], options: {} }, response)
}
resolveWhenKeyRecovered(uuid) {
return new Promise((resolve) => {
this.application.keyRecoveryService.addEventObserver((_eventName, keys) => {
this.keyRecovery.addEventObserver((_eventName, keys) => {
if (Uuids(keys).includes(uuid)) {
resolve()
}
@@ -196,7 +212,7 @@ export class AppContext {
resolveWhenSharedVaultUserKeysResolved() {
return new Promise((resolve) => {
this.application.vaultService.collaboration.addEventObserver((eventName) => {
this.application.vaults.collaboration.addEventObserver((eventName) => {
if (eventName === SharedVaultServiceEvent.SharedVaultStatusChanged) {
resolve()
}
@@ -206,7 +222,7 @@ export class AppContext {
async awaitSignInEvent() {
return new Promise((resolve) => {
this.application.userService.addEventObserver((eventName) => {
this.application.user.addEventObserver((eventName) => {
if (eventName === AccountEvent.SignedInOrRegistered) {
resolve()
}
@@ -235,7 +251,7 @@ export class AppContext {
awaitNextSucessfulSync() {
return new Promise((resolve) => {
const removeObserver = this.application.syncService.addEventObserver((event) => {
const removeObserver = this.application.sync.addEventObserver((event) => {
if (event === SyncEvent.SyncCompletedWithAllItemsUploadedAndDownloaded) {
removeObserver()
resolve()
@@ -246,7 +262,7 @@ export class AppContext {
awaitNextSyncEvent(eventName) {
return new Promise((resolve) => {
const removeObserver = this.application.syncService.addEventObserver((event, data) => {
const removeObserver = this.application.sync.addEventObserver((event, data) => {
if (event === eventName) {
removeObserver()
resolve(data)
@@ -257,7 +273,7 @@ export class AppContext {
awaitNextSyncSharedVaultFromScratchEvent() {
return new Promise((resolve) => {
const removeObserver = this.application.syncService.addEventObserver((event, data) => {
const removeObserver = this.application.sync.addEventObserver((event, data) => {
if (event === SyncEvent.PaginatedSyncRequestCompleted && data?.options?.sharedVaultUuids) {
removeObserver()
resolve(data)
@@ -268,7 +284,7 @@ export class AppContext {
resolveWithUploadedPayloads() {
return new Promise((resolve) => {
this.application.syncService.addEventObserver((event, data) => {
this.application.sync.addEventObserver((event, data) => {
if (event === SyncEvent.PaginatedSyncRequestCompleted) {
resolve(data.uploadedPayloads)
}
@@ -278,7 +294,7 @@ export class AppContext {
resolveWithConflicts() {
return new Promise((resolve) => {
this.application.syncService.addEventObserver((event, response) => {
this.application.sync.addEventObserver((event, response) => {
if (event === SyncEvent.PaginatedSyncRequestCompleted) {
resolve(response.rawConflictObjects)
}
@@ -288,7 +304,7 @@ export class AppContext {
resolveWhenSavedSyncPayloadsIncludesItemUuid(uuid) {
return new Promise((resolve) => {
this.application.syncService.addEventObserver((event, response) => {
this.application.sync.addEventObserver((event, response) => {
if (event === SyncEvent.PaginatedSyncRequestCompleted) {
const savedPayload = response.savedPayloads.find((payload) => payload.uuid === uuid)
if (savedPayload) {
@@ -301,7 +317,7 @@ export class AppContext {
resolveWhenSavedSyncPayloadsIncludesItemThatIsDuplicatedOf(uuid) {
return new Promise((resolve) => {
this.application.syncService.addEventObserver((event, response) => {
this.application.sync.addEventObserver((event, response) => {
if (event === SyncEvent.PaginatedSyncRequestCompleted) {
const savedPayload = response.savedPayloads.find((payload) => payload.duplicate_of === uuid)
if (savedPayload) {
@@ -354,7 +370,7 @@ export class AppContext {
resolveWhenUserMessagesProcessingCompletes() {
return new Promise((resolve) => {
const objectToSpy = this.application.userEventService
const objectToSpy = this.application.dependencies.get(TYPES.UserEventService)
sinon.stub(objectToSpy, 'handleReceivedUserEvents').callsFake(async (params) => {
objectToSpy.handleReceivedUserEvents.restore()
const result = await objectToSpy.handleReceivedUserEvents(params)
@@ -364,12 +380,36 @@ export class AppContext {
})
}
resolveWhenAllInboundAsymmetricMessagesAreDeleted() {
return new Promise((resolve) => {
const objectToSpy = this.application.dependencies.get(TYPES.AsymmetricMessageServer)
sinon.stub(objectToSpy, 'deleteAllInboundMessages').callsFake(async (params) => {
objectToSpy.deleteAllInboundMessages.restore()
const result = await objectToSpy.deleteAllInboundMessages(params)
resolve()
return result
})
})
}
resolveWhenAllInboundSharedVaultInvitesAreDeleted() {
return new Promise((resolve) => {
const objectToSpy = this.application.sharedVaults.invitesServer
sinon.stub(objectToSpy, 'deleteAllInboundInvites').callsFake(async (params) => {
objectToSpy.deleteAllInboundInvites.restore()
const result = await objectToSpy.deleteAllInboundInvites(params)
resolve()
return result
})
})
}
resolveWhenSharedVaultServiceSendsContactShareMessage() {
return new Promise((resolve) => {
const objectToSpy = this.sharedVaults
sinon.stub(objectToSpy, 'shareContactWithUserAdministeredSharedVaults').callsFake(async (contact) => {
objectToSpy.shareContactWithUserAdministeredSharedVaults.restore()
const result = await objectToSpy.shareContactWithUserAdministeredSharedVaults(contact)
sinon.stub(objectToSpy, 'shareContactWithVaults').callsFake(async (contact) => {
objectToSpy.shareContactWithVaults.restore()
const result = await objectToSpy.shareContactWithVaults(contact)
resolve()
return result
})
@@ -405,14 +445,14 @@ export class AppContext {
}
awaitUserPrefsSingletonCreation() {
const preferences = this.application.preferencesService.preferences
const preferences = this.application.preferences.preferences
if (preferences) {
return
}
let didCompleteRelevantSync = false
return new Promise((resolve) => {
this.application.syncService.addEventObserver((eventName, data) => {
this.application.sync.addEventObserver((eventName, data) => {
if (!didCompleteRelevantSync) {
if (data?.savedPayloads) {
const matching = data.savedPayloads.find((p) => {
@@ -430,7 +470,7 @@ export class AppContext {
awaitUserPrefsSingletonResolution() {
return new Promise((resolve) => {
this.application.preferencesService.addEventObserver((eventName) => {
this.application.preferences.addEventObserver((eventName) => {
if (eventName === PreferencesServiceEvent.PreferencesChanged) {
resolve()
}
@@ -473,7 +513,7 @@ export class AppContext {
}
findPayload(uuid) {
return this.application.payloadManager.findPayload(uuid)
return this.application.payloads.findPayload(uuid)
}
get itemsKeys() {
@@ -491,15 +531,15 @@ export class AppContext {
}
disableKeyRecoveryServerSignIn() {
this.application.keyRecoveryService.performServerSignIn = () => {
console.warn('application.keyRecoveryService.performServerSignIn has been stubbed with an empty implementation')
this.keyRecovery.performServerSignIn = () => {
console.warn('application.keyRecovery.performServerSignIn has been stubbed with an empty implementation')
}
}
preventKeyRecoveryOfKeys(ids) {
const originalImpl = this.application.keyRecoveryService.handleUndecryptableItemsKeys
const originalImpl = this.keyRecovery.handleUndecryptableItemsKeys
this.application.keyRecoveryService.handleUndecryptableItemsKeys = function (keys) {
this.keyRecovery.handleUndecryptableItemsKeys = function (keys) {
const filtered = keys.filter((k) => !ids.includes(k.uuid))
originalImpl.apply(this, [filtered])
@@ -520,18 +560,18 @@ export class AppContext {
const payload = createNotePayload(title, text)
const item = await this.application.mutator.emitItemFromPayload(payload, PayloadEmitSource.LocalChanged)
await this.application.mutator.setItemDirty(item)
await this.application.syncService.sync(MaximumSyncOptions)
await this.application.sync.sync(MaximumSyncOptions)
const note = this.application.items.findItem(payload.uuid)
return note
}
lockSyncing() {
this.application.syncService.lockSyncing()
this.application.sync.lockSyncing()
}
unlockSyncing() {
this.application.syncService.unlockSyncing()
this.application.sync.unlockSyncing()
}
async deleteItemAndSync(item) {
@@ -624,7 +664,9 @@ export class AppContext {
await Utils.sleep(2)
} catch (error) {
console.warn(`Mock events service not available. You are probalby running a test suite for home server: ${error.message}`)
console.warn(
`Mock events service not available. You are probalby running a test suite for home server: ${error.message}`,
)
}
try {
@@ -632,7 +674,9 @@ export class AppContext {
await Utils.sleep(1)
} catch (error) {
console.warn(`Home server not available. You are probalby running a test suite for self hosted setup: ${error.message}`)
console.warn(
`Home server not available. You are probalby running a test suite for self hosted setup: ${error.message}`,
)
}
}
}

View File

@@ -15,7 +15,7 @@ export const createTrustedContactForUserOfContext = async (
contextAddingNewContact,
contextImportingContactInfoFrom,
) => {
const contact = await contextAddingNewContact.application.contactService.createOrEditTrustedContact({
const contact = await contextAddingNewContact.contacts.createOrEditTrustedContact({
name: 'John Doe',
publicKey: contextImportingContactInfoFrom.publicKey,
signingPublicKey: contextImportingContactInfoFrom.signingPublicKey,
@@ -27,6 +27,10 @@ export const createTrustedContactForUserOfContext = async (
export const acceptAllInvites = async (context) => {
const inviteRecords = context.sharedVaults.getCachedPendingInviteRecords()
if (inviteRecords.length === 0) {
throw new Error('No pending invites to accept')
}
for (const record of inviteRecords) {
await context.sharedVaults.acceptPendingSharedVaultInvite(record)
}
@@ -72,7 +76,7 @@ export const createSharedVaultWithUnacceptedButTrustedInvite = async (
const contact = await createTrustedContactForUserOfContext(context, contactContext)
await createTrustedContactForUserOfContext(contactContext, context)
const invite = await context.sharedVaults.inviteContactToSharedVault(sharedVault, contact, permissions)
const invite = (await context.sharedVaults.inviteContactToSharedVault(sharedVault, contact, permissions)).getValue()
await contactContext.sync()
return { sharedVault, contact, contactContext, deinitContactContext, invite }
@@ -87,7 +91,7 @@ export const createSharedVaultWithUnacceptedAndUntrustedInvite = async (
const { contactContext, deinitContactContext } = await createContactContext()
const contact = await createTrustedContactForUserOfContext(context, contactContext)
const invite = await context.sharedVaults.inviteContactToSharedVault(sharedVault, contact, permissions)
const invite = (await context.sharedVaults.inviteContactToSharedVault(sharedVault, contact, permissions)).getValue()
await contactContext.sync()
return { sharedVault, contact, contactContext, deinitContactContext, invite }

View File

@@ -8,10 +8,10 @@ export async function safeDeinit(application) {
return
}
await application.diskStorageService.awaitPersist()
await application.storage.awaitPersist()
/** Limit waiting to 1s */
await Promise.race([sleep(1), application.syncService?.awaitCurrentSyncs()])
await Promise.race([sleep(1), application.sync?.awaitCurrentSyncs()])
await application.prepareForDeinit()

View File

@@ -58,7 +58,7 @@ export async function createAppContext({ identifier, crypto, email, password, ho
}
export function disableIntegrityAutoHeal(application) {
application.syncService.emitOutOfSyncRemotePayloads = () => {
application.sync.emitOutOfSyncRemotePayloads = () => {
console.warn('Integrity self-healing is disabled for this test')
}
}
@@ -112,12 +112,12 @@ export function registerUserToApplication({ application, email, password, epheme
}
export async function setOldVersionPasscode({ application, passcode, version }) {
const identifier = await application.encryptionService.crypto.generateUUID()
const operator = application.encryptionService.operators.operatorForVersion(version)
const identifier = await application.encryption.crypto.generateUUID()
const operator = application.dependencies.get(TYPES.EncryptionOperators).operatorForVersion(version)
const key = await operator.createRootKey(identifier, passcode, KeyParamsOrigination.PasscodeCreate)
await application.encryptionService.setNewRootKeyWrapper(key)
await application.userService.rewriteItemsKeys()
await application.syncService.sync(syncOptions)
await application.encryption.setNewRootKeyWrapper(key)
await application.user.rewriteItemsKeys()
await application.sync.sync(syncOptions)
}
/**
@@ -127,25 +127,26 @@ export async function setOldVersionPasscode({ application, passcode, version })
export async function registerOldUser({ application, email, password, version }) {
if (!email) email = Utils.generateUuid()
if (!password) password = Utils.generateUuid()
const operator = application.encryptionService.operators.operatorForVersion(version)
const operator = application.dependencies.get(TYPES.EncryptionOperators).operatorForVersion(version)
const accountKey = await operator.createRootKey(email, password, KeyParamsOrigination.Registration)
const response = await application.userApiService.register({
const response = await application.dependencies.get(TYPES.UserApiService).register({
email: email,
serverPassword: accountKey.serverPassword,
keyParams: accountKey.keyParams,
})
/** Mark all existing items as dirty. */
await application.mutator.changeItems(application.itemManager.items, (m) => {
await application.mutator.changeItems(application.items.items, (m) => {
m.dirty = true
})
await application.sessionManager.handleSuccessAuthResponse(response, accountKey)
await application.sessions.handleSuccessAuthResponse(response, accountKey)
application.notifyEvent(ApplicationEvent.SignedIn)
await application.syncService.sync({
await application.sync.sync({
mode: SyncMode.DownloadFirst,
...syncOptions,
})
await application.encryptionService.decryptErroredPayloads()
await application.encryption.decryptErroredPayloads()
}
export function createStorageItemPayload(contentType) {
@@ -182,13 +183,13 @@ export async function createSyncedNote(application, title, text) {
const payload = createNotePayload(title, text)
const item = await application.mutator.emitItemFromPayload(payload, PayloadEmitSource.LocalChanged)
await application.mutator.setItemDirty(item)
await application.syncService.sync(syncOptions)
await application.sync.sync(syncOptions)
const note = application.items.findItem(payload.uuid)
return note
}
export async function getStoragePayloadsOfType(application, type) {
const rawPayloads = await application.diskStorageService.getAllRawPayloads()
const rawPayloads = await application.storage.getAllRawPayloads()
return rawPayloads
.filter((rp) => rp.content_type === type)
.map((rp) => {
@@ -263,7 +264,7 @@ export async function restartApplication(application) {
}
export async function storagePayloadCount(application) {
const payloads = await application.diskStorageService.getAllRawPayloads()
const payloads = await application.storage.getAllRawPayloads()
return payloads.length
}
@@ -397,28 +398,28 @@ export async function insertItemWithOverride(application, contentType, content,
errorDecrypting,
})
await application.payloadManager.emitPayload(encrypted)
await application.payloads.emitPayload(encrypted)
} else {
const decrypted = new DecryptedPayload({
...item.payload.ejected(),
})
await application.payloadManager.emitPayload(decrypted)
await application.payloads.emitPayload(decrypted)
}
return application.itemManager.findAnyItem(item.uuid)
return application.items.findAnyItem(item.uuid)
}
export async function alternateUuidForItem(application, uuid) {
const item = application.itemManager.findItem(uuid)
const item = application.items.findItem(uuid)
const payload = new DecryptedPayload(item)
const results = await PayloadsByAlternatingUuid(payload, application.payloadManager.getMasterCollection())
await application.payloadManager.emitPayloads(results, PayloadEmitSource.LocalChanged)
await application.syncService.persistPayloads(results)
return application.itemManager.findItem(results[0].uuid)
const results = await PayloadsByAlternatingUuid(payload, application.payloads.getMasterCollection())
await application.payloads.emitPayloads(results, PayloadEmitSource.LocalChanged)
await application.sync.persistPayloads(results)
return application.items.findItem(results[0].uuid)
}
export async function markDirtyAndSyncItem(application, itemToLookupUuidFor) {
const item = application.itemManager.findItem(itemToLookupUuidFor.uuid)
const item = application.items.findItem(itemToLookupUuidFor.uuid)
if (!item) {
throw Error('Attempting to save non-inserted item')
}
@@ -433,11 +434,11 @@ export async function changePayloadTimeStampAndSync(application, payload, timest
await application.sync.sync(syncOptions)
return application.itemManager.findAnyItem(payload.uuid)
return application.items.findAnyItem(payload.uuid)
}
export async function changePayloadTimeStamp(application, payload, timestamp, contentOverride) {
payload = application.payloadManager.collection.find(payload.uuid)
payload = application.payloads.collection.find(payload.uuid)
const changedPayload = new DecryptedPayload({
...payload,
dirty: true,
@@ -451,11 +452,11 @@ export async function changePayloadTimeStamp(application, payload, timestamp, co
await application.mutator.emitItemFromPayload(changedPayload)
return application.itemManager.findAnyItem(payload.uuid)
return application.items.findAnyItem(payload.uuid)
}
export async function changePayloadUpdatedAt(application, payload, updatedAt) {
const latestPayload = application.payloadManager.collection.find(payload.uuid)
const latestPayload = application.payloads.collection.find(payload.uuid)
const changedPayload = new DecryptedPayload({
...latestPayload.ejected(),
@@ -468,7 +469,7 @@ export async function changePayloadUpdatedAt(application, payload, updatedAt) {
}
export async function changePayloadTimeStampDeleteAndSync(application, payload, timestamp, syncOptions) {
payload = application.payloadManager.collection.find(payload.uuid)
payload = application.payloads.collection.find(payload.uuid)
const changedPayload = new DeletedPayload({
...payload,
content: undefined,
@@ -478,6 +479,6 @@ export async function changePayloadTimeStampDeleteAndSync(application, payload,
updated_at_timestamp: timestamp,
})
await application.payloadManager.emitPayload(changedPayload)
await application.payloads.emitPayload(changedPayload)
await application.sync.sync(syncOptions)
}

View File

@@ -139,8 +139,8 @@ export default class FakeWebCrypto {
const data = {
message,
nonce,
senderSecretKey,
recipientPublicKey,
senderSecretKey,
}
return btoa(JSON.stringify(data))
}

View File

@@ -54,11 +54,11 @@ describe('mfa service', () => {
const secret = await snApp.generateMfaSecret()
const token = await snApp.getOtpToken(secret)
sinon.spy(snApp.challengeService, 'sendChallenge')
sinon.spy(snApp.challenges, 'sendChallenge')
await snApp.enableMfa(secret, token)
await snApp.disableMfa()
const spyCall = snApp.challengeService.sendChallenge.getCall(0)
const spyCall = snApp.challenges.sendChallenge.getCall(0)
const challenge = spyCall.firstArg
expect(challenge.prompts).to.have.lengthOf(2)
expect(challenge.prompts[0].validation).to.equal(ChallengeValidation.AccountPassword)

View File

@@ -15,39 +15,39 @@ describe('migrations', () => {
it('version number is stored as string', async function () {
const application = await Factory.createInitAppWithFakeCrypto()
const version = await application.migrationService.getStoredSnjsVersion()
const version = await application.migrations.getStoredSnjsVersion()
expect(typeof version).to.equal('string')
await Factory.safeDeinit(application)
})
it('should return correct required migrations if stored version is 1.0.0', async function () {
expect((await SNMigrationService.getRequiredMigrations('1.0.0')).length).to.equal(allMigrationsLength)
expect((await MigrationService.getRequiredMigrations('1.0.0')).length).to.equal(allMigrationsLength)
})
it('should return correct required migrations if stored version is 2.0.0', async function () {
expect((await SNMigrationService.getRequiredMigrations('2.0.0')).length).to.equal(allMigrationsLength)
expect((await MigrationService.getRequiredMigrations('2.0.0')).length).to.equal(allMigrationsLength)
})
it('should return 0 required migrations if stored version is futuristic', async function () {
expect((await SNMigrationService.getRequiredMigrations('100.0.1')).length).to.equal(0)
expect((await MigrationService.getRequiredMigrations('100.0.1')).length).to.equal(0)
})
it('after running base migration with no present storage values, should set version to current', async function () {
const application = await Factory.createAppWithRandNamespace()
await application.migrationService.runBaseMigrationPreRun()
expect(await application.migrationService.getStoredSnjsVersion()).to.equal(SnjsVersion)
await application.migrations.runBaseMigrationPreRun()
expect(await application.migrations.getStoredSnjsVersion()).to.equal(SnjsVersion)
await Factory.safeDeinit(application)
})
it('after running all migrations from a 2.0.0 installation, should set stored version to current', async function () {
const application = await Factory.createAppWithRandNamespace()
/** Set up 2.0.0 structure with tell-tale storage key */
await application.deviceInterface.setRawStorageValue('last_migration_timestamp', JSON.stringify(['anything']))
await application.device.setRawStorageValue('last_migration_timestamp', JSON.stringify(['anything']))
await application.prepareForLaunch({
receiveChallenge: () => {},
})
await application.launch(true)
expect(await application.migrationService.getStoredSnjsVersion()).to.equal(SnjsVersion)
expect(await application.migrations.getStoredSnjsVersion()).to.equal(SnjsVersion)
await Factory.safeDeinit(application)
})
@@ -72,18 +72,18 @@ describe('migrations', () => {
await application.sync.sync()
expect(application.items.getItems('SF|MFA').length).to.equal(1)
expect(
(await application.diskStorageService.getAllRawPayloads()).filter((p) => p.content_type === 'SF|MFA').length,
).to.equal(1)
expect((await application.storage.getAllRawPayloads()).filter((p) => p.content_type === 'SF|MFA').length).to.equal(
1,
)
/** Run migration */
const migration = new Migration2_20_0(application.migrationService.services)
const migration = new Migration2_20_0(application.migrations.services)
await migration.handleStage(ApplicationStage.LoadedDatabase_12)
expect(application.items.getItems('SF|MFA').length).to.equal(0)
expect(
(await application.diskStorageService.getAllRawPayloads()).filter((p) => p.content_type === 'SF|MFA').length,
).to.equal(0)
expect((await application.storage.getAllRawPayloads()).filter((p) => p.content_type === 'SF|MFA').length).to.equal(
0,
)
await Factory.safeDeinit(application)
})
@@ -113,7 +113,7 @@ describe('migrations', () => {
expect(application.items.getItems(ContentType.TYPES.Theme).length).to.equal(1)
/** Run migration */
const migration = new Migration2_42_0(application.migrationService.services)
const migration = new Migration2_42_0(application.migrations.services)
await migration.handleStage(ApplicationStage.FullSyncCompleted_13)
await application.sync.sync()
@@ -156,7 +156,7 @@ describe('migrations', () => {
expect(application.items.getItems(ContentType.TYPES.Component).length).to.equal(1)
/** Run migration */
const migration = new Migration2_202_1(application.migrationService.services)
const migration = new Migration2_202_1(application.migrations.services)
await migration.handleStage(ApplicationStage.FullSyncCompleted_13)
await application.sync.sync()
@@ -181,7 +181,7 @@ describe('migrations', () => {
expect(application.items.getItems(ContentType.TYPES.Component).length).to.equal(1)
/** Run migration */
const migration = new Migration2_202_1(application.migrationService.services)
const migration = new Migration2_202_1(application.migrations.services)
await migration.handleStage(ApplicationStage.FullSyncCompleted_13)
await application.sync.sync()

View File

@@ -171,7 +171,7 @@ const makeTags = async (application, titles) => {
const extractTagHierarchy = (application) => {
const result = {}
const roots = application.itemManager.getRootTags()
const roots = application.items.getRootTags()
const constructHierarchy = (currentTag, result) => {
result[currentTag.title] = { _uuid: currentTag.uuid }

View File

@@ -30,8 +30,8 @@ describe('app models', () => {
await Factory.safeDeinit(this.application)
})
it('payloadManager should be defined', () => {
expect(sharedApplication.payloadManager).to.be.ok
it('payloads should be defined', () => {
expect(sharedApplication.payloads).to.be.ok
})
it('item should be defined', () => {
@@ -75,14 +75,14 @@ describe('app models', () => {
await this.application.mutator.emitItemsFromPayloads([mutated], PayloadEmitSource.LocalChanged)
await this.application.mutator.emitItemsFromPayloads([params2], PayloadEmitSource.LocalChanged)
const item1 = this.application.itemManager.findItem(params1.uuid)
const item2 = this.application.itemManager.findItem(params2.uuid)
const item1 = this.application.items.findItem(params1.uuid)
const item2 = this.application.items.findItem(params2.uuid)
expect(item1.content.references.length).to.equal(1)
expect(item2.content.references.length).to.equal(0)
expect(this.application.itemManager.itemsReferencingItem(item1).length).to.equal(0)
expect(this.application.itemManager.itemsReferencingItem(item2).length).to.equal(1)
expect(this.application.items.itemsReferencingItem(item1).length).to.equal(0)
expect(this.application.items.itemsReferencingItem(item2).length).to.equal(1)
})
it('mapping an item twice shouldnt cause problems', async function () {
@@ -103,7 +103,7 @@ describe('app models', () => {
item = items[0]
expect(item.content.foo).to.equal('bar')
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
})
it('mapping item twice should preserve references', async function () {
@@ -117,7 +117,7 @@ describe('app models', () => {
mutator.e2ePendingRefactor_addItemAsRelationship(item1)
})
const refreshedItem = this.application.itemManager.findItem(item1.uuid)
const refreshedItem = this.application.items.findItem(item1.uuid)
expect(refreshedItem.content.references.length).to.equal(1)
})
@@ -132,8 +132,8 @@ describe('app models', () => {
mutator.e2ePendingRefactor_addItemAsRelationship(item1)
})
const refreshedItem1 = this.application.itemManager.findItem(item1.uuid)
const refreshedItem2 = this.application.itemManager.findItem(item2.uuid)
const refreshedItem1 = this.application.items.findItem(item1.uuid)
const refreshedItem2 = this.application.items.findItem(item2.uuid)
expect(refreshedItem1.content.references.length).to.equal(1)
expect(refreshedItem2.content.references.length).to.equal(1)
@@ -147,8 +147,8 @@ describe('app models', () => {
})
await this.application.mutator.emitItemsFromPayloads([damagedPayload], PayloadEmitSource.LocalChanged)
const refreshedItem1_2 = this.application.itemManager.findItem(item1.uuid)
const refreshedItem2_2 = this.application.itemManager.findItem(item2.uuid)
const refreshedItem1_2 = this.application.items.findItem(item1.uuid)
const refreshedItem2_2 = this.application.items.findItem(item2.uuid)
expect(refreshedItem1_2.content.references.length).to.equal(0)
expect(refreshedItem2_2.content.references.length).to.equal(1)
@@ -164,14 +164,14 @@ describe('app models', () => {
mutator.e2ePendingRefactor_addItemAsRelationship(item1)
})
const refreshedItem1 = this.application.itemManager.findItem(item1.uuid)
const refreshedItem2 = this.application.itemManager.findItem(item2.uuid)
const refreshedItem1 = this.application.items.findItem(item1.uuid)
const refreshedItem2 = this.application.items.findItem(item2.uuid)
expect(refreshedItem1.content.references.length).to.equal(1)
expect(refreshedItem2.content.references.length).to.equal(1)
expect(this.application.itemManager.itemsReferencingItem(item1)).to.include(refreshedItem2)
expect(this.application.itemManager.itemsReferencingItem(item2)).to.include(refreshedItem1)
expect(this.application.items.itemsReferencingItem(item1)).to.include(refreshedItem2)
expect(this.application.items.itemsReferencingItem(item2)).to.include(refreshedItem1)
await this.application.mutator.changeItem(item1, (mutator) => {
mutator.removeItemAsRelationship(item2)
@@ -180,14 +180,14 @@ describe('app models', () => {
mutator.removeItemAsRelationship(item1)
})
const refreshedItem1_2 = this.application.itemManager.findItem(item1.uuid)
const refreshedItem2_2 = this.application.itemManager.findItem(item2.uuid)
const refreshedItem1_2 = this.application.items.findItem(item1.uuid)
const refreshedItem2_2 = this.application.items.findItem(item2.uuid)
expect(refreshedItem1_2.content.references.length).to.equal(0)
expect(refreshedItem2_2.content.references.length).to.equal(0)
expect(this.application.itemManager.itemsReferencingItem(item1).length).to.equal(0)
expect(this.application.itemManager.itemsReferencingItem(item2).length).to.equal(0)
expect(this.application.items.itemsReferencingItem(item1).length).to.equal(0)
expect(this.application.items.itemsReferencingItem(item2).length).to.equal(0)
})
it('properly duplicates item with no relationships', async function () {
@@ -213,10 +213,10 @@ describe('app models', () => {
expect(duplicate.uuid).to.not.equal(item1.uuid)
expect(duplicate.content.references.length).to.equal(1)
expect(this.application.itemManager.itemsReferencingItem(item1).length).to.equal(0)
expect(this.application.itemManager.itemsReferencingItem(item2).length).to.equal(2)
expect(this.application.items.itemsReferencingItem(item1).length).to.equal(0)
expect(this.application.items.itemsReferencingItem(item2).length).to.equal(2)
const refreshedItem1_2 = this.application.itemManager.findItem(item1.uuid)
const refreshedItem1_2 = this.application.items.findItem(item1.uuid)
expect(refreshedItem1_2.isItemContentEqualWith(duplicate)).to.equal(true)
expect(refreshedItem1_2.created_at.toISOString()).to.equal(duplicate.created_at.toISOString())
expect(refreshedItem1_2.content_type).to.equal(duplicate.content_type)
@@ -240,8 +240,8 @@ describe('app models', () => {
PayloadEmitSource.LocalChanged,
)
expect(this.application.itemManager.itemsReferencingItem(item2).length).to.equal(0)
expect(this.application.itemManager.itemsReferencingItem(item1).length).to.equal(0)
expect(this.application.items.itemsReferencingItem(item2).length).to.equal(0)
expect(this.application.items.itemsReferencingItem(item1).length).to.equal(0)
expect(refreshedItem1_2.content.references.length).to.equal(0)
})
@@ -254,18 +254,18 @@ describe('app models', () => {
})
expect(refreshedItem1.content.references.length).to.equal(1)
expect(this.application.itemManager.itemsReferencingItem(item2).length).to.equal(1)
expect(this.application.items.itemsReferencingItem(item2).length).to.equal(1)
const alternatedItem = await Factory.alternateUuidForItem(this.application, item1.uuid)
const refreshedItem1_2 = this.application.itemManager.findItem(item1.uuid)
const refreshedItem1_2 = this.application.items.findItem(item1.uuid)
expect(refreshedItem1_2).to.not.be.ok
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(2)
expect(this.application.items.getDisplayableNotes().length).to.equal(2)
expect(alternatedItem.content.references.length).to.equal(1)
expect(this.application.itemManager.itemsReferencingItem(alternatedItem.uuid).length).to.equal(0)
expect(this.application.items.itemsReferencingItem(alternatedItem.uuid).length).to.equal(0)
expect(this.application.itemManager.itemsReferencingItem(item2).length).to.equal(1)
expect(this.application.items.itemsReferencingItem(item2).length).to.equal(1)
expect(alternatedItem.isReferencingItem(item2)).to.equal(true)
expect(alternatedItem.dirty).to.equal(true)
@@ -279,10 +279,10 @@ describe('app models', () => {
it('alterating itemskey uuid should update errored items encrypted with that key', async function () {
const item1 = await Factory.createMappedNote(this.application)
const itemsKey = this.application.itemManager.getDisplayableItemsKeys()[0]
const itemsKey = this.application.items.getDisplayableItemsKeys()[0]
/** Encrypt item1 and emit as errored so it persists with items_key_id */
const encrypted = await this.application.encryptionService.encryptSplitSingle({
const encrypted = await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [item1.payload],
},
@@ -292,17 +292,17 @@ describe('app models', () => {
waitingForKey: true,
})
await this.application.payloadManager.emitPayload(errored)
await this.application.payloads.emitPayload(errored)
expect(this.application.payloadManager.findOne(item1.uuid).errorDecrypting).to.equal(true)
expect(this.application.payloadManager.findOne(item1.uuid).items_key_id).to.equal(itemsKey.uuid)
expect(this.application.payloads.findOne(item1.uuid).errorDecrypting).to.equal(true)
expect(this.application.payloads.findOne(item1.uuid).items_key_id).to.equal(itemsKey.uuid)
sinon.stub(this.application.encryptionService.itemsEncryption, 'decryptErroredItemPayloads').callsFake(() => {
sinon.stub(this.application.encryption.itemsEncryption, 'decryptErroredItemPayloads').callsFake(() => {
// prevent auto decryption
})
const alternatedKey = await Factory.alternateUuidForItem(this.application, itemsKey.uuid)
const updatedPayload = this.application.payloadManager.findOne(item1.uuid)
const updatedPayload = this.application.payloads.findOne(item1.uuid)
expect(updatedPayload.items_key_id).to.equal(alternatedKey.uuid)
})
@@ -316,22 +316,22 @@ describe('app models', () => {
mutator.e2ePendingRefactor_addItemAsRelationship(item2)
})
expect(this.application.itemManager.itemsReferencingItem(item2).length).to.equal(1)
expect(this.application.items.itemsReferencingItem(item2).length).to.equal(1)
const alternatedItem1 = await Factory.alternateUuidForItem(this.application, item1.uuid)
const alternatedItem2 = await Factory.alternateUuidForItem(this.application, item2.uuid)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
expect(item1.uuid).to.not.equal(alternatedItem1.uuid)
expect(item2.uuid).to.not.equal(alternatedItem2.uuid)
const refreshedAltItem1 = this.application.itemManager.findItem(alternatedItem1.uuid)
const refreshedAltItem1 = this.application.items.findItem(alternatedItem1.uuid)
expect(refreshedAltItem1.content.references.length).to.equal(1)
expect(refreshedAltItem1.content.references[0].uuid).to.equal(alternatedItem2.uuid)
expect(alternatedItem2.content.references.length).to.equal(0)
expect(this.application.itemManager.itemsReferencingItem(alternatedItem2).length).to.equal(1)
expect(this.application.items.itemsReferencingItem(alternatedItem2).length).to.equal(1)
expect(refreshedAltItem1.isReferencingItem(alternatedItem2)).to.equal(true)
expect(alternatedItem2.isReferencingItem(refreshedAltItem1)).to.equal(false)
@@ -350,12 +350,12 @@ describe('app models', () => {
const noteCopy = await this.application.mutator.duplicateItem(note)
expect(note.uuid).to.not.equal(noteCopy.uuid)
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(2)
expect(this.application.itemManager.getDisplayableTags().length).to.equal(1)
expect(this.application.items.getDisplayableNotes().length).to.equal(2)
expect(this.application.items.getDisplayableTags().length).to.equal(1)
expect(note.content.references.length).to.equal(0)
expect(noteCopy.content.references.length).to.equal(0)
const refreshedTag_2 = this.application.itemManager.findItem(tag.uuid)
const refreshedTag_2 = this.application.items.findItem(tag.uuid)
expect(refreshedTag_2.content.references.length).to.equal(2)
})

View File

@@ -73,14 +73,14 @@ describe('importing', function () {
await application.mutator.emitItemsFromPayloads([notePayload, tagPayload], PayloadEmitSource.LocalChanged)
expectedItemCount += 2
const note = application.itemManager.getItems([ContentType.TYPES.Note])[0]
const tag = application.itemManager.getItems([ContentType.TYPES.Tag])[0]
const note = application.items.getItems([ContentType.TYPES.Note])[0]
const tag = application.items.getItems([ContentType.TYPES.Tag])[0]
expect(tag.content.references.length).to.equal(1)
expect(tag.noteCount).to.equal(1)
expect(note.content.references.length).to.equal(0)
expect(application.itemManager.itemsReferencingItem(note).length).to.equal(1)
expect(application.items.itemsReferencingItem(note).length).to.equal(1)
await application.importData(
{
@@ -89,13 +89,13 @@ describe('importing', function () {
true,
)
expect(application.itemManager.items.length).to.equal(expectedItemCount)
expect(application.items.items.length).to.equal(expectedItemCount)
expect(tag.content.references.length).to.equal(1)
expect(tag.noteCount).to.equal(1)
expect(note.content.references.length).to.equal(0)
expect(application.itemManager.itemsReferencingItem(note).length).to.equal(1)
expect(application.items.itemsReferencingItem(note).length).to.equal(1)
})
it('importing same note many times should create only one duplicate', async function () {
@@ -121,8 +121,8 @@ describe('importing', function () {
true,
)
expectedItemCount++
expect(application.itemManager.getDisplayableNotes().length).to.equal(2)
const imported = application.itemManager.getDisplayableNotes().find((n) => n.uuid !== notePayload.uuid)
expect(application.items.getDisplayableNotes().length).to.equal(2)
const imported = application.items.getDisplayableNotes().find((n) => n.uuid !== notePayload.uuid)
expect(imported.content.title).to.equal(mutatedNote.content.title)
})
@@ -144,8 +144,8 @@ describe('importing', function () {
},
true,
)
expect(application.itemManager.getDisplayableTags().length).to.equal(1)
expect(application.itemManager.findItem(tagPayload.uuid).content.references.length).to.equal(1)
expect(application.items.getDisplayableTags().length).to.equal(1)
expect(application.items.findItem(tagPayload.uuid).content.references.length).to.equal(1)
})
it('importing data with differing content should create duplicates', async function () {
@@ -155,8 +155,8 @@ describe('importing', function () {
const tagPayload = pair[1]
await application.mutator.emitItemsFromPayloads(pair, PayloadEmitSource.LocalChanged)
expectedItemCount += 2
const note = application.itemManager.getDisplayableNotes()[0]
const tag = application.itemManager.getDisplayableTags()[0]
const note = application.items.getDisplayableNotes()[0]
const tag = application.items.getDisplayableTags()[0]
const mutatedNote = new DecryptedPayload({
...notePayload,
content: {
@@ -178,27 +178,27 @@ describe('importing', function () {
true,
)
expectedItemCount += 2
expect(application.itemManager.items.length).to.equal(expectedItemCount)
expect(application.items.items.length).to.equal(expectedItemCount)
const newNote = application.itemManager.getDisplayableNotes().find((n) => n.uuid !== notePayload.uuid)
const newTag = application.itemManager.getDisplayableTags().find((t) => t.uuid !== tagPayload.uuid)
const newNote = application.items.getDisplayableNotes().find((n) => n.uuid !== notePayload.uuid)
const newTag = application.items.getDisplayableTags().find((t) => t.uuid !== tagPayload.uuid)
expect(newNote.uuid).to.not.equal(note.uuid)
expect(newTag.uuid).to.not.equal(tag.uuid)
const refreshedTag = application.itemManager.findItem(tag.uuid)
const refreshedTag = application.items.findItem(tag.uuid)
expect(refreshedTag.content.references.length).to.equal(2)
expect(refreshedTag.noteCount).to.equal(2)
const refreshedNote = application.itemManager.findItem(note.uuid)
const refreshedNote = application.items.findItem(note.uuid)
expect(refreshedNote.content.references.length).to.equal(0)
expect(application.itemManager.itemsReferencingItem(refreshedNote).length).to.equal(2)
expect(application.items.itemsReferencingItem(refreshedNote).length).to.equal(2)
expect(newTag.content.references.length).to.equal(1)
expect(newTag.noteCount).to.equal(1)
expect(newNote.content.references.length).to.equal(0)
expect(application.itemManager.itemsReferencingItem(newNote).length).to.equal(1)
expect(application.items.itemsReferencingItem(newNote).length).to.equal(1)
})
it('when importing items, imported values should not be used to determine if changed', async function () {
@@ -249,9 +249,9 @@ describe('importing', function () {
expectedItemCount += 1
/** We expect now that the total item count is 3, not 4. */
expect(application.itemManager.items.length).to.equal(expectedItemCount)
expect(application.items.items.length).to.equal(expectedItemCount)
const refreshedTag = application.itemManager.findItem(tag.uuid)
const refreshedTag = application.items.findItem(tag.uuid)
/** References from both items have merged. */
expect(refreshedTag.content.references.length).to.equal(2)
})
@@ -286,10 +286,10 @@ describe('importing', function () {
true,
)
expect(application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(application.items.getDisplayableNotes().length).to.equal(1)
expect(application.items.findItem(note.uuid).deleted).to.not.be.ok
expect(application.itemManager.getDisplayableTags().length).to.equal(1)
expect(application.items.getDisplayableTags().length).to.equal(1)
expect(application.items.findItem(tag.uuid).deleted).to.not.be.ok
})
@@ -320,8 +320,8 @@ describe('importing', function () {
true,
)
expect(application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(application.itemManager.getDisplayableNotes()[0].uuid).to.not.equal(note.uuid)
expect(application.items.getDisplayableNotes().length).to.equal(1)
expect(application.items.getDisplayableNotes()[0].uuid).to.not.equal(note.uuid)
})
it('should maintain consistency between storage and PayloadManager after an import with conflicts', async function () {
@@ -350,8 +350,8 @@ describe('importing', function () {
true,
)
const storedPayloads = await application.diskStorageService.getAllRawPayloads()
expect(application.itemManager.items.length).to.equal(storedPayloads.length)
const storedPayloads = await application.storage.getAllRawPayloads()
expect(application.items.items.length).to.equal(storedPayloads.length)
const notes = storedPayloads.filter((p) => p.content_type === ContentType.TYPES.Note)
const itemsKeys = storedPayloads.filter((p) => p.content_type === ContentType.TYPES.ItemsKey)
expect(notes.length).to.equal(1)
@@ -383,10 +383,10 @@ describe('importing', function () {
await application.importData(backupData, true)
expect(application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(application.items.getDisplayableNotes().length).to.equal(1)
expect(application.items.findItem(note.uuid).deleted).to.not.be.ok
expect(application.itemManager.getDisplayableTags().length).to.equal(1)
expect(application.items.getDisplayableTags().length).to.equal(1)
expect(application.items.findItem(tag.uuid).deleted).to.not.be.ok
})
@@ -465,10 +465,10 @@ describe('importing', function () {
expect(result.affectedItems.length).to.be.eq(backupData.items.length)
expect(result.errorCount).to.be.eq(0)
const decryptedNote = application.itemManager.findItem(noteItem.uuid)
const decryptedNote = application.items.findItem(noteItem.uuid)
expect(decryptedNote.title).to.be.eq('Encrypted note')
expect(decryptedNote.text).to.be.eq('On protocol version 003.')
expect(application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(application.items.getDisplayableNotes().length).to.equal(1)
})
it('should import data from 003 encrypted payload using server generated backup with 004 key params', async function () {
@@ -546,10 +546,10 @@ describe('importing', function () {
expect(result.affectedItems.length).to.be.eq(backupData.items.length)
expect(result.errorCount).to.be.eq(0)
const decryptedNote = application.itemManager.findItem(noteItem.uuid)
const decryptedNote = application.items.findItem(noteItem.uuid)
expect(decryptedNote.title).to.be.eq('Encrypted note')
expect(decryptedNote.text).to.be.eq('On protocol version 004.')
expect(application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(application.items.getDisplayableNotes().length).to.equal(1)
})
it('should return correct errorCount', async function () {
@@ -624,7 +624,7 @@ describe('importing', function () {
expect(result.affectedItems.length).to.be.eq(0)
expect(result.errorCount).to.be.eq(backupData.items.length)
expect(application.itemManager.getDisplayableNotes().length).to.equal(0)
expect(application.items.getDisplayableNotes().length).to.equal(0)
})
it('should not import data from 004 encrypted payload if an invalid password is provided', async function () {
@@ -655,7 +655,7 @@ describe('importing', function () {
expect(result).to.not.be.undefined
expect(result.affectedItems.length).to.be.eq(0)
expect(result.errorCount).to.be.eq(backupData.items.length)
expect(application.itemManager.getDisplayableNotes().length).to.equal(0)
expect(application.items.getDisplayableNotes().length).to.equal(0)
})
it('should not import encrypted data with no keyParams or auth_params', async function () {
@@ -710,7 +710,7 @@ describe('importing', function () {
expect(result.affectedItems.length).to.equal(BaseItemCounts.BackupFileRootKeyEncryptedItems)
expect(result.errorCount).to.be.eq(backupData.items.length - BaseItemCounts.BackupFileRootKeyEncryptedItems)
expect(application.itemManager.getDisplayableNotes().length).to.equal(0)
expect(application.items.getDisplayableNotes().length).to.equal(0)
})
it('importing data with no items key should use the root key generated by the file password', async function () {
@@ -726,7 +726,7 @@ describe('importing', function () {
const identifier = 'standardnotes'
const application = await Factory.createApplicationWithRealCrypto(identifier)
/** Create legacy migrations value so that base migration detects old app */
await application.deviceInterface.setRawStorageValue(
await application.device.setRawStorageValue(
'keychain',
JSON.stringify({
[identifier]: {
@@ -736,7 +736,7 @@ describe('importing', function () {
},
}),
)
await application.deviceInterface.setRawStorageValue(
await application.device.setRawStorageValue(
'descriptors',
JSON.stringify({
[identifier]: {
@@ -746,8 +746,8 @@ describe('importing', function () {
},
}),
)
await application.deviceInterface.setRawStorageValue('standardnotes-snjs_version', '2.0.11')
await application.deviceInterface.saveDatabaseEntry(
await application.device.setRawStorageValue('standardnotes-snjs_version', '2.0.11')
await application.device.saveDatabaseEntry(
{
content:
'003:9f2c7527eb8b2a1f8bfb3ea6b885403b6886bce2640843ebd57a6c479cbf7597:58e3322b-269a-4be3-a658-b035dffcd70f:9140b23a0fa989e224e292049f133154:SESTNOgIGf2+ZqmJdFnGU4EMgQkhKOzpZNoSzx76SJaImsayzctAgbUmJ+UU2gSQAHADS3+Z5w11bXvZgIrStTsWriwvYkNyyKmUPadKHNSBwOk4WeBZpWsA9gtI5zgI04Q5pvb8hS+kNW2j1DjM4YWqd0JQxMOeOrMIrxr/6Awn5TzYE+9wCbXZdYHyvRQcp9ui/G02ZJ67IA86vNEdjTTBAAWipWqTqKH9VDZbSQ2W/IOKfIquB373SFDKZb1S1NmBFvcoG2G7w//fAl/+ehYiL6UdiNH5MhXCDAOTQRFNfOh57HFDWVnz1VIp8X+VAPy6d9zzQH+8aws1JxHq/7BOhXrFE8UCueV6kERt9njgQxKJzd9AH32ShSiUB9X/sPi0fUXbS178xAZMJrNx3w==:eyJwd19ub25jZSI6IjRjYjEwM2FhODljZmY0NTYzYTkxMWQzZjM5NjU4M2NlZmM2ODMzYzY2Zjg4MGZiZWUwNmJkYTk0YzMxZjg2OGIiLCJwd19jb3N0IjoxMTAwMDAsImlkZW50aWZpZXIiOiJub3YyMzIyQGJpdGFyLmlvIiwidmVyc2lvbiI6IjAwMyIsIm9yaWdpbmF0aW9uIjoicmVnaXN0cmF0aW9uIn0=',
@@ -763,7 +763,7 @@ describe('importing', function () {
/**
* Note that this storage contains "sync.standardnotes.org" as the API Host param.
*/
await application.deviceInterface.setRawStorageValue(
await application.device.setRawStorageValue(
'standardnotes-storage',
JSON.stringify({
wrapped: {
@@ -874,13 +874,13 @@ describe('importing', function () {
await application.importData(backupData, true)
expect(application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(application.itemManager.getDisplayableTags().length).to.equal(1)
expect(application.items.getDisplayableNotes().length).to.equal(1)
expect(application.items.getDisplayableTags().length).to.equal(1)
const importedNote = application.itemManager.getDisplayableNotes()[0]
const importedTag = application.itemManager.getDisplayableTags()[0]
expect(application.itemManager.referencesForItem(importedTag).length).to.equal(1)
expect(application.itemManager.itemsReferencingItem(importedNote).length).to.equal(1)
const importedNote = application.items.getDisplayableNotes()[0]
const importedTag = application.items.getDisplayableTags()[0]
expect(application.items.referencesForItem(importedTag).length).to.equal(1)
expect(application.items.itemsReferencingItem(importedNote).length).to.equal(1)
})
it('should decrypt backup file which contains a vaulted note without a synced key system root key', async () => {

View File

@@ -23,11 +23,11 @@ describe('items', () => {
it('setting an item as dirty should update its client updated at', async function () {
const params = Factory.createNotePayload()
await this.application.mutator.emitItemsFromPayloads([params], PayloadEmitSource.LocalChanged)
const item = this.application.itemManager.items[0]
const item = this.application.items.items[0]
const prevDate = item.userModifiedDate.getTime()
await Factory.sleep(0.1)
await this.application.mutator.setItemDirty(item, true)
const refreshedItem = this.application.itemManager.findItem(item.uuid)
const refreshedItem = this.application.items.findItem(item.uuid)
const newDate = refreshedItem.userModifiedDate.getTime()
expect(prevDate).to.not.equal(newDate)
})
@@ -35,7 +35,7 @@ describe('items', () => {
it('setting an item as dirty with option to skip client updated at', async function () {
const params = Factory.createNotePayload()
await this.application.mutator.emitItemsFromPayloads([params], PayloadEmitSource.LocalChanged)
const item = this.application.itemManager.items[0]
const item = this.application.items.items[0]
const prevDate = item.userModifiedDate.getTime()
await Factory.sleep(0.1)
await this.application.mutator.setItemDirty(item)
@@ -47,7 +47,7 @@ describe('items', () => {
const params = Factory.createNotePayload()
await this.application.mutator.emitItemsFromPayloads([params], PayloadEmitSource.LocalChanged)
const item = this.application.itemManager.items[0]
const item = this.application.items.items[0]
expect(item.pinned).to.not.be.ok
const refreshedItem = await this.application.changeAndSaveItem(
@@ -71,8 +71,8 @@ describe('items', () => {
const params2 = Factory.createNotePayload()
await this.application.mutator.emitItemsFromPayloads([params1, params2], PayloadEmitSource.LocalChanged)
let item1 = this.application.itemManager.getDisplayableNotes()[0]
let item2 = this.application.itemManager.getDisplayableNotes()[1]
let item1 = this.application.items.getDisplayableNotes()[0]
let item2 = this.application.items.getDisplayableNotes()[1]
expect(item1.isItemContentEqualWith(item2)).to.equal(true)
@@ -176,8 +176,8 @@ describe('items', () => {
const params2 = Factory.createNotePayload()
await this.application.mutator.emitItemsFromPayloads([params1, params2], PayloadEmitSource.LocalChanged)
let item1 = this.application.itemManager.getDisplayableNotes()[0]
const item2 = this.application.itemManager.getDisplayableNotes()[1]
let item1 = this.application.items.getDisplayableNotes()[0]
const item2 = this.application.items.getDisplayableNotes()[1]
item1 = await this.application.changeAndSaveItem(
item1,

View File

@@ -22,7 +22,7 @@ describe('model manager mapping', () => {
const payload = Factory.createNotePayload()
await this.application.mutator.emitItemsFromPayloads([payload], PayloadEmitSource.LocalChanged)
this.expectedItemCount++
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
})
it('mapping nonexistent deleted item doesnt create it', async function () {
@@ -31,8 +31,8 @@ describe('model manager mapping', () => {
dirty: false,
deleted: true,
})
await this.application.payloadManager.emitPayload(payload, PayloadEmitSource.LocalChanged)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
await this.application.payloads.emitPayload(payload, PayloadEmitSource.LocalChanged)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
})
it('mapping and deleting nonexistent item creates and deletes it', async function () {
@@ -41,7 +41,7 @@ describe('model manager mapping', () => {
this.expectedItemCount++
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
const changedParams = new DeletedPayload({
...payload,
@@ -53,7 +53,7 @@ describe('model manager mapping', () => {
await this.application.mutator.emitItemsFromPayloads([changedParams], PayloadEmitSource.LocalChanged)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
})
it('mapping deleted but dirty item should not delete it', async function () {
@@ -63,13 +63,13 @@ describe('model manager mapping', () => {
this.expectedItemCount++
await this.application.payloadManager.emitPayload(new DeleteItemMutator(item).getDeletedResult())
await this.application.payloads.emitPayload(new DeleteItemMutator(item).getDeletedResult())
const payload2 = new DeletedPayload(this.application.payloadManager.findOne(payload.uuid).ejected())
const payload2 = new DeletedPayload(this.application.payloads.findOne(payload.uuid).ejected())
await this.application.payloadManager.emitPayloads([payload2], PayloadEmitSource.LocalChanged)
await this.application.payloads.emitPayloads([payload2], PayloadEmitSource.LocalChanged)
expect(this.application.payloadManager.collection.all().length).to.equal(this.expectedItemCount)
expect(this.application.payloads.collection.all().length).to.equal(this.expectedItemCount)
})
it('mapping existing item updates its properties', async function () {
@@ -85,7 +85,7 @@ describe('model manager mapping', () => {
},
})
await this.application.mutator.emitItemsFromPayloads([mutated], PayloadEmitSource.LocalChanged)
const item = this.application.itemManager.getDisplayableNotes()[0]
const item = this.application.items.getDisplayableNotes()[0]
expect(item.content.title).to.equal(newTitle)
})
@@ -93,9 +93,9 @@ describe('model manager mapping', () => {
it('setting an item dirty should retrieve it in dirty items', async function () {
const payload = Factory.createNotePayload()
await this.application.mutator.emitItemsFromPayloads([payload], PayloadEmitSource.LocalChanged)
const note = this.application.itemManager.getDisplayableNotes()[0]
const note = this.application.items.getDisplayableNotes()[0]
await this.application.mutator.setItemDirty(note)
const dirtyItems = this.application.itemManager.getDirtyItems()
const dirtyItems = this.application.items.getDirtyItems()
expect(Uuids(dirtyItems).includes(note.uuid))
})
@@ -107,18 +107,18 @@ describe('model manager mapping', () => {
payloads.push(Factory.createNotePayload())
}
await this.application.mutator.emitItemsFromPayloads(payloads, PayloadEmitSource.LocalChanged)
await this.application.syncService.markAllItemsAsNeedingSyncAndPersist()
await this.application.sync.markAllItemsAsNeedingSyncAndPersist()
const dirtyItems = this.application.itemManager.getDirtyItems()
const dirtyItems = this.application.items.getDirtyItems()
expect(dirtyItems.length).to.equal(this.expectedItemCount)
})
it('sync observers should be notified of changes', async function () {
const payload = Factory.createNotePayload()
await this.application.mutator.emitItemsFromPayloads([payload], PayloadEmitSource.LocalChanged)
const item = this.application.itemManager.items[0]
const item = this.application.items.items[0]
return new Promise((resolve) => {
this.application.itemManager.addObserver(ContentType.TYPES.Any, ({ changed }) => {
this.application.items.addObserver(ContentType.TYPES.Any, ({ changed }) => {
expect(changed[0].uuid === item.uuid)
resolve()
})

View File

@@ -26,7 +26,7 @@ describe('notes and tags', () => {
it('uses proper class for note', async function () {
const payload = Factory.createNotePayload()
await this.application.mutator.emitItemFromPayload(payload, PayloadEmitSource.LocalChanged)
const note = this.application.itemManager.getItems([ContentType.TYPES.Note])[0]
const note = this.application.items.getItems([ContentType.TYPES.Note])[0]
expect(note.constructor === SNNote).to.equal(true)
})
@@ -74,11 +74,11 @@ describe('notes and tags', () => {
})
await this.application.mutator.emitItemsFromPayloads([mutatedNote, mutatedTag], PayloadEmitSource.LocalChanged)
const note = this.application.itemManager.getItems([ContentType.TYPES.Note])[0]
const tag = this.application.itemManager.getItems([ContentType.TYPES.Tag])[0]
const note = this.application.items.getItems([ContentType.TYPES.Note])[0]
const tag = this.application.items.getItems([ContentType.TYPES.Tag])[0]
expect(note.content.references.length).to.equal(1)
expect(this.application.itemManager.itemsReferencingItem(tag).length).to.equal(1)
expect(this.application.items.itemsReferencingItem(tag).length).to.equal(1)
})
it('creates relationship between note and tag', async function () {
@@ -90,8 +90,8 @@ describe('notes and tags', () => {
expect(tagPayload.content.references.length).to.equal(1)
await this.application.mutator.emitItemsFromPayloads([notePayload, tagPayload], PayloadEmitSource.LocalChanged)
let note = this.application.itemManager.getDisplayableNotes()[0]
let tag = this.application.itemManager.getDisplayableTags()[0]
let note = this.application.items.getDisplayableNotes()[0]
let tag = this.application.items.getDisplayableTags()[0]
expect(note.dirty).to.not.be.ok
expect(tag.dirty).to.not.be.ok
@@ -102,26 +102,26 @@ describe('notes and tags', () => {
expect(note.isReferencingItem(tag)).to.equal(false)
expect(tag.isReferencingItem(note)).to.equal(true)
expect(this.application.itemManager.itemsReferencingItem(note).length).to.equal(1)
expect(this.application.items.itemsReferencingItem(note).length).to.equal(1)
expect(note.payload.references.length).to.equal(0)
expect(tag.noteCount).to.equal(1)
await this.application.mutator.setItemToBeDeleted(note)
tag = this.application.itemManager.getDisplayableTags()[0]
tag = this.application.items.getDisplayableTags()[0]
const deletedNotePayload = this.application.payloadManager.findOne(note.uuid)
const deletedNotePayload = this.application.payloads.findOne(note.uuid)
expect(deletedNotePayload.dirty).to.be.true
expect(tag.dirty).to.be.true
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
expect(tag.content.references.length).to.equal(0)
expect(this.application.itemManager.itemsReferencingItem(note).length).to.equal(0)
expect(this.application.items.itemsReferencingItem(note).length).to.equal(0)
expect(tag.noteCount).to.equal(0)
tag = this.application.itemManager.getDisplayableTags()[0]
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(0)
tag = this.application.items.getDisplayableTags()[0]
expect(this.application.items.getDisplayableNotes().length).to.equal(0)
expect(tag.dirty).to.be.false
})
@@ -131,13 +131,13 @@ describe('notes and tags', () => {
const tagPayload = pair[1]
await this.application.mutator.emitItemsFromPayloads(pair, PayloadEmitSource.LocalChanged)
let note = this.application.itemManager.getItems([ContentType.TYPES.Note])[0]
let tag = this.application.itemManager.getItems([ContentType.TYPES.Tag])[0]
let note = this.application.items.getItems([ContentType.TYPES.Note])[0]
let tag = this.application.items.getItems([ContentType.TYPES.Tag])[0]
expect(note.content.references.length).to.equal(0)
expect(tag.content.references.length).to.equal(1)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
const mutatedTag = new DecryptedPayload({
...tagPayload,
@@ -149,11 +149,11 @@ describe('notes and tags', () => {
})
await this.application.mutator.emitItemsFromPayloads([mutatedTag], PayloadEmitSource.LocalChanged)
note = this.application.itemManager.findItem(note.uuid)
tag = this.application.itemManager.findItem(tag.uuid)
note = this.application.items.findItem(note.uuid)
tag = this.application.items.findItem(tag.uuid)
expect(tag.content.references.length).to.equal(0)
expect(this.application.itemManager.itemsReferencingItem(note).length).to.equal(0)
expect(this.application.items.itemsReferencingItem(note).length).to.equal(0)
expect(tag.noteCount).to.equal(0)
// expect to be false
@@ -178,8 +178,8 @@ describe('notes and tags', () => {
const tagPayload = pair[1]
await this.application.mutator.emitItemsFromPayloads([notePayload, tagPayload], PayloadEmitSource.LocalChanged)
const note = this.application.itemManager.getItems([ContentType.TYPES.Note])[0]
let tag = this.application.itemManager.getItems([ContentType.TYPES.Tag])[0]
const note = this.application.items.getItems([ContentType.TYPES.Note])[0]
let tag = this.application.items.getItems([ContentType.TYPES.Tag])[0]
expect(note.content.references.length).to.equal(0)
expect(tag.content.references.length).to.equal(1)
@@ -194,21 +194,21 @@ describe('notes and tags', () => {
syncOptions,
)
expect(this.application.itemManager.itemsReferencingItem(note).length).to.equal(0)
expect(this.application.items.itemsReferencingItem(note).length).to.equal(0)
expect(tag.noteCount).to.equal(0)
})
it('properly handles tag duplication', async function () {
const pair = createRelatedNoteTagPairPayload()
await this.application.mutator.emitItemsFromPayloads(pair, PayloadEmitSource.LocalChanged)
let note = this.application.itemManager.getDisplayableNotes()[0]
let tag = this.application.itemManager.getDisplayableTags()[0]
let note = this.application.items.getDisplayableNotes()[0]
let tag = this.application.items.getDisplayableTags()[0]
const duplicateTag = await this.application.mutator.duplicateItem(tag, true)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
note = this.application.itemManager.findItem(note.uuid)
tag = this.application.itemManager.findItem(tag.uuid)
note = this.application.items.findItem(note.uuid)
tag = this.application.items.findItem(tag.uuid)
expect(tag.uuid).to.not.equal(duplicateTag.uuid)
expect(tag.content.references.length).to.equal(1)
@@ -216,7 +216,7 @@ describe('notes and tags', () => {
expect(duplicateTag.content.references.length).to.equal(1)
expect(duplicateTag.noteCount).to.equal(1)
const noteTags = this.application.itemManager.itemsReferencingItem(note)
const noteTags = this.application.items.itemsReferencingItem(note)
expect(noteTags.length).to.equal(2)
const noteTag1 = noteTags[0]
@@ -233,12 +233,12 @@ describe('notes and tags', () => {
const notePayload = pair[0]
const tagPayload = pair[1]
await this.application.mutator.emitItemsFromPayloads([notePayload, tagPayload], PayloadEmitSource.LocalChanged)
const note = this.application.itemManager.getItems([ContentType.TYPES.Note])[0]
const note = this.application.items.getItems([ContentType.TYPES.Note])[0]
const duplicateNote = await this.application.mutator.duplicateItem(note, true)
expect(note.uuid).to.not.equal(duplicateNote.uuid)
expect(this.application.itemManager.itemsReferencingItem(duplicateNote).length).to.equal(
this.application.itemManager.itemsReferencingItem(note).length,
expect(this.application.items.itemsReferencingItem(duplicateNote).length).to.equal(
this.application.items.itemsReferencingItem(note).length,
)
})
@@ -247,24 +247,24 @@ describe('notes and tags', () => {
const notePayload = pair[0]
const tagPayload = pair[1]
await this.application.mutator.emitItemsFromPayloads([notePayload, tagPayload], PayloadEmitSource.LocalChanged)
const note = this.application.itemManager.getItems([ContentType.TYPES.Note])[0]
let tag = this.application.itemManager.getItems([ContentType.TYPES.Tag])[0]
const note = this.application.items.getItems([ContentType.TYPES.Note])[0]
let tag = this.application.items.getItems([ContentType.TYPES.Tag])[0]
expect(tag.content.references.length).to.equal(1)
expect(tag.noteCount).to.equal(1)
expect(note.content.references.length).to.equal(0)
expect(this.application.itemManager.itemsReferencingItem(note).length).to.equal(1)
expect(this.application.items.itemsReferencingItem(note).length).to.equal(1)
await this.application.mutator.setItemToBeDeleted(tag)
tag = this.application.itemManager.findItem(tag.uuid)
tag = this.application.items.findItem(tag.uuid)
expect(tag).to.not.be.ok
})
it('modifying item content should not modify payload content', async function () {
const notePayload = Factory.createNotePayload()
await this.application.mutator.emitItemsFromPayloads([notePayload], PayloadEmitSource.LocalChanged)
let note = this.application.itemManager.getItems([ContentType.TYPES.Note])[0]
let note = this.application.items.getItems([ContentType.TYPES.Note])[0]
note = await this.application.changeAndSaveItem(
note,
(mutator) => {
@@ -286,14 +286,14 @@ describe('notes and tags', () => {
const tagPayload = pair[1]
await this.application.mutator.emitItemsFromPayloads([notePayload, tagPayload], PayloadEmitSource.LocalChanged)
let note = this.application.itemManager.getItems([ContentType.TYPES.Note])[0]
let tag = this.application.itemManager.getItems([ContentType.TYPES.Tag])[0]
let note = this.application.items.getItems([ContentType.TYPES.Note])[0]
let tag = this.application.items.getItems([ContentType.TYPES.Tag])[0]
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
await this.application.mutator.setItemToBeDeleted(tag)
note = this.application.itemManager.findItem(note.uuid)
this.application.itemManager.findItem(tag.uuid)
note = this.application.items.findItem(note.uuid)
this.application.items.findItem(tag.uuid)
expect(note.dirty).to.not.be.ok
})
@@ -320,7 +320,7 @@ describe('notes and tags', () => {
title: 'Foo',
})
await this.application.mutator.insertItem(note)
note = this.application.itemManager.findItem(note.uuid)
note = this.application.items.findItem(note.uuid)
expect(note.content.title).to.equal('Foo')
})
@@ -385,13 +385,13 @@ describe('notes and tags', () => {
)
}),
)
const pinnedNote = this.application.itemManager.getDisplayableNotes().find((note) => note.title === 'B')
const pinnedNote = this.application.items.getDisplayableNotes().find((note) => note.title === 'B')
await this.application.mutator.changeItem(pinnedNote, (mutator) => {
mutator.pinned = true
})
const tag = await this.application.mutator.findOrCreateTag('A')
await this.application.mutator.changeItem(tag, (mutator) => {
for (const note of this.application.itemManager.getDisplayableNotes()) {
for (const note of this.application.items.getDisplayableNotes()) {
mutator.e2ePendingRefactor_addItemAsRelationship(note)
}
})

View File

@@ -65,8 +65,8 @@ describe('mapping performance', () => {
const expectedRunTime = 3 // seconds
expect(seconds).to.be.at.most(expectedRunTime)
for (const note of application.itemManager.getItems(ContentType.TYPES.Note)) {
expect(application.itemManager.itemsReferencingItem(note).length).to.be.above(0)
for (const note of application.items.getItems(ContentType.TYPES.Note)) {
expect(application.items.itemsReferencingItem(note).length).to.be.above(0)
}
await Factory.safeDeinit(application)
}).timeout(20000)
@@ -131,9 +131,9 @@ describe('mapping performance', () => {
const MAX_RUN_TIME = 15.0 // seconds
expect(seconds).to.be.at.most(MAX_RUN_TIME)
application.itemManager.getItems(ContentType.TYPES.Tag)[0]
for (const note of application.itemManager.getItems(ContentType.TYPES.Note)) {
expect(application.itemManager.itemsReferencingItem(note).length).to.equal(1)
application.items.getItems(ContentType.TYPES.Tag)[0]
for (const note of application.items.getItems(ContentType.TYPES.Note)) {
expect(application.items.itemsReferencingItem(note).length).to.equal(1)
}
await Factory.safeDeinit(application)
}).timeout(20000)

View File

@@ -155,7 +155,7 @@ describe('mutator service', function () {
const sandbox = sinon.createSandbox()
beforeEach(async function () {
this.emitPayloads = sandbox.spy(application.items.payloadManager, 'emitPayloads')
this.emitPayloads = sandbox.spy(application.payloads, 'emitPayloads')
})
afterEach(async function () {

View File

@@ -40,7 +40,7 @@ describe('payload encryption', function () {
lastSyncBegan: new Date(),
})
const encryptedPayload = await this.application.encryptionService.encryptSplitSingle({
const encryptedPayload = await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [notePayload],
},
@@ -114,7 +114,7 @@ describe('payload encryption', function () {
it('returns valid encrypted params for syncing', async function () {
const payload = Factory.createNotePayload()
const encryptedPayload = CreateEncryptedServerSyncPushPayload(
await this.application.encryptionService.encryptSplitSingle({
await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [payload],
},
@@ -126,7 +126,7 @@ describe('payload encryption', function () {
expect(encryptedPayload.content_type).to.be.ok
expect(encryptedPayload.created_at).to.be.ok
expect(encryptedPayload.content).to.satisfy((string) => {
return string.startsWith(this.application.encryptionService.getLatestVersion())
return string.startsWith(this.application.encryption.getLatestVersion())
})
}).timeout(5000)
@@ -134,7 +134,7 @@ describe('payload encryption', function () {
const payload = Factory.createNotePayload()
const encryptedPayload = CreateEncryptedLocalStorageContextPayload(
await this.application.encryptionService.encryptSplitSingle({
await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [payload],
},
@@ -150,14 +150,14 @@ describe('payload encryption', function () {
expect(encryptedPayload.deleted).to.not.be.ok
expect(encryptedPayload.errorDecrypting).to.not.be.ok
expect(encryptedPayload.content).to.satisfy((string) => {
return string.startsWith(this.application.encryptionService.getLatestVersion())
return string.startsWith(this.application.encryption.getLatestVersion())
})
})
it('omits deleted for export file', async function () {
const payload = Factory.createNotePayload()
const encryptedPayload = CreateEncryptedBackupFileContextPayload(
await this.application.encryptionService.encryptSplitSingle({
await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [payload],
},
@@ -170,7 +170,7 @@ describe('payload encryption', function () {
expect(encryptedPayload.created_at).to.be.ok
expect(encryptedPayload.deleted).to.not.be.ok
expect(encryptedPayload.content).to.satisfy((string) => {
return string.startsWith(this.application.encryptionService.getLatestVersion())
return string.startsWith(this.application.encryption.getLatestVersion())
})
})

View File

@@ -106,7 +106,7 @@ describe('preferences', function () {
Factory.initializeApplication(this.application)
await willSyncPromise
expect(this.application.preferencesService.preferences).to.exist
expect(this.application.preferences.preferences).to.exist
expect(this.application.getPreference(prefKey)).to.equal(prefValue)
})
})

View File

@@ -287,8 +287,8 @@ describe('protections', function () {
it('handles session length', async function () {
application = await Factory.createInitAppWithFakeCrypto()
await application.protectionService.setSessionLength(300)
const length = await application.protectionService.getLastSessionLength()
await application.protections.setSessionLength(300)
const length = await application.protections.getLastSessionLength()
expect(length).to.equal(300)
const expirey = await application.getProtectionSessionExpiryDate()
expect(expirey).to.be.ok
@@ -296,8 +296,8 @@ describe('protections', function () {
it('handles session length', async function () {
application = await Factory.createInitAppWithFakeCrypto()
await application.protectionService.setSessionLength(UnprotectedAccessSecondsDuration.OneMinute)
const length = await application.protectionService.getLastSessionLength()
await application.protections.setSessionLength(UnprotectedAccessSecondsDuration.OneMinute)
const length = await application.protections.getLastSessionLength()
expect(length).to.equal(UnprotectedAccessSecondsDuration.OneMinute)
const expirey = await application.getProtectionSessionExpiryDate()
expect(expirey).to.be.ok
@@ -388,7 +388,7 @@ describe('protections', function () {
it('should return true when session length has been set', async function () {
application = await Factory.createInitAppWithFakeCrypto()
await application.addPasscode('passcode')
await application.protectionService.setSessionLength(UnprotectedAccessSecondsDuration.OneMinute)
await application.protections.setSessionLength(UnprotectedAccessSecondsDuration.OneMinute)
expect(application.hasUnprotectedAccessSession()).to.be.true
})

View File

@@ -19,43 +19,43 @@ describe('protocol', function () {
})
it('checks version to make sure its 004', function () {
expect(this.application.encryptionService.getLatestVersion()).to.equal('004')
expect(this.application.encryption.getLatestVersion()).to.equal('004')
})
it('checks supported versions to make sure it includes 001, 002, 003, 004', function () {
expect(this.application.encryptionService.supportedVersions()).to.eql(['001', '002', '003', '004'])
expect(this.application.encryption.supportedVersions()).to.eql(['001', '002', '003', '004'])
})
it('platform derivation support', function () {
expect(
this.application.encryptionService.platformSupportsKeyDerivation({
this.application.encryption.platformSupportsKeyDerivation({
version: '001',
}),
).to.equal(true)
expect(
this.application.encryptionService.platformSupportsKeyDerivation({
this.application.encryption.platformSupportsKeyDerivation({
version: '002',
}),
).to.equal(true)
expect(
this.application.encryptionService.platformSupportsKeyDerivation({
this.application.encryption.platformSupportsKeyDerivation({
version: '003',
}),
).to.equal(true)
expect(
this.application.encryptionService.platformSupportsKeyDerivation({
this.application.encryption.platformSupportsKeyDerivation({
version: '004',
}),
).to.equal(true)
expect(
this.application.encryptionService.platformSupportsKeyDerivation({
this.application.encryption.platformSupportsKeyDerivation({
version: '005',
}),
).to.equal(true)
})
it('key params versions <= 002 should include pw_cost in portable value', function () {
const keyParams002 = this.application.encryptionService.createKeyParams({
const keyParams002 = this.application.encryption.createKeyParams({
version: '002',
pw_cost: 5000,
})
@@ -63,15 +63,15 @@ describe('protocol', function () {
})
it('version comparison of 002 should be older than library version', function () {
expect(this.application.encryptionService.isVersionNewerThanLibraryVersion('002')).to.equal(false)
expect(this.application.encryption.isVersionNewerThanLibraryVersion('002')).to.equal(false)
})
it('version comparison of 005 should be newer than library version', function () {
expect(this.application.encryptionService.isVersionNewerThanLibraryVersion('005')).to.equal(true)
expect(this.application.encryption.isVersionNewerThanLibraryVersion('005')).to.equal(true)
})
it('library version should not be outdated', function () {
var currentVersion = this.application.encryptionService.getLatestVersion()
var currentVersion = this.application.encryption.getLatestVersion()
expect(isProtocolVersionExpired(currentVersion)).to.equal(false)
})
@@ -91,7 +91,7 @@ describe('protocol', function () {
const payload = Factory.createNotePayload()
let error
try {
await this.application.encryptionService.decryptSplitSingle({
await this.application.encryption.decryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [payload],
},
@@ -106,7 +106,7 @@ describe('protocol', function () {
await this.application.addPasscode('123')
const payload = Factory.createNotePayload()
const result = CreateEncryptedServerSyncPushPayload(
await this.application.encryptionService.encryptSplitSingle({
await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [payload],
},
@@ -121,7 +121,7 @@ describe('protocol', function () {
it('encrypted payload for server should include duplicate_of field', async function () {
const payload = Factory.createNotePayload('Test')
const encryptedPayload = CreateEncryptedServerSyncPushPayload(
await this.application.encryptionService.encryptSplitSingle({
await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [payload],
},
@@ -134,7 +134,7 @@ describe('protocol', function () {
it('ejected payload for server should include duplicate_of field', async function () {
const payload = Factory.createNotePayload('Test')
const encryptedPayload = CreateEncryptedServerSyncPushPayload(
await this.application.encryptionService.encryptSplitSingle({
await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [payload],
},
@@ -147,7 +147,7 @@ describe('protocol', function () {
it('encrypted payload for storage should include duplicate_of field', async function () {
const payload = Factory.createNotePayload('Test')
const encryptedPayload = CreateEncryptedLocalStorageContextPayload(
await this.application.encryptionService.encryptSplitSingle({
await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [payload],
},
@@ -160,7 +160,7 @@ describe('protocol', function () {
it('ejected payload for storage should include duplicate_of field', async function () {
const payload = Factory.createNotePayload('Test')
const encryptedPayload = CreateEncryptedLocalStorageContextPayload(
await this.application.encryptionService.encryptSplitSingle({
await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [payload],
},
@@ -173,7 +173,7 @@ describe('protocol', function () {
it('encrypted payload for file should include duplicate_of field', async function () {
const payload = Factory.createNotePayload('Test')
const encryptedPayload = CreateEncryptedBackupFileContextPayload(
await this.application.encryptionService.encryptSplitSingle({
await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [payload],
},
@@ -186,7 +186,7 @@ describe('protocol', function () {
it('ejected payload for file should include duplicate_of field', async function () {
const payload = Factory.createNotePayload('Test')
const encryptedPayload = CreateEncryptedBackupFileContextPayload(
await this.application.encryptionService.encryptSplitSingle({
await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [payload],
},

View File

@@ -44,7 +44,7 @@ describe('account recovery', function () {
application = await context.signout()
expect(await application.encryptionService.getRootKey()).to.not.be.ok
expect(await application.encryption.getRootKey()).to.not.be.ok
await application.signInWithRecoveryCodes.execute({
recoveryCodes: generatedRecoveryCodes.getValue(),
@@ -52,7 +52,7 @@ describe('account recovery', function () {
password: context.password,
})
expect(await application.encryptionService.getRootKey()).to.be.ok
expect(await application.encryption.getRootKey()).to.be.ok
})
it('should automatically generate new recovery code after recovery sign in', async () => {
@@ -96,7 +96,7 @@ describe('account recovery', function () {
application = await context.signout()
expect(await application.encryptionService.getRootKey()).to.not.be.ok
expect(await application.encryption.getRootKey()).to.not.be.ok
await application.signInWithRecoveryCodes.execute({
recoveryCodes: generatedRecoveryCodes.getValue(),
@@ -104,7 +104,7 @@ describe('account recovery', function () {
password: 'foobar',
})
expect(await application.encryptionService.getRootKey()).to.not.be.ok
expect(await application.encryption.getRootKey()).to.not.be.ok
})
it('should not allow to sign in with invalid recovery code', async () => {
@@ -112,7 +112,7 @@ describe('account recovery', function () {
application = await context.signout()
expect(await application.encryptionService.getRootKey()).to.not.be.ok
expect(await application.encryption.getRootKey()).to.not.be.ok
await application.signInWithRecoveryCodes.execute({
recoveryCodes: 'invalid recovery code',
@@ -120,13 +120,13 @@ describe('account recovery', function () {
password: context.paswword,
})
expect(await application.encryptionService.getRootKey()).to.not.be.ok
expect(await application.encryption.getRootKey()).to.not.be.ok
})
it('should not allow to sign in with recovery code if user has none', async () => {
application = await context.signout()
expect(await application.encryptionService.getRootKey()).to.not.be.ok
expect(await application.encryption.getRootKey()).to.not.be.ok
await application.signInWithRecoveryCodes.execute({
recoveryCodes: 'foo bar',
@@ -134,6 +134,6 @@ describe('account recovery', function () {
password: context.paswword,
})
expect(await application.encryptionService.getRootKey()).to.not.be.ok
expect(await application.encryption.getRootKey()).to.not.be.ok
})
})

View File

@@ -30,7 +30,7 @@ describe('server session', function () {
})
async function sleepUntilSessionExpires(application, basedOnAccessToken = true) {
const currentSession = application.apiService.session
const currentSession = application.legacyApi.session
const timestamp = basedOnAccessToken ? currentSession.accessToken.expiresAt : currentSession.refreshToken.expiresAt
const timeRemaining = (timestamp - Date.now()) / 1000 // in ms
/*
@@ -42,7 +42,7 @@ describe('server session', function () {
}
async function getSessionFromStorage(application) {
return application.diskStorageService.getValue(StorageKey.Session)
return application.storage.getValue(StorageKey.Session)
}
it('should succeed when a sync request is perfomed with an expired access token', async function () {
@@ -56,7 +56,7 @@ describe('server session', function () {
await sleepUntilSessionExpires(this.application)
const response = await this.application.apiService.sync([])
const response = await this.application.legacyApi.sync([])
expect(response.status).to.equal(200)
})
@@ -68,7 +68,7 @@ describe('server session', function () {
password: this.password,
})
const response = await this.application.apiService.refreshSession()
const response = await this.application.legacyApi.refreshSession()
expect(response.status).to.equal(200)
expect(response.data.session.access_token).to.be.a('string')
@@ -87,7 +87,7 @@ describe('server session', function () {
})
// Saving the current session information for later...
const sessionBeforeSync = this.application.apiService.getSession()
const sessionBeforeSync = this.application.legacyApi.getSession()
// Waiting enough time for the access token to expire, before performing a new sync request.
await sleepUntilSessionExpires(this.application)
@@ -96,7 +96,7 @@ describe('server session', function () {
await this.application.sync.sync(syncOptions)
// After the above sync request is completed, we obtain the session information.
const sessionAfterSync = this.application.apiService.getSession()
const sessionAfterSync = this.application.legacyApi.getSession()
expect(sessionBeforeSync.accessToken.value).to.not.equal(sessionAfterSync.accessToken.value)
expect(sessionBeforeSync.refreshToken.value).to.not.equal(sessionAfterSync.refreshToken.value)
@@ -119,10 +119,10 @@ describe('server session', function () {
// Apply a latency simulation so that ` this.inProgressRefreshSessionPromise = this.refreshSession()` does
// not have the chance to complete before it is assigned to the variable. This test came along with a fix
// where runHttp does not await a pending refreshSession promise if the request being made is itself a refreshSession request.
this.application.httpService.__latencySimulatorMs = 1000
this.application.http.__latencySimulatorMs = 1000
await this.application.sync.sync(syncOptions)
const sessionAfterSync = this.application.apiService.getSession()
const sessionAfterSync = this.application.legacyApi.getSession()
expect(sessionAfterSync.accessToken.expiresAt).to.be.greaterThan(Date.now())
})
@@ -137,7 +137,7 @@ describe('server session', function () {
await this.application.signIn(this.email, this.password, false, true)
const response = await this.application.apiService.sync([])
const response = await this.application.legacyApi.sync([])
expect(response.status).to.equal(200)
})
@@ -149,7 +149,7 @@ describe('server session', function () {
ephemeral: true,
})
const response = await this.application.apiService.sync([])
const response = await this.application.legacyApi.sync([])
expect(response.status).to.equal(200)
})
@@ -161,7 +161,7 @@ describe('server session', function () {
})
const sessionFromStorage = await getSessionFromStorage(this.application)
const sessionFromApiService = this.application.apiService.getSession()
const sessionFromApiService = this.application.legacyApi.getSession()
expect(sessionFromStorage.accessToken).to.equal(sessionFromApiService.accessToken.value)
expect(sessionFromStorage.refreshToken).to.equal(sessionFromApiService.refreshToken.value)
@@ -169,10 +169,10 @@ describe('server session', function () {
expect(sessionFromStorage.refreshExpiration).to.equal(sessionFromApiService.refreshToken.expiresAt)
expect(sessionFromStorage.readonlyAccess).to.equal(sessionFromApiService.isReadOnly())
await this.application.apiService.refreshSession()
await this.application.legacyApi.refreshSession()
const updatedSessionFromStorage = await getSessionFromStorage(this.application)
const updatedSessionFromApiService = this.application.apiService.getSession()
const updatedSessionFromApiService = this.application.legacyApi.getSession()
expect(updatedSessionFromStorage.accessToken).to.equal(updatedSessionFromApiService.accessToken.value)
expect(updatedSessionFromStorage.refreshToken).to.equal(updatedSessionFromApiService.refreshToken.value)
@@ -188,11 +188,11 @@ describe('server session', function () {
password: this.password,
})
const signOutResponse = await this.application.apiService.signOut()
const signOutResponse = await this.application.legacyApi.signOut()
expect(signOutResponse.status).to.equal(204)
Factory.ignoreChallenges(this.application)
const syncResponse = await this.application.apiService.sync([])
const syncResponse = await this.application.legacyApi.sync([])
expect(syncResponse.status).to.equal(401)
expect(syncResponse.data.error.tag).to.equal('invalid-auth')
expect(syncResponse.data.error.message).to.equal('Invalid login credentials.')
@@ -210,11 +210,11 @@ describe('server session', function () {
// Waiting enough time for the access token to expire, before performing a sign out request.
await sleepUntilSessionExpires(this.application)
const signOutResponse = await this.application.apiService.signOut()
const signOutResponse = await this.application.legacyApi.signOut()
expect(signOutResponse.status).to.equal(204)
Factory.ignoreChallenges(this.application)
const syncResponse = await this.application.apiService.sync([])
const syncResponse = await this.application.legacyApi.sync([])
expect(syncResponse.status).to.equal(401)
expect(syncResponse.data.error.tag).to.equal('invalid-auth')
expect(syncResponse.data.error.message).to.equal('Invalid login credentials.')
@@ -250,7 +250,7 @@ describe('server session', function () {
registerUser: true,
})
application.diskStorageService.setValue(StorageKey.Session, {
application.storage.setValue(StorageKey.Session, {
accessToken: 'this-is-a-fake-token-1234',
refreshToken: 'this-is-a-fake-token-1234',
accessExpiration: 999999999999999,
@@ -345,7 +345,7 @@ describe('server session', function () {
password: this.password,
})
this.application.diskStorageService.setValue(StorageKey.Session, {
this.application.storage.setValue(StorageKey.Session, {
accessToken: 'this-is-a-fake-token-1234',
refreshToken: 'this-is-a-fake-token-1234',
accessExpiration: 999999999999999,
@@ -385,12 +385,12 @@ describe('server session', function () {
password: this.password,
})
await this.application.apiService.signOut()
this.application.apiService.session = undefined
await this.application.legacyApi.signOut()
this.application.legacyApi.session = undefined
await this.application.sessionManager.signIn(this.email, this.password)
await this.application.sessions.signIn(this.email, this.password)
const currentSession = this.application.apiService.getSession()
const currentSession = this.application.legacyApi.getSession()
expect(currentSession).to.be.ok
expect(currentSession.accessToken).to.be.ok
@@ -409,7 +409,7 @@ describe('server session', function () {
await sleepUntilSessionExpires(this.application, false)
const refreshSessionResponse = await this.application.apiService.refreshSession()
const refreshSessionResponse = await this.application.legacyApi.refreshSession()
expect(refreshSessionResponse.status).to.equal(400)
expect(refreshSessionResponse.data.error.tag).to.equal('expired-refresh-token')
@@ -420,7 +420,7 @@ describe('server session', function () {
Here we make sure that any subsequent requests will fail.
*/
Factory.ignoreChallenges(this.application)
const syncResponse = await this.application.apiService.sync([])
const syncResponse = await this.application.legacyApi.sync([])
expect(syncResponse.status).to.equal(401)
expect(syncResponse.data.error.tag).to.equal('invalid-auth')
expect(syncResponse.data.error.message).to.equal('Invalid login credentials.')
@@ -433,9 +433,9 @@ describe('server session', function () {
password: this.password,
})
const originalSession = this.application.apiService.getSession()
const originalSession = this.application.legacyApi.getSession()
this.application.diskStorageService.setValue(StorageKey.Session, {
this.application.storage.setValue(StorageKey.Session, {
accessToken: originalSession.accessToken.value,
refreshToken: 'this-is-a-fake-token-1234',
accessExpiration: originalSession.accessToken.expiresAt,
@@ -444,14 +444,14 @@ describe('server session', function () {
})
this.application.sessions.initializeFromDisk()
const refreshSessionResponse = await this.application.apiService.refreshSession()
const refreshSessionResponse = await this.application.legacyApi.refreshSession()
expect(refreshSessionResponse.status).to.equal(400)
expect(refreshSessionResponse.data.error.tag).to.equal('invalid-refresh-token')
expect(refreshSessionResponse.data.error.message).to.equal('The refresh token is not valid.')
// Access token should remain valid.
const syncResponse = await this.application.apiService.sync([])
const syncResponse = await this.application.legacyApi.sync([])
expect(syncResponse.status).to.equal(200)
})
@@ -462,8 +462,8 @@ describe('server session', function () {
password: this.password,
})
const refreshPromise = this.application.apiService.refreshSession()
const syncResponse = await this.application.apiService.sync([])
const refreshPromise = this.application.legacyApi.refreshSession()
const syncResponse = await this.application.legacyApi.sync([])
expect(syncResponse.data.error).to.be.ok
@@ -485,19 +485,19 @@ describe('server session', function () {
const notesBeforeSync = await Factory.createManyMappedNotes(this.application, 5)
await sleepUntilSessionExpires(this.application)
await this.application.syncService.sync(syncOptions)
expect(this.application.syncService.isOutOfSync()).to.equal(false)
await this.application.sync.sync(syncOptions)
expect(this.application.sync.isOutOfSync()).to.equal(false)
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
await this.application.signIn(this.email, this.password, undefined, undefined, undefined, true)
const expectedNotesUuids = notesBeforeSync.map((n) => n.uuid)
const notesResults = await this.application.itemManager.findItems(expectedNotesUuids)
const notesResults = await this.application.items.findItems(expectedNotesUuids)
expect(notesResults.length).to.equal(notesBeforeSync.length)
for (const aNoteBeforeSync of notesBeforeSync) {
const noteResult = await this.application.itemManager.findItem(aNoteBeforeSync.uuid)
const noteResult = await this.application.items.findItem(aNoteBeforeSync.uuid)
expect(aNoteBeforeSync.isItemContentEqualWith(noteResult)).to.equal(true)
}
})
@@ -574,10 +574,10 @@ describe('server session', function () {
password: password,
})
const oldRootKey = await appA.encryptionService.getRootKey()
const oldRootKey = await appA.encryption.getRootKey()
/** Set the session as nonsense */
appA.diskStorageService.setValue(StorageKey.Session, {
appA.storage.setValue(StorageKey.Session, {
accessToken: 'foo',
refreshToken: 'bar',
accessExpiration: 999999999999999,
@@ -593,11 +593,11 @@ describe('server session', function () {
await Factory.sleep(5.0)
expect(didPromptForSignIn).to.equal(true)
expect(appA.apiService.session.accessToken.value).to.not.equal('foo')
expect(appA.apiService.session.refreshToken.value).to.not.equal('bar')
expect(appA.legacyApi.session.accessToken.value).to.not.equal('foo')
expect(appA.legacyApi.session.refreshToken.value).to.not.equal('bar')
/** Expect that the session recovery replaces the global root key */
const newRootKey = await appA.encryptionService.getRootKey()
const newRootKey = await appA.encryption.getRootKey()
expect(oldRootKey).to.not.equal(newRootKey)
await Factory.safeDeinit(appA)
@@ -610,7 +610,7 @@ describe('server session', function () {
password: this.password,
})
const response = await this.application.apiService.getSessionsList()
const response = await this.application.legacyApi.getSessionsList()
expect(response.data[0].current).to.equal(true)
})
@@ -625,12 +625,12 @@ describe('server session', function () {
const app2 = await Factory.createAndInitializeApplication('app2')
await app2.signIn(this.email, this.password)
const response = await this.application.apiService.getSessionsList()
const response = await this.application.legacyApi.getSessionsList()
expect(response.data.length).to.equal(2)
await app2.user.signOut()
const response2 = await this.application.apiService.getSessionsList()
const response2 = await this.application.legacyApi.getSessionsList()
expect(response2.data.length).to.equal(1)
})
@@ -699,7 +699,7 @@ describe('server session', function () {
password: this.password,
})
this.application.diskStorageService.setValue(StorageKey.Session, {
this.application.storage.setValue(StorageKey.Session, {
accessToken: undefined,
refreshToken: undefined,
accessExpiration: 999999999999999,
@@ -708,7 +708,7 @@ describe('server session', function () {
})
this.application.sessions.initializeFromDisk()
const storageKey = this.application.diskStorageService.getPersistenceKey()
const storageKey = this.application.storage.getPersistenceKey()
expect(localStorage.getItem(storageKey)).to.be.ok
await this.application.user.signOut()

View File

@@ -151,7 +151,7 @@ describe('settings service', function () {
const response = await fetch('/packages/snjs/mocha/assets/small_file.md')
const buffer = new Uint8Array(await response.arrayBuffer())
await Files.uploadFile(application.fileService, buffer, 'my-file', 'md', 1000)
await Files.uploadFile(application.files, buffer, 'my-file', 'md', 1000)
await Factory.sleep(1)

View File

@@ -24,8 +24,8 @@ describe('singletons', function () {
return new DecryptedPayload(params)
}
function findOrCreatePrefsSingleton(application) {
return application.singletonManager.findOrCreateContentTypeSingleton(ContentType.TYPES.UserPrefs, FillItemContent({}))
function findOrCreatePrefsSingleton(context) {
return context.singletons.findOrCreateContentTypeSingleton(ContentType.TYPES.UserPrefs, FillItemContent({}))
}
beforeEach(async function () {
@@ -49,7 +49,7 @@ describe('singletons', function () {
}
this.signOut = async () => {
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
this.application = await this.context.signout()
}
this.signIn = async () => {
@@ -78,10 +78,10 @@ describe('singletons', function () {
})
afterEach(async function () {
expect(this.application.syncService.isOutOfSync()).to.equal(false)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.sync.isOutOfSync()).to.equal(false)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
expect(rawPayloads.length).to.equal(this.expectedItemCount)
await Factory.safeDeinit(this.application)
@@ -100,8 +100,8 @@ describe('singletons', function () {
PayloadEmitSource.LocalChanged,
)
await this.application.mutator.setItemsDirty(items)
await this.application.syncService.sync(syncOptions)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
await this.application.sync.sync(syncOptions)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
})
it('duplicate components should auto-resolve to 1', async function () {
@@ -121,30 +121,30 @@ describe('singletons', function () {
await this.application.sync.sync(syncOptions)
expect(this.application.itemManager.itemsMatchingPredicate(ContentType.TYPES.Component, this.extPred).length).to.equal(1)
expect(this.application.items.itemsMatchingPredicate(ContentType.TYPES.Component, this.extPred).length).to.equal(1)
})
it('resolves via find or create', async function () {
/* Set to never synced as singleton manager will attempt to sync before resolving */
this.application.syncService.ut_clearLastSyncDate()
this.application.syncService.ut_setDatabaseLoaded(false)
this.application.sync.ut_clearLastSyncDate()
this.application.sync.ut_setDatabaseLoaded(false)
const contentType = ContentType.TYPES.UserPrefs
const predicate = new Predicate('content_type', '=', contentType)
/* Start a sync right after we await singleton resolve below */
setTimeout(() => {
this.application.syncService.ut_setDatabaseLoaded(true)
this.application.sync.ut_setDatabaseLoaded(true)
this.application.sync.sync({
/* Simulate the first sync occuring as that is handled specially by sync service */
mode: SyncMode.DownloadFirst,
})
})
const userPreferences = await this.application.singletonManager.findOrCreateContentTypeSingleton(contentType, {})
const userPreferences = await this.context.singletons.findOrCreateContentTypeSingleton(contentType, {})
expect(userPreferences).to.be.ok
const refreshedUserPrefs = this.application.items.findItem(userPreferences.uuid)
expect(refreshedUserPrefs).to.be.ok
await this.application.sync.sync(syncOptions)
expect(this.application.itemManager.itemsMatchingPredicate(contentType, predicate).length).to.equal(1)
expect(this.application.items.itemsMatchingPredicate(contentType, predicate).length).to.equal(1)
})
it('resolves registered predicate with signing in/out', async function () {
@@ -187,7 +187,7 @@ describe('singletons', function () {
let didCompleteRelevantSync = false
let beginCheckingResponse = false
this.application.syncService.addEventObserver(async (eventName, data) => {
this.application.sync.addEventObserver(async (eventName, data) => {
if (eventName === SyncEvent.DownloadFirstSyncCompleted) {
beginCheckingResponse = true
}
@@ -202,7 +202,7 @@ describe('singletons', function () {
expect(matching).to.not.be.ok
}
})
await this.application.syncService.sync({ mode: SyncMode.DownloadFirst })
await this.application.sync.sync({ mode: SyncMode.DownloadFirst })
expect(didCompleteRelevantSync).to.equal(true)
}).timeout(10000)
@@ -210,12 +210,14 @@ describe('singletons', function () {
await this.registerUser()
/** Create prefs */
const ogPrefs = await findOrCreatePrefsSingleton(this.application)
const ogPrefs = await findOrCreatePrefsSingleton(this.context)
await this.application.sync.sync(syncOptions)
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
this.application = await this.context.signout()
/** Create another instance while signed out */
await findOrCreatePrefsSingleton(this.application)
await findOrCreatePrefsSingleton(this.context)
await Factory.loginToApplication({
application: this.application,
email: this.email,
@@ -223,36 +225,36 @@ describe('singletons', function () {
})
/** After signing in, the instance retrieved from the server should be the one kept */
const latestPrefs = await findOrCreatePrefsSingleton(this.application)
const latestPrefs = await findOrCreatePrefsSingleton(this.context)
expect(latestPrefs.uuid).to.equal(ogPrefs.uuid)
const allPrefs = this.application.itemManager.getItems(ogPrefs.content_type)
const allPrefs = this.application.items.getItems(ogPrefs.content_type)
expect(allPrefs.length).to.equal(1)
})
it('resolving singleton before first sync, then signing in, should result in correct number of instances', async function () {
await this.registerUser()
/** Create prefs and associate them with account */
const ogPrefs = await findOrCreatePrefsSingleton(this.application)
const ogPrefs = await findOrCreatePrefsSingleton(this.context)
await this.application.sync.sync(syncOptions)
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
this.application = await this.context.signout()
/** Create another instance while signed out */
await findOrCreatePrefsSingleton(this.application)
await findOrCreatePrefsSingleton(this.context)
await Factory.loginToApplication({
application: this.application,
email: this.email,
password: this.password,
})
/** After signing in, the instance retrieved from the server should be the one kept */
const latestPrefs = await findOrCreatePrefsSingleton(this.application)
const latestPrefs = await findOrCreatePrefsSingleton(this.context)
expect(latestPrefs.uuid).to.equal(ogPrefs.uuid)
const allPrefs = this.application.itemManager.getItems(ogPrefs.content_type)
const allPrefs = this.application.items.getItems(ogPrefs.content_type)
expect(allPrefs.length).to.equal(1)
})
it('if only result is errorDecrypting, create new item', async function () {
const item = this.application.itemManager.items.find((item) => item.content_type === ContentType.TYPES.UserPrefs)
const item = this.application.items.items.find((item) => item.content_type === ContentType.TYPES.UserPrefs)
const erroredPayload = new EncryptedPayload({
...item.payload.ejected(),
@@ -260,16 +262,13 @@ describe('singletons', function () {
errorDecrypting: true,
})
await this.application.payloadManager.emitPayload(erroredPayload)
await this.application.payloads.emitPayload(erroredPayload)
const resolvedItem = await this.application.singletonManager.findOrCreateContentTypeSingleton(
item.content_type,
item.content,
)
const resolvedItem = await this.context.singletons.findOrCreateContentTypeSingleton(item.content_type, item.content)
await this.application.sync.sync({ awaitAll: true })
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
expect(resolvedItem.uuid).to.not.equal(item.uuid)
expect(resolvedItem.errorDecrypting).to.not.be.ok
})
@@ -318,34 +317,34 @@ describe('singletons', function () {
errorDecrypting: false,
})
await this.application.payloadManager.emitPayload(notErrored)
await this.application.payloads.emitPayload(notErrored)
/** Item will get decrypted on current tick, so wait one before syncing */
await Factory.sleep(0)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
expect(this.application.itemManager.itemsMatchingPredicate(ContentType.TYPES.Component, this.extPred).length).to.equal(1)
expect(this.application.items.itemsMatchingPredicate(ContentType.TYPES.Component, this.extPred).length).to.equal(1)
})
it('alternating the uuid of a singleton should return correct result', async function () {
const payload = createPrefsPayload()
const item = await this.application.mutator.emitItemFromPayload(payload, PayloadEmitSource.LocalChanged)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
const predicate = new Predicate('content_type', '=', item.content_type)
let resolvedItem = await this.application.singletonManager.findOrCreateContentTypeSingleton(
let resolvedItem = await this.context.singletons.findOrCreateContentTypeSingleton(
payload.content_type,
payload.content,
)
const originalUuid = resolvedItem.uuid
await Factory.alternateUuidForItem(this.application, resolvedItem.uuid)
await this.application.syncService.sync(syncOptions)
const resolvedItem2 = await this.application.singletonManager.findOrCreateContentTypeSingleton(
await this.application.sync.sync(syncOptions)
const resolvedItem2 = await this.context.singletons.findOrCreateContentTypeSingleton(
payload.content_type,
payload.content,
)
resolvedItem = this.application.items.findItem(resolvedItem.uuid)
expect(resolvedItem).to.not.be.ok
expect(resolvedItem2.uuid).to.not.equal(originalUuid)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
})
})

View File

@@ -31,23 +31,23 @@ describe('storage manager', function () {
it('should set and retrieve values', async function () {
const key = 'foo'
const value = 'bar'
await this.application.diskStorageService.setValue(key, value)
expect(await this.application.diskStorageService.getValue(key)).to.eql(value)
await this.application.storage.setValue(key, value)
expect(await this.application.storage.getValue(key)).to.eql(value)
})
it('should set and retrieve items', async function () {
const payload = Factory.createNotePayload()
await this.application.diskStorageService.savePayload(payload)
const payloads = await this.application.diskStorageService.getAllRawPayloads()
await this.application.storage.savePayload(payload)
const payloads = await this.application.storage.getAllRawPayloads()
expect(payloads.length).to.equal(BaseItemCounts.DefaultItems + 1)
})
it('should clear values', async function () {
const key = 'foo'
const value = 'bar'
await this.application.diskStorageService.setValue(key, value)
await this.application.diskStorageService.clearAllData()
expect(await this.application.diskStorageService.getValue(key)).to.not.be.ok
await this.application.storage.setValue(key, value)
await this.application.storage.clearAllData()
expect(await this.application.storage.getValue(key)).to.not.be.ok
})
it('serverPassword should not be saved to keychain', async function () {
@@ -57,7 +57,7 @@ describe('storage manager', function () {
password: this.password,
ephemeral: false,
})
const keychainValue = await this.application.deviceInterface.getNamespacedKeychainValue(this.application.identifier)
const keychainValue = await this.application.device.getNamespacedKeychainValue(this.application.identifier)
expect(keychainValue.masterKey).to.be.ok
expect(keychainValue.serverPassword).to.not.be.ok
})
@@ -71,10 +71,10 @@ describe('storage manager', function () {
})
const key = 'foo'
const value = 'bar'
await this.application.diskStorageService.setValue(key, value)
await this.application.storage.setValue(key, value)
/** Items are stored in local storage */
expect(Object.keys(localStorage).length).to.equal(this.expectedKeyCount + BaseItemCounts.DefaultItems)
const retrievedValue = await this.application.diskStorageService.getValue(key)
const retrievedValue = await this.application.storage.getValue(key)
expect(retrievedValue).to.equal(value)
})
@@ -88,12 +88,12 @@ describe('storage manager', function () {
})
const key = 'foo'
const value = 'bar'
await this.application.diskStorageService.setValueAndAwaitPersist(key, value)
await this.application.storage.setValueAndAwaitPersist(key, value)
const expectedKeys = ['keychain']
expect(Object.keys(localStorage).length).to.equal(expectedKeys.length)
const retrievedValue = await this.application.diskStorageService.getValue(key)
const retrievedValue = await this.application.storage.getValue(key)
expect(retrievedValue).to.equal(value)
})
@@ -105,21 +105,21 @@ describe('storage manager', function () {
ephemeral: true,
})
await Factory.createSyncedNote(this.application)
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
expect(rawPayloads.length).to.equal(0)
})
it('storage with no account and no passcode should not be encrypted', async function () {
await this.application.diskStorageService.setValueAndAwaitPersist('foo', 'bar')
const wrappedValue = this.application.diskStorageService.values[ValueModesKeys.Wrapped]
await this.application.storage.setValueAndAwaitPersist('foo', 'bar')
const wrappedValue = this.application.storage.values[ValueModesKeys.Wrapped]
const payload = new DecryptedPayload(wrappedValue)
expect(payload.content).to.be.an.instanceof(Object)
})
it('storage aftering adding passcode should be encrypted', async function () {
await this.application.diskStorageService.setValueAndAwaitPersist('foo', 'bar')
await this.application.storage.setValueAndAwaitPersist('foo', 'bar')
await this.application.addPasscode('123')
const wrappedValue = this.application.diskStorageService.values[ValueModesKeys.Wrapped]
const wrappedValue = this.application.storage.values[ValueModesKeys.Wrapped]
const payload = new EncryptedPayload(wrappedValue)
expect(payload.content).to.be.a('string')
})
@@ -127,11 +127,11 @@ describe('storage manager', function () {
it('storage after adding passcode then removing passcode should not be encrypted', async function () {
const passcode = '123'
Factory.handlePasswordChallenges(this.application, passcode)
await this.application.diskStorageService.setValueAndAwaitPersist('foo', 'bar')
await this.application.storage.setValueAndAwaitPersist('foo', 'bar')
await this.application.addPasscode(passcode)
await this.application.diskStorageService.setValueAndAwaitPersist('bar', 'foo')
await this.application.storage.setValueAndAwaitPersist('bar', 'foo')
await this.application.removePasscode()
const wrappedValue = this.application.diskStorageService.values[ValueModesKeys.Wrapped]
const wrappedValue = this.application.storage.values[ValueModesKeys.Wrapped]
const payload = new DecryptedPayload(wrappedValue)
expect(payload.content).to.be.an.instanceof(Object)
})
@@ -148,35 +148,35 @@ describe('storage manager', function () {
email: this.email,
password: this.password,
})
expect(await this.application.deviceInterface.getNamespacedKeychainValue(this.application.identifier)).to.be.ok
await this.application.diskStorageService.setValueAndAwaitPersist('foo', 'bar')
expect(await this.application.device.getNamespacedKeychainValue(this.application.identifier)).to.be.ok
await this.application.storage.setValueAndAwaitPersist('foo', 'bar')
Factory.handlePasswordChallenges(this.application, this.password)
await this.application.addPasscode(passcode)
expect(await this.application.deviceInterface.getNamespacedKeychainValue(this.application.identifier)).to.not.be.ok
await this.application.diskStorageService.setValueAndAwaitPersist('bar', 'foo')
expect(await this.application.device.getNamespacedKeychainValue(this.application.identifier)).to.not.be.ok
await this.application.storage.setValueAndAwaitPersist('bar', 'foo')
Factory.handlePasswordChallenges(this.application, passcode)
await this.application.removePasscode()
expect(await this.application.deviceInterface.getNamespacedKeychainValue(this.application.identifier)).to.be.ok
expect(await this.application.device.getNamespacedKeychainValue(this.application.identifier)).to.be.ok
const wrappedValue = this.application.diskStorageService.values[ValueModesKeys.Wrapped]
const wrappedValue = this.application.storage.values[ValueModesKeys.Wrapped]
const payload = new EncryptedPayload(wrappedValue)
expect(payload.content).to.be.a('string')
})
it('adding account should encrypt storage with account keys', async function () {
await this.application.diskStorageService.setValueAndAwaitPersist('foo', 'bar')
await this.application.storage.setValueAndAwaitPersist('foo', 'bar')
await Factory.registerUserToApplication({
application: this.application,
email: this.email,
password: this.password,
ephemeral: true,
})
const accountKey = await this.application.encryptionService.getRootKey()
expect(await this.application.diskStorageService.canDecryptWithKey(accountKey)).to.equal(true)
const accountKey = await this.application.encryption.getRootKey()
expect(await this.application.storage.canDecryptWithKey(accountKey)).to.equal(true)
})
it('signing out of account should decrypt storage', async function () {
await this.application.diskStorageService.setValueAndAwaitPersist('foo', 'bar')
await this.application.storage.setValueAndAwaitPersist('foo', 'bar')
await Factory.registerUserToApplication({
application: this.application,
email: this.email,
@@ -184,15 +184,15 @@ describe('storage manager', function () {
ephemeral: true,
})
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
await this.application.diskStorageService.setValueAndAwaitPersist('bar', 'foo')
const wrappedValue = this.application.diskStorageService.values[ValueModesKeys.Wrapped]
await this.application.storage.setValueAndAwaitPersist('bar', 'foo')
const wrappedValue = this.application.storage.values[ValueModesKeys.Wrapped]
const payload = new DecryptedPayload(wrappedValue)
expect(payload.content).to.be.an.instanceof(Object)
})
it('adding account then passcode should encrypt storage with account keys', async function () {
/** Should encrypt storage with account keys and encrypt account keys with passcode */
await this.application.diskStorageService.setValueAndAwaitPersist('foo', 'bar')
await this.application.storage.setValueAndAwaitPersist('foo', 'bar')
await Factory.registerUserToApplication({
application: this.application,
email: this.email,
@@ -201,23 +201,23 @@ describe('storage manager', function () {
})
/** Should not be wrapped root key yet */
expect(await this.application.encryptionService.rootKeyManager.getWrappedRootKey()).to.not.be.ok
expect(await this.application.encryption.rootKeyManager.getWrappedRootKey()).to.not.be.ok
const passcode = '123'
Factory.handlePasswordChallenges(this.application, this.password)
await this.application.addPasscode(passcode)
await this.application.diskStorageService.setValueAndAwaitPersist('bar', 'foo')
await this.application.storage.setValueAndAwaitPersist('bar', 'foo')
/** Root key should now be wrapped */
expect(await this.application.encryptionService.rootKeyManager.getWrappedRootKey()).to.be.ok
expect(await this.application.encryption.rootKeyManager.getWrappedRootKey()).to.be.ok
const accountKey = await this.application.encryptionService.getRootKey()
expect(await this.application.diskStorageService.canDecryptWithKey(accountKey)).to.equal(true)
const passcodeKey = await this.application.encryptionService.computeWrappingKey(passcode)
const wrappedRootKey = await this.application.encryptionService.rootKeyManager.getWrappedRootKey()
const accountKey = await this.application.encryption.getRootKey()
expect(await this.application.storage.canDecryptWithKey(accountKey)).to.equal(true)
const passcodeKey = await this.application.encryption.computeWrappingKey(passcode)
const wrappedRootKey = await this.application.encryption.rootKeyManager.getWrappedRootKey()
/** Expect that we can decrypt wrapped root key with passcode key */
const payload = new EncryptedPayload(wrappedRootKey)
const decrypted = await this.application.encryptionService.decryptSplitSingle({
const decrypted = await this.application.encryption.decryptSplitSingle({
usesRootKey: {
items: [payload],
key: passcodeKey,
@@ -229,7 +229,7 @@ describe('storage manager', function () {
it('stored payloads should not contain metadata fields', async function () {
await this.application.addPasscode('123')
await Factory.createSyncedNote(this.application)
const payloads = await this.application.diskStorageService.getAllRawPayloads()
const payloads = await this.application.storage.getAllRawPayloads()
const payload = payloads[0]
expect(payload.fields).to.not.be.ok
expect(payload.source).to.not.be.ok
@@ -239,7 +239,7 @@ describe('storage manager', function () {
it('storing an offline synced payload should not include dirty flag', async function () {
await this.application.addPasscode('123')
await Factory.createSyncedNote(this.application)
const payloads = await this.application.diskStorageService.getAllRawPayloads()
const payloads = await this.application.storage.getAllRawPayloads()
const payload = payloads[0]
expect(payload.dirty).to.not.be.ok
@@ -254,7 +254,7 @@ describe('storage manager', function () {
})
await Factory.createSyncedNote(this.application)
const payloads = await this.application.diskStorageService.getAllRawPayloads()
const payloads = await this.application.storage.getAllRawPayloads()
const payload = payloads[0]
expect(payload.dirty).to.not.be.ok
@@ -269,7 +269,7 @@ describe('storage manager', function () {
})
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
const values = this.application.diskStorageService.values[ValueModesKeys.Unwrapped]
const values = this.application.storage.values[ValueModesKeys.Unwrapped]
expect(Object.keys(values).length).to.equal(0)
})

View File

@@ -1,5 +1,5 @@
import * as Factory from './lib/factory.js'
import * as Events from './lib/Events.js'
chai.use(chaiAsPromised)
const expect = chai.expect
@@ -9,7 +9,6 @@ describe('subscriptions', function () {
let application
let context
let subscriptionManager
let subscriptionId = 3001
afterEach(async function () {
await Factory.safeDeinit(application)
@@ -24,9 +23,9 @@ describe('subscriptions', function () {
await context.launch()
application = context.application
subscriptionManager = context.application.subscriptionManager
subscriptionManager = context.subscriptions
const result = await Factory.registerUserToApplication({
await Factory.registerUserToApplication({
application: application,
email: context.email,
password: context.password,
@@ -40,7 +39,7 @@ describe('subscriptions', function () {
const existingInvites = await subscriptionManager.listSubscriptionInvitations()
const newlyCreatedInvite = existingInvites.find(invite => invite.inviteeIdentifier === 'test@test.te')
const newlyCreatedInvite = existingInvites.find((invite) => invite.inviteeIdentifier === 'test@test.te')
expect(newlyCreatedInvite.status).to.equal('sent')
})
@@ -69,17 +68,17 @@ describe('subscriptions', function () {
let existingInvites = await subscriptionManager.listSubscriptionInvitations()
expect (existingInvites.length).to.equal(2)
expect(existingInvites.length).to.equal(2)
const newlyCreatedInvite = existingInvites.find(invite => invite.inviteeIdentifier === 'test@test.te')
const newlyCreatedInvite = existingInvites.find((invite) => invite.inviteeIdentifier === 'test@test.te')
await subscriptionManager.cancelInvitation(newlyCreatedInvite.uuid)
existingInvites = await subscriptionManager.listSubscriptionInvitations()
expect (existingInvites.length).to.equal(2)
expect(existingInvites.length).to.equal(2)
expect(existingInvites.filter(invite => invite.status === 'canceled').length).to.equal(1)
expect(existingInvites.filter((invite) => invite.status === 'canceled').length).to.equal(1)
})
it('should invite a user by email if the limit of shared subscription is restored', async () => {
@@ -99,6 +98,6 @@ describe('subscriptions', function () {
existingInvites = await subscriptionManager.listSubscriptionInvitations()
expect(existingInvites.find(invite => invite.inviteeIdentifier === 'test6@test.te')).not.to.equal(undefined)
expect(existingInvites.find((invite) => invite.inviteeIdentifier === 'test6@test.te')).not.to.equal(undefined)
})
})

View File

@@ -30,10 +30,10 @@ describe('online conflict handling', function () {
await this.context.register()
this.sharedFinalAssertions = async function () {
expect(this.application.syncService.isOutOfSync()).to.equal(false)
const items = this.application.itemManager.items
expect(this.application.sync.isOutOfSync()).to.equal(false)
const items = this.application.items.items
expect(items.length).to.equal(this.expectedItemCount)
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
expect(rawPayloads.length).to.equal(this.expectedItemCount)
}
})
@@ -68,7 +68,7 @@ describe('online conflict handling', function () {
this.expectedItemCount++
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
/** First modify the item without saving so that our local contents digress from the server's */
await this.application.mutator.changeItem(item, (mutator) => {
@@ -85,7 +85,7 @@ describe('online conflict handling', function () {
syncOptions,
)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
await this.sharedFinalAssertions()
})
@@ -93,7 +93,7 @@ describe('online conflict handling', function () {
const payload = createDirtyPayload(ContentType.TYPES.ItemsKey)
const item = await this.application.mutator.emitItemFromPayload(payload, PayloadEmitSource.LocalChanged)
this.expectedItemCount++
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
/** First modify the item without saving so that
* our local contents digress from the server's */
await this.application.mutator.changeItem(item, (mutator) => {
@@ -110,7 +110,7 @@ describe('online conflict handling', function () {
syncOptions,
)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
await this.sharedFinalAssertions()
})
@@ -119,9 +119,9 @@ describe('online conflict handling', function () {
const note = await Factory.createMappedNote(this.application)
this.expectedItemCount++
await this.application.mutator.setItemDirty(note)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
expect(rawPayloads.length).to.equal(this.expectedItemCount)
const originalValue = note.title
@@ -141,27 +141,27 @@ describe('online conflict handling', function () {
})
// Download all items from the server, which will include this note.
await this.application.syncService.clearSyncPositionTokens()
await this.application.syncService.sync({
await this.application.sync.clearSyncPositionTokens()
await this.application.sync.sync({
...syncOptions,
awaitAll: true,
})
// We expect this item to be duplicated
this.expectedItemCount++
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(2)
expect(this.application.items.getDisplayableNotes().length).to.equal(2)
const allItems = this.application.itemManager.items
const allItems = this.application.items.items
expect(allItems.length).to.equal(this.expectedItemCount)
const originalItem = this.application.itemManager.findItem(note.uuid)
const originalItem = this.application.items.findItem(note.uuid)
const duplicateItem = allItems.find((i) => i.content.conflict_of === note.uuid)
expect(originalItem.title).to.equal(dirtyValue)
expect(duplicateItem.title).to.equal(originalValue)
expect(originalItem.title).to.not.equal(duplicateItem.title)
const newRawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const newRawPayloads = await this.application.storage.getAllRawPayloads()
expect(newRawPayloads.length).to.equal(this.expectedItemCount)
await this.sharedFinalAssertions()
})
@@ -172,7 +172,7 @@ describe('online conflict handling', function () {
await Factory.markDirtyAndSyncItem(this.application, note)
this.expectedItemCount++
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
expect(rawPayloads.length).to.equal(this.expectedItemCount)
/** First modify the item without saving so that
* our local contents digress from the server's */
@@ -192,11 +192,11 @@ describe('online conflict handling', function () {
// We expect this item to be duplicated
this.expectedItemCount++
const allItems = this.application.itemManager.items
const allItems = this.application.items.items
expect(allItems.length).to.equal(this.expectedItemCount)
const note1 = this.application.itemManager.getDisplayableNotes()[0]
const note2 = this.application.itemManager.getDisplayableNotes()[1]
const note1 = this.application.items.getDisplayableNotes()[0]
const note2 = this.application.items.getDisplayableNotes()[1]
expect(note1.content.title).to.not.equal(note2.content.title)
await this.sharedFinalAssertions()
})
@@ -222,16 +222,16 @@ describe('online conflict handling', function () {
)
this.expectedItemCount++
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
// clear sync token, clear storage, download all items, and ensure none of them have error decrypting
await this.application.syncService.clearSyncPositionTokens()
await this.application.diskStorageService.clearAllPayloads()
await this.application.payloadManager.resetState()
await this.application.itemManager.resetState()
await this.application.syncService.sync(syncOptions)
await this.application.sync.clearSyncPositionTokens()
await this.application.storage.clearAllPayloads()
await this.application.payloads.resetState()
await this.application.items.resetState()
await this.application.sync.sync(syncOptions)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
await this.sharedFinalAssertions()
})
@@ -239,7 +239,7 @@ describe('online conflict handling', function () {
let note = await Factory.createMappedNote(this.application)
await this.application.mutator.setItemDirty(note)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
this.expectedItemCount++
@@ -263,15 +263,15 @@ describe('online conflict handling', function () {
// We expect this item to be duplicated
this.expectedItemCount++
await this.application.syncService.clearSyncPositionTokens()
await this.application.syncService.sync(syncOptions)
await this.application.sync.clearSyncPositionTokens()
await this.application.sync.sync(syncOptions)
note = this.application.items.findItem(note.uuid)
// We expect the item title to be the new title, and not rolled back to original value
expect(note.content.title).to.equal(newTitle)
const allItems = this.application.itemManager.items
const allItems = this.application.items.items
expect(allItems.length).to.equal(this.expectedItemCount)
await this.sharedFinalAssertions()
})
@@ -280,16 +280,16 @@ describe('online conflict handling', function () {
const note = await Factory.createMappedNote(this.application)
this.expectedItemCount++
await this.application.mutator.setItemDirty(note)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
// keep item as is and set dirty
await this.application.mutator.setItemDirty(note)
// clear sync token so that all items are retrieved on next sync
this.application.syncService.clearSyncPositionTokens()
this.application.sync.clearSyncPositionTokens()
await this.application.syncService.sync(syncOptions)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
await this.application.sync.sync(syncOptions)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
await this.sharedFinalAssertions()
})
@@ -310,7 +310,7 @@ describe('online conflict handling', function () {
)
// client B
await this.application.syncService.clearSyncPositionTokens()
await this.application.sync.clearSyncPositionTokens()
await this.application.mutator.changeItem(
note,
(mutator) => {
@@ -323,7 +323,7 @@ describe('online conflict handling', function () {
// conflict_of is a key to ignore when comparing content, so item should
// not be duplicated.
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
await this.sharedFinalAssertions()
})
@@ -348,7 +348,7 @@ describe('online conflict handling', function () {
mutator.title = `${Math.random()}`
})
// client B
await this.application.syncService.clearSyncPositionTokens()
await this.application.sync.clearSyncPositionTokens()
await Factory.changePayloadTimeStampAndSync(
this.application,
@@ -370,17 +370,17 @@ describe('online conflict handling', function () {
const originalPayload = note.payloadRepresentation()
this.expectedItemCount++
await this.application.mutator.setItemDirty(note)
await this.application.syncService.sync(syncOptions)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
await this.application.sync.sync(syncOptions)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
// client A
await this.application.mutator.setItemToBeDeleted(note)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
this.expectedItemCount--
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
// client B
await this.application.syncService.clearSyncPositionTokens()
await this.application.sync.clearSyncPositionTokens()
// Add the item back and say it's not deleted
const mutatedPayload = new DecryptedPayload({
...originalPayload,
@@ -388,13 +388,13 @@ describe('online conflict handling', function () {
updated_at: Factory.yesterday(),
})
await this.application.mutator.emitItemsFromPayloads([mutatedPayload], PayloadEmitSource.LocalChanged)
const resultNote = this.application.itemManager.findItem(note.uuid)
const resultNote = this.application.items.findItem(note.uuid)
expect(resultNote.uuid).to.equal(note.uuid)
await this.application.mutator.setItemDirty(resultNote)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
// We expect that this item is now gone for good, and a duplicate has not been created.
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
await this.sharedFinalAssertions()
})
@@ -404,11 +404,11 @@ describe('online conflict handling', function () {
this.expectedItemCount++
// client A
await this.application.syncService.sync(syncOptions)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
await this.application.sync.sync(syncOptions)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
// client B
await this.application.syncService.clearSyncPositionTokens()
await this.application.sync.clearSyncPositionTokens()
// This client says this item is deleted, but the server is saying its not deleted.
// In this case, we want to keep the server copy.
@@ -420,14 +420,14 @@ describe('online conflict handling', function () {
)
// We expect that this item maintained.
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
await this.sharedFinalAssertions()
})
it('should create conflict if syncing an item that is stale', async function () {
let note = await Factory.createMappedNote(this.application)
await this.application.mutator.setItemDirty(note)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
note = this.application.items.findItem(note.uuid)
expect(note.dirty).to.equal(false)
this.expectedItemCount++
@@ -452,7 +452,7 @@ describe('online conflict handling', function () {
// We expect now that the item was conflicted
this.expectedItemCount++
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
expect(rawPayloads.length).to.equal(this.expectedItemCount)
for (const payload of rawPayloads) {
expect(payload.dirty).to.not.be.ok
@@ -465,7 +465,7 @@ describe('online conflict handling', function () {
await this.application.mutator.setItemDirty(note)
this.expectedItemCount++
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
await Factory.changePayloadTimeStampAndSync(
this.application,
@@ -475,7 +475,7 @@ describe('online conflict handling', function () {
syncOptions,
)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
await this.sharedFinalAssertions()
})
@@ -488,11 +488,11 @@ describe('online conflict handling', function () {
await Factory.createManyMappedNotes(this.application, largeItemCount)
/** Upload */
this.application.syncService.sync(syncOptions)
this.application.sync.sync(syncOptions)
await this.context.awaitNextSucessfulSync()
this.expectedItemCount += largeItemCount
const items = this.application.itemManager.items
const items = this.application.items.items
expect(items.length).to.equal(this.expectedItemCount)
/**
@@ -500,9 +500,9 @@ describe('online conflict handling', function () {
* the server as dirty, with no sync token, so that the server also
* gives us everything it has.
*/
this.application.syncService.lockSyncing()
this.application.sync.lockSyncing()
const yesterday = Factory.yesterday()
for (const note of this.application.itemManager.getDisplayableNotes()) {
for (const note of this.application.items.getDisplayableNotes()) {
/** First modify the item without saving so that
* our local contents digress from the server's */
await this.application.mutator.changeItem(note, (mutator) => {
@@ -516,13 +516,13 @@ describe('online conflict handling', function () {
// We expect all the notes to be duplicated.
this.expectedItemCount++
}
this.application.syncService.unlockSyncing()
this.application.sync.unlockSyncing()
await this.application.syncService.clearSyncPositionTokens()
this.application.syncService.sync(syncOptions)
await this.application.sync.clearSyncPositionTokens()
this.application.sync.sync(syncOptions)
await this.context.awaitNextSucessfulSync()
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(largeItemCount * 2)
expect(this.application.items.getDisplayableNotes().length).to.equal(largeItemCount * 2)
await this.sharedFinalAssertions()
}).timeout(60000)
@@ -532,8 +532,8 @@ describe('online conflict handling', function () {
this.expectedItemCount -= 1 /** auto-created user preferences */
await this.application.mutator.emitItemsFromPayloads([payload1, payload2], PayloadEmitSource.LocalChanged)
this.expectedItemCount += 2
let tag = this.application.itemManager.getItems(ContentType.TYPES.Tag)[0]
let userPrefs = this.application.itemManager.getItems(ContentType.TYPES.UserPrefs)[0]
let tag = this.application.items.getItems(ContentType.TYPES.Tag)[0]
let userPrefs = this.application.items.getItems(ContentType.TYPES.UserPrefs)[0]
expect(tag).to.be.ok
expect(userPrefs).to.be.ok
@@ -544,11 +544,11 @@ describe('online conflict handling', function () {
await this.application.mutator.setItemDirty(userPrefs)
userPrefs = this.application.items.findItem(userPrefs.uuid)
expect(this.application.itemManager.itemsReferencingItem(userPrefs).length).to.equal(1)
expect(this.application.itemManager.itemsReferencingItem(userPrefs)).to.include(tag)
expect(this.application.items.itemsReferencingItem(userPrefs).length).to.equal(1)
expect(this.application.items.itemsReferencingItem(userPrefs)).to.include(tag)
await this.application.syncService.sync(syncOptions)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
await this.application.sync.sync(syncOptions)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
tag = await Factory.changePayloadTimeStamp(
this.application,
@@ -559,32 +559,32 @@ describe('online conflict handling', function () {
},
)
await this.application.syncService.sync({ ...syncOptions, awaitAll: true })
await this.application.sync.sync({ ...syncOptions, awaitAll: true })
// fooItem should now be conflicted and a copy created
this.expectedItemCount++
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
const rawPayloads = await this.application.storage.getAllRawPayloads()
expect(rawPayloads.length).to.equal(this.expectedItemCount)
const fooItems = this.application.itemManager.getItems(ContentType.TYPES.Tag)
const fooItems = this.application.items.getItems(ContentType.TYPES.Tag)
const fooItem2 = fooItems[1]
expect(fooItem2.content.conflict_of).to.equal(tag.uuid)
// Two items now link to this original object
const referencingItems = this.application.itemManager.itemsReferencingItem(userPrefs)
const referencingItems = this.application.items.itemsReferencingItem(userPrefs)
expect(referencingItems.length).to.equal(2)
expect(referencingItems[0]).to.not.equal(referencingItems[1])
expect(this.application.itemManager.itemsReferencingItem(tag).length).to.equal(0)
expect(this.application.itemManager.itemsReferencingItem(fooItem2).length).to.equal(0)
expect(this.application.items.itemsReferencingItem(tag).length).to.equal(0)
expect(this.application.items.itemsReferencingItem(fooItem2).length).to.equal(0)
expect(tag.content.references.length).to.equal(1)
expect(fooItem2.content.references.length).to.equal(1)
expect(userPrefs.content.references.length).to.equal(0)
expect(this.application.itemManager.getDirtyItems().length).to.equal(0)
for (const item of this.application.itemManager.items) {
expect(this.application.items.getDirtyItems().length).to.equal(0)
for (const item of this.application.items.items) {
expect(item.dirty).to.not.be.ok
}
await this.sharedFinalAssertions()
@@ -611,7 +611,7 @@ describe('online conflict handling', function () {
await this.application.mutator.setItemDirty(note)
this.expectedItemCount += 2
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
// conflict the note
const newText = `${Math.random()}`
@@ -645,7 +645,7 @@ describe('online conflict handling', function () {
* and not 2 (the note and tag)
*/
this.expectedItemCount += 1
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
expect(tag.content.references.length).to.equal(2)
await this.sharedFinalAssertions()
})
@@ -680,7 +680,7 @@ describe('online conflict handling', function () {
await this.application.sync.sync()
/** Expect that no duplicates have been created, and that the note's title is now finalTitle */
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
const finalNote = this.application.items.findItem(note.uuid)
expect(finalNote.title).to.equal(finalTitle)
await this.sharedFinalAssertions()
@@ -713,8 +713,8 @@ describe('online conflict handling', function () {
/**
* Retrieve this note from the server by clearing sync token
*/
await this.application.syncService.clearSyncPositionTokens()
await this.application.syncService.sync({
await this.application.sync.clearSyncPositionTokens()
await this.application.sync.sync({
...syncOptions,
awaitAll: true,
})
@@ -724,7 +724,7 @@ describe('online conflict handling', function () {
*/
const resultNote = await this.application.items.findItem(note.uuid)
expect(resultNote.errorDecrypting).to.not.be.ok
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
await this.sharedFinalAssertions()
})
@@ -748,8 +748,8 @@ describe('online conflict handling', function () {
/** Create bulk data belonging to another account and sync */
const largeItemCount = SyncUpDownLimit + 10
await Factory.createManyMappedNotes(this.application, largeItemCount)
await this.application.syncService.sync(syncOptions)
const priorData = this.application.itemManager.items
await this.application.sync.sync(syncOptions)
const priorData = this.application.items.items
/** Register new account and import this same data */
const newApp = await Factory.signOutApplicationAndReturnNew(this.application)
@@ -759,9 +759,9 @@ describe('online conflict handling', function () {
password: Utils.generateUuid(),
})
await newApp.mutator.emitItemsFromPayloads(priorData.map((i) => i.payload))
await newApp.syncService.markAllItemsAsNeedingSyncAndPersist()
await newApp.syncService.sync(syncOptions)
expect(newApp.payloadManager.invalidPayloads.length).to.equal(0)
await newApp.sync.markAllItemsAsNeedingSyncAndPersist()
await newApp.sync.sync(syncOptions)
expect(newApp.payloads.invalidPayloads.length).to.equal(0)
await Factory.safeDeinit(newApp)
},
).timeout(80000)
@@ -787,8 +787,8 @@ describe('online conflict handling', function () {
})
Factory.handlePasswordChallenges(newApp, password)
await newApp.importData(backupFile, true)
expect(newApp.itemManager.getDisplayableTags().length).to.equal(1)
expect(newApp.itemManager.getDisplayableNotes().length).to.equal(1)
expect(newApp.items.getDisplayableTags().length).to.equal(1)
expect(newApp.items.getDisplayableNotes().length).to.equal(1)
await Factory.safeDeinit(newApp)
}).timeout(10000)
@@ -799,7 +799,7 @@ describe('online conflict handling', function () {
*/
/** Create primary account and export data */
await createSyncedNoteWithTag(this.application)
const tag = this.application.itemManager.getDisplayableTags()[0]
const tag = this.application.items.getDisplayableTags()[0]
const note2 = await Factory.createMappedNote(this.application)
await this.application.changeAndSaveItem(tag, (mutator) => {
mutator.e2ePendingRefactor_addItemAsRelationship(note2)
@@ -822,7 +822,7 @@ describe('online conflict handling', function () {
})
Factory.handlePasswordChallenges(newApp, password)
await newApp.importData(backupFile, true)
const newTag = newApp.itemManager.getDisplayableTags()[0]
const newTag = newApp.items.getDisplayableTags()[0]
const notes = newApp.items.referencesForItem(newTag)
expect(notes.length).to.equal(2)
await Factory.safeDeinit(newApp)
@@ -857,7 +857,7 @@ describe('online conflict handling', function () {
})
await this.application.mutator.emitItemFromPayload(modified)
await this.application.sync.sync()
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
await this.sharedFinalAssertions()
})
@@ -881,7 +881,7 @@ describe('online conflict handling', function () {
this.expectedItemCount++
await this.application.mutator.emitItemFromPayload(modified)
await this.application.sync.sync()
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(2)
expect(this.application.items.getDisplayableNotes().length).to.equal(2)
await this.sharedFinalAssertions()
})
@@ -913,7 +913,7 @@ describe('online conflict handling', function () {
this.expectedItemCount++
await this.application.mutator.emitItemFromPayload(modified)
await this.application.sync.sync()
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(2)
expect(this.application.items.getDisplayableNotes().length).to.equal(2)
await this.sharedFinalAssertions()
})

View File

@@ -28,7 +28,7 @@ describe('sync integrity', () => {
const awaitSyncEventPromise = (application, targetEvent) => {
return new Promise((resolve) => {
application.syncService.addEventObserver((event) => {
application.sync.addEventObserver((event) => {
if (event === targetEvent) {
resolve()
}
@@ -37,8 +37,8 @@ describe('sync integrity', () => {
}
afterEach(async function () {
expect(this.application.syncService.isOutOfSync()).to.equal(false)
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
expect(this.application.sync.isOutOfSync()).to.equal(false)
const rawPayloads = await this.application.storage.getAllRawPayloads()
expect(rawPayloads.length).to.equal(this.expectedItemCount)
await Factory.safeDeinit(this.application)
})
@@ -51,10 +51,10 @@ describe('sync integrity', () => {
this.expectedItemCount++
const didEnterOutOfSync = awaitSyncEventPromise(this.application, SyncEvent.EnterOutOfSync)
await this.application.syncService.sync({ checkIntegrity: true })
await this.application.sync.sync({ checkIntegrity: true })
await this.application.itemManager.removeItemLocally(item)
await this.application.syncService.sync({ checkIntegrity: true, awaitAll: true })
await this.application.items.removeItemLocally(item)
await this.application.sync.sync({ checkIntegrity: true, awaitAll: true })
await didEnterOutOfSync
})
@@ -69,11 +69,11 @@ describe('sync integrity', () => {
const didEnterOutOfSync = awaitSyncEventPromise(this.application, SyncEvent.EnterOutOfSync)
const didExitOutOfSync = awaitSyncEventPromise(this.application, SyncEvent.ExitOutOfSync)
await this.application.syncService.sync({ checkIntegrity: true })
await this.application.itemManager.removeItemLocally(item)
await this.application.syncService.sync({ checkIntegrity: true, awaitAll: true })
await this.application.sync.sync({ checkIntegrity: true })
await this.application.items.removeItemLocally(item)
await this.application.sync.sync({ checkIntegrity: true, awaitAll: true })
await Promise.all([didEnterOutOfSync, didExitOutOfSync])
expect(this.application.syncService.isOutOfSync()).to.equal(false)
expect(this.application.sync.isOutOfSync()).to.equal(false)
})
})

View File

@@ -34,12 +34,12 @@ describe('notes + tags syncing', function () {
it('syncing an item then downloading it should include items_key_id', async function () {
const note = await Factory.createMappedNote(this.application)
await this.application.mutator.setItemDirty(note)
await this.application.syncService.sync(syncOptions)
await this.application.payloadManager.resetState()
await this.application.itemManager.resetState()
await this.application.syncService.clearSyncPositionTokens()
await this.application.syncService.sync(syncOptions)
const downloadedNote = this.application.itemManager.getDisplayableNotes()[0]
await this.application.sync.sync(syncOptions)
await this.application.payloads.resetState()
await this.application.items.resetState()
await this.application.sync.clearSyncPositionTokens()
await this.application.sync.sync(syncOptions)
const downloadedNote = this.application.items.getDisplayableNotes()[0]
expect(downloadedNote.items_key_id).to.not.be.ok
// Allow time for waitingForKey
await Factory.sleep(0.1)
@@ -53,20 +53,20 @@ describe('notes + tags syncing', function () {
const tagPayload = pair[1]
await this.application.mutator.emitItemsFromPayloads([notePayload, tagPayload], PayloadEmitSource.LocalChanged)
const note = this.application.itemManager.getItems([ContentType.TYPES.Note])[0]
const tag = this.application.itemManager.getItems([ContentType.TYPES.Tag])[0]
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(this.application.itemManager.getDisplayableTags().length).to.equal(1)
const note = this.application.items.getItems([ContentType.TYPES.Note])[0]
const tag = this.application.items.getItems([ContentType.TYPES.Tag])[0]
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDisplayableTags().length).to.equal(1)
for (let i = 0; i < 9; i++) {
await this.application.mutator.setItemsDirty([note, tag])
await this.application.syncService.sync(syncOptions)
this.application.syncService.clearSyncPositionTokens()
await this.application.sync.sync(syncOptions)
this.application.sync.clearSyncPositionTokens()
expect(tag.content.references.length).to.equal(1)
expect(this.application.itemManager.itemsReferencingItem(note).length).to.equal(1)
expect(this.application.items.itemsReferencingItem(note).length).to.equal(1)
expect(tag.noteCount).to.equal(1)
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(this.application.itemManager.getDisplayableTags().length).to.equal(1)
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDisplayableTags().length).to.equal(1)
console.warn('Waiting 0.1s...')
await Factory.sleep(0.1)
}
@@ -77,32 +77,32 @@ describe('notes + tags syncing', function () {
const notePayload = pair[0]
const tagPayload = pair[1]
await this.application.mutator.emitItemsFromPayloads([notePayload, tagPayload], PayloadEmitSource.LocalChanged)
const originalNote = this.application.itemManager.getDisplayableNotes()[0]
const originalTag = this.application.itemManager.getDisplayableTags()[0]
const originalNote = this.application.items.getDisplayableNotes()[0]
const originalTag = this.application.items.getDisplayableTags()[0]
await this.application.mutator.setItemsDirty([originalNote, originalTag])
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
expect(originalTag.content.references.length).to.equal(1)
expect(originalTag.noteCount).to.equal(1)
expect(this.application.itemManager.itemsReferencingItem(originalNote).length).to.equal(1)
expect(this.application.items.itemsReferencingItem(originalNote).length).to.equal(1)
// when signing in, all local items are cleared from storage (but kept in memory; to clear desktop logs),
// then resaved with alternated uuids.
await this.application.diskStorageService.clearAllPayloads()
await this.application.syncService.markAllItemsAsNeedingSyncAndPersist()
await this.application.storage.clearAllPayloads()
await this.application.sync.markAllItemsAsNeedingSyncAndPersist()
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(this.application.itemManager.getDisplayableTags().length).to.equal(1)
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDisplayableTags().length).to.equal(1)
const note = this.application.itemManager.getDisplayableNotes()[0]
const tag = this.application.itemManager.getDisplayableTags()[0]
const note = this.application.items.getDisplayableNotes()[0]
const tag = this.application.items.getDisplayableTags()[0]
expect(tag.content.references.length).to.equal(1)
expect(note.content.references.length).to.equal(0)
expect(tag.noteCount).to.equal(1)
expect(this.application.itemManager.itemsReferencingItem(note).length).to.equal(1)
expect(this.application.items.itemsReferencingItem(note).length).to.equal(1)
})
it('duplicating a tag should maintian its relationships', async function () {
@@ -110,22 +110,22 @@ describe('notes + tags syncing', function () {
const notePayload = pair[0]
const tagPayload = pair[1]
await this.application.mutator.emitItemsFromPayloads([notePayload, tagPayload], PayloadEmitSource.LocalChanged)
let note = this.application.itemManager.getDisplayableNotes()[0]
let tag = this.application.itemManager.getDisplayableTags()[0]
expect(this.application.itemManager.itemsReferencingItem(note).length).to.equal(1)
let note = this.application.items.getDisplayableNotes()[0]
let tag = this.application.items.getDisplayableTags()[0]
expect(this.application.items.itemsReferencingItem(note).length).to.equal(1)
await this.application.mutator.setItemsDirty([note, tag])
await this.application.syncService.sync(syncOptions)
await this.application.syncService.clearSyncPositionTokens()
await this.application.sync.sync(syncOptions)
await this.application.sync.clearSyncPositionTokens()
note = this.application.itemManager.findItem(note.uuid)
tag = this.application.itemManager.findItem(tag.uuid)
note = this.application.items.findItem(note.uuid)
tag = this.application.items.findItem(tag.uuid)
expect(note.dirty).to.equal(false)
expect(tag.dirty).to.equal(false)
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(this.application.itemManager.getDisplayableTags().length).to.equal(1)
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDisplayableTags().length).to.equal(1)
await Factory.changePayloadTimeStampAndSync(
this.application,
@@ -137,13 +137,13 @@ describe('notes + tags syncing', function () {
syncOptions,
)
tag = this.application.itemManager.findItem(tag.uuid)
tag = this.application.items.findItem(tag.uuid)
// tag should now be conflicted and a copy created
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(this.application.itemManager.getDisplayableTags().length).to.equal(2)
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDisplayableTags().length).to.equal(2)
const tags = this.application.itemManager.getDisplayableTags()
const tags = this.application.items.getDisplayableTags()
const conflictedTag = tags.find((tag) => {
return !!tag.content.conflict_of
})
@@ -157,11 +157,11 @@ describe('notes + tags syncing', function () {
expect(conflictedTag.content.conflict_of).to.equal(originalTag.uuid)
expect(conflictedTag.noteCount).to.equal(originalTag.noteCount)
expect(this.application.itemManager.itemsReferencingItem(conflictedTag).length).to.equal(0)
expect(this.application.itemManager.itemsReferencingItem(originalTag).length).to.equal(0)
expect(this.application.items.itemsReferencingItem(conflictedTag).length).to.equal(0)
expect(this.application.items.itemsReferencingItem(originalTag).length).to.equal(0)
// Two tags now link to this note
const referencingItems = this.application.itemManager.itemsReferencingItem(note)
const referencingItems = this.application.items.itemsReferencingItem(note)
expect(referencingItems.length).to.equal(2)
expect(referencingItems[0]).to.not.equal(referencingItems[1])
}).timeout(10000)

View File

@@ -19,7 +19,7 @@ describe('offline syncing', () => {
})
afterEach(async function () {
expect(this.application.syncService.isOutOfSync()).to.equal(false)
expect(this.application.sync.isOutOfSync()).to.equal(false)
await Factory.safeDeinit(this.application)
})
@@ -38,19 +38,19 @@ describe('offline syncing', () => {
await Factory.alternateUuidForItem(this.application, note.uuid)
await this.application.sync.sync(syncOptions)
const notes = this.application.itemManager.getDisplayableNotes()
const notes = this.application.items.getDisplayableNotes()
expect(notes.length).to.equal(1)
expect(notes[0].uuid).to.not.equal(note.uuid)
const items = this.application.itemManager.allTrackedItems()
const items = this.application.items.allTrackedItems()
expect(items.length).to.equal(this.expectedItemCount)
})
it('should sync item with no passcode', async function () {
let note = await Factory.createMappedNote(this.application)
expect(Uuids(this.application.itemManager.getDirtyItems()).includes(note.uuid))
expect(Uuids(this.application.items.getDirtyItems()).includes(note.uuid))
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
note = this.application.items.findItem(note.uuid)
@@ -59,9 +59,9 @@ describe('offline syncing', () => {
this.expectedItemCount++
expect(this.application.itemManager.getDirtyItems().length).to.equal(0)
expect(this.application.items.getDirtyItems().length).to.equal(0)
const rawPayloads2 = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads2 = await this.application.storage.getAllRawPayloads()
expect(rawPayloads2.length).to.equal(this.expectedItemCount)
const itemsKeyRaw = (await Factory.getStoragePayloadsOfType(this.application, ContentType.TYPES.ItemsKey))[0]
@@ -77,26 +77,26 @@ describe('offline syncing', () => {
it('should sync item encrypted with passcode', async function () {
await this.application.addPasscode('foobar')
await Factory.createMappedNote(this.application)
expect(this.application.itemManager.getDirtyItems().length).to.equal(1)
const rawPayloads1 = await this.application.diskStorageService.getAllRawPayloads()
expect(this.application.items.getDirtyItems().length).to.equal(1)
const rawPayloads1 = await this.application.storage.getAllRawPayloads()
expect(rawPayloads1.length).to.equal(this.expectedItemCount)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
this.expectedItemCount++
expect(this.application.itemManager.getDirtyItems().length).to.equal(0)
const rawPayloads2 = await this.application.diskStorageService.getAllRawPayloads()
expect(this.application.items.getDirtyItems().length).to.equal(0)
const rawPayloads2 = await this.application.storage.getAllRawPayloads()
expect(rawPayloads2.length).to.equal(this.expectedItemCount)
const payload = rawPayloads2[0]
expect(typeof payload.content).to.equal('string')
expect(payload.content.startsWith(this.application.encryptionService.getLatestVersion())).to.equal(true)
expect(payload.content.startsWith(this.application.encryption.getLatestVersion())).to.equal(true)
})
it('signing out while offline should succeed', async function () {
await Factory.createMappedNote(this.application)
this.expectedItemCount++
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
expect(this.application.noAccount()).to.equal(true)
expect(this.application.getUser()).to.not.be.ok

View File

@@ -42,12 +42,12 @@ describe('online syncing', function () {
})
afterEach(async function () {
expect(this.application.syncService.isOutOfSync()).to.equal(false)
expect(this.application.sync.isOutOfSync()).to.equal(false)
const items = this.application.itemManager.allTrackedItems()
const items = this.application.items.allTrackedItems()
expect(items.length).to.equal(this.expectedItemCount)
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
expect(rawPayloads.length).to.equal(this.expectedItemCount)
await Factory.safeDeinit(this.application)
localStorage.clear()
@@ -60,11 +60,11 @@ describe('online syncing', function () {
it('should register and sync basic model online', async function () {
let note = await Factory.createSyncedNote(this.application)
this.expectedItemCount++
expect(this.application.itemManager.getDirtyItems().length).to.equal(0)
expect(this.application.items.getDirtyItems().length).to.equal(0)
note = this.application.items.findItem(note.uuid)
expect(note.dirty).to.not.be.ok
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
const notePayloads = noteObjectsFromObjects(rawPayloads)
expect(notePayloads.length).to.equal(1)
for (const rawNote of notePayloads) {
@@ -83,7 +83,7 @@ describe('online syncing', function () {
password: this.password,
})
const notes = this.application.itemManager.getDisplayableNotes()
const notes = this.application.items.getDisplayableNotes()
expect(notes.length).to.equal(1)
expect(notes[0].title).to.equal(note.title)
})
@@ -99,7 +99,7 @@ describe('online syncing', function () {
this.application = await this.context.signout()
expect(this.application.itemManager.items.length).to.equal(BaseItemCounts.DefaultItems)
expect(this.application.items.items.length).to.equal(BaseItemCounts.DefaultItems)
const promise = Factory.loginToApplication({
application: this.application,
@@ -132,7 +132,7 @@ describe('online syncing', function () {
mergeLocal: true,
})
const notes = this.application.itemManager.getDisplayableNotes()
const notes = this.application.items.getDisplayableNotes()
expect(notes.length).to.equal(1)
/** uuid should have been alternated */
expect(notes[0].uuid).to.equal(note.uuid)
@@ -143,8 +143,8 @@ describe('online syncing', function () {
let successes = 0
let events = 0
this.application.syncService.ut_beginLatencySimulator(250)
this.application.syncService.addEventObserver((event, data) => {
this.application.sync.ut_beginLatencySimulator(250)
this.application.sync.addEventObserver((event, data) => {
if (event === SyncEvent.SyncCompletedWithAllItemsUploaded) {
events++
}
@@ -153,7 +153,7 @@ describe('online syncing', function () {
const promises = []
for (let i = 0; i < syncCount; i++) {
promises.push(
this.application.syncService
this.application.sync
.sync({
queueStrategy: SyncQueueStrategy.ResolveOnNext,
})
@@ -169,7 +169,7 @@ describe('online syncing', function () {
// We don't know how many will execute above.
expect(events).to.be.at.least(1)
this.application.syncService.ut_endLatencySimulator()
this.application.sync.ut_endLatencySimulator()
// Since the syncs all happen after one another, extra syncs may be queued on that we are not awaiting.
await Factory.sleep(0.5)
})
@@ -179,9 +179,9 @@ describe('online syncing', function () {
let successes = 0
let events = 0
this.application.syncService.ut_beginLatencySimulator(250)
this.application.sync.ut_beginLatencySimulator(250)
this.application.syncService.addEventObserver((event, data) => {
this.application.sync.addEventObserver((event, data) => {
if (event === SyncEvent.SyncCompletedWithAllItemsUploaded) {
events++
}
@@ -190,7 +190,7 @@ describe('online syncing', function () {
const promises = []
for (let i = 0; i < syncCount; i++) {
promises.push(
this.application.syncService
this.application.sync
.sync({
queueStrategy: SyncQueueStrategy.ForceSpawnNew,
})
@@ -202,7 +202,7 @@ describe('online syncing', function () {
await Promise.all(promises)
expect(successes).to.equal(syncCount)
expect(events).to.equal(syncCount)
this.application.syncService.ut_endLatencySimulator()
this.application.sync.ut_endLatencySimulator()
})
it('retrieving new items should not mark them as dirty', async function () {
@@ -211,7 +211,7 @@ describe('online syncing', function () {
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
const promise = new Promise((resolve) => {
this.application.syncService.addEventObserver(async (event) => {
this.application.sync.addEventObserver(async (event) => {
if (event === SyncEvent.PaginatedSyncRequestCompleted) {
const note = this.application.items.findItem(originalNote.uuid)
if (note) {
@@ -226,22 +226,22 @@ describe('online syncing', function () {
})
it('allows saving of data after sign out', async function () {
expect(this.application.itemManager.getDisplayableItemsKeys().length).to.equal(1)
expect(this.application.items.getDisplayableItemsKeys().length).to.equal(1)
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
expect(this.application.itemManager.getDisplayableItemsKeys().length).to.equal(1)
expect(this.application.items.getDisplayableItemsKeys().length).to.equal(1)
const note = await Factory.createMappedNote(this.application)
this.expectedItemCount++
await this.application.mutator.setItemDirty(note)
await this.application.syncService.sync(syncOptions)
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
await this.application.sync.sync(syncOptions)
const rawPayloads = await this.application.storage.getAllRawPayloads()
const notePayload = noteObjectsFromObjects(rawPayloads)
expect(notePayload.length).to.equal(1)
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
// set item to be merged for when sign in occurs
await this.application.syncService.markAllItemsAsNeedingSyncAndPersist()
expect(this.application.syncService.isOutOfSync()).to.equal(false)
expect(this.application.itemManager.getDirtyItems().length).to.equal(BaseItemCounts.DefaultItems + 1)
await this.application.sync.markAllItemsAsNeedingSyncAndPersist()
expect(this.application.sync.isOutOfSync()).to.equal(false)
expect(this.application.items.getDirtyItems().length).to.equal(BaseItemCounts.DefaultItems + 1)
// Sign back in for next tests
await Factory.loginToApplication({
@@ -250,16 +250,16 @@ describe('online syncing', function () {
password: this.password,
})
expect(this.application.itemManager.getDirtyItems().length).to.equal(0)
expect(this.application.itemManager.getDisplayableItemsKeys().length).to.equal(1)
expect(this.application.syncService.isOutOfSync()).to.equal(false)
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDirtyItems().length).to.equal(0)
expect(this.application.items.getDisplayableItemsKeys().length).to.equal(1)
expect(this.application.sync.isOutOfSync()).to.equal(false)
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
for (const item of this.application.itemManager.getDisplayableNotes()) {
for (const item of this.application.items.getDisplayableNotes()) {
expect(item.content.title).to.be.ok
}
const updatedRawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const updatedRawPayloads = await this.application.storage.getAllRawPayloads()
for (const payload of updatedRawPayloads) {
// if an item comes back from the server, it is saved to disk immediately without a dirty value.
expect(payload.dirty).to.not.be.ok
@@ -274,10 +274,10 @@ describe('online syncing', function () {
const originalTitle = note.content.title
await this.application.mutator.setItemDirty(note)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
const encrypted = CreateEncryptedServerSyncPushPayload(
await this.application.encryptionService.encryptSplitSingle({
await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [note.payloadRepresentation()],
},
@@ -291,11 +291,11 @@ describe('online syncing', function () {
const items = await this.application.mutator.emitItemsFromPayloads([errorred], PayloadEmitSource.LocalChanged)
const mappedItem = this.application.itemManager.findAnyItem(errorred.uuid)
const mappedItem = this.application.items.findAnyItem(errorred.uuid)
expect(typeof mappedItem.content).to.equal('string')
const decryptedPayload = await this.application.encryptionService.decryptSplitSingle({
const decryptedPayload = await this.application.encryption.decryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [errorred],
},
@@ -319,7 +319,7 @@ describe('online syncing', function () {
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
await this.application.signIn(this.email, this.password, undefined, undefined, undefined, true)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
})
it('removes item from storage upon deletion', async function () {
@@ -327,41 +327,41 @@ describe('online syncing', function () {
this.expectedItemCount++
await this.application.mutator.setItemDirty(note)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
note = this.application.items.findItem(note.uuid)
expect(note.dirty).to.equal(false)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
await this.application.mutator.setItemToBeDeleted(note)
note = this.application.items.findAnyItem(note.uuid)
expect(note.dirty).to.equal(true)
this.expectedItemCount--
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
note = this.application.items.findItem(note.uuid)
expect(note).to.not.be.ok
// We expect that this item is now gone for good, and no duplicate has been created.
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
await Factory.sleep(0.5)
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
expect(rawPayloads.length).to.equal(this.expectedItemCount)
})
it('retrieving item with no content should correctly map local state', async function () {
const note = await Factory.createMappedNote(this.application)
await this.application.mutator.setItemDirty(note)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
const syncToken = await this.application.syncService.getLastSyncToken()
const syncToken = await this.application.sync.getLastSyncToken()
this.expectedItemCount++
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
// client A
await this.application.mutator.setItemToBeDeleted(note)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
// Subtract 1
this.expectedItemCount--
@@ -369,10 +369,10 @@ describe('online syncing', function () {
// client B
// Clearing sync tokens wont work as server wont return deleted items.
// Set saved sync token instead
await this.application.syncService.setLastSyncToken(syncToken)
await this.application.syncService.sync(syncOptions)
await this.application.sync.setLastSyncToken(syncToken)
await this.application.sync.sync(syncOptions)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
})
it('changing an item while it is being synced should sync again', async function () {
@@ -381,7 +381,7 @@ describe('online syncing', function () {
this.expectedItemCount++
/** Begin syncing it with server but introduce latency so we can sneak in a delete */
this.application.syncService.ut_beginLatencySimulator(500)
this.application.sync.ut_beginLatencySimulator(500)
const sync = this.application.sync.sync()
@@ -395,11 +395,11 @@ describe('online syncing', function () {
await sync
this.application.syncService.ut_endLatencySimulator()
this.application.sync.ut_endLatencySimulator()
await this.application.sync.sync(syncOptions)
const latestNote = this.application.itemManager.findItem(note.uuid)
const latestNote = this.application.items.findItem(note.uuid)
expect(latestNote.title).to.equal('latest title')
})
@@ -409,7 +409,7 @@ describe('online syncing', function () {
this.expectedItemCount++
/** Begin syncing it with server but introduce latency so we can sneak in a delete */
this.application.syncService.ut_beginLatencySimulator(500)
this.application.sync.ut_beginLatencySimulator(500)
const sync = this.application.sync.sync()
@@ -423,12 +423,12 @@ describe('online syncing', function () {
await sync
this.application.syncService.ut_endLatencySimulator()
this.application.sync.ut_endLatencySimulator()
await this.application.sync.sync(syncOptions)
/** We expect that item has been deleted */
const allItems = this.application.itemManager.items
const allItems = this.application.items.items
expect(allItems.length).to.equal(this.expectedItemCount)
})
@@ -440,7 +440,7 @@ describe('online syncing', function () {
let success = true
let didCompleteRelevantSync = false
let beginCheckingResponse = false
this.application.syncService.addEventObserver((eventName, data) => {
this.application.sync.addEventObserver((eventName, data) => {
if (eventName === SyncEvent.DownloadFirstSyncCompleted) {
beginCheckingResponse = true
}
@@ -456,7 +456,7 @@ describe('online syncing', function () {
}
}
})
await this.application.syncService.sync({ mode: SyncMode.DownloadFirst })
await this.application.sync.sync({ mode: SyncMode.DownloadFirst })
expect(didCompleteRelevantSync).to.equal(true)
expect(success).to.equal(true)
})
@@ -469,7 +469,7 @@ describe('online syncing', function () {
let success = true
let didCompleteRelevantSync = false
let beginCheckingResponse = false
this.application.syncService.addEventObserver(async (eventName, data) => {
this.application.sync.addEventObserver(async (eventName, data) => {
if (eventName === SyncEvent.DownloadFirstSyncCompleted) {
await this.application.mutator.setItemToBeDeleted(note)
beginCheckingResponse = true
@@ -486,7 +486,7 @@ describe('online syncing', function () {
}
}
})
await this.application.syncService.sync({ mode: SyncMode.DownloadFirst })
await this.application.sync.sync({ mode: SyncMode.DownloadFirst })
expect(didCompleteRelevantSync).to.equal(true)
expect(success).to.equal(true)
})
@@ -496,16 +496,16 @@ describe('online syncing', function () {
this.expectedItemCount++
await this.application.syncService.markAllItemsAsNeedingSyncAndPersist()
await this.application.sync.markAllItemsAsNeedingSyncAndPersist()
this.application.itemManager.resetState()
this.application.payloadManager.resetState()
this.application.items.resetState()
this.application.payloads.resetState()
await this.application.syncService.clearSyncPositionTokens()
await this.application.sync.clearSyncPositionTokens()
expect(this.application.itemManager.items.length).to.equal(0)
expect(this.application.items.items.length).to.equal(0)
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
const encryptedPayloads = rawPayloads.map((rawPayload) => {
return new EncryptedPayload(rawPayload)
@@ -515,17 +515,17 @@ describe('online syncing', function () {
const keyedSplit = CreateDecryptionSplitWithKeyLookup(encryptionSplit)
const decryptionResults = await this.application.encryptionService.decryptSplit(keyedSplit)
const decryptionResults = await this.application.encryption.decryptSplit(keyedSplit)
await this.application.mutator.emitItemsFromPayloads(decryptionResults, PayloadEmitSource.LocalChanged)
expect(this.application.itemManager.allTrackedItems().length).to.equal(this.expectedItemCount)
expect(this.application.items.allTrackedItems().length).to.equal(this.expectedItemCount)
const foundNote = this.application.itemManager.findAnyItem(note.uuid)
const foundNote = this.application.items.findAnyItem(note.uuid)
expect(foundNote.dirty).to.equal(true)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
})
/** Temporarily skipping due to long run time */
@@ -538,8 +538,8 @@ describe('online syncing', function () {
this.expectedItemCount += largeItemCount
await this.application.syncService.sync(syncOptions)
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
await this.application.sync.sync(syncOptions)
const rawPayloads = await this.application.storage.getAllRawPayloads()
expect(rawPayloads.length).to.equal(this.expectedItemCount)
}).timeout(15000)
@@ -551,32 +551,32 @@ describe('online syncing', function () {
await this.application.mutator.setItemDirty(note)
}
/** Upload */
this.application.syncService.sync({ awaitAll: true, checkIntegrity: false })
this.application.sync.sync({ awaitAll: true, checkIntegrity: false })
await this.context.awaitNextSucessfulSync()
this.expectedItemCount += largeItemCount
/** Clear local data */
await this.application.payloadManager.resetState()
await this.application.itemManager.resetState()
await this.application.syncService.clearSyncPositionTokens()
await this.application.diskStorageService.clearAllPayloads()
expect(this.application.itemManager.items.length).to.equal(0)
await this.application.payloads.resetState()
await this.application.items.resetState()
await this.application.sync.clearSyncPositionTokens()
await this.application.storage.clearAllPayloads()
expect(this.application.items.items.length).to.equal(0)
/** Download all data */
this.application.syncService.sync(syncOptions)
this.application.sync.sync(syncOptions)
await this.context.awaitNextSucessfulSync()
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
expect(rawPayloads.length).to.equal(this.expectedItemCount)
}).timeout(30000)
it('syncing an item should storage it encrypted', async function () {
const note = await Factory.createMappedNote(this.application)
await this.application.mutator.setItemDirty(note)
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
this.expectedItemCount++
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
const notePayload = rawPayloads.find((p) => p.content_type === ContentType.TYPES.Note)
expect(typeof notePayload.content).to.equal('string')
})
@@ -587,12 +587,12 @@ describe('online syncing', function () {
this.expectedItemCount++
/** Simulate database not loaded */
await this.application.syncService.clearSyncPositionTokens()
this.application.syncService.ut_setDatabaseLoaded(false)
this.application.syncService.sync(syncOptions)
await this.application.sync.clearSyncPositionTokens()
this.application.sync.ut_setDatabaseLoaded(false)
this.application.sync.sync(syncOptions)
await Factory.sleep(0.3)
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
const notePayload = rawPayloads.find((p) => p.content_type === ContentType.TYPES.Note)
expect(typeof notePayload.content).to.equal('string')
})
@@ -610,18 +610,18 @@ describe('online syncing', function () {
syncOptions,
)
this.expectedItemCount++
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
const notePayload = rawPayloads.find((p) => p.content_type === ContentType.TYPES.Note)
expect(typeof notePayload.content).to.equal('string')
expect(notePayload.content.length).to.be.above(text.length)
})
it('syncing a new item before local data has loaded should still persist the item to disk', async function () {
this.application.syncService.ut_setDatabaseLoaded(false)
this.application.sync.ut_setDatabaseLoaded(false)
/** You don't want to clear model manager state as we'll lose encrypting items key */
// await this.application.payloadManager.resetState();
await this.application.syncService.clearSyncPositionTokens()
expect(this.application.itemManager.getDirtyItems().length).to.equal(0)
// await this.application.payloads.resetState();
await this.application.sync.clearSyncPositionTokens()
expect(this.application.items.getDirtyItems().length).to.equal(0)
let note = await Factory.createMappedNote(this.application)
note = await this.application.mutator.changeItem(note, (mutator) => {
@@ -629,15 +629,15 @@ describe('online syncing', function () {
})
/** This sync request should exit prematurely as we called ut_setDatabaseNotLoaded */
/** Do not await. Sleep instead. */
this.application.syncService.sync(syncOptions)
this.application.sync.sync(syncOptions)
await Factory.sleep(0.3)
this.expectedItemCount++
/** Item should still be dirty */
expect(note.dirty).to.equal(true)
expect(this.application.itemManager.getDirtyItems().length).to.equal(1)
expect(this.application.items.getDirtyItems().length).to.equal(1)
const rawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await this.application.storage.getAllRawPayloads()
expect(rawPayloads.length).to.equal(this.expectedItemCount)
const rawPayload = rawPayloads.find((p) => p.uuid === note.uuid)
expect(rawPayload.uuid).to.equal(note.uuid)
@@ -645,16 +645,16 @@ describe('online syncing', function () {
expect(typeof rawPayload.content).to.equal('string')
/** Clear state data and upload item from storage to server */
await this.application.syncService.clearSyncPositionTokens()
await this.application.payloadManager.resetState()
await this.application.itemManager.resetState()
await this.application.syncService.loadDatabasePayloads()
await this.application.syncService.sync(syncOptions)
await this.application.sync.clearSyncPositionTokens()
await this.application.payloads.resetState()
await this.application.items.resetState()
await this.application.sync.loadDatabasePayloads()
await this.application.sync.sync(syncOptions)
const newRawPayloads = await this.application.diskStorageService.getAllRawPayloads()
const newRawPayloads = await this.application.storage.getAllRawPayloads()
expect(newRawPayloads.length).to.equal(this.expectedItemCount)
const currentItem = this.application.itemManager.findItem(note.uuid)
const currentItem = this.application.items.findItem(note.uuid)
expect(currentItem.content.text).to.equal(note.content.text)
expect(currentItem.text).to.equal(note.text)
expect(currentItem.dirty).to.not.be.ok
@@ -680,16 +680,16 @@ describe('online syncing', function () {
const largeItemCount = 50
await Factory.createManyMappedNotes(this.application, largeItemCount)
this.expectedItemCount += largeItemCount
await this.application.syncService.sync(syncOptions)
await this.application.sync.sync(syncOptions)
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
await this.application.signIn(this.email, this.password, undefined, undefined, undefined, true)
this.application.syncService.ut_setDatabaseLoaded(false)
await this.application.syncService.loadDatabasePayloads()
await this.application.syncService.sync(syncOptions)
this.application.sync.ut_setDatabaseLoaded(false)
await this.application.sync.loadDatabasePayloads()
await this.application.sync.sync(syncOptions)
const items = await this.application.itemManager.items
const items = await this.application.items.items
expect(items.length).to.equal(this.expectedItemCount)
}).timeout(20000)
@@ -717,7 +717,7 @@ describe('online syncing', function () {
it('syncing twice without waiting should only execute 1 online sync', async function () {
const expectedEvents = 1
let actualEvents = 0
this.application.syncService.addEventObserver((event, data) => {
this.application.sync.addEventObserver((event, data) => {
if (event === SyncEvent.SyncCompletedWithAllItemsUploaded && data.source === SyncSource.External) {
actualEvents++
}
@@ -742,8 +742,8 @@ describe('online syncing', function () {
this.expectedItemCount++
// client A. Don't await, we want to do other stuff.
this.application.syncService.ut_beginLatencySimulator(1500)
const slowSync = this.application.syncService.sync(syncOptions)
this.application.sync.ut_beginLatencySimulator(1500)
const slowSync = this.application.sync.sync(syncOptions)
await Factory.sleep(0.1)
expect(note.dirty).to.equal(true)
@@ -758,8 +758,8 @@ describe('online syncing', function () {
expect(note.payload.dirtyIndex).to.be.above(note.payload.globalDirtyIndexAtLastSync)
// Now do a regular sync with no latency.
this.application.syncService.ut_endLatencySimulator()
const midSync = this.application.syncService.sync(syncOptions)
this.application.sync.ut_endLatencySimulator()
const midSync = this.application.sync.sync(syncOptions)
await slowSync
await midSync
@@ -770,14 +770,14 @@ describe('online syncing', function () {
expect(note.content.text).to.equal(text)
// client B
await this.application.payloadManager.resetState()
await this.application.itemManager.resetState()
await this.application.syncService.clearSyncPositionTokens()
await this.application.syncService.sync(syncOptions)
await this.application.payloads.resetState()
await this.application.items.resetState()
await this.application.sync.clearSyncPositionTokens()
await this.application.sync.sync(syncOptions)
// Expect that the server value and client value match, and no conflicts are created.
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
const foundItem = this.application.itemManager.findItem(note.uuid)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
const foundItem = this.application.items.findItem(note.uuid)
expect(foundItem.content.text).to.equal(text)
expect(foundItem.text).to.equal(text)
})
@@ -790,17 +790,17 @@ describe('online syncing', function () {
/** Create an item and sync it */
let note = await Factory.createMappedNote(this.application)
this.application.itemManager.addObserver(ContentType.TYPES.Note, ({ source }) => {
this.application.items.addObserver(ContentType.TYPES.Note, ({ source }) => {
if (source === PayloadEmitSource.RemoteSaved) {
actualSaveCount++
}
})
this.expectedItemCount++
this.application.syncService.ut_beginLatencySimulator(150)
this.application.sync.ut_beginLatencySimulator(150)
/** Dont await */
const syncRequest = this.application.syncService.sync(syncOptions)
const syncRequest = this.application.sync.sync(syncOptions)
/** Dirty the item 100ms into 150ms request */
const newText = `${Math.random()}`
@@ -837,7 +837,7 @@ describe('online syncing', function () {
/** Create an item and sync it */
let note = await Factory.createMappedNote(this.application)
this.application.itemManager.addObserver(ContentType.TYPES.Note, ({ source }) => {
this.application.items.addObserver(ContentType.TYPES.Note, ({ source }) => {
if (source === PayloadEmitSource.RemoteSaved) {
actualSaveCount++
}
@@ -845,13 +845,13 @@ describe('online syncing', function () {
this.expectedItemCount++
/** Dont await */
const syncRequest = this.application.syncService.sync(syncOptions)
const syncRequest = this.application.sync.sync(syncOptions)
/** Dirty the item before lastSyncBegan is set */
let didPerformMutatation = false
const newText = `${Math.random()}`
this.application.syncService.addEventObserver(async (eventName) => {
this.application.sync.addEventObserver(async (eventName) => {
if (eventName === SyncEvent.SyncDidBeginProcessing && !didPerformMutatation) {
didPerformMutatation = true
await this.application.mutator.changeItem(note, (mutator) => {
@@ -876,7 +876,7 @@ describe('online syncing', function () {
let didPerformMutatation = false
const newText = `${Math.random()}`
this.application.itemManager.addObserver(ContentType.TYPES.Note, async ({ changed, source }) => {
this.application.items.addObserver(ContentType.TYPES.Note, async ({ changed, source }) => {
if (source === PayloadEmitSource.RemoteSaved) {
actualSaveCount++
} else if (source === PayloadEmitSource.PreSyncSave && !didPerformMutatation) {
@@ -895,7 +895,7 @@ describe('online syncing', function () {
this.expectedItemCount++
/** Dont await */
const syncRequest = this.application.syncService.sync(syncOptions)
const syncRequest = this.application.sync.sync(syncOptions)
await syncRequest
expect(actualSaveCount).to.equal(expectedSaveCount)
note = this.application.items.findItem(note.uuid)
@@ -904,12 +904,12 @@ describe('online syncing', function () {
it('retreiving a remote deleted item should succeed', async function () {
const note = await Factory.createSyncedNote(this.application)
const preDeleteSyncToken = await this.application.syncService.getLastSyncToken()
const preDeleteSyncToken = await this.application.sync.getLastSyncToken()
await this.application.mutator.deleteItem(note)
await this.application.sync.sync()
await this.application.syncService.setLastSyncToken(preDeleteSyncToken)
await this.application.sync.setLastSyncToken(preDeleteSyncToken)
await this.application.sync.sync(syncOptions)
expect(this.application.itemManager.items.length).to.equal(this.expectedItemCount)
expect(this.application.items.items.length).to.equal(this.expectedItemCount)
})
it('errored items should not be synced', async function () {
@@ -918,7 +918,7 @@ describe('online syncing', function () {
const lastSyncBegan = note.lastSyncBegan
const lastSyncEnd = note.lastSyncEnd
const encrypted = await this.application.encryptionService.encryptSplitSingle({
const encrypted = await this.application.encryption.encryptSplitSingle({
usesItemsKeyWithKeyLookup: {
items: [note.payload],
},
@@ -929,7 +929,7 @@ describe('online syncing', function () {
dirty: true,
})
await this.application.payloadManager.emitPayload(errored)
await this.application.payloads.emitPayload(errored)
await this.application.sync.sync(syncOptions)
const updatedNote = this.application.items.findAnyItem(note.uuid)
@@ -957,10 +957,10 @@ describe('online syncing', function () {
},
})
await this.application.syncService.handleSuccessServerResponse({ payloadsSavedOrSaving: [], options: {} }, response)
await this.application.sync.handleSuccessServerResponse({ payloadsSavedOrSaving: [], options: {} }, response)
expect(this.application.payloadManager.findOne(invalidPayload.uuid)).to.not.be.ok
expect(this.application.payloadManager.findOne(validPayload.uuid)).to.be.ok
expect(this.application.payloads.findOne(invalidPayload.uuid)).to.not.be.ok
expect(this.application.payloads.findOne(validPayload.uuid)).to.be.ok
})
it('retrieved items should have both updated_at and updated_at_timestamps', async function () {
@@ -996,13 +996,13 @@ describe('online syncing', function () {
it('should call onPresyncSave before sync begins', async function () {
const events = []
this.application.syncService.addEventObserver((event) => {
this.application.sync.addEventObserver((event) => {
if (event === SyncEvent.SyncDidBeginProcessing) {
events.push('sync-will-begin')
}
})
await this.application.syncService.sync({
await this.application.sync.sync({
onPresyncSave: () => {
events.push('on-presync-save')
},

View File

@@ -92,11 +92,11 @@ describe('upgrading', () => {
version: oldVersion,
})
expect((await this.application.encryptionService.rootKeyManager.getRootKeyWrapperKeyParams()).version).to.equal(
expect((await this.application.encryption.rootKeyManager.getRootKeyWrapperKeyParams()).version).to.equal(
oldVersion,
)
expect((await this.application.encryptionService.getRootKeyParams()).version).to.equal(oldVersion)
expect((await this.application.encryptionService.getRootKey()).keyVersion).to.equal(oldVersion)
expect((await this.application.encryption.getRootKeyParams()).version).to.equal(oldVersion)
expect((await this.application.encryption.getRootKey()).keyVersion).to.equal(oldVersion)
this.application.setLaunchCallback({
receiveChallenge: this.receiveChallenge,
@@ -104,15 +104,15 @@ describe('upgrading', () => {
const result = await this.application.upgradeProtocolVersion()
expect(result).to.deep.equal({ success: true })
const wrappedRootKey = await this.application.encryptionService.rootKeyManager.getWrappedRootKey()
const wrappedRootKey = await this.application.encryption.rootKeyManager.getWrappedRootKey()
const payload = new EncryptedPayload(wrappedRootKey)
expect(payload.version).to.equal(newVersion)
expect((await this.application.encryptionService.rootKeyManager.getRootKeyWrapperKeyParams()).version).to.equal(
expect((await this.application.encryption.rootKeyManager.getRootKeyWrapperKeyParams()).version).to.equal(
newVersion,
)
expect((await this.application.encryptionService.getRootKeyParams()).version).to.equal(newVersion)
expect((await this.application.encryptionService.getRootKey()).keyVersion).to.equal(newVersion)
expect((await this.application.encryption.getRootKeyParams()).version).to.equal(newVersion)
expect((await this.application.encryption.getRootKey()).keyVersion).to.equal(newVersion)
/**
* Immediately logging out ensures we don't rely on subsequent
@@ -120,8 +120,8 @@ describe('upgrading', () => {
*/
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
await this.application.signIn(this.email, this.password, undefined, undefined, undefined, true)
expect(this.application.itemManager.getDisplayableNotes().length).to.equal(1)
expect(this.application.payloadManager.invalidPayloads).to.be.empty
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
expect(this.application.payloads.invalidPayloads).to.be.empty
}).timeout(15000)
it('upgrading from 003 to 004 with passcode only then reiniting app should create valid state', async function () {
@@ -155,7 +155,7 @@ describe('upgrading', () => {
await appFirst.launch(true)
const result = await appFirst.upgradeProtocolVersion()
expect(result).to.deep.equal({ success: true })
expect(appFirst.payloadManager.invalidPayloads).to.be.empty
expect(appFirst.payloads.invalidPayloads).to.be.empty
await Factory.safeDeinit(appFirst)
/** Recreate the once more */
@@ -166,15 +166,15 @@ describe('upgrading', () => {
},
})
await appSecond.launch(true)
expect(appSecond.payloadManager.invalidPayloads).to.be.empty
expect(appSecond.payloads.invalidPayloads).to.be.empty
await Factory.safeDeinit(appSecond)
}).timeout(15000)
it('protocol version should be upgraded on password change', async function () {
/** Delete default items key that is created on launch */
const itemsKey = await this.application.encryptionService.getSureDefaultItemsKey()
const itemsKey = await this.application.encryption.getSureDefaultItemsKey()
await this.application.mutator.setItemToBeDeleted(itemsKey)
expect(Uuids(this.application.itemManager.getDisplayableItemsKeys()).includes(itemsKey.uuid)).to.equal(false)
expect(Uuids(this.application.items.getDisplayableItemsKeys()).includes(itemsKey.uuid)).to.equal(false)
Factory.createMappedNote(this.application)
@@ -186,10 +186,10 @@ describe('upgrading', () => {
version: ProtocolVersion.V003,
})
expect(this.application.itemManager.getDisplayableItemsKeys().length).to.equal(1)
expect(this.application.items.getDisplayableItemsKeys().length).to.equal(1)
expect((await this.application.encryptionService.getRootKeyParams()).version).to.equal(ProtocolVersion.V003)
expect((await this.application.encryptionService.getRootKey()).keyVersion).to.equal(ProtocolVersion.V003)
expect((await this.application.encryption.getRootKeyParams()).version).to.equal(ProtocolVersion.V003)
expect((await this.application.encryption.getRootKey()).keyVersion).to.equal(ProtocolVersion.V003)
/** Ensure note is encrypted with 003 */
const notePayloads = await Factory.getStoragePayloadsOfType(this.application, ContentType.TYPES.Note)
@@ -199,16 +199,16 @@ describe('upgrading', () => {
const { error } = await this.application.changePassword(this.password, 'foobarfoo')
expect(error).to.not.exist
const latestVersion = this.application.encryptionService.getLatestVersion()
expect((await this.application.encryptionService.getRootKeyParams()).version).to.equal(latestVersion)
expect((await this.application.encryptionService.getRootKey()).keyVersion).to.equal(latestVersion)
const latestVersion = this.application.encryption.getLatestVersion()
expect((await this.application.encryption.getRootKeyParams()).version).to.equal(latestVersion)
expect((await this.application.encryption.getRootKey()).keyVersion).to.equal(latestVersion)
const defaultItemsKey = await this.application.encryptionService.getSureDefaultItemsKey()
const defaultItemsKey = await this.application.encryption.getSureDefaultItemsKey()
expect(defaultItemsKey.keyVersion).to.equal(latestVersion)
/** After change, note should now be encrypted with latest protocol version */
const note = this.application.itemManager.getDisplayableNotes()[0]
const note = this.application.items.getDisplayableNotes()[0]
await Factory.markDirtyAndSyncItem(this.application, note)
const refreshedNotePayloads = await Factory.getStoragePayloadsOfType(this.application, ContentType.TYPES.Note)
@@ -243,44 +243,44 @@ describe('upgrading', () => {
})
it('rolls back the local protocol upgrade if syncing fails', async function () {
sinon.replace(this.application.syncService, 'sync', sinon.fake())
sinon.replace(this.application.sync, 'sync', sinon.fake())
this.application.setLaunchCallback({
receiveChallenge: this.receiveChallenge,
})
expect((await this.application.encryptionService.rootKeyManager.getRootKeyWrapperKeyParams()).version).to.equal(
expect((await this.application.encryption.rootKeyManager.getRootKeyWrapperKeyParams()).version).to.equal(
oldVersion,
)
const errors = await this.application.upgradeProtocolVersion()
expect(errors).to.not.be.empty
/** Ensure we're still on 003 */
expect((await this.application.encryptionService.rootKeyManager.getRootKeyWrapperKeyParams()).version).to.equal(
expect((await this.application.encryption.rootKeyManager.getRootKeyWrapperKeyParams()).version).to.equal(
oldVersion,
)
expect((await this.application.encryptionService.getRootKeyParams()).version).to.equal(oldVersion)
expect((await this.application.encryptionService.getRootKey()).keyVersion).to.equal(oldVersion)
expect((await this.application.encryptionService.getSureDefaultItemsKey()).keyVersion).to.equal(oldVersion)
expect((await this.application.encryption.getRootKeyParams()).version).to.equal(oldVersion)
expect((await this.application.encryption.getRootKey()).keyVersion).to.equal(oldVersion)
expect((await this.application.encryption.getSureDefaultItemsKey()).keyVersion).to.equal(oldVersion)
})
it('rolls back the local protocol upgrade if the server responds with an error', async function () {
sinon.replace(this.application.sessionManager, 'changeCredentials', () => [Error()])
sinon.replace(this.application.sessions, 'changeCredentials', () => [Error()])
this.application.setLaunchCallback({
receiveChallenge: this.receiveChallenge,
})
expect((await this.application.encryptionService.rootKeyManager.getRootKeyWrapperKeyParams()).version).to.equal(
expect((await this.application.encryption.rootKeyManager.getRootKeyWrapperKeyParams()).version).to.equal(
oldVersion,
)
const errors = await this.application.upgradeProtocolVersion()
expect(errors).to.not.be.empty
/** Ensure we're still on 003 */
expect((await this.application.encryptionService.rootKeyManager.getRootKeyWrapperKeyParams()).version).to.equal(
expect((await this.application.encryption.rootKeyManager.getRootKeyWrapperKeyParams()).version).to.equal(
oldVersion,
)
expect((await this.application.encryptionService.getRootKeyParams()).version).to.equal(oldVersion)
expect((await this.application.encryptionService.getRootKey()).keyVersion).to.equal(oldVersion)
expect((await this.application.encryptionService.getSureDefaultItemsKey()).keyVersion).to.equal(oldVersion)
expect((await this.application.encryption.getRootKeyParams()).version).to.equal(oldVersion)
expect((await this.application.encryption.getRootKey()).keyVersion).to.equal(oldVersion)
expect((await this.application.encryption.getSureDefaultItemsKey()).keyVersion).to.equal(oldVersion)
})
})
})

View File

@@ -34,10 +34,14 @@ describe('asymmetric messages', function () {
const { contactContext, deinitContactContext } = await Collaboration.createSharedVaultWithAcceptedInvite(context)
const eventData = {
oldKeyPair: context.encryption.getKeyPair(),
oldSigningKeyPair: context.encryption.getSigningKeyPair(),
newKeyPair: context.encryption.getKeyPair(),
newSigningKeyPair: context.encryption.getSigningKeyPair(),
current: {
encryption: context.encryption.getKeyPair(),
signing: context.encryption.getSigningKeyPair(),
},
previous: {
encryption: context.encryption.getKeyPair(),
signing: context.encryption.getSigningKeyPair(),
},
}
await service.sendOwnContactChangeEventToAllContacts(eventData)
@@ -92,6 +96,38 @@ describe('asymmetric messages', function () {
await deinitThirdPartyContext()
})
it('should send contact share message when a member is added to a vault', async () => {
const { sharedVault, contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
const handleInitialContactShareMessage = contactContext.resolveWhenAsymmetricMessageProcessingCompletes()
const { thirdPartyContext, deinitThirdPartyContext } = await Collaboration.inviteNewPartyToSharedVault(
context,
sharedVault,
)
await Collaboration.acceptAllInvites(thirdPartyContext)
const firstPartySpy = sinon.spy(context.asymmetric, 'handleTrustedContactShareMessage')
const secondPartySpy = sinon.spy(contactContext.asymmetric, 'handleTrustedContactShareMessage')
const thirdPartySpy = sinon.spy(thirdPartyContext.asymmetric, 'handleTrustedContactShareMessage')
await contactContext.sync()
await handleInitialContactShareMessage
await context.sync()
await contactContext.sync()
await thirdPartyContext.sync()
expect(firstPartySpy.callCount).to.equal(0)
expect(secondPartySpy.callCount).to.equal(1)
expect(thirdPartySpy.callCount).to.equal(0)
await deinitThirdPartyContext()
await deinitContactContext()
})
it('should not send contact share message to self or to contact who is changed', async () => {
const { sharedVault, contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
@@ -100,12 +136,10 @@ describe('asymmetric messages', function () {
context,
sharedVault,
)
const handleInitialContactShareMessage = contactContext.resolveWhenAsymmetricMessageProcessingCompletes()
await Collaboration.acceptAllInvites(thirdPartyContext)
await contactContext.sync()
await handleInitialContactShareMessage
const sendContactSharePromise = context.resolveWhenSharedVaultServiceSendsContactShareMessage()
@@ -161,8 +195,8 @@ describe('asymmetric messages', function () {
description: 'New Description',
})
const firstPartySpy = sinon.spy(context.asymmetric, 'handleVaultMetadataChangedMessage')
const secondPartySpy = sinon.spy(contactContext.asymmetric, 'handleVaultMetadataChangedMessage')
const firstPartySpy = sinon.spy(context.asymmetric, 'handleTrustedVaultMetadataChangedMessage')
const secondPartySpy = sinon.spy(contactContext.asymmetric, 'handleTrustedVaultMetadataChangedMessage')
await context.sync()
await contactContext.sync()
@@ -201,6 +235,61 @@ describe('asymmetric messages', function () {
await deinitContactContext()
})
it('should trust and process messages sent after sender keypair changed', async () => {
const { sharedVault, contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
await context.changePassword('new password')
await context.vaults.changeVaultNameAndDescription(sharedVault, {
name: 'New Name',
description: 'New Description',
})
const completedProcessingMessagesPromise = contactContext.resolveWhenAsymmetricMessageProcessingCompletes()
await contactContext.sync()
await completedProcessingMessagesPromise
const updatedVault = contactContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })
expect(updatedVault.name).to.equal('New Name')
expect(updatedVault.description).to.equal('New Description')
await deinitContactContext()
})
it('should not send back a vault change message after receiving a vault change message', async () => {
/**
* If userA receives a vault change message and mutates their vault locally, this should not create a
* chain of vault change messages that then ping-pongs back and forth between the two users.
*/
const { sharedVault, contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
await context.changePassword('new password')
await context.vaults.changeVaultNameAndDescription(sharedVault, {
name: 'New Name',
description: 'New Description',
})
context.lockSyncing()
const completedProcessingMessagesPromise = contactContext.resolveWhenAsymmetricMessageProcessingCompletes()
await contactContext.sync()
await completedProcessingMessagesPromise
/**
* There's really no good way to await the exact call since
* the relevant part fires in the SharedVaultSerivce item observer
*/
await context.sleep(0.25)
const messages = await context.asymmetric.getInboundMessages()
expect(messages.length).to.equal(0)
await deinitContactContext()
})
it('should process sender keypair changed message', async () => {
const { contactContext, deinitContactContext } = await Collaboration.createContactContext()
await Collaboration.createTrustedContactForUserOfContext(context, contactContext)
@@ -272,6 +361,28 @@ describe('asymmetric messages', function () {
it('should delete all inbound messages after changing user password', async () => {
/** Messages to user are encrypted with old keypair and are no longer decryptable */
console.error('TODO: implement test')
const { sharedVault, contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
contactContext.lockSyncing()
await context.vaults.changeVaultNameAndDescription(sharedVault, {
name: 'New Name',
description: 'New Description',
})
const promise = contactContext.resolveWhenAllInboundAsymmetricMessagesAreDeleted()
await contactContext.changePassword('new-password')
await promise
const messages = await contactContext.asymmetric.getInboundMessages()
expect(messages.length).to.equal(0)
const updatedVault = contactContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })
expect(updatedVault.name).to.not.equal('New Name')
expect(updatedVault.description).to.not.equal('New Description')
await deinitContactContext()
})
})

View File

@@ -71,6 +71,18 @@ describe('contacts', function () {
expect(updatedSelfContact.publicKeySet.signing).to.equal(context.signingPublicKey)
})
it('should update self contact reference when changed', async () => {
const selfContact = context.contacts.getSelfContact()
await context.mutator.changeItem(selfContact, (mutator) => {
mutator.name = 'New Name'
})
const updatedSelfContact = context.contacts.getSelfContact()
expect(updatedSelfContact.name).to.equal('New Name')
})
it('should not be able to delete self contact', async () => {
const selfContact = context.contacts.getSelfContact()
@@ -80,4 +92,8 @@ describe('contacts', function () {
it('should not be able to delete a trusted contact if it belongs to a vault I administer', async () => {
console.error('TODO: implement test')
})
it('should be able to refresh a contact using a collaborationID that includes full chain of previouos public keys', async () => {
console.error('TODO: implement test')
})
})

View File

@@ -50,9 +50,10 @@ describe('shared vault crypto', function () {
await Collaboration.createSharedVaultWithAcceptedInviteAndNote(context)
await contactContext.changeNoteTitleAndSync(note, 'new title')
await context.sync()
const rawPayloads = await context.application.diskStorageService.getAllRawPayloads()
const rawPayloads = await context.application.storage.getAllRawPayloads()
const noteRawPayload = rawPayloads.find((payload) => payload.uuid === note.uuid)
expect(noteRawPayload.signatureData).to.not.be.undefined
@@ -166,11 +167,13 @@ describe('shared vault crypto', function () {
const { note, contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithAcceptedInviteAndNote(context)
expect(context.contacts.isItemAuthenticallySigned(note)).to.equal('not-applicable')
expect(context.contacts.isItemAuthenticallySigned(note)).to.equal(ItemSignatureValidationResult.NotApplicable)
const contactNote = contactContext.items.findItem(note.uuid)
expect(contactContext.contacts.isItemAuthenticallySigned(contactNote)).to.equal('yes')
expect(contactContext.contacts.isItemAuthenticallySigned(contactNote)).to.equal(
ItemSignatureValidationResult.Trusted,
)
await contactContext.changeNoteTitleAndSync(contactNote, 'new title')
@@ -178,27 +181,9 @@ describe('shared vault crypto', function () {
let updatedNote = context.items.findItem(note.uuid)
expect(context.contacts.isItemAuthenticallySigned(updatedNote)).to.equal('yes')
expect(context.contacts.isItemAuthenticallySigned(updatedNote)).to.equal(ItemSignatureValidationResult.Trusted)
await deinitContactContext()
})
})
describe('keypair revocation', () => {
it('should be able to revoke non-current keypair', async () => {
console.error('TODO')
})
it('revoking a keypair should send a keypair revocation event to trusted contacts', async () => {
console.error('TODO')
})
it('should not be able to revoke current key pair', async () => {
console.error('TODO')
})
it('should distrust revoked keypair as contact', async () => {
console.error('TODO')
})
})
})

View File

@@ -30,7 +30,9 @@ describe('shared vault invites', function () {
const { contactContext, deinitContactContext } = await Collaboration.createContactContext()
const contact = await Collaboration.createTrustedContactForUserOfContext(context, contactContext)
const vaultInvite = await sharedVaults.inviteContactToSharedVault(sharedVault, contact, SharedVaultPermission.Write)
const vaultInvite = (
await sharedVaults.inviteContactToSharedVault(sharedVault, contact, SharedVaultPermission.Write)
).getValue()
expect(vaultInvite).to.not.be.undefined
expect(vaultInvite.shared_vault_uuid).to.equal(sharedVault.sharing.sharedVaultUuid)
@@ -78,8 +80,10 @@ describe('shared vault invites', function () {
const message = invites[0].message
const delegatedContacts = message.data.trustedContacts
expect(delegatedContacts.length).to.equal(1)
expect(delegatedContacts[0].contactUuid).to.equal(contactContext.userUuid)
expect(delegatedContacts.length).to.equal(2)
expect(delegatedContacts.some((contact) => contact.contactUuid === context.userUuid)).to.be.true
expect(delegatedContacts.some((contact) => contact.contactUuid === contactContext.userUuid)).to.be.true
await deinitThirdPartyContext()
await deinitContactContext()
@@ -197,7 +201,17 @@ describe('shared vault invites', function () {
it('should delete all inbound invites after changing user password', async () => {
/** Invites to user are encrypted with old keypair and are no longer decryptable */
console.error('TODO: implement test')
const { contactContext, deinitContactContext } =
await Collaboration.createSharedVaultWithUnacceptedButTrustedInvite(context)
const promise = contactContext.resolveWhenAllInboundSharedVaultInvitesAreDeleted()
await contactContext.changePassword('new-password')
await promise
const invites = await contactContext.sharedVaults.downloadInboundInvites()
expect(invites.length).to.equal(0)
await deinitContactContext()
})
it('sharing a vault with user inputted and ephemeral password should share the key as synced for the recipient', async () => {

View File

@@ -34,7 +34,7 @@ describe('shared vault key rotation', function () {
contactContext.lockSyncing()
const spy = sinon.spy(context.encryption, 'reencryptKeySystemItemsKeysForVault')
const spy = sinon.spy(context.keys, 'reencryptKeySystemItemsKeysForVault')
const promise = context.resolveWhenSharedVaultKeyRotationInvitesGetSent(sharedVault)
await vaults.rotateVaultRootKey(sharedVault)

View File

@@ -0,0 +1,41 @@
import * as Factory from '../lib/factory.js'
import * as Collaboration from '../lib/Collaboration.js'
chai.use(chaiAsPromised)
const expect = chai.expect
describe('keypair change', function () {
this.timeout(Factory.TwentySecondTimeout)
let context
afterEach(async function () {
await context.deinit()
localStorage.clear()
})
beforeEach(async function () {
localStorage.clear()
context = await Factory.createAppContextWithRealCrypto()
await context.launch()
await context.register()
})
it('contacts should be able to handle receiving multiple keypair changed messages and trust them in order', async () => {
console.error('TODO: implement test')
})
it('should not trust messages sent with previous key pair', async () => {
console.error('TODO: implement test')
})
it('should reupload invites after rotating keypair', async () => {
console.error('TODO: implement test')
})
it('should reupload asymmetric messages after rotating keypair', async () => {
console.error('TODO: implement test')
})
})

View File

@@ -43,7 +43,7 @@ describe('shared vault permissions', function () {
SharedVaultPermission.Write,
)
expect(isClientDisplayableError(result)).to.be.true
expect(result.isFailed()).to.be.true
await deinitContactContext()
})

View File

@@ -63,15 +63,15 @@ describe('shared vaults', function () {
await promise
expect(contactContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })).to.be.undefined
expect(contactContext.encryption.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier)).to.be.undefined
expect(contactContext.encryption.keys.getKeySystemItemsKeys(sharedVault.systemIdentifier)).to.be.empty
expect(contactContext.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier)).to.be.undefined
expect(contactContext.keys.getKeySystemItemsKeys(sharedVault.systemIdentifier)).to.be.empty
const recreatedContext = await Factory.createAppContextWithRealCrypto(contactContext.identifier)
await recreatedContext.launch()
expect(recreatedContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })).to.be.undefined
expect(recreatedContext.encryption.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier)).to.be.undefined
expect(recreatedContext.encryption.keys.getKeySystemItemsKeys(sharedVault.systemIdentifier)).to.be.empty
expect(recreatedContext.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier)).to.be.undefined
expect(recreatedContext.keys.getKeySystemItemsKeys(sharedVault.systemIdentifier)).to.be.empty
await deinitContactContext()
await recreatedContext.deinit()
@@ -90,15 +90,15 @@ describe('shared vaults', function () {
await promise
expect(contactContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })).to.be.undefined
expect(contactContext.encryption.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier)).to.be.undefined
expect(contactContext.encryption.keys.getKeySystemItemsKeys(sharedVault.systemIdentifier)).to.be.empty
expect(contactContext.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier)).to.be.undefined
expect(contactContext.keys.getKeySystemItemsKeys(sharedVault.systemIdentifier)).to.be.empty
const recreatedContext = await Factory.createAppContextWithRealCrypto(contactContext.identifier)
await recreatedContext.launch()
expect(recreatedContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })).to.be.undefined
expect(recreatedContext.encryption.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier)).to.be.undefined
expect(recreatedContext.encryption.keys.getKeySystemItemsKeys(sharedVault.systemIdentifier)).to.be.empty
expect(recreatedContext.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier)).to.be.undefined
expect(recreatedContext.keys.getKeySystemItemsKeys(sharedVault.systemIdentifier)).to.be.empty
await deinitContactContext()
await recreatedContext.deinit()

View File

@@ -0,0 +1,33 @@
import * as Factory from '../lib/factory.js'
import * as Collaboration from '../lib/Collaboration.js'
chai.use(chaiAsPromised)
const expect = chai.expect
describe('signatures', function () {
this.timeout(Factory.TwentySecondTimeout)
let context
afterEach(async function () {
await context.deinit()
localStorage.clear()
})
beforeEach(async function () {
localStorage.clear()
context = await Factory.createAppContextWithRealCrypto()
await context.launch()
await context.register()
})
it('signatures should be marked as of questionable integrity when signed with non root contact public key', async () => {
console.error('TODO: implement test')
})
it('items marked with questionable integrity should have option to trust the item which would resync it', async () => {
console.error('TODO: implement test')
})
})