diff --git a/.yarn/cache/@standardnotes-domain-core-npm-1.25.0-51a2ed924b-f99196f620.zip b/.yarn/cache/@standardnotes-domain-core-npm-1.25.0-51a2ed924b-f99196f620.zip new file mode 100644 index 00000000000..aa20e6ae09b Binary files /dev/null and b/.yarn/cache/@standardnotes-domain-core-npm-1.25.0-51a2ed924b-f99196f620.zip differ diff --git a/packages/api/package.json b/packages/api/package.json index 17d59d117c7..76f037330c0 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -36,7 +36,7 @@ }, "dependencies": { "@standardnotes/common": "^1.50.0", - "@standardnotes/domain-core": "^1.24.0", + "@standardnotes/domain-core": "^1.25.0", "@standardnotes/models": "workspace:*", "@standardnotes/responses": "workspace:*", "@standardnotes/utils": "workspace:*", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 4ab062cb815..0db4bb802f7 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -35,7 +35,7 @@ }, "dependencies": { "@electron/remote": "^2.0.9", - "@standardnotes/domain-core": "^1.24.0", + "@standardnotes/domain-core": "^1.25.0", "@standardnotes/electron-clear-data": "1.1.1", "@standardnotes/web": "workspace:*", "axios": "^1.1.3", diff --git a/packages/encryption/package.json b/packages/encryption/package.json index 605cfe6836d..205d6ec6e3b 100644 --- a/packages/encryption/package.json +++ b/packages/encryption/package.json @@ -29,7 +29,7 @@ }, "dependencies": { "@standardnotes/common": "^1.50.0", - "@standardnotes/domain-core": "^1.24.0", + "@standardnotes/domain-core": "^1.25.0", "@standardnotes/models": "workspace:*", "@standardnotes/responses": "workspace:*", "@standardnotes/sncrypto-common": "workspace:*", diff --git a/packages/encryption/src/Domain/Keys/ItemsKey/ItemsKey.ts b/packages/encryption/src/Domain/Keys/ItemsKey/ItemsKey.ts index 73b0b9e78bd..0d08bf19817 100644 --- a/packages/encryption/src/Domain/Keys/ItemsKey/ItemsKey.ts +++ b/packages/encryption/src/Domain/Keys/ItemsKey/ItemsKey.ts @@ -1,4 +1,3 @@ -import { ProtocolVersion } from '@standardnotes/common' import { ContentType } from '@standardnotes/domain-core' import { ConflictStrategy, @@ -8,6 +7,7 @@ import { HistoryEntryInterface, ItemsKeyContent, ItemsKeyInterface, + ProtocolVersion, } from '@standardnotes/models' export function isItemsKey(x: unknown): x is ItemsKeyInterface { diff --git a/packages/encryption/src/Domain/Keys/KeySystemItemsKey/KeySystemItemsKey.ts b/packages/encryption/src/Domain/Keys/KeySystemItemsKey/KeySystemItemsKey.ts index 691218c96b5..359fc3fed4f 100644 --- a/packages/encryption/src/Domain/Keys/KeySystemItemsKey/KeySystemItemsKey.ts +++ b/packages/encryption/src/Domain/Keys/KeySystemItemsKey/KeySystemItemsKey.ts @@ -1,6 +1,6 @@ -import { ProtocolVersion } from '@standardnotes/common' import { ContentType } from '@standardnotes/domain-core' import { + ProtocolVersion, ConflictStrategy, DecryptedItem, DecryptedItemInterface, diff --git a/packages/encryption/src/Domain/Keys/RootKey/Functions.ts b/packages/encryption/src/Domain/Keys/RootKey/Functions.ts index c29ec1b4013..583e11cbfc5 100644 --- a/packages/encryption/src/Domain/Keys/RootKey/Functions.ts +++ b/packages/encryption/src/Domain/Keys/RootKey/Functions.ts @@ -1,5 +1,5 @@ -import { ProtocolVersion } from '@standardnotes/common' import { + ProtocolVersion, DecryptedPayload, FillItemContentSpecialized, PayloadTimestampDefaults, diff --git a/packages/encryption/src/Domain/Keys/RootKey/RootKey.ts b/packages/encryption/src/Domain/Keys/RootKey/RootKey.ts index 03e77431aba..473e31a87cd 100644 --- a/packages/encryption/src/Domain/Keys/RootKey/RootKey.ts +++ b/packages/encryption/src/Domain/Keys/RootKey/RootKey.ts @@ -1,5 +1,5 @@ -import { ProtocolVersion } from '@standardnotes/common' import { + ProtocolVersion, DecryptedItem, DecryptedPayloadInterface, NamespacedRootKeyInKeychain, diff --git a/packages/encryption/src/Domain/Operator/004/Operator004.spec.ts b/packages/encryption/src/Domain/Operator/004/Operator004.spec.ts index 083764c4bd3..a6fdcd89564 100644 --- a/packages/encryption/src/Domain/Operator/004/Operator004.spec.ts +++ b/packages/encryption/src/Domain/Operator/004/Operator004.spec.ts @@ -1,5 +1,10 @@ -import { ProtocolVersion } from '@standardnotes/common' -import { DecryptedPayload, ItemContent, ItemsKeyContent, PayloadTimestampDefaults } from '@standardnotes/models' +import { + DecryptedPayload, + ItemContent, + ItemsKeyContent, + PayloadTimestampDefaults, + ProtocolVersion, +} from '@standardnotes/models' import { SNItemsKey } from '../../Keys/ItemsKey/ItemsKey' import { SNProtocolOperator004 } from './Operator004' import { getMockedCrypto } from './MockedCrypto' diff --git a/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/CreateKeySystemItemsKey.ts b/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/CreateKeySystemItemsKey.ts index 594652e5eb0..dbe35020d02 100644 --- a/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/CreateKeySystemItemsKey.ts +++ b/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/CreateKeySystemItemsKey.ts @@ -7,10 +7,10 @@ import { KeySystemItemsKeyContentSpecialized, KeySystemItemsKeyInterface, PayloadTimestampDefaults, + ProtocolVersion, } from '@standardnotes/models' import { PureCryptoInterface } from '@standardnotes/sncrypto-common' import { V004Algorithm } from '../../../../Algorithm' -import { ProtocolVersion } from '@standardnotes/common' import { ContentType } from '@standardnotes/domain-core' export class CreateKeySystemItemsKeyUseCase { diff --git a/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/CreateRandomKeySystemRootKey.ts b/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/CreateRandomKeySystemRootKey.ts index 4c05181039b..54bedfcd5c7 100644 --- a/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/CreateRandomKeySystemRootKey.ts +++ b/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/CreateRandomKeySystemRootKey.ts @@ -4,8 +4,8 @@ import { KeySystemRootKeyInterface, KeySystemRootKeyParamsInterface, KeySystemPasswordType, + ProtocolVersion, } from '@standardnotes/models' -import { ProtocolVersion } from '@standardnotes/common' import { DeriveKeySystemRootKeyUseCase } from './DeriveKeySystemRootKey' export class CreateRandomKeySystemRootKey { diff --git a/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/CreateUserInputKeySystemRootKey.ts b/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/CreateUserInputKeySystemRootKey.ts index 818890c8a4e..fd4166448f7 100644 --- a/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/CreateUserInputKeySystemRootKey.ts +++ b/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/CreateUserInputKeySystemRootKey.ts @@ -5,8 +5,8 @@ import { KeySystemRootKeyInterface, KeySystemRootKeyParamsInterface, KeySystemPasswordType, + ProtocolVersion, } from '@standardnotes/models' -import { ProtocolVersion } from '@standardnotes/common' import { DeriveKeySystemRootKeyUseCase } from './DeriveKeySystemRootKey' export class CreateUserInputKeySystemRootKey { diff --git a/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/DeriveKeySystemRootKey.ts b/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/DeriveKeySystemRootKey.ts index d0aed46cb8c..54c9c034934 100644 --- a/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/DeriveKeySystemRootKey.ts +++ b/packages/encryption/src/Domain/Operator/004/UseCase/KeySystem/DeriveKeySystemRootKey.ts @@ -11,8 +11,8 @@ import { KeySystemRootKeyInterface, PayloadTimestampDefaults, KeySystemRootKeyParamsInterface, + ProtocolVersion, } from '@standardnotes/models' -import { ProtocolVersion } from '@standardnotes/common' import { ContentType } from '@standardnotes/domain-core' export class DeriveKeySystemRootKeyUseCase { diff --git a/packages/encryption/src/Domain/Operator/004/UseCase/RootKey/DeriveRootKey.ts b/packages/encryption/src/Domain/Operator/004/UseCase/RootKey/DeriveRootKey.ts index 57186d0afde..e3d74ea7247 100644 --- a/packages/encryption/src/Domain/Operator/004/UseCase/RootKey/DeriveRootKey.ts +++ b/packages/encryption/src/Domain/Operator/004/UseCase/RootKey/DeriveRootKey.ts @@ -2,10 +2,9 @@ import { PureCryptoInterface } from '@standardnotes/sncrypto-common' import { splitString, truncateHexString } from '@standardnotes/utils' import { V004PartitionCharacter } from '../../V004AlgorithmTypes' import { V004Algorithm } from '../../../../Algorithm' -import { RootKeyInterface } from '@standardnotes/models' +import { RootKeyInterface, ProtocolVersion } from '@standardnotes/models' import { SNRootKeyParams } from '../../../../Keys/RootKey/RootKeyParams' import { CreateNewRootKey } from '../../../../Keys/RootKey/Functions' -import { ProtocolVersion } from '@standardnotes/common' export class DeriveRootKeyUseCase { constructor(private readonly crypto: PureCryptoInterface) {} diff --git a/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateAuthenticatedData.ts b/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateAuthenticatedData.ts index 6f31e729073..14c8f072356 100644 --- a/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateAuthenticatedData.ts +++ b/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateAuthenticatedData.ts @@ -7,11 +7,11 @@ import { isKeySystemRootKey, ContentTypeUsesRootKeyEncryption, ContentTypeUsesKeySystemRootKeyEncryption, + ProtocolVersion, } from '@standardnotes/models' import { ItemAuthenticatedData } from '../../../../Types/ItemAuthenticatedData' import { RootKeyEncryptedAuthenticatedData } from '../../../../Types/RootKeyEncryptedAuthenticatedData' import { KeySystemItemsKeyAuthenticatedData } from '../../../../Types/KeySystemItemsKeyAuthenticatedData' -import { ProtocolVersion } from '@standardnotes/common' import { isItemsKey } from '../../../../Keys/ItemsKey/ItemsKey' import { isKeySystemItemsKey } from '../../../../Keys/KeySystemItemsKey/KeySystemItemsKey' diff --git a/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateEncryptedParameters.ts b/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateEncryptedParameters.ts index cbd2cce4708..cc5b3123ced 100644 --- a/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateEncryptedParameters.ts +++ b/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateEncryptedParameters.ts @@ -1,4 +1,3 @@ -import { ProtocolVersion } from '@standardnotes/common' import { PkcKeyPair, PureCryptoInterface } from '@standardnotes/sncrypto-common' import { DecryptedPayloadInterface, @@ -6,6 +5,7 @@ import { KeySystemItemsKeyInterface, KeySystemRootKeyInterface, RootKeyInterface, + ProtocolVersion, } from '@standardnotes/models' import { CreateConsistentBase64JsonPayloadUseCase } from '../Utils/CreateConsistentBase64JsonPayload' import { doesPayloadRequireSigning } from '../../V004AlgorithmHelpers' diff --git a/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateEncryptedProtocolString.spec.ts b/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateEncryptedProtocolString.spec.ts index 331cdaa04d6..e0180b4bdcb 100644 --- a/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateEncryptedProtocolString.spec.ts +++ b/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateEncryptedProtocolString.spec.ts @@ -1,6 +1,5 @@ -import { ProtocolVersion } from '@standardnotes/common' +import { ProtocolVersion } from '@standardnotes/models' import { PureCryptoInterface } from '@standardnotes/sncrypto-common' - import { ItemAuthenticatedData } from './../../../../Types/ItemAuthenticatedData' import { GenerateEncryptedProtocolStringUseCase } from './GenerateEncryptedProtocolString' import { AdditionalData } from '../../../../Types/EncryptionAdditionalData' diff --git a/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateEncryptedProtocolString.ts b/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateEncryptedProtocolString.ts index caca147fcb3..570bc32f033 100644 --- a/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateEncryptedProtocolString.ts +++ b/packages/encryption/src/Domain/Operator/004/UseCase/Symmetric/GenerateEncryptedProtocolString.ts @@ -1,6 +1,6 @@ import { Base64String, HexString, PureCryptoInterface, Utf8String } from '@standardnotes/sncrypto-common' import { V004PartitionCharacter, V004StringComponents } from '../../V004AlgorithmTypes' -import { ProtocolVersion } from '@standardnotes/common' +import { ProtocolVersion } from '@standardnotes/models' import { V004Algorithm } from '../../../../Algorithm' export class GenerateEncryptedProtocolStringUseCase { diff --git a/packages/encryption/src/Domain/Operator/EncryptionOperatorsInterface.ts b/packages/encryption/src/Domain/Operator/EncryptionOperatorsInterface.ts index 7123bb64c52..bb3e7172dda 100644 --- a/packages/encryption/src/Domain/Operator/EncryptionOperatorsInterface.ts +++ b/packages/encryption/src/Domain/Operator/EncryptionOperatorsInterface.ts @@ -1,4 +1,4 @@ -import { ProtocolVersion } from '@standardnotes/common' +import { ProtocolVersion } from '@standardnotes/models' import { AnyOperatorInterface } from './OperatorInterface/TypeCheck' export interface EncryptionOperatorsInterface { diff --git a/packages/encryption/src/Domain/Operator/Functions.ts b/packages/encryption/src/Domain/Operator/Functions.ts index d04186101d0..3228b48d5b4 100644 --- a/packages/encryption/src/Domain/Operator/Functions.ts +++ b/packages/encryption/src/Domain/Operator/Functions.ts @@ -1,4 +1,4 @@ -import { ProtocolVersion } from '@standardnotes/common' +import { ProtocolVersion } from '@standardnotes/models' import { PureCryptoInterface } from '@standardnotes/sncrypto-common' import { SNProtocolOperator001 } from '../Operator/001/Operator001' import { SNProtocolOperator002 } from '../Operator/002/Operator002' diff --git a/packages/encryption/src/Domain/Types/EncryptedParameters.ts b/packages/encryption/src/Domain/Types/EncryptedParameters.ts index 3a3ec53ed49..e6759c8c676 100644 --- a/packages/encryption/src/Domain/Types/EncryptedParameters.ts +++ b/packages/encryption/src/Domain/Types/EncryptedParameters.ts @@ -1,5 +1,9 @@ -import { ProtocolVersion } from '@standardnotes/common' -import { EncryptedPayloadInterface, DecryptedPayloadInterface, PersistentSignatureData } from '@standardnotes/models' +import { + EncryptedPayloadInterface, + DecryptedPayloadInterface, + PersistentSignatureData, + ProtocolVersion, +} from '@standardnotes/models' import { DecryptedParameters } from './DecryptedParameters' export type EncryptedOutputParameters = { diff --git a/packages/encryption/src/Domain/Types/ItemAuthenticatedData.ts b/packages/encryption/src/Domain/Types/ItemAuthenticatedData.ts index b9bf704f3af..7b5da2a03e0 100644 --- a/packages/encryption/src/Domain/Types/ItemAuthenticatedData.ts +++ b/packages/encryption/src/Domain/Types/ItemAuthenticatedData.ts @@ -1,4 +1,4 @@ -import { ProtocolVersion } from '@standardnotes/common' +import { ProtocolVersion } from '@standardnotes/models' type UserUuid = string type KeySystemIdentifier = string diff --git a/packages/features/package.json b/packages/features/package.json index a8a4a82f1ca..4d0b28b57d1 100644 --- a/packages/features/package.json +++ b/packages/features/package.json @@ -26,7 +26,7 @@ }, "dependencies": { "@standardnotes/common": "^1.50.0", - "@standardnotes/domain-core": "^1.24.0", + "@standardnotes/domain-core": "^1.25.0", "reflect-metadata": "^0.1.13" }, "devDependencies": { diff --git a/packages/models/package.json b/packages/models/package.json index 3e1452bd76b..62407b72a5a 100644 --- a/packages/models/package.json +++ b/packages/models/package.json @@ -23,7 +23,7 @@ }, "dependencies": { "@standardnotes/common": "^1.50.0", - "@standardnotes/domain-core": "^1.24.0", + "@standardnotes/domain-core": "^1.25.0", "@standardnotes/features": "workspace:*", "@standardnotes/responses": "workspace:*", "@standardnotes/sncrypto-common": "workspace:^", diff --git a/packages/models/src/Domain/Abstract/Contextual/FilteredServerItem.ts b/packages/models/src/Domain/Abstract/Contextual/FilteredServerItem.ts index 57c402664e2..187c3c36554 100644 --- a/packages/models/src/Domain/Abstract/Contextual/FilteredServerItem.ts +++ b/packages/models/src/Domain/Abstract/Contextual/FilteredServerItem.ts @@ -12,14 +12,38 @@ function CreateFilteredServerItem(item: ServerItemResponse): FilteredServerItem } } -export function FilterDisallowedRemotePayloadsAndMap(payloads: ServerItemResponse[]): FilteredServerItem[] { - return payloads.filter(isRemotePayloadAllowed).map(CreateFilteredServerItem) +export function FilterDisallowedRemotePayloadsAndMap(payloads: ServerItemResponse[]): { + filtered: FilteredServerItem[] + disallowed: ServerItemResponse[] +} { + const filtered = [] + const disallowed = [] + for (const payload of payloads) { + const result = checkRemotePayloadAllowed(payload) + if (result.allowed === undefined) { + disallowed.push(payload) + } else { + filtered.push(CreateFilteredServerItem(result.allowed)) + } + } + + return { + filtered, + disallowed, + } } -export function isRemotePayloadAllowed(payload: ServerItemResponse): boolean { +export function checkRemotePayloadAllowed(payload: ServerItemResponse): { + allowed?: ServerItemResponse + disallowed?: ServerItemResponse +} { if (isCorruptTransferPayload(payload)) { - return false + return { disallowed: payload } } - return isEncryptedTransferPayload(payload) || payload.content == undefined + if (isEncryptedTransferPayload(payload) || payload.content == undefined) { + return { allowed: payload } + } else { + return { disallowed: payload } + } } diff --git a/packages/models/src/Domain/Abstract/Item/Interfaces/EncryptedItem.ts b/packages/models/src/Domain/Abstract/Item/Interfaces/EncryptedItem.ts index 5c3c3071e96..62c9cbe2539 100644 --- a/packages/models/src/Domain/Abstract/Item/Interfaces/EncryptedItem.ts +++ b/packages/models/src/Domain/Abstract/Item/Interfaces/EncryptedItem.ts @@ -1,4 +1,4 @@ -import { ProtocolVersion } from '@standardnotes/common' +import { ProtocolVersion } from '../../../Local/Protocol/ProtocolVersion' import { EncryptedPayloadInterface } from '../../Payload/Interfaces/EncryptedPayload' import { ItemInterface } from './ItemInterface' diff --git a/packages/models/src/Domain/Abstract/Payload/Implementations/EncryptedPayload.ts b/packages/models/src/Domain/Abstract/Payload/Implementations/EncryptedPayload.ts index 1bf32260df8..09983335b7a 100644 --- a/packages/models/src/Domain/Abstract/Payload/Implementations/EncryptedPayload.ts +++ b/packages/models/src/Domain/Abstract/Payload/Implementations/EncryptedPayload.ts @@ -1,4 +1,5 @@ -import { ProtocolVersion, protocolVersionFromEncryptedString } from '@standardnotes/common' +import { ProtocolVersion } from '../../../Local/Protocol/ProtocolVersion' +import { ProtocolVersionFromEncryptedString } from '../../../Local/Protocol/ProtocolVersionFromEncryptedString' import { SyncResolvedParams, SyncResolvedPayload } from '../../../Runtime/Deltas/Utilities/SyncResolvedPayload' import { EncryptedTransferPayload } from '../../TransferPayload/Interfaces/EncryptedTransferPayload' import { EncryptedPayloadInterface } from '../Interfaces/EncryptedPayload' @@ -18,13 +19,18 @@ export class EncryptedPayload extends PurePayload impl constructor(rawPayload: EncryptedTransferPayload, source = PayloadSource.Constructor) { super(rawPayload, source) + const versionResult = ProtocolVersionFromEncryptedString(rawPayload.content) + if (versionResult.isFailed()) { + throw new Error('EncryptedPayload constructor versionResult is failed') + } + this.auth_hash = rawPayload.auth_hash this.content = rawPayload.content this.deleted = false this.enc_item_key = rawPayload.enc_item_key this.errorDecrypting = rawPayload.errorDecrypting this.items_key_id = rawPayload.items_key_id - this.version = protocolVersionFromEncryptedString(this.content) + this.version = versionResult.getValue() this.waitingForKey = rawPayload.waitingForKey } diff --git a/packages/models/src/Domain/Abstract/Payload/Interfaces/EncryptedPayload.ts b/packages/models/src/Domain/Abstract/Payload/Interfaces/EncryptedPayload.ts index 33c86621e62..0448a093b6f 100644 --- a/packages/models/src/Domain/Abstract/Payload/Interfaces/EncryptedPayload.ts +++ b/packages/models/src/Domain/Abstract/Payload/Interfaces/EncryptedPayload.ts @@ -1,4 +1,4 @@ -import { ProtocolVersion } from '@standardnotes/common' +import { ProtocolVersion } from '../../../Local/Protocol/ProtocolVersion' import { EncryptedTransferPayload } from '../../TransferPayload/Interfaces/EncryptedTransferPayload' import { PayloadInterface } from './PayloadInterface' diff --git a/packages/models/src/Domain/Abstract/TransferPayload/Interfaces/TypeCheck.spec.ts b/packages/models/src/Domain/Abstract/TransferPayload/Interfaces/TypeCheck.spec.ts index 9234b150a15..02f93e3dd30 100644 --- a/packages/models/src/Domain/Abstract/TransferPayload/Interfaces/TypeCheck.spec.ts +++ b/packages/models/src/Domain/Abstract/TransferPayload/Interfaces/TypeCheck.spec.ts @@ -42,7 +42,7 @@ describe('type check', () => { expect( isCorruptTransferPayload({ uuid: '123', - content_type: ContentType.TYPES.Unknown, + content_type: 'Unknown', content: '123', ...PayloadTimestampDefaults(), }), diff --git a/packages/models/src/Domain/Abstract/TransferPayload/Interfaces/TypeCheck.ts b/packages/models/src/Domain/Abstract/TransferPayload/Interfaces/TypeCheck.ts index 9466a6d9679..b8c96e1686f 100644 --- a/packages/models/src/Domain/Abstract/TransferPayload/Interfaces/TypeCheck.ts +++ b/packages/models/src/Domain/Abstract/TransferPayload/Interfaces/TypeCheck.ts @@ -26,5 +26,7 @@ export function isDeletedTransferPayload(payload: TransferPayload): payload is D export function isCorruptTransferPayload(payload: TransferPayload): boolean { const invalidDeletedState = payload.deleted === true && payload.content != undefined - return payload.uuid == undefined || invalidDeletedState || payload.content_type === ContentType.TYPES.Unknown + const contenTypeOrError = ContentType.create(payload.content_type) + + return payload.uuid == undefined || invalidDeletedState || contenTypeOrError.isFailed() } diff --git a/packages/models/src/Domain/Local/ApplicationIdentifier.ts b/packages/models/src/Domain/Local/ApplicationIdentifier.ts new file mode 100644 index 00000000000..20c51e9e31b --- /dev/null +++ b/packages/models/src/Domain/Local/ApplicationIdentifier.ts @@ -0,0 +1 @@ +export type ApplicationIdentifier = string diff --git a/packages/models/src/Domain/Local/KeyParams/KeySystemRootKeyParamsInterface.ts b/packages/models/src/Domain/Local/KeyParams/KeySystemRootKeyParamsInterface.ts index e8211d61ad4..5d0a985e466 100644 --- a/packages/models/src/Domain/Local/KeyParams/KeySystemRootKeyParamsInterface.ts +++ b/packages/models/src/Domain/Local/KeyParams/KeySystemRootKeyParamsInterface.ts @@ -1,5 +1,5 @@ -import { ProtocolVersion } from '@standardnotes/common' import { KeySystemIdentifier } from '../../Syncable/KeySystemRootKey/KeySystemIdentifier' +import { ProtocolVersion } from '../Protocol/ProtocolVersion' import { KeySystemPasswordType } from './KeySystemPasswordType' /** diff --git a/packages/models/src/Domain/Local/Protocol/ProtocolVersion.ts b/packages/models/src/Domain/Local/Protocol/ProtocolVersion.ts new file mode 100644 index 00000000000..58f40c0aabc --- /dev/null +++ b/packages/models/src/Domain/Local/Protocol/ProtocolVersion.ts @@ -0,0 +1,47 @@ +export enum ProtocolVersion { + V001 = '001', + V002 = '002', + V003 = '003', + V004 = '004', +} + +export const ProtocolVersionLatest = ProtocolVersion.V004 + +/** The last protocol version to not use root-key based items keys */ +export const ProtocolVersionLastNonrootItemsKey = ProtocolVersion.V003 + +export const ProtocolExpirationDates: Partial> = Object.freeze({ + [ProtocolVersion.V001]: Date.parse('2018-01-01'), + [ProtocolVersion.V002]: Date.parse('2020-01-01'), +}) + +export function isProtocolVersionExpired(version: ProtocolVersion) { + const expireDate = ProtocolExpirationDates[version] + if (!expireDate) { + return false + } + + const expired = new Date().getTime() > expireDate + return expired +} + +export const ProtocolVersionLength = 3 + +/** + * -1 if a < b + * 0 if a == b + * 1 if a > b + */ +export function compareVersions(a: ProtocolVersion, b: ProtocolVersion): number { + const aNum = Number(a) + const bNum = Number(b) + return aNum - bNum +} + +export function leftVersionGreaterThanOrEqualToRight(a: ProtocolVersion, b: ProtocolVersion): boolean { + return compareVersions(a, b) >= 0 +} + +export function isVersionLessThanOrEqualTo(input: ProtocolVersion, compareTo: ProtocolVersion): boolean { + return compareVersions(input, compareTo) <= 0 +} diff --git a/packages/models/src/Domain/Local/Protocol/ProtocolVersionFromEncryptedString.ts b/packages/models/src/Domain/Local/Protocol/ProtocolVersionFromEncryptedString.ts new file mode 100644 index 00000000000..1c77e8bc8ca --- /dev/null +++ b/packages/models/src/Domain/Local/Protocol/ProtocolVersionFromEncryptedString.ts @@ -0,0 +1,15 @@ +import { Result } from '@standardnotes/domain-core' +import { ProtocolVersion, ProtocolVersionLength } from './ProtocolVersion' + +export function ProtocolVersionFromEncryptedString(string: string): Result { + try { + const version = string.substring(0, ProtocolVersionLength) as ProtocolVersion + if (Object.values(ProtocolVersion).includes(version)) { + return Result.ok(version) + } + } catch (error) { + return Result.fail(JSON.stringify(error)) + } + + return Result.fail(`Invalid encrypted string ${string}`) +} diff --git a/packages/models/src/Domain/Local/RootKey/RootKeyInterface.ts b/packages/models/src/Domain/Local/RootKey/RootKeyInterface.ts index 58ab73b94a5..9655c7b631b 100644 --- a/packages/models/src/Domain/Local/RootKey/RootKeyInterface.ts +++ b/packages/models/src/Domain/Local/RootKey/RootKeyInterface.ts @@ -1,9 +1,9 @@ import { PkcKeyPair } from '@standardnotes/sncrypto-common' -import { ProtocolVersion } from '@standardnotes/common' import { DecryptedItemInterface } from '../../Abstract/Item/Interfaces/DecryptedItem' import { RootKeyParamsInterface } from '../KeyParams/RootKeyParamsInterface' import { NamespacedRootKeyInKeychain, RootKeyContentInStorage } from './KeychainTypes' import { RootKeyContent } from './RootKeyContent' +import { ProtocolVersion } from '../Protocol/ProtocolVersion' export interface RootKeyInterface extends DecryptedItemInterface { readonly keyParams: RootKeyParamsInterface diff --git a/packages/models/src/Domain/Runtime/AsymmetricMessage/MessageTypes/AsymmetricMessageSharedVaultInvite.ts b/packages/models/src/Domain/Runtime/AsymmetricMessage/MessageTypes/AsymmetricMessageSharedVaultInvite.ts index 9091dcdfba7..e459c277ee9 100644 --- a/packages/models/src/Domain/Runtime/AsymmetricMessage/MessageTypes/AsymmetricMessageSharedVaultInvite.ts +++ b/packages/models/src/Domain/Runtime/AsymmetricMessage/MessageTypes/AsymmetricMessageSharedVaultInvite.ts @@ -19,6 +19,7 @@ export type AsymmetricMessageSharedVaultInvite = { name: string description?: string iconString: IconType | EmojiString + fileBytesUsed: number } } } diff --git a/packages/models/src/Domain/Syncable/ItemsKey/ItemsKeyInterface.ts b/packages/models/src/Domain/Syncable/ItemsKey/ItemsKeyInterface.ts index 6271147e9a0..3104f4c1cfa 100644 --- a/packages/models/src/Domain/Syncable/ItemsKey/ItemsKeyInterface.ts +++ b/packages/models/src/Domain/Syncable/ItemsKey/ItemsKeyInterface.ts @@ -1,6 +1,6 @@ -import { ProtocolVersion } from '@standardnotes/common' import { DecryptedItemInterface } from './../../Abstract/Item/Interfaces/DecryptedItem' import { ItemContent, SpecializedContent } from '../../Abstract/Content/ItemContent' +import { ProtocolVersion } from '../../Local/Protocol/ProtocolVersion' export interface ItemsKeyContentSpecialized extends SpecializedContent { version: ProtocolVersion diff --git a/packages/models/src/Domain/Syncable/KeySystemItemsKey/KeySystemItemsKeyContent.ts b/packages/models/src/Domain/Syncable/KeySystemItemsKey/KeySystemItemsKeyContent.ts index 7fb19d50c9b..dbda3af83d0 100644 --- a/packages/models/src/Domain/Syncable/KeySystemItemsKey/KeySystemItemsKeyContent.ts +++ b/packages/models/src/Domain/Syncable/KeySystemItemsKey/KeySystemItemsKeyContent.ts @@ -1,5 +1,5 @@ -import { ProtocolVersion } from '@standardnotes/common' import { ItemContent, SpecializedContent } from '../../Abstract/Content/ItemContent' +import { ProtocolVersion } from '../../Local/Protocol/ProtocolVersion' export interface KeySystemItemsKeyContentSpecialized extends SpecializedContent { version: ProtocolVersion diff --git a/packages/models/src/Domain/Syncable/KeySystemItemsKey/KeySystemItemsKeyInterface.ts b/packages/models/src/Domain/Syncable/KeySystemItemsKey/KeySystemItemsKeyInterface.ts index 46d7c23e2af..9781a7e5027 100644 --- a/packages/models/src/Domain/Syncable/KeySystemItemsKey/KeySystemItemsKeyInterface.ts +++ b/packages/models/src/Domain/Syncable/KeySystemItemsKey/KeySystemItemsKeyInterface.ts @@ -1,5 +1,5 @@ -import { ProtocolVersion } from '@standardnotes/common' import { DecryptedItemInterface } from '../../Abstract/Item/Interfaces/DecryptedItem' +import { ProtocolVersion } from '../../Local/Protocol/ProtocolVersion' import { KeySystemItemsKeyContent } from './KeySystemItemsKeyContent' export interface KeySystemItemsKeyInterface extends DecryptedItemInterface { diff --git a/packages/models/src/Domain/Syncable/KeySystemRootKey/KeySystemRootKey.ts b/packages/models/src/Domain/Syncable/KeySystemRootKey/KeySystemRootKey.ts index 39d5893e7b3..57dce30f3df 100644 --- a/packages/models/src/Domain/Syncable/KeySystemRootKey/KeySystemRootKey.ts +++ b/packages/models/src/Domain/Syncable/KeySystemRootKey/KeySystemRootKey.ts @@ -1,4 +1,3 @@ -import { ProtocolVersion } from '@standardnotes/common' import { ConflictStrategy, DecryptedItem } from '../../Abstract/Item' import { DecryptedPayloadInterface } from '../../Abstract/Payload' import { HistoryEntryInterface } from '../../Runtime/History' @@ -7,6 +6,7 @@ import { KeySystemRootKeyInterface } from './KeySystemRootKeyInterface' import { KeySystemIdentifier } from './KeySystemIdentifier' import { KeySystemRootKeyParamsInterface } from '../../Local/KeyParams/KeySystemRootKeyParamsInterface' import { ContentType } from '@standardnotes/domain-core' +import { ProtocolVersion } from '../../Local/Protocol/ProtocolVersion' export function isKeySystemRootKey(x: { content_type: string }): x is KeySystemRootKey { return x.content_type === ContentType.TYPES.KeySystemRootKey diff --git a/packages/models/src/Domain/Syncable/KeySystemRootKey/KeySystemRootKeyContent.ts b/packages/models/src/Domain/Syncable/KeySystemRootKey/KeySystemRootKeyContent.ts index 4c370dec0fe..5c0904a5b33 100644 --- a/packages/models/src/Domain/Syncable/KeySystemRootKey/KeySystemRootKeyContent.ts +++ b/packages/models/src/Domain/Syncable/KeySystemRootKey/KeySystemRootKeyContent.ts @@ -1,7 +1,7 @@ -import { ProtocolVersion } from '@standardnotes/common' import { ItemContent } from '../../Abstract/Content/ItemContent' import { KeySystemIdentifier } from './KeySystemIdentifier' import { KeySystemRootKeyParamsInterface } from '../../Local/KeyParams/KeySystemRootKeyParamsInterface' +import { ProtocolVersion } from '../../Local/Protocol/ProtocolVersion' export type KeySystemRootKeyContentSpecialized = { keyParams: KeySystemRootKeyParamsInterface diff --git a/packages/models/src/Domain/Syncable/KeySystemRootKey/KeySystemRootKeyInterface.ts b/packages/models/src/Domain/Syncable/KeySystemRootKey/KeySystemRootKeyInterface.ts index 0b5e3ef9fc9..b4b137269c6 100644 --- a/packages/models/src/Domain/Syncable/KeySystemRootKey/KeySystemRootKeyInterface.ts +++ b/packages/models/src/Domain/Syncable/KeySystemRootKey/KeySystemRootKeyInterface.ts @@ -1,8 +1,8 @@ -import { ProtocolVersion } from '@standardnotes/common' import { DecryptedItemInterface } from '../../Abstract/Item/Interfaces/DecryptedItem' import { KeySystemRootKeyContent } from './KeySystemRootKeyContent' import { KeySystemIdentifier } from './KeySystemIdentifier' import { KeySystemRootKeyParamsInterface } from '../../Local/KeyParams/KeySystemRootKeyParamsInterface' +import { ProtocolVersion } from '../../Local/Protocol/ProtocolVersion' export interface KeySystemRootKeyInterface extends DecryptedItemInterface { keyParams: KeySystemRootKeyParamsInterface diff --git a/packages/models/src/Domain/Syncable/VaultListing/VaultListingSharingInfo.ts b/packages/models/src/Domain/Syncable/VaultListing/VaultListingSharingInfo.ts index f35657e32d4..93725b32673 100644 --- a/packages/models/src/Domain/Syncable/VaultListing/VaultListingSharingInfo.ts +++ b/packages/models/src/Domain/Syncable/VaultListing/VaultListingSharingInfo.ts @@ -1,4 +1,5 @@ export type VaultListingSharingInfo = { sharedVaultUuid: string ownerUserUuid: string + fileBytesUsed: number } diff --git a/packages/models/src/Domain/index.ts b/packages/models/src/Domain/index.ts index d552db11941..c4caf0ddb91 100644 --- a/packages/models/src/Domain/index.ts +++ b/packages/models/src/Domain/index.ts @@ -15,7 +15,6 @@ export * from './Abstract/Contextual/ComponentCreate' export * from './Abstract/Contextual/ComponentRetrieved' export * from './Abstract/Contextual/ContextPayload' export * from './Abstract/Contextual/FilteredServerItem' -export * from './Abstract/Contextual/TrustedConflictParams' export * from './Abstract/Contextual/Functions' export * from './Abstract/Contextual/LocalStorage' export * from './Abstract/Contextual/OfflineSyncPush' @@ -23,30 +22,33 @@ export * from './Abstract/Contextual/OfflineSyncSaved' export * from './Abstract/Contextual/ServerSyncPush' export * from './Abstract/Contextual/ServerSyncSaved' export * from './Abstract/Contextual/SessionHistory' +export * from './Abstract/Contextual/TrustedConflictParams' export * from './Abstract/Item' export * from './Abstract/Payload' export * from './Abstract/TransferPayload' - export * from './Api/Subscription/Invitation' export * from './Api/Subscription/InvitationStatus' export * from './Api/Subscription/InviteeIdentifierType' export * from './Api/Subscription/InviterIdentifierType' - export * from './Device/Environment' export * from './Device/Platform' - -export * from './Local/KeyParams/RootKeyParamsInterface' -export * from './Local/KeyParams/KeySystemRootKeyParamsInterface' +export * from './Local/ApplicationIdentifier' export * from './Local/KeyParams/KeySystemPasswordType' +export * from './Local/KeyParams/KeySystemRootKeyParamsInterface' +export * from './Local/KeyParams/RootKeyParamsInterface' +export * from './Local/Protocol/ProtocolVersion' +export * from './Local/Protocol/ProtocolVersionFromEncryptedString' export * from './Local/RootKey/KeychainTypes' export * from './Local/RootKey/RootKeyContent' export * from './Local/RootKey/RootKeyInterface' export * from './Local/RootKey/RootKeyWithKeyPairsInterface' - -export * from './Runtime/Feature/TypeGuards' -export * from './Runtime/Feature/UIFeature' -export * from './Runtime/Feature/UIFeatureInterface' - +export * from './Runtime/AsymmetricMessage/AsymmetricMessagePayload' +export * from './Runtime/AsymmetricMessage/AsymmetricMessagePayloadType' +export * from './Runtime/AsymmetricMessage/MessageTypes/AsymmetricMessageSenderKeypairChanged' +export * from './Runtime/AsymmetricMessage/MessageTypes/AsymmetricMessageSharedVaultInvite' +export * from './Runtime/AsymmetricMessage/MessageTypes/AsymmetricMessageSharedVaultMetadataChanged' +export * from './Runtime/AsymmetricMessage/MessageTypes/AsymmetricMessageSharedVaultRootKeyChanged' +export * from './Runtime/AsymmetricMessage/MessageTypes/AsymmetricMessageTrustedContactShare' export * from './Runtime/Collection/CollectionSort' export * from './Runtime/Collection/Item/ItemCollection' export * from './Runtime/Collection/Item/ItemCounter' @@ -57,6 +59,13 @@ export * from './Runtime/DirtyCounter/DirtyCounter' export * from './Runtime/Display' export * from './Runtime/Display/ItemDisplayController' export * from './Runtime/Display/Types' +export * from './Runtime/Encryption/ContentTypesUsingRootKeyEncryption' +export * from './Runtime/Encryption/ContentTypeUsesKeySystemRootKeyEncryption' +export * from './Runtime/Encryption/ContentTypeUsesRootKeyEncryption' +export * from './Runtime/Encryption/PersistentSignatureData' +export * from './Runtime/Feature/TypeGuards' +export * from './Runtime/Feature/UIFeature' +export * from './Runtime/Feature/UIFeatureInterface' export * from './Runtime/History' export * from './Runtime/Index/ItemDelta' export * from './Runtime/Index/SNIndex' @@ -69,20 +78,6 @@ export * from './Runtime/Predicate/NotPredicate' export * from './Runtime/Predicate/Operator' export * from './Runtime/Predicate/Predicate' export * from './Runtime/Predicate/Utils' - -export * from './Runtime/AsymmetricMessage/AsymmetricMessagePayload' -export * from './Runtime/AsymmetricMessage/AsymmetricMessagePayloadType' -export * from './Runtime/AsymmetricMessage/MessageTypes/AsymmetricMessageSenderKeypairChanged' -export * from './Runtime/AsymmetricMessage/MessageTypes/AsymmetricMessageSharedVaultInvite' -export * from './Runtime/AsymmetricMessage/MessageTypes/AsymmetricMessageSharedVaultMetadataChanged' -export * from './Runtime/AsymmetricMessage/MessageTypes/AsymmetricMessageSharedVaultRootKeyChanged' -export * from './Runtime/AsymmetricMessage/MessageTypes/AsymmetricMessageTrustedContactShare' - -export * from './Runtime/Encryption/PersistentSignatureData' -export * from './Runtime/Encryption/ContentTypeUsesRootKeyEncryption' -export * from './Runtime/Encryption/ContentTypesUsingRootKeyEncryption' -export * from './Runtime/Encryption/ContentTypeUsesKeySystemRootKeyEncryption' - export * from './Syncable/ActionsExtension' export * from './Syncable/Component' export * from './Syncable/Editor' @@ -90,36 +85,32 @@ export * from './Syncable/FeatureRepo' export * from './Syncable/File' export * from './Syncable/ItemsKey/ItemsKeyInterface' export * from './Syncable/ItemsKey/ItemsKeyMutatorInterface' +export * from './Syncable/KeySystemItemsKey/KeySystemItemsKeyContent' +export * from './Syncable/KeySystemItemsKey/KeySystemItemsKeyInterface' +export * from './Syncable/KeySystemItemsKey/KeySystemItemsKeyMutatorInterface' +export * from './Syncable/KeySystemRootKey/KeySystemIdentifier' +export * from './Syncable/KeySystemRootKey/KeySystemRootKey' +export * from './Syncable/KeySystemRootKey/KeySystemRootKeyContent' +export * from './Syncable/KeySystemRootKey/KeySystemRootKeyInterface' +export * from './Syncable/KeySystemRootKey/KeySystemRootKeyMutator' +export * from './Syncable/KeySystemRootKey/KeySystemRootKeyStorageMode' export * from './Syncable/Note' export * from './Syncable/SmartView' export * from './Syncable/Tag' -export * from './Syncable/UserPrefs' - -export * from './Syncable/TrustedContact/TrustedContact' -export * from './Syncable/TrustedContact/Mutator/TrustedContactMutator' export * from './Syncable/TrustedContact/Content/TrustedContactContent' -export * from './Syncable/TrustedContact/TrustedContactInterface' -export * from './Syncable/TrustedContact/PublicKeySet/ContactPublicKeySetInterface' +export * from './Syncable/TrustedContact/Mutator/TrustedContactMutator' export * from './Syncable/TrustedContact/PublicKeySet/ContactPublicKeySet' +export * from './Syncable/TrustedContact/PublicKeySet/ContactPublicKeySetInterface' +export * from './Syncable/TrustedContact/TrustedContact' +export * from './Syncable/TrustedContact/TrustedContactInterface' export * from './Syncable/TrustedContact/Types/PortablePublicKeySet' export * from './Syncable/TrustedContact/Types/PublicKeyTrustStatus' - -export * from './Syncable/KeySystemRootKey/KeySystemRootKey' -export * from './Syncable/KeySystemRootKey/KeySystemRootKeyMutator' -export * from './Syncable/KeySystemRootKey/KeySystemRootKeyContent' -export * from './Syncable/KeySystemRootKey/KeySystemRootKeyInterface' -export * from './Syncable/KeySystemRootKey/KeySystemRootKeyStorageMode' - -export * from './Syncable/KeySystemItemsKey/KeySystemItemsKeyInterface' -export * from './Syncable/KeySystemItemsKey/KeySystemItemsKeyContent' -export * from './Syncable/KeySystemItemsKey/KeySystemItemsKeyMutatorInterface' - +export * from './Syncable/UserPrefs' export * from './Syncable/VaultListing/VaultListing' export * from './Syncable/VaultListing/VaultListingContent' export * from './Syncable/VaultListing/VaultListingInterface' export * from './Syncable/VaultListing/VaultListingMutator' export * from './Syncable/VaultListing/VaultListingSharingInfo' - export * from './Utilities/Icon/IconType' export * from './Utilities/Item/FindItem' export * from './Utilities/Item/ItemContentsDiffer' @@ -132,4 +123,3 @@ export * from './Utilities/Payload/PayloadContentsEqual' export * from './Utilities/Payload/PayloadsByAlternatingUuid' export * from './Utilities/Payload/PayloadsByDuplicating' export * from './Utilities/Payload/PayloadSplit' -export * from './Syncable/KeySystemRootKey/KeySystemIdentifier' diff --git a/packages/responses/src/Domain/Item/ConflictType.ts b/packages/responses/src/Domain/Item/ConflictType.ts index c3f80a782a4..534f6510db4 100644 --- a/packages/responses/src/Domain/Item/ConflictType.ts +++ b/packages/responses/src/Domain/Item/ConflictType.ts @@ -5,6 +5,7 @@ export enum ConflictType { ContentError = 'content_error', ReadOnlyError = 'readonly_error', UuidError = 'uuid_error', + InvalidServerItem = 'invalid_server_item', SharedVaultSnjsVersionError = 'shared_vault_snjs_version_error', SharedVaultInsufficientPermissionsError = 'shared_vault_insufficient_permissions_error', diff --git a/packages/responses/src/Domain/SharedVaults/SharedVaultServerHash.ts b/packages/responses/src/Domain/SharedVaults/SharedVaultServerHash.ts index aefd70529f5..0134b5ffba8 100644 --- a/packages/responses/src/Domain/SharedVaults/SharedVaultServerHash.ts +++ b/packages/responses/src/Domain/SharedVaults/SharedVaultServerHash.ts @@ -1,4 +1,8 @@ export interface SharedVaultServerHash { uuid: string user_uuid: string + file_upload_bytes_used: number + file_upload_bytes_limit: number + created_at_timestamp: number + updated_at_timestamp: number } diff --git a/packages/services/package.json b/packages/services/package.json index 25ad013212a..8e2f8dc01ea 100644 --- a/packages/services/package.json +++ b/packages/services/package.json @@ -18,7 +18,7 @@ "dependencies": { "@standardnotes/api": "workspace:^", "@standardnotes/common": "^1.50.0", - "@standardnotes/domain-core": "^1.24.0", + "@standardnotes/domain-core": "^1.25.0", "@standardnotes/encryption": "workspace:^", "@standardnotes/features": "workspace:^", "@standardnotes/files": "workspace:^", diff --git a/packages/services/src/Domain/Application/ApplicationInterface.ts b/packages/services/src/Domain/Application/ApplicationInterface.ts index 81c71266146..28c145686d3 100644 --- a/packages/services/src/Domain/Application/ApplicationInterface.ts +++ b/packages/services/src/Domain/Application/ApplicationInterface.ts @@ -22,8 +22,7 @@ import { AsymmetricMessageServiceInterface } from './../AsymmetricMessage/Asymme import { ImportDataResult } from '../Import/ImportDataResult' import { ChallengeServiceInterface } from './../Challenge/ChallengeServiceInterface' import { VaultServiceInterface } from '../Vault/VaultServiceInterface' -import { ApplicationIdentifier } from '@standardnotes/common' -import { BackupFile, Environment, Platform, PrefKey, PrefValue } from '@standardnotes/models' +import { BackupFile, Environment, Platform, PrefKey, PrefValue, ApplicationIdentifier } from '@standardnotes/models' import { BackupServiceInterface, FilesClientInterface } from '@standardnotes/files' import { AlertService } from '../Alert/AlertService' diff --git a/packages/services/src/Domain/Application/Options/RequiredOptions.ts b/packages/services/src/Domain/Application/Options/RequiredOptions.ts index bd4702afff0..99bf22bbc56 100644 --- a/packages/services/src/Domain/Application/Options/RequiredOptions.ts +++ b/packages/services/src/Domain/Application/Options/RequiredOptions.ts @@ -1,5 +1,4 @@ -import { Environment, Platform } from '@standardnotes/models' -import { ApplicationIdentifier } from '@standardnotes/common' +import { Environment, Platform, ApplicationIdentifier } from '@standardnotes/models' import { AlertService, DeviceInterface } from '@standardnotes/services' import { PureCryptoInterface } from '@standardnotes/sncrypto-common' diff --git a/packages/services/src/Domain/AsymmetricMessage/UseCase/ProcessAcceptedVaultInvite.spec.ts b/packages/services/src/Domain/AsymmetricMessage/UseCase/ProcessAcceptedVaultInvite.spec.ts index a7a52f25fa5..33f8f882fa7 100644 --- a/packages/services/src/Domain/AsymmetricMessage/UseCase/ProcessAcceptedVaultInvite.spec.ts +++ b/packages/services/src/Domain/AsymmetricMessage/UseCase/ProcessAcceptedVaultInvite.spec.ts @@ -38,6 +38,7 @@ describe('ProcessAcceptedVaultInvite', () => { metadata: { name: 'test-name', iconString: 'safe-square', + fileBytesUsed: 0, }, trustedContacts: [], }, diff --git a/packages/services/src/Domain/AsymmetricMessage/UseCase/ProcessAcceptedVaultInvite.ts b/packages/services/src/Domain/AsymmetricMessage/UseCase/ProcessAcceptedVaultInvite.ts index b3fa74e4e55..110abc2da41 100644 --- a/packages/services/src/Domain/AsymmetricMessage/UseCase/ProcessAcceptedVaultInvite.ts +++ b/packages/services/src/Domain/AsymmetricMessage/UseCase/ProcessAcceptedVaultInvite.ts @@ -36,6 +36,7 @@ export class ProcessAcceptedVaultInvite { sharing: { sharedVaultUuid: sharedVaultUuid, ownerUserUuid: ownerUuid, + fileBytesUsed: metadata.fileBytesUsed, }, } diff --git a/packages/services/src/Domain/Device/DeviceInterface.ts b/packages/services/src/Domain/Device/DeviceInterface.ts index ca0bf6d9318..ff1948684bc 100644 --- a/packages/services/src/Domain/Device/DeviceInterface.ts +++ b/packages/services/src/Domain/Device/DeviceInterface.ts @@ -1,5 +1,5 @@ -import { ApplicationIdentifier } from '@standardnotes/common' import { + ApplicationIdentifier, FullyFormedTransferPayload, TransferPayload, NamespacedRootKeyInKeychain, diff --git a/packages/services/src/Domain/Encryption/UseCase/Asymmetric/DecryptMessage.spec.ts b/packages/services/src/Domain/Encryption/UseCase/Asymmetric/DecryptMessage.spec.ts index 95ff4515890..607b24e2ac6 100644 --- a/packages/services/src/Domain/Encryption/UseCase/Asymmetric/DecryptMessage.spec.ts +++ b/packages/services/src/Domain/Encryption/UseCase/Asymmetric/DecryptMessage.spec.ts @@ -3,10 +3,10 @@ import { ContactPublicKeySetInterface, PublicKeyTrustStatus, TrustedContactInterface, + ProtocolVersion, } from '@standardnotes/models' import { DecryptMessage } from './DecryptMessage' import { OperatorInterface, EncryptionOperatorsInterface } from '@standardnotes/encryption' -import { ProtocolVersion } from '@standardnotes/common' function createMockPublicKeySetChain(): ContactPublicKeySetInterface { const nMinusOne = new ContactPublicKeySet({ diff --git a/packages/services/src/Domain/ItemsEncryption/ItemsEncryption.ts b/packages/services/src/Domain/ItemsEncryption/ItemsEncryption.ts index 059e35cf304..9bbe2579ca8 100644 --- a/packages/services/src/Domain/ItemsEncryption/ItemsEncryption.ts +++ b/packages/services/src/Domain/ItemsEncryption/ItemsEncryption.ts @@ -1,5 +1,4 @@ import { FindDefaultItemsKey } from './../Encryption/UseCase/ItemsKey/FindDefaultItemsKey' -import { ProtocolVersion } from '@standardnotes/common' import { DecryptedParameters, ErrorDecryptingParameters, @@ -23,6 +22,7 @@ import { PayloadEmitSource, KeySystemItemsKeyInterface, SureFindPayload, + ProtocolVersion, ContentTypeUsesRootKeyEncryption, } from '@standardnotes/models' import { InternalEventBusInterface } from '../Internal/InternalEventBusInterface' diff --git a/packages/services/src/Domain/Session/SessionsClientInterface.ts b/packages/services/src/Domain/Session/SessionsClientInterface.ts index fe87cdf3cab..5c1e4e6882f 100644 --- a/packages/services/src/Domain/Session/SessionsClientInterface.ts +++ b/packages/services/src/Domain/Session/SessionsClientInterface.ts @@ -1,7 +1,6 @@ import { UserRegistrationResponseBody } from '@standardnotes/api' -import { ProtocolVersion } from '@standardnotes/common' import { SNRootKey } from '@standardnotes/encryption' -import { RootKeyInterface } from '@standardnotes/models' +import { RootKeyInterface, ProtocolVersion } from '@standardnotes/models' import { SessionBody, SignInResponse, diff --git a/packages/services/src/Domain/SharedVaults/SharedVaultService.spec.ts b/packages/services/src/Domain/SharedVaults/SharedVaultService.spec.ts index 1d02300d0a4..d5da6bb8dff 100644 --- a/packages/services/src/Domain/SharedVaults/SharedVaultService.spec.ts +++ b/packages/services/src/Domain/SharedVaults/SharedVaultService.spec.ts @@ -14,9 +14,11 @@ import { SyncServiceInterface } from '../Sync/SyncServiceInterface' import { ItemManagerInterface } from '../Item/ItemManagerInterface' import { SessionsClientInterface } from '../Session/SessionsClientInterface' import { ContactPublicKeySetInterface, TrustedContactInterface } from '@standardnotes/models' +import { SyncLocalVaultsWithRemoteSharedVaults } from './UseCase/SyncLocalVaultsWithRemoteSharedVaults' describe('SharedVaultService', () => { let service: SharedVaultService + let syncLocalVaultsWithRemoteSharedVaults: SyncLocalVaultsWithRemoteSharedVaults beforeEach(() => { const sync = {} as jest.Mocked @@ -37,12 +39,16 @@ describe('SharedVaultService', () => { const deleteSharedVaultUseCase = {} as jest.Mocked const discardItemsLocally = {} as jest.Mocked + syncLocalVaultsWithRemoteSharedVaults = {} as jest.Mocked + syncLocalVaultsWithRemoteSharedVaults.execute = jest.fn() + const eventBus = {} as jest.Mocked eventBus.addEventHandler = jest.fn() service = new SharedVaultService( items, session, + syncLocalVaultsWithRemoteSharedVaults, getVault, getOwnedVaults, createSharedVaultUseCase, diff --git a/packages/services/src/Domain/SharedVaults/SharedVaultService.ts b/packages/services/src/Domain/SharedVaults/SharedVaultService.ts index 92ac053010d..08a1ff0c856 100644 --- a/packages/services/src/Domain/SharedVaults/SharedVaultService.ts +++ b/packages/services/src/Domain/SharedVaults/SharedVaultService.ts @@ -32,6 +32,7 @@ import { ContentType, NotificationType, Uuid } from '@standardnotes/domain-core' import { HandleKeyPairChange } from '../Contacts/UseCase/HandleKeyPairChange' import { FindContact } from '../Contacts/UseCase/FindContact' import { GetOwnedSharedVaults } from './UseCase/GetOwnedSharedVaults' +import { SyncLocalVaultsWithRemoteSharedVaults } from './UseCase/SyncLocalVaultsWithRemoteSharedVaults' export class SharedVaultService extends AbstractService @@ -40,6 +41,7 @@ export class SharedVaultService constructor( private items: ItemManagerInterface, private session: SessionsClientInterface, + private _syncLocalVaultsWithRemoteSharedVaults: SyncLocalVaultsWithRemoteSharedVaults, private _getVault: GetVault, private _getOwnedSharedVaults: GetOwnedSharedVaults, private _createSharedVault: CreateSharedVault, @@ -67,6 +69,7 @@ export class SharedVaultService super.deinit() ;(this.items as unknown) = undefined ;(this.session as unknown) = undefined + ;(this._syncLocalVaultsWithRemoteSharedVaults as unknown) = undefined ;(this._getVault as unknown) = undefined ;(this._createSharedVault as unknown) = undefined ;(this._handleKeyPairChange as unknown) = undefined @@ -88,7 +91,7 @@ export class SharedVaultService break } case NotificationServiceEvent.NotificationReceived: - await this.handleUserEvent(event.payload as NotificationServiceEventPayload) + await this.handleNotification(event.payload as NotificationServiceEventPayload) break case SyncEvent.ReceivedRemoteSharedVaults: void this.notifyEventSync(SharedVaultServiceEvent.SharedVaultStatusChanged) @@ -96,7 +99,7 @@ export class SharedVaultService } } - private async handleUserEvent(event: NotificationServiceEventPayload): Promise { + private async handleNotification(event: NotificationServiceEventPayload): Promise { switch (event.eventPayload.props.type.value) { case NotificationType.TYPES.RemovedFromSharedVault: { const vault = this._getVault.execute({ @@ -114,6 +117,19 @@ export class SharedVaultService } break } + case NotificationType.TYPES.SharedVaultFileRemoved: + case NotificationType.TYPES.SharedVaultFileUploaded: { + const vaultOrError = this._getVault.execute({ + sharedVaultUuid: event.eventPayload.props.sharedVaultUuid.value, + }) + if (!vaultOrError.isFailed()) { + await this._syncLocalVaultsWithRemoteSharedVaults.execute([vaultOrError.getValue()]) + + void this.notifyEventSync(SharedVaultServiceEvent.SharedVaultStatusChanged) + } + + break + } } } diff --git a/packages/services/src/Domain/SharedVaults/SharedVaultServiceEvent.ts b/packages/services/src/Domain/SharedVaults/SharedVaultServiceEvent.ts index ac210e91f48..4f91e79eb09 100644 --- a/packages/services/src/Domain/SharedVaults/SharedVaultServiceEvent.ts +++ b/packages/services/src/Domain/SharedVaults/SharedVaultServiceEvent.ts @@ -2,6 +2,7 @@ import { KeySystemIdentifier } from '@standardnotes/models' export enum SharedVaultServiceEvent { SharedVaultStatusChanged = 'SharedVaultStatusChanged', + SharedVaultFileStorageUsageChanged = 'SharedVaultFileStorageUsageChanged', } export type SharedVaultServiceEventPayload = { diff --git a/packages/services/src/Domain/SharedVaults/UseCase/ConvertToSharedVault.ts b/packages/services/src/Domain/SharedVaults/UseCase/ConvertToSharedVault.ts index c75c897c82c..63812bb0a11 100644 --- a/packages/services/src/Domain/SharedVaults/UseCase/ConvertToSharedVault.ts +++ b/packages/services/src/Domain/SharedVaults/UseCase/ConvertToSharedVault.ts @@ -31,6 +31,7 @@ export class ConvertToSharedVault { mutator.sharing = { sharedVaultUuid: serverVaultHash.uuid, ownerUserUuid: serverVaultHash.user_uuid, + fileBytesUsed: serverVaultHash.file_upload_bytes_used, } }, ) diff --git a/packages/services/src/Domain/SharedVaults/UseCase/CreateSharedVault.ts b/packages/services/src/Domain/SharedVaults/UseCase/CreateSharedVault.ts index 97decf85927..a9cb7baaff5 100644 --- a/packages/services/src/Domain/SharedVaults/UseCase/CreateSharedVault.ts +++ b/packages/services/src/Domain/SharedVaults/UseCase/CreateSharedVault.ts @@ -50,6 +50,7 @@ export class CreateSharedVault { mutator.sharing = { sharedVaultUuid: serverVaultHash.uuid, ownerUserUuid: serverVaultHash.user_uuid, + fileBytesUsed: serverVaultHash.file_upload_bytes_used, } }, ) diff --git a/packages/services/src/Domain/SharedVaults/UseCase/SyncLocalVaultsWithRemoteSharedVaults.spec.ts b/packages/services/src/Domain/SharedVaults/UseCase/SyncLocalVaultsWithRemoteSharedVaults.spec.ts new file mode 100644 index 00000000000..dff7e572a21 --- /dev/null +++ b/packages/services/src/Domain/SharedVaults/UseCase/SyncLocalVaultsWithRemoteSharedVaults.spec.ts @@ -0,0 +1,80 @@ +import { MutatorClientInterface, SharedVaultServerInterface, VaultListingInterface } from '@standardnotes/snjs' +import { SyncLocalVaultsWithRemoteSharedVaults } from './SyncLocalVaultsWithRemoteSharedVaults' + +describe('SyncLocalVaultsWithRemoteSharedVaults', () => { + let sharedVaultServer: SharedVaultServerInterface + let mutator: MutatorClientInterface + + const createUseCase = () => new SyncLocalVaultsWithRemoteSharedVaults(sharedVaultServer, mutator) + + beforeEach(() => { + sharedVaultServer = {} as jest.Mocked + sharedVaultServer.getSharedVaults = jest.fn().mockResolvedValue({ data: { sharedVaults: [{ + uuid: '1-2-3', + user_uuid: '2-3-4', + file_upload_bytes_used: 123, + file_upload_bytes_limit: 10000000, + created_at_timestamp: 123, + updated_at_timestamp: 123, + }] } }) + + mutator = {} as jest.Mocked + mutator.changeItem = jest.fn() + }) + + it('should sync local vaults with remote shared vaults to update file storage usage', async () => { + const localVaults = [{ + uuid: '1-2-3', + name: 'Vault', + isSharedVaultListing: () => true, + sharing: { + sharedVaultUuid: '1-2-3', + ownerUserUuid: '2-3-4', + fileBytesUsed: 0, + }, + } as jest.Mocked] + + const useCase = createUseCase() + await useCase.execute(localVaults) + + expect(mutator.changeItem).toHaveBeenCalledWith(localVaults[0], expect.any(Function)) + }) + + it('should fail if shared vault server returns error', async () => { + sharedVaultServer.getSharedVaults = jest.fn().mockResolvedValue({ data: { error: { message: 'test-error' } } }) + + const localVaults = [{ + uuid: '1-2-3', + name: 'Vault', + isSharedVaultListing: () => true, + sharing: { + sharedVaultUuid: '1-2-3', + ownerUserUuid: '2-3-4', + fileBytesUsed: 0, + }, + } as jest.Mocked] + + const useCase = createUseCase() + const result = await useCase.execute(localVaults) + + expect(result.isFailed()).toBe(true) + }) + + it('should not sync local vaults with remote shared vaults if local vault is not shared', async () => { + const localVaults = [{ + uuid: '1-2-3', + name: 'Vault', + isSharedVaultListing: () => false, + sharing: { + sharedVaultUuid: '1-2-3', + ownerUserUuid: '2-3-4', + fileBytesUsed: 0, + }, + } as jest.Mocked] + + const useCase = createUseCase() + await useCase.execute(localVaults) + + expect(mutator.changeItem).not.toHaveBeenCalled() + }) +}) diff --git a/packages/services/src/Domain/SharedVaults/UseCase/SyncLocalVaultsWithRemoteSharedVaults.ts b/packages/services/src/Domain/SharedVaults/UseCase/SyncLocalVaultsWithRemoteSharedVaults.ts new file mode 100644 index 00000000000..2769a23a320 --- /dev/null +++ b/packages/services/src/Domain/SharedVaults/UseCase/SyncLocalVaultsWithRemoteSharedVaults.ts @@ -0,0 +1,40 @@ +import { Result, UseCaseInterface } from '@standardnotes/domain-core' +import { SharedVaultServerInterface } from '@standardnotes/api' +import { HttpError, isErrorResponse } from '@standardnotes/responses' +import { SharedVaultListingInterface, VaultListingInterface, VaultListingMutator } from '@standardnotes/models' + +import { MutatorClientInterface } from '../../Mutator/MutatorClientInterface' + +export class SyncLocalVaultsWithRemoteSharedVaults implements UseCaseInterface { + constructor( + private sharedVaultServer: SharedVaultServerInterface, + private mutator: MutatorClientInterface, + ) {} + + async execute(localVaults: VaultListingInterface[]): Promise> { + const remoteVaultsResponse = await this.sharedVaultServer.getSharedVaults() + if (isErrorResponse(remoteVaultsResponse)) { + return Result.fail((remoteVaultsResponse.data.error as HttpError).message as string) + } + const remoteVaults = remoteVaultsResponse.data.sharedVaults + + for (const localVault of localVaults) { + if (!localVault.isSharedVaultListing()) { + continue + } + const remoteVault = remoteVaults.find((vault) => vault.uuid === localVault.sharing.sharedVaultUuid) + if (remoteVault) { + await this.mutator.changeItem(localVault, (mutator) => { + /* istanbul ignore next */ + mutator.sharing = { + sharedVaultUuid: remoteVault.uuid, + ownerUserUuid: remoteVault.user_uuid, + fileBytesUsed: remoteVault.file_upload_bytes_used, + } + }) + } + } + + return Result.ok() + } +} diff --git a/packages/services/src/Domain/Strings/Messages.ts b/packages/services/src/Domain/Strings/Messages.ts index 0814b9535d1..ab341475636 100644 --- a/packages/services/src/Domain/Strings/Messages.ts +++ b/packages/services/src/Domain/Strings/Messages.ts @@ -1,4 +1,4 @@ -import { ProtocolVersion } from '@standardnotes/common' +import { ProtocolVersion } from '@standardnotes/models' export const API_MESSAGE_GENERIC_INVALID_LOGIN = 'A server error occurred while trying to sign in. Please try again.' export const API_MESSAGE_GENERIC_REGISTRATION_FAIL = diff --git a/packages/services/src/Domain/VaultInvite/UseCase/InviteToVault.ts b/packages/services/src/Domain/VaultInvite/UseCase/InviteToVault.ts index 01b55d9f2b6..bd333ca098f 100644 --- a/packages/services/src/Domain/VaultInvite/UseCase/InviteToVault.ts +++ b/packages/services/src/Domain/VaultInvite/UseCase/InviteToVault.ts @@ -123,6 +123,7 @@ export class InviteToVault implements UseCaseInterface(TYPES.ItemManager)) }) + this.factory.set(TYPES.SyncLocalVaultsWithRemoteSharedVaults, () => { + return new SyncLocalVaultsWithRemoteSharedVaults( + this.get(TYPES.SharedVaultServer), + this.get(TYPES.MutatorService), + ) + }) + this.factory.set(TYPES.ChangeAndSaveItem, () => { return new ChangeAndSaveItem( this.get(TYPES.ItemManager), @@ -893,6 +901,7 @@ export class Dependencies { return new SharedVaultService( this.get(TYPES.ItemManager), this.get(TYPES.SessionManager), + this.get(TYPES.SyncLocalVaultsWithRemoteSharedVaults), this.get(TYPES.GetVault), this.get(TYPES.GetOwnedSharedVaults), this.get(TYPES.CreateSharedVault), diff --git a/packages/snjs/lib/Application/Dependencies/Types.ts b/packages/snjs/lib/Application/Dependencies/Types.ts index 5db17ce7090..e145da9c9c6 100644 --- a/packages/snjs/lib/Application/Dependencies/Types.ts +++ b/packages/snjs/lib/Application/Dependencies/Types.ts @@ -98,6 +98,7 @@ export const TYPES = { ValidateItemSigner: Symbol.for('ValidateItemSigner'), GetVault: Symbol.for('GetVault'), GetVaults: Symbol.for('GetVaults'), + SyncLocalVaultsWithRemoteSharedVaults: Symbol.for('SyncLocalVaultsWithRemoteSharedVaults'), GetSharedVaults: Symbol.for('GetSharedVaults'), GetOwnedSharedVaults: Symbol.for('GetOwnedSharedVaults'), ChangeVaultKeyOptions: Symbol.for('ChangeVaultKeyOptions'), diff --git a/packages/snjs/lib/ApplicationGroup/ApplicationDescriptor.ts b/packages/snjs/lib/ApplicationGroup/ApplicationDescriptor.ts index a55b1c8a33f..c44c8ae3176 100644 --- a/packages/snjs/lib/ApplicationGroup/ApplicationDescriptor.ts +++ b/packages/snjs/lib/ApplicationGroup/ApplicationDescriptor.ts @@ -1,4 +1,4 @@ -import { ApplicationIdentifier } from '@standardnotes/common' +import { ApplicationIdentifier } from '@standardnotes/models' export type ApplicationDescriptor = { identifier: ApplicationIdentifier diff --git a/packages/snjs/lib/Domain/UseCase/GetRevision/GetRevision.spec.ts b/packages/snjs/lib/Domain/UseCase/GetRevision/GetRevision.spec.ts index d43d74da2c3..6ecf3a1facb 100644 --- a/packages/snjs/lib/Domain/UseCase/GetRevision/GetRevision.spec.ts +++ b/packages/snjs/lib/Domain/UseCase/GetRevision/GetRevision.spec.ts @@ -5,10 +5,10 @@ jest.mock('@standardnotes/models', () => { return { ...original, - isRemotePayloadAllowed: jest.fn(), + checkRemotePayloadAllowed: jest.fn(), } }) -const isRemotePayloadAllowed = require('@standardnotes/models').isRemotePayloadAllowed +const checkRemotePayloadAllowed = require('@standardnotes/models').checkRemotePayloadAllowed import { Revision } from '../../Revision/Revision' @@ -44,7 +44,7 @@ describe('GetRevision', () => { encryptedPayload.copy = jest.fn().mockReturnValue(encryptedPayload) encryptionService.decryptSplitSingle = jest.fn().mockReturnValue(encryptedPayload) - isRemotePayloadAllowed.mockImplementation(() => true) + checkRemotePayloadAllowed.mockImplementation(() => ({ allowed: {} })) }) it('should get revision', async () => { @@ -145,7 +145,7 @@ describe('GetRevision', () => { }) it('should fail if remote payload is not allowed', async () => { - isRemotePayloadAllowed.mockImplementation(() => false) + checkRemotePayloadAllowed.mockImplementation(() => ({ disallowed: {} })) const useCase = createUseCase() diff --git a/packages/snjs/lib/Domain/UseCase/GetRevision/GetRevision.ts b/packages/snjs/lib/Domain/UseCase/GetRevision/GetRevision.ts index 18fee0deb7f..bdadba5c533 100644 --- a/packages/snjs/lib/Domain/UseCase/GetRevision/GetRevision.ts +++ b/packages/snjs/lib/Domain/UseCase/GetRevision/GetRevision.ts @@ -5,7 +5,7 @@ import { EncryptedPayload, HistoryEntry, isErrorDecryptingPayload, - isRemotePayloadAllowed, + checkRemotePayloadAllowed, NoteContent, PayloadTimestampDefaults, } from '@standardnotes/models' @@ -71,7 +71,8 @@ export class GetRevision implements UseCaseInterface { uuid: sourceItemUuid || revision.item_uuid, }) - if (!isRemotePayloadAllowed(payload as ServerItemResponse)) { + const remotePayloadAllowedResult = checkRemotePayloadAllowed(payload as ServerItemResponse) + if (remotePayloadAllowedResult.disallowed !== undefined) { return Result.fail(`Remote payload is disallowed: ${JSON.stringify(payload)}`) } diff --git a/packages/snjs/lib/Migrations/MigrationServices.ts b/packages/snjs/lib/Migrations/MigrationServices.ts index bc08c8feb60..ca465a81658 100644 --- a/packages/snjs/lib/Migrations/MigrationServices.ts +++ b/packages/snjs/lib/Migrations/MigrationServices.ts @@ -1,5 +1,5 @@ import { BackupServiceInterface } from '@standardnotes/files' -import { Environment, Platform } from '@standardnotes/models' +import { Environment, Platform, ApplicationIdentifier } from '@standardnotes/models' import { DeviceInterface, InternalEventBusInterface, @@ -8,7 +8,6 @@ import { PreferenceServiceInterface, } from '@standardnotes/services' import { SessionManager } from '../Services/Session/SessionManager' -import { ApplicationIdentifier } from '@standardnotes/common' import { ItemManager } from '@Lib/Services/Items/ItemManager' import { ChallengeService, SingletonManager, FeaturesService, DiskStorageService } from '@Lib/Services' import { LegacySession, MapperInterface } from '@standardnotes/domain-core' diff --git a/packages/snjs/lib/Migrations/StorageReaders/Functions.ts b/packages/snjs/lib/Migrations/StorageReaders/Functions.ts index 62b4228ba07..6d6a621e6b9 100644 --- a/packages/snjs/lib/Migrations/StorageReaders/Functions.ts +++ b/packages/snjs/lib/Migrations/StorageReaders/Functions.ts @@ -1,5 +1,4 @@ -import { ApplicationIdentifier } from '@standardnotes/common' -import { Environment } from '@standardnotes/models' +import { Environment, ApplicationIdentifier } from '@standardnotes/models' import { compareSemVersions, isRightVersionGreaterThanLeft } from '@Lib/Version' import { DeviceInterface } from '@standardnotes/services' import { StorageReader } from './Reader' diff --git a/packages/snjs/lib/Migrations/StorageReaders/Reader.ts b/packages/snjs/lib/Migrations/StorageReaders/Reader.ts index 8ec650acc01..9b8f0c4bb14 100644 --- a/packages/snjs/lib/Migrations/StorageReaders/Reader.ts +++ b/packages/snjs/lib/Migrations/StorageReaders/Reader.ts @@ -1,5 +1,4 @@ -import { Environment } from '@standardnotes/models' -import { ApplicationIdentifier } from '@standardnotes/common' +import { Environment, ApplicationIdentifier } from '@standardnotes/models' import { DeviceInterface } from '@standardnotes/services' /** diff --git a/packages/snjs/lib/Services/Sync/Account/Response.ts b/packages/snjs/lib/Services/Sync/Account/Response.ts index dc9720cfd8b..4b0e86c0f1c 100644 --- a/packages/snjs/lib/Services/Sync/Account/Response.ts +++ b/packages/snjs/lib/Services/Sync/Account/Response.ts @@ -10,6 +10,8 @@ import { NotificationServerHash, AsymmetricMessageServerHash, getErrorFromErrorResponse, + ConflictType, + ServerItemResponse, } from '@standardnotes/responses' import { FilterDisallowedRemotePayloadsAndMap, @@ -44,15 +46,21 @@ export class ServerSyncResponse { const legacyConflicts = this.successResponseData?.unsaved || [] this.rawConflictObjects = conflicts.concat(legacyConflicts) - this.savedPayloads = FilterDisallowedRemotePayloadsAndMap(this.successResponseData?.saved_items || []).map( - (rawItem) => { - return CreateServerSyncSavedPayload(rawItem) - }, - ) + const disallowedPayloads = [] + + const savedItemsFilteringResult = FilterDisallowedRemotePayloadsAndMap(this.successResponseData?.saved_items || []) + this.savedPayloads = savedItemsFilteringResult.filtered.map((rawItem) => { + return CreateServerSyncSavedPayload(rawItem) + }) + disallowedPayloads.push(...savedItemsFilteringResult.disallowed) - this.retrievedPayloads = FilterDisallowedRemotePayloadsAndMap(this.successResponseData?.retrieved_items || []) + const retrievedItemsFilteringResult = FilterDisallowedRemotePayloadsAndMap( + this.successResponseData?.retrieved_items || [], + ) + this.retrievedPayloads = retrievedItemsFilteringResult.filtered + disallowedPayloads.push(...retrievedItemsFilteringResult.disallowed) - this.conflicts = this.filterConflicts() + this.conflicts = this.filterConflictsAndDisallowedPayloads(disallowedPayloads) this.vaults = this.successResponseData?.shared_vaults || [] @@ -65,20 +73,48 @@ export class ServerSyncResponse { deepFreeze(this) } - private filterConflicts(): TrustedServerConflictMap { + private filterConflictsAndDisallowedPayloads(disallowedPayloads: ServerItemResponse[]): TrustedServerConflictMap { const conflicts = this.rawConflictObjects const trustedConflicts: TrustedServerConflictMap = {} + trustedConflicts[ConflictType.InvalidServerItem] = [] + const invalidServerConflictsArray = trustedConflicts[ConflictType.InvalidServerItem] + + for (const payload of disallowedPayloads) { + invalidServerConflictsArray.push({ + type: ConflictType.InvalidServerItem, + server_item: payload, + }) + } + for (const conflict of conflicts) { let serverItem: FilteredServerItem | undefined let unsavedItem: FilteredServerItem | undefined if (conflict.unsaved_item) { - unsavedItem = FilterDisallowedRemotePayloadsAndMap([conflict.unsaved_item])[0] + const unsavedItemFilteringResult = FilterDisallowedRemotePayloadsAndMap([conflict.unsaved_item]) + if (unsavedItemFilteringResult.filtered.length === 1) { + unsavedItem = unsavedItemFilteringResult.filtered[0] + } + if (unsavedItemFilteringResult.disallowed.length === 1) { + invalidServerConflictsArray.push({ + type: ConflictType.InvalidServerItem, + unsaved_item: unsavedItemFilteringResult.disallowed[0], + }) + } } if (conflict.server_item) { - serverItem = FilterDisallowedRemotePayloadsAndMap([conflict.server_item])[0] + const serverItemFilteringResult = FilterDisallowedRemotePayloadsAndMap([conflict.server_item]) + if (serverItemFilteringResult.filtered.length === 1) { + serverItem = serverItemFilteringResult.filtered[0] + } + if (serverItemFilteringResult.disallowed.length === 1) { + invalidServerConflictsArray.push({ + type: ConflictType.InvalidServerItem, + server_item: serverItemFilteringResult.disallowed[0], + }) + } } if (!trustedConflicts[conflict.type]) { diff --git a/packages/snjs/lib/Services/Sync/Account/ResponseResolver.ts b/packages/snjs/lib/Services/Sync/Account/ResponseResolver.ts index 646606db378..93d9c1798e5 100644 --- a/packages/snjs/lib/Services/Sync/Account/ResponseResolver.ts +++ b/packages/snjs/lib/Services/Sync/Account/ResponseResolver.ts @@ -92,6 +92,7 @@ export class ServerSyncResponseResolver { ...this.getConflictsForType(ConflictType.SharedVaultInsufficientPermissionsError), ...this.getConflictsForType(ConflictType.SharedVaultNotMemberError), ...this.getConflictsForType(ConflictType.SharedVaultInvalidState), + ...this.getConflictsForType(ConflictType.InvalidServerItem), ] const delta = new DeltaRemoteRejected(this.baseCollection, conflicts) diff --git a/packages/snjs/lib/Services/Sync/Account/Utilities.ts b/packages/snjs/lib/Services/Sync/Account/Utilities.ts index dc7bd1eb0a0..4b407820b0e 100644 --- a/packages/snjs/lib/Services/Sync/Account/Utilities.ts +++ b/packages/snjs/lib/Services/Sync/Account/Utilities.ts @@ -1,3 +1,4 @@ +import { Result } from '@standardnotes/domain-core' import { EncryptedPayloadInterface, DeletedPayloadInterface, @@ -10,22 +11,27 @@ import { export function CreatePayloadFromRawServerItem( rawItem: FilteredServerItem, source: PayloadSource, -): EncryptedPayloadInterface | DeletedPayloadInterface { +): Result { if (rawItem.deleted) { - return new DeletedPayload({ ...rawItem, content: undefined, deleted: true }, source) + return Result.ok(new DeletedPayload({ ...rawItem, content: undefined, deleted: true }, source)) } else if (rawItem.content != undefined) { - return new EncryptedPayload( - { - ...rawItem, - items_key_id: rawItem.items_key_id, - content: rawItem.content, - deleted: false, - errorDecrypting: false, - waitingForKey: false, - }, - source, - ) - } else { - throw Error('Unhandled case in createPayloadFromRawItem') + try { + return Result.ok( + new EncryptedPayload( + { + ...rawItem, + items_key_id: rawItem.items_key_id, + content: rawItem.content, + deleted: false, + errorDecrypting: false, + waitingForKey: false, + }, + source, + ), + ) + } catch (error) { + return Result.fail(JSON.stringify(error)) + } } + return Result.fail('Unhandled case in createPayloadFromRawItem') } diff --git a/packages/snjs/lib/Services/Sync/SyncService.ts b/packages/snjs/lib/Services/Sync/SyncService.ts index bafe7607280..fe896389f27 100644 --- a/packages/snjs/lib/Services/Sync/SyncService.ts +++ b/packages/snjs/lib/Services/Sync/SyncService.ts @@ -1110,7 +1110,12 @@ export class SyncService items: FilteredServerItem[], source: PayloadSource, ): Promise { - const payloads = items.map((i) => CreatePayloadFromRawServerItem(i, source)) + const payloads = items + .map((i) => { + const result = CreatePayloadFromRawServerItem(i, source) + return result.isFailed() ? undefined : result.getValue() + }) + .filter(isNotUndefined) const { encrypted, deleted } = CreateNonDecryptedPayloadSplit(payloads) @@ -1408,9 +1413,16 @@ export class SyncService return } - const receivedPayloads = FilterDisallowedRemotePayloadsAndMap(rawPayloads).map((rawPayload) => { - return CreatePayloadFromRawServerItem(rawPayload, PayloadSource.RemoteRetrieved) - }) + const rawPayloadsFilteringResult = FilterDisallowedRemotePayloadsAndMap(rawPayloads) + const receivedPayloads = rawPayloadsFilteringResult.filtered + .map((rawPayload) => { + const result = CreatePayloadFromRawServerItem(rawPayload, PayloadSource.RemoteRetrieved) + if (result.isFailed()) { + return undefined + } + return result.getValue() + }) + .filter(isNotUndefined) const payloadSplit = CreateNonDecryptedPayloadSplit(receivedPayloads) diff --git a/packages/snjs/lib/index.ts b/packages/snjs/lib/index.ts index 32d61d28c4d..e4eb70b8cb6 100644 --- a/packages/snjs/lib/index.ts +++ b/packages/snjs/lib/index.ts @@ -8,7 +8,7 @@ export * from './Migrations' export * from './Services' export * from './Types' export * from './Version' -export * from '@standardnotes/common' +export { KeyParamsOrigination } from '@standardnotes/common' export * from '@standardnotes/domain-core' export * from '@standardnotes/api' export * from '@standardnotes/encryption' diff --git a/packages/snjs/mocha/lib/factory.js b/packages/snjs/mocha/lib/factory.js index 9cb682d2d96..26892bbed1d 100644 --- a/packages/snjs/mocha/lib/factory.js +++ b/packages/snjs/mocha/lib/factory.js @@ -1,4 +1,3 @@ - import FakeWebCrypto from './fake_web_crypto.js' import { AppContext } from './AppContext.js' import { VaultsContext } from './VaultsContext.js' @@ -303,8 +302,10 @@ export function tomorrow() { return new Date(new Date().setDate(new Date().getDate() + 1)) } -export async function sleep(seconds, reason) { - console.log('[Factory] Sleeping for reason', reason) +export async function sleep(seconds, reason, dontLog = false) { + if (!dontLog) { + console.log('[Factory] Sleeping for reason', reason) + } return Utils.sleep(seconds) } diff --git a/packages/snjs/mocha/payload.test.js b/packages/snjs/mocha/payload.test.js index 97195b849ed..1bf69315fa0 100644 --- a/packages/snjs/mocha/payload.test.js +++ b/packages/snjs/mocha/payload.test.js @@ -74,7 +74,7 @@ describe('payload', () => { content_type: ContentType.TYPES.Note, content: '000:somebase64string', }), - 'Unrecognized protocol version 000', + 'EncryptedPayload constructor versionResult is failed', ) }) diff --git a/packages/snjs/mocha/sync_tests/online.test.js b/packages/snjs/mocha/sync_tests/online.test.js index 2dd6c639e84..df1cb80b011 100644 --- a/packages/snjs/mocha/sync_tests/online.test.js +++ b/packages/snjs/mocha/sync_tests/online.test.js @@ -113,7 +113,7 @@ describe('online syncing', function () { for (let i = 0; i < syncCount; i++) { application.sync.sync(syncOptions) - await Factory.sleep(0.01) + await Factory.sleep(0.01, undefined, true) } await promise expect(promise).to.be.fulfilled @@ -958,6 +958,11 @@ describe('online syncing', function () { }, }) + context.anticipateConsoleError( + 'Error decrypting payload', + 'The encrypted payload above is not a valid encrypted payload.', + ) + await application.sync.handleSuccessServerResponse({ payloadsSavedOrSaving: [], options: {} }, response) expect(application.payloads.findOne(invalidPayload.uuid)).to.not.be.ok diff --git a/packages/snjs/package.json b/packages/snjs/package.json index 563cf25f255..067af4f890c 100644 --- a/packages/snjs/package.json +++ b/packages/snjs/package.json @@ -37,7 +37,7 @@ "@babel/preset-env": "*", "@standardnotes/api": "workspace:*", "@standardnotes/common": "^1.50.0", - "@standardnotes/domain-core": "^1.24.0", + "@standardnotes/domain-core": "^1.25.0", "@standardnotes/domain-events": "^2.108.1", "@standardnotes/encryption": "workspace:*", "@standardnotes/features": "workspace:*", diff --git a/packages/ui-services/package.json b/packages/ui-services/package.json index e3c0b071461..8036d1bf979 100644 --- a/packages/ui-services/package.json +++ b/packages/ui-services/package.json @@ -16,7 +16,7 @@ }, "dependencies": { "@standardnotes/common": "^1.50.0", - "@standardnotes/domain-core": "^1.24.0", + "@standardnotes/domain-core": "^1.25.0", "@standardnotes/features": "workspace:^", "@standardnotes/filepicker": "workspace:^", "@standardnotes/models": "workspace:^", diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults.tsx index b93e19c2d54..c7e88443004 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults.tsx @@ -77,6 +77,14 @@ const Vaults = () => { }) }, [application.sharedVaults, updateAllData]) + useEffect(() => { + return application.sharedVaults.addEventObserver((event) => { + if (event === SharedVaultServiceEvent.SharedVaultFileStorageUsageChanged) { + void updateAllData() + } + }) + }, [application.sharedVaults, updateAllData]) + useEffect(() => { return application.vaultUsers.addEventObserver((event) => { if (event === VaultUserServiceEvent.UsersChanged) { diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults/VaultItem.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults/VaultItem.tsx index 6fee6bd50e0..cea705aca55 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults/VaultItem.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Vaults/Vaults/VaultItem.tsx @@ -1,12 +1,13 @@ +import { formatSizeToReadableString } from '@standardnotes/filepicker' +import { ButtonType, VaultListingInterface, isClientDisplayableError } from '@standardnotes/snjs' +import { useCallback, useState } from 'react' + import { useApplication } from '@/Components/ApplicationProvider' import Button from '@/Components/Button/Button' import Icon from '@/Components/Icon/Icon' import ModalOverlay from '@/Components/Modal/ModalOverlay' -import { ButtonType, VaultListingInterface, isClientDisplayableError } from '@standardnotes/snjs' -import { useCallback, useState } from 'react' import ContactInviteModal from '../Invites/ContactInviteModal' import EditVaultModal from './VaultModal/EditVaultModal' - type Props = { vault: VaultListingInterface } @@ -123,6 +124,10 @@ const VaultItem = ({ vault }: Props) => { )} Vault ID: {vault.systemIdentifier} + + File storage used: {formatSizeToReadableString(vault.sharing?.fileBytesUsed ?? 0)} + +