chore: display shared vault file usage (#2399)
* chore: display shared vault file usage * fix: specs * fix: reshape filtering result * fix: resolving invalid server items * fix: get revisions specs * fix: processing issue * fix: tests --------- Co-authored-by: Mo <mo@standardnotes.com>
This commit is contained in:
BIN
.yarn/cache/@standardnotes-domain-core-npm-1.25.0-51a2ed924b-f99196f620.zip
vendored
Normal file
BIN
.yarn/cache/@standardnotes-domain-core-npm-1.25.0-51a2ed924b-f99196f620.zip
vendored
Normal file
Binary file not shown.
@@ -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:*",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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:*",
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ProtocolVersion } from '@standardnotes/common'
|
||||
import { ContentType } from '@standardnotes/domain-core'
|
||||
import {
|
||||
ProtocolVersion,
|
||||
ConflictStrategy,
|
||||
DecryptedItem,
|
||||
DecryptedItemInterface,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ProtocolVersion } from '@standardnotes/common'
|
||||
import {
|
||||
ProtocolVersion,
|
||||
DecryptedPayload,
|
||||
FillItemContentSpecialized,
|
||||
PayloadTimestampDefaults,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ProtocolVersion } from '@standardnotes/common'
|
||||
import {
|
||||
ProtocolVersion,
|
||||
DecryptedItem,
|
||||
DecryptedPayloadInterface,
|
||||
NamespacedRootKeyInKeychain,
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -4,8 +4,8 @@ import {
|
||||
KeySystemRootKeyInterface,
|
||||
KeySystemRootKeyParamsInterface,
|
||||
KeySystemPasswordType,
|
||||
ProtocolVersion,
|
||||
} from '@standardnotes/models'
|
||||
import { ProtocolVersion } from '@standardnotes/common'
|
||||
import { DeriveKeySystemRootKeyUseCase } from './DeriveKeySystemRootKey'
|
||||
|
||||
export class CreateRandomKeySystemRootKey {
|
||||
|
||||
@@ -5,8 +5,8 @@ import {
|
||||
KeySystemRootKeyInterface,
|
||||
KeySystemRootKeyParamsInterface,
|
||||
KeySystemPasswordType,
|
||||
ProtocolVersion,
|
||||
} from '@standardnotes/models'
|
||||
import { ProtocolVersion } from '@standardnotes/common'
|
||||
import { DeriveKeySystemRootKeyUseCase } from './DeriveKeySystemRootKey'
|
||||
|
||||
export class CreateUserInputKeySystemRootKey {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ProtocolVersion } from '@standardnotes/common'
|
||||
import { ProtocolVersion } from '@standardnotes/models'
|
||||
import { AnyOperatorInterface } from './OperatorInterface/TypeCheck'
|
||||
|
||||
export interface EncryptionOperatorsInterface {
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ProtocolVersion } from '@standardnotes/common'
|
||||
import { ProtocolVersion } from '@standardnotes/models'
|
||||
|
||||
type UserUuid = string
|
||||
type KeySystemIdentifier = string
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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:^",
|
||||
|
||||
@@ -12,14 +12,38 @@ function CreateFilteredServerItem(item: ServerItemResponse): FilteredServerItem
|
||||
}
|
||||
}
|
||||
|
||||
export function FilterDisallowedRemotePayloadsAndMap(payloads: ServerItemResponse[]): FilteredServerItem[] {
|
||||
return payloads.filter(isRemotePayloadAllowed).map(CreateFilteredServerItem)
|
||||
}
|
||||
|
||||
export function isRemotePayloadAllowed(payload: ServerItemResponse): boolean {
|
||||
if (isCorruptTransferPayload(payload)) {
|
||||
return false
|
||||
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 isEncryptedTransferPayload(payload) || payload.content == undefined
|
||||
return {
|
||||
filtered,
|
||||
disallowed,
|
||||
}
|
||||
}
|
||||
|
||||
export function checkRemotePayloadAllowed(payload: ServerItemResponse): {
|
||||
allowed?: ServerItemResponse
|
||||
disallowed?: ServerItemResponse
|
||||
} {
|
||||
if (isCorruptTransferPayload(payload)) {
|
||||
return { disallowed: payload }
|
||||
}
|
||||
|
||||
if (isEncryptedTransferPayload(payload) || payload.content == undefined) {
|
||||
return { allowed: payload }
|
||||
} else {
|
||||
return { disallowed: payload }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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<EncryptedTransferPayload> 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
|
||||
}
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ describe('type check', () => {
|
||||
expect(
|
||||
isCorruptTransferPayload({
|
||||
uuid: '123',
|
||||
content_type: ContentType.TYPES.Unknown,
|
||||
content_type: 'Unknown',
|
||||
content: '123',
|
||||
...PayloadTimestampDefaults(),
|
||||
}),
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export type ApplicationIdentifier = string
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ProtocolVersion } from '@standardnotes/common'
|
||||
import { KeySystemIdentifier } from '../../Syncable/KeySystemRootKey/KeySystemIdentifier'
|
||||
import { ProtocolVersion } from '../Protocol/ProtocolVersion'
|
||||
import { KeySystemPasswordType } from './KeySystemPasswordType'
|
||||
|
||||
/**
|
||||
|
||||
47
packages/models/src/Domain/Local/Protocol/ProtocolVersion.ts
Normal file
47
packages/models/src/Domain/Local/Protocol/ProtocolVersion.ts
Normal file
@@ -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<Record<ProtocolVersion, number>> = 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
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Result } from '@standardnotes/domain-core'
|
||||
import { ProtocolVersion, ProtocolVersionLength } from './ProtocolVersion'
|
||||
|
||||
export function ProtocolVersionFromEncryptedString(string: string): Result<ProtocolVersion> {
|
||||
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}`)
|
||||
}
|
||||
@@ -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<RootKeyContent> {
|
||||
readonly keyParams: RootKeyParamsInterface
|
||||
|
||||
@@ -19,6 +19,7 @@ export type AsymmetricMessageSharedVaultInvite = {
|
||||
name: string
|
||||
description?: string
|
||||
iconString: IconType | EmojiString
|
||||
fileBytesUsed: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<KeySystemItemsKeyContent> {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<KeySystemRootKeyContent> {
|
||||
keyParams: KeySystemRootKeyParamsInterface
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export type VaultListingSharingInfo = {
|
||||
sharedVaultUuid: string
|
||||
ownerUserUuid: string
|
||||
fileBytesUsed: number
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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:^",
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ describe('ProcessAcceptedVaultInvite', () => {
|
||||
metadata: {
|
||||
name: 'test-name',
|
||||
iconString: 'safe-square',
|
||||
fileBytesUsed: 0,
|
||||
},
|
||||
trustedContacts: [],
|
||||
},
|
||||
|
||||
@@ -36,6 +36,7 @@ export class ProcessAcceptedVaultInvite {
|
||||
sharing: {
|
||||
sharedVaultUuid: sharedVaultUuid,
|
||||
ownerUserUuid: ownerUuid,
|
||||
fileBytesUsed: metadata.fileBytesUsed,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ApplicationIdentifier } from '@standardnotes/common'
|
||||
import {
|
||||
ApplicationIdentifier,
|
||||
FullyFormedTransferPayload,
|
||||
TransferPayload,
|
||||
NamespacedRootKeyInKeychain,
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<SyncServiceInterface>
|
||||
@@ -37,12 +39,16 @@ describe('SharedVaultService', () => {
|
||||
const deleteSharedVaultUseCase = {} as jest.Mocked<DeleteSharedVault>
|
||||
const discardItemsLocally = {} as jest.Mocked<DiscardItemsLocally>
|
||||
|
||||
syncLocalVaultsWithRemoteSharedVaults = {} as jest.Mocked<SyncLocalVaultsWithRemoteSharedVaults>
|
||||
syncLocalVaultsWithRemoteSharedVaults.execute = jest.fn()
|
||||
|
||||
const eventBus = {} as jest.Mocked<InternalEventBusInterface>
|
||||
eventBus.addEventHandler = jest.fn()
|
||||
|
||||
service = new SharedVaultService(
|
||||
items,
|
||||
session,
|
||||
syncLocalVaultsWithRemoteSharedVaults,
|
||||
getVault,
|
||||
getOwnedVaults,
|
||||
createSharedVaultUseCase,
|
||||
|
||||
@@ -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<SharedVaultServiceEvent, SharedVaultServiceEventPayload>
|
||||
@@ -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<void> {
|
||||
private async handleNotification(event: NotificationServiceEventPayload): Promise<void> {
|
||||
switch (event.eventPayload.props.type.value) {
|
||||
case NotificationType.TYPES.RemovedFromSharedVault: {
|
||||
const vault = this._getVault.execute<SharedVaultListingInterface>({
|
||||
@@ -114,6 +117,19 @@ export class SharedVaultService
|
||||
}
|
||||
break
|
||||
}
|
||||
case NotificationType.TYPES.SharedVaultFileRemoved:
|
||||
case NotificationType.TYPES.SharedVaultFileUploaded: {
|
||||
const vaultOrError = this._getVault.execute<SharedVaultListingInterface>({
|
||||
sharedVaultUuid: event.eventPayload.props.sharedVaultUuid.value,
|
||||
})
|
||||
if (!vaultOrError.isFailed()) {
|
||||
await this._syncLocalVaultsWithRemoteSharedVaults.execute([vaultOrError.getValue()])
|
||||
|
||||
void this.notifyEventSync(SharedVaultServiceEvent.SharedVaultStatusChanged)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { KeySystemIdentifier } from '@standardnotes/models'
|
||||
|
||||
export enum SharedVaultServiceEvent {
|
||||
SharedVaultStatusChanged = 'SharedVaultStatusChanged',
|
||||
SharedVaultFileStorageUsageChanged = 'SharedVaultFileStorageUsageChanged',
|
||||
}
|
||||
|
||||
export type SharedVaultServiceEventPayload = {
|
||||
|
||||
@@ -31,6 +31,7 @@ export class ConvertToSharedVault {
|
||||
mutator.sharing = {
|
||||
sharedVaultUuid: serverVaultHash.uuid,
|
||||
ownerUserUuid: serverVaultHash.user_uuid,
|
||||
fileBytesUsed: serverVaultHash.file_upload_bytes_used,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -50,6 +50,7 @@ export class CreateSharedVault {
|
||||
mutator.sharing = {
|
||||
sharedVaultUuid: serverVaultHash.uuid,
|
||||
ownerUserUuid: serverVaultHash.user_uuid,
|
||||
fileBytesUsed: serverVaultHash.file_upload_bytes_used,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -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<SharedVaultServerInterface>
|
||||
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<MutatorClientInterface>
|
||||
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<VaultListingInterface>]
|
||||
|
||||
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<VaultListingInterface>]
|
||||
|
||||
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<VaultListingInterface>]
|
||||
|
||||
const useCase = createUseCase()
|
||||
await useCase.execute(localVaults)
|
||||
|
||||
expect(mutator.changeItem).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@@ -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<void> {
|
||||
constructor(
|
||||
private sharedVaultServer: SharedVaultServerInterface,
|
||||
private mutator: MutatorClientInterface,
|
||||
) {}
|
||||
|
||||
async execute(localVaults: VaultListingInterface[]): Promise<Result<void>> {
|
||||
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<VaultListingMutator, SharedVaultListingInterface>(localVault, (mutator) => {
|
||||
/* istanbul ignore next */
|
||||
mutator.sharing = {
|
||||
sharedVaultUuid: remoteVault.uuid,
|
||||
ownerUserUuid: remoteVault.user_uuid,
|
||||
fileBytesUsed: remoteVault.file_upload_bytes_used,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
}
|
||||
@@ -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 =
|
||||
|
||||
@@ -123,6 +123,7 @@ export class InviteToVault implements UseCaseInterface<SharedVaultInviteServerHa
|
||||
name: params.sharedVault.name,
|
||||
description: params.sharedVault.description,
|
||||
iconString: params.sharedVault.iconString,
|
||||
fileBytesUsed: params.sharedVault.sharing.fileBytesUsed,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -161,6 +161,7 @@ export * from './SharedVaults/UseCase/NotifyVaultUsersOfKeyRotation'
|
||||
export * from './SharedVaults/UseCase/SendVaultDataChangedMessage'
|
||||
export * from './SharedVaults/UseCase/SendVaultKeyChangedMessage'
|
||||
export * from './SharedVaults/UseCase/ShareContactWithVault'
|
||||
export * from './SharedVaults/UseCase/SyncLocalVaultsWithRemoteSharedVaults'
|
||||
export * from './Singleton/SingletonManagerInterface'
|
||||
export * from './Status/StatusService'
|
||||
export * from './Status/StatusServiceInterface'
|
||||
|
||||
@@ -140,6 +140,7 @@ import {
|
||||
IsApplicationUsingThirdPartyHost,
|
||||
CreateDecryptedBackupFile,
|
||||
CreateEncryptedBackupFile,
|
||||
SyncLocalVaultsWithRemoteSharedVaults,
|
||||
} from '@standardnotes/services'
|
||||
import { ItemManager } from '../../Services/Items/ItemManager'
|
||||
import { PayloadManager } from '../../Services/Payloads/PayloadManager'
|
||||
@@ -399,6 +400,13 @@ export class Dependencies {
|
||||
return new GetVaults(this.get<ItemManager>(TYPES.ItemManager))
|
||||
})
|
||||
|
||||
this.factory.set(TYPES.SyncLocalVaultsWithRemoteSharedVaults, () => {
|
||||
return new SyncLocalVaultsWithRemoteSharedVaults(
|
||||
this.get<SharedVaultServer>(TYPES.SharedVaultServer),
|
||||
this.get<MutatorService>(TYPES.MutatorService),
|
||||
)
|
||||
})
|
||||
|
||||
this.factory.set(TYPES.ChangeAndSaveItem, () => {
|
||||
return new ChangeAndSaveItem(
|
||||
this.get<ItemManager>(TYPES.ItemManager),
|
||||
@@ -893,6 +901,7 @@ export class Dependencies {
|
||||
return new SharedVaultService(
|
||||
this.get<ItemManager>(TYPES.ItemManager),
|
||||
this.get<SessionManager>(TYPES.SessionManager),
|
||||
this.get<SyncLocalVaultsWithRemoteSharedVaults>(TYPES.SyncLocalVaultsWithRemoteSharedVaults),
|
||||
this.get<GetVault>(TYPES.GetVault),
|
||||
this.get<GetOwnedSharedVaults>(TYPES.GetOwnedSharedVaults),
|
||||
this.get<CreateSharedVault>(TYPES.CreateSharedVault),
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ApplicationIdentifier } from '@standardnotes/common'
|
||||
import { ApplicationIdentifier } from '@standardnotes/models'
|
||||
|
||||
export type ApplicationDescriptor = {
|
||||
identifier: ApplicationIdentifier
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
EncryptedPayload,
|
||||
HistoryEntry,
|
||||
isErrorDecryptingPayload,
|
||||
isRemotePayloadAllowed,
|
||||
checkRemotePayloadAllowed,
|
||||
NoteContent,
|
||||
PayloadTimestampDefaults,
|
||||
} from '@standardnotes/models'
|
||||
@@ -71,7 +71,8 @@ export class GetRevision implements UseCaseInterface<HistoryEntry> {
|
||||
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)}`)
|
||||
}
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) => {
|
||||
const disallowedPayloads = []
|
||||
|
||||
const savedItemsFilteringResult = FilterDisallowedRemotePayloadsAndMap(this.successResponseData?.saved_items || [])
|
||||
this.savedPayloads = savedItemsFilteringResult.filtered.map((rawItem) => {
|
||||
return CreateServerSyncSavedPayload(rawItem)
|
||||
},
|
||||
})
|
||||
disallowedPayloads.push(...savedItemsFilteringResult.disallowed)
|
||||
|
||||
const retrievedItemsFilteringResult = FilterDisallowedRemotePayloadsAndMap(
|
||||
this.successResponseData?.retrieved_items || [],
|
||||
)
|
||||
this.retrievedPayloads = retrievedItemsFilteringResult.filtered
|
||||
disallowedPayloads.push(...retrievedItemsFilteringResult.disallowed)
|
||||
|
||||
this.retrievedPayloads = FilterDisallowedRemotePayloadsAndMap(this.successResponseData?.retrieved_items || [])
|
||||
|
||||
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(<TrustedConflictParams>{
|
||||
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(<TrustedConflictParams>{
|
||||
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(<TrustedConflictParams>{
|
||||
type: ConflictType.InvalidServerItem,
|
||||
server_item: serverItemFilteringResult.disallowed[0],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (!trustedConflicts[conflict.type]) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Result } from '@standardnotes/domain-core'
|
||||
import {
|
||||
EncryptedPayloadInterface,
|
||||
DeletedPayloadInterface,
|
||||
@@ -10,11 +11,13 @@ import {
|
||||
export function CreatePayloadFromRawServerItem(
|
||||
rawItem: FilteredServerItem,
|
||||
source: PayloadSource,
|
||||
): EncryptedPayloadInterface | DeletedPayloadInterface {
|
||||
): Result<EncryptedPayloadInterface | DeletedPayloadInterface> {
|
||||
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(
|
||||
try {
|
||||
return Result.ok(
|
||||
new EncryptedPayload(
|
||||
{
|
||||
...rawItem,
|
||||
items_key_id: rawItem.items_key_id,
|
||||
@@ -24,8 +27,11 @@ export function CreatePayloadFromRawServerItem(
|
||||
waitingForKey: false,
|
||||
},
|
||||
source,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
throw Error('Unhandled case in createPayloadFromRawItem')
|
||||
} catch (error) {
|
||||
return Result.fail(JSON.stringify(error))
|
||||
}
|
||||
}
|
||||
return Result.fail('Unhandled case in createPayloadFromRawItem')
|
||||
}
|
||||
|
||||
@@ -1110,7 +1110,12 @@ export class SyncService
|
||||
items: FilteredServerItem[],
|
||||
source: PayloadSource,
|
||||
): Promise<FullyFormedPayloadInterface[]> {
|
||||
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)
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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) {
|
||||
export async function sleep(seconds, reason, dontLog = false) {
|
||||
if (!dontLog) {
|
||||
console.log('[Factory] Sleeping for reason', reason)
|
||||
}
|
||||
return Utils.sleep(seconds)
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ describe('payload', () => {
|
||||
content_type: ContentType.TYPES.Note,
|
||||
content: '000:somebase64string',
|
||||
}),
|
||||
'Unrecognized protocol version 000',
|
||||
'EncryptedPayload constructor versionResult is failed',
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:*",
|
||||
|
||||
@@ -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:^",
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) => {
|
||||
)}
|
||||
<span className="mr-auto overflow-hidden text-ellipsis text-sm">Vault ID: {vault.systemIdentifier}</span>
|
||||
|
||||
<span className="mr-auto overflow-hidden text-ellipsis text-sm">
|
||||
File storage used: {formatSizeToReadableString(vault.sharing?.fileBytesUsed ?? 0)}
|
||||
</span>
|
||||
|
||||
<div className="mt-2 flex w-full">
|
||||
<Button label="Edit" className="mr-3 text-xs" onClick={openEditModal} />
|
||||
{isAdmin && <Button colorStyle="danger" label="Delete" className="mr-3 text-xs" onClick={deleteVault} />}
|
||||
|
||||
@@ -18,8 +18,8 @@ import {
|
||||
SyncServiceInterface,
|
||||
User,
|
||||
UserServiceInterface,
|
||||
UserRequestType,
|
||||
} from '@standardnotes/snjs'
|
||||
import { UserRequestType } from '@standardnotes/common'
|
||||
|
||||
import { AccountMenuController } from '@/Controllers/AccountMenu/AccountMenuController'
|
||||
import { PreferencesController } from '@/Controllers/PreferencesController'
|
||||
|
||||
27
yarn.lock
27
yarn.lock
@@ -4140,7 +4140,7 @@ __metadata:
|
||||
resolution: "@standardnotes/api@workspace:packages/api"
|
||||
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:*"
|
||||
@@ -4290,7 +4290,7 @@ __metadata:
|
||||
"@babel/core": "*"
|
||||
"@babel/preset-env": "*"
|
||||
"@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:*"
|
||||
"@types/fs-extra": ^11.0.1
|
||||
@@ -4333,7 +4333,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@standardnotes/domain-core@npm:^1.24.0, @standardnotes/domain-core@npm:^1.24.1":
|
||||
"@standardnotes/domain-core@npm:^1.24.1":
|
||||
version: 1.24.1
|
||||
resolution: "@standardnotes/domain-core@npm:1.24.1"
|
||||
dependencies:
|
||||
@@ -4342,6 +4342,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@standardnotes/domain-core@npm:^1.25.0":
|
||||
version: 1.25.0
|
||||
resolution: "@standardnotes/domain-core@npm:1.25.0"
|
||||
dependencies:
|
||||
uuid: ^9.0.0
|
||||
checksum: f99196f6209a05a50e84371d3a59cf870937a5589f4ba4caab0f2eb17c2cfa733142b18ca8788016c81ca609d1f5a0461e51bcf159a67d631e249a04a5568244
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@standardnotes/domain-events@npm:^2.108.1":
|
||||
version: 2.113.1
|
||||
resolution: "@standardnotes/domain-events@npm:2.113.1"
|
||||
@@ -4385,7 +4394,7 @@ __metadata:
|
||||
dependencies:
|
||||
"@standardnotes/common": ^1.50.0
|
||||
"@standardnotes/config": 2.4.3
|
||||
"@standardnotes/domain-core": ^1.24.0
|
||||
"@standardnotes/domain-core": ^1.25.0
|
||||
"@standardnotes/models": "workspace:*"
|
||||
"@standardnotes/responses": "workspace:*"
|
||||
"@standardnotes/sncrypto-common": "workspace:*"
|
||||
@@ -4420,7 +4429,7 @@ __metadata:
|
||||
resolution: "@standardnotes/features@workspace:packages/features"
|
||||
dependencies:
|
||||
"@standardnotes/common": ^1.50.0
|
||||
"@standardnotes/domain-core": ^1.24.0
|
||||
"@standardnotes/domain-core": ^1.25.0
|
||||
"@types/jest": ^29.2.3
|
||||
"@typescript-eslint/eslint-plugin": "*"
|
||||
eslint: "*"
|
||||
@@ -4626,7 +4635,7 @@ __metadata:
|
||||
resolution: "@standardnotes/models@workspace:packages/models"
|
||||
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:^"
|
||||
@@ -4712,7 +4721,7 @@ __metadata:
|
||||
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:^"
|
||||
@@ -4811,7 +4820,7 @@ __metadata:
|
||||
"@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:*"
|
||||
@@ -4936,7 +4945,7 @@ __metadata:
|
||||
resolution: "@standardnotes/ui-services@workspace:packages/ui-services"
|
||||
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:^"
|
||||
|
||||
Reference in New Issue
Block a user