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:
Karol Sójko
2023-08-11 08:59:16 +02:00
committed by GitHub
parent 05f3672526
commit 5bca53736b
87 changed files with 505 additions and 169 deletions

View File

@@ -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)
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]) {

View File

@@ -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)

View File

@@ -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<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(
{
...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')
}

View File

@@ -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)