|
@@ -11,6 +11,7 @@ import { GetSharedVaultInvitesSentToUser } from '../../SharedVaults/GetSharedVau
|
|
import { GetMessagesSentToUser } from '../../Messaging/GetMessagesSentToUser/GetMessagesSentToUser'
|
|
import { GetMessagesSentToUser } from '../../Messaging/GetMessagesSentToUser/GetMessagesSentToUser'
|
|
import { GetUserNotifications } from '../../Messaging/GetUserNotifications/GetUserNotifications'
|
|
import { GetUserNotifications } from '../../Messaging/GetUserNotifications/GetUserNotifications'
|
|
import { ItemRepositoryResolverInterface } from '../../../Item/ItemRepositoryResolverInterface'
|
|
import { ItemRepositoryResolverInterface } from '../../../Item/ItemRepositoryResolverInterface'
|
|
|
|
+import { Logger } from 'winston'
|
|
|
|
|
|
export class SyncItems implements UseCaseInterface<SyncItemsResponse> {
|
|
export class SyncItems implements UseCaseInterface<SyncItemsResponse> {
|
|
constructor(
|
|
constructor(
|
|
@@ -21,99 +22,111 @@ export class SyncItems implements UseCaseInterface<SyncItemsResponse> {
|
|
private getSharedVaultInvitesSentToUserUseCase: GetSharedVaultInvitesSentToUser,
|
|
private getSharedVaultInvitesSentToUserUseCase: GetSharedVaultInvitesSentToUser,
|
|
private getMessagesSentToUser: GetMessagesSentToUser,
|
|
private getMessagesSentToUser: GetMessagesSentToUser,
|
|
private getUserNotifications: GetUserNotifications,
|
|
private getUserNotifications: GetUserNotifications,
|
|
|
|
+ private logger: Logger,
|
|
) {}
|
|
) {}
|
|
|
|
|
|
async execute(dto: SyncItemsDTO): Promise<Result<SyncItemsResponse>> {
|
|
async execute(dto: SyncItemsDTO): Promise<Result<SyncItemsResponse>> {
|
|
- const roleNamesOrError = RoleNameCollection.create(dto.roleNames)
|
|
|
|
- if (roleNamesOrError.isFailed()) {
|
|
|
|
- return Result.fail(roleNamesOrError.getError())
|
|
|
|
- }
|
|
|
|
- const roleNames = roleNamesOrError.getValue()
|
|
|
|
-
|
|
|
|
- const getItemsResultOrError = await this.getItemsUseCase.execute({
|
|
|
|
- userUuid: dto.userUuid,
|
|
|
|
- syncToken: dto.syncToken,
|
|
|
|
- cursorToken: dto.cursorToken,
|
|
|
|
- limit: dto.limit,
|
|
|
|
- contentType: dto.contentType,
|
|
|
|
- sharedVaultUuids: dto.sharedVaultUuids,
|
|
|
|
- roleNames: dto.roleNames,
|
|
|
|
- })
|
|
|
|
- if (getItemsResultOrError.isFailed()) {
|
|
|
|
- return Result.fail(getItemsResultOrError.getError())
|
|
|
|
- }
|
|
|
|
- const getItemsResult = getItemsResultOrError.getValue()
|
|
|
|
-
|
|
|
|
- const saveItemsResultOrError = await this.saveItemsUseCase.execute({
|
|
|
|
- itemHashes: dto.itemHashes,
|
|
|
|
- userUuid: dto.userUuid,
|
|
|
|
- apiVersion: dto.apiVersion,
|
|
|
|
- readOnlyAccess: dto.readOnlyAccess,
|
|
|
|
- sessionUuid: dto.sessionUuid,
|
|
|
|
- snjsVersion: dto.snjsVersion,
|
|
|
|
- roleNames: dto.roleNames,
|
|
|
|
- onGoingRevisionsTransition: dto.onGoingRevisionsTransition,
|
|
|
|
- })
|
|
|
|
- if (saveItemsResultOrError.isFailed()) {
|
|
|
|
- return Result.fail(saveItemsResultOrError.getError())
|
|
|
|
- }
|
|
|
|
- const saveItemsResult = saveItemsResultOrError.getValue()
|
|
|
|
-
|
|
|
|
- let retrievedItems = this.filterOutSyncConflictsForConsecutiveSyncs(getItemsResult.items, saveItemsResult.conflicts)
|
|
|
|
- const isSharedVaultExclusiveSync = dto.sharedVaultUuids && dto.sharedVaultUuids.length > 0
|
|
|
|
- if (this.isFirstSync(dto) && !isSharedVaultExclusiveSync) {
|
|
|
|
- retrievedItems = await this.frontLoadKeysItemsToTop(dto.userUuid, roleNames, retrievedItems)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- const sharedVaultsOrError = await this.getSharedVaultsUseCase.execute({
|
|
|
|
- userUuid: dto.userUuid,
|
|
|
|
- lastSyncTime: getItemsResult.lastSyncTime ?? undefined,
|
|
|
|
- })
|
|
|
|
- if (sharedVaultsOrError.isFailed()) {
|
|
|
|
- return Result.fail(sharedVaultsOrError.getError())
|
|
|
|
- }
|
|
|
|
- const sharedVaults = sharedVaultsOrError.getValue()
|
|
|
|
-
|
|
|
|
- const sharedVaultInvitesOrError = await this.getSharedVaultInvitesSentToUserUseCase.execute({
|
|
|
|
- userUuid: dto.userUuid,
|
|
|
|
- lastSyncTime: getItemsResult.lastSyncTime ?? undefined,
|
|
|
|
- })
|
|
|
|
- if (sharedVaultInvitesOrError.isFailed()) {
|
|
|
|
- return Result.fail(sharedVaultInvitesOrError.getError())
|
|
|
|
- }
|
|
|
|
- const sharedVaultInvites = sharedVaultInvitesOrError.getValue()
|
|
|
|
|
|
+ try {
|
|
|
|
+ const roleNamesOrError = RoleNameCollection.create(dto.roleNames)
|
|
|
|
+ if (roleNamesOrError.isFailed()) {
|
|
|
|
+ return Result.fail(roleNamesOrError.getError())
|
|
|
|
+ }
|
|
|
|
+ const roleNames = roleNamesOrError.getValue()
|
|
|
|
+
|
|
|
|
+ const getItemsResultOrError = await this.getItemsUseCase.execute({
|
|
|
|
+ userUuid: dto.userUuid,
|
|
|
|
+ syncToken: dto.syncToken,
|
|
|
|
+ cursorToken: dto.cursorToken,
|
|
|
|
+ limit: dto.limit,
|
|
|
|
+ contentType: dto.contentType,
|
|
|
|
+ sharedVaultUuids: dto.sharedVaultUuids,
|
|
|
|
+ roleNames: dto.roleNames,
|
|
|
|
+ })
|
|
|
|
+ if (getItemsResultOrError.isFailed()) {
|
|
|
|
+ return Result.fail(getItemsResultOrError.getError())
|
|
|
|
+ }
|
|
|
|
+ const getItemsResult = getItemsResultOrError.getValue()
|
|
|
|
+
|
|
|
|
+ const saveItemsResultOrError = await this.saveItemsUseCase.execute({
|
|
|
|
+ itemHashes: dto.itemHashes,
|
|
|
|
+ userUuid: dto.userUuid,
|
|
|
|
+ apiVersion: dto.apiVersion,
|
|
|
|
+ readOnlyAccess: dto.readOnlyAccess,
|
|
|
|
+ sessionUuid: dto.sessionUuid,
|
|
|
|
+ snjsVersion: dto.snjsVersion,
|
|
|
|
+ roleNames: dto.roleNames,
|
|
|
|
+ onGoingRevisionsTransition: dto.onGoingRevisionsTransition,
|
|
|
|
+ })
|
|
|
|
+ if (saveItemsResultOrError.isFailed()) {
|
|
|
|
+ return Result.fail(saveItemsResultOrError.getError())
|
|
|
|
+ }
|
|
|
|
+ const saveItemsResult = saveItemsResultOrError.getValue()
|
|
|
|
+
|
|
|
|
+ let retrievedItems = this.filterOutSyncConflictsForConsecutiveSyncs(
|
|
|
|
+ getItemsResult.items,
|
|
|
|
+ saveItemsResult.conflicts,
|
|
|
|
+ )
|
|
|
|
+ const isSharedVaultExclusiveSync = dto.sharedVaultUuids && dto.sharedVaultUuids.length > 0
|
|
|
|
+ if (this.isFirstSync(dto) && !isSharedVaultExclusiveSync) {
|
|
|
|
+ retrievedItems = await this.frontLoadKeysItemsToTop(dto.userUuid, roleNames, retrievedItems)
|
|
|
|
+ }
|
|
|
|
|
|
- const messagesOrError = await this.getMessagesSentToUser.execute({
|
|
|
|
- recipientUuid: dto.userUuid,
|
|
|
|
- lastSyncTime: getItemsResult.lastSyncTime ?? undefined,
|
|
|
|
- })
|
|
|
|
- if (messagesOrError.isFailed()) {
|
|
|
|
- return Result.fail(messagesOrError.getError())
|
|
|
|
- }
|
|
|
|
- const messages = messagesOrError.getValue()
|
|
|
|
|
|
+ const sharedVaultsOrError = await this.getSharedVaultsUseCase.execute({
|
|
|
|
+ userUuid: dto.userUuid,
|
|
|
|
+ lastSyncTime: getItemsResult.lastSyncTime ?? undefined,
|
|
|
|
+ })
|
|
|
|
+ if (sharedVaultsOrError.isFailed()) {
|
|
|
|
+ return Result.fail(sharedVaultsOrError.getError())
|
|
|
|
+ }
|
|
|
|
+ const sharedVaults = sharedVaultsOrError.getValue()
|
|
|
|
+
|
|
|
|
+ const sharedVaultInvitesOrError = await this.getSharedVaultInvitesSentToUserUseCase.execute({
|
|
|
|
+ userUuid: dto.userUuid,
|
|
|
|
+ lastSyncTime: getItemsResult.lastSyncTime ?? undefined,
|
|
|
|
+ })
|
|
|
|
+ if (sharedVaultInvitesOrError.isFailed()) {
|
|
|
|
+ return Result.fail(sharedVaultInvitesOrError.getError())
|
|
|
|
+ }
|
|
|
|
+ const sharedVaultInvites = sharedVaultInvitesOrError.getValue()
|
|
|
|
+
|
|
|
|
+ const messagesOrError = await this.getMessagesSentToUser.execute({
|
|
|
|
+ recipientUuid: dto.userUuid,
|
|
|
|
+ lastSyncTime: getItemsResult.lastSyncTime ?? undefined,
|
|
|
|
+ })
|
|
|
|
+ if (messagesOrError.isFailed()) {
|
|
|
|
+ return Result.fail(messagesOrError.getError())
|
|
|
|
+ }
|
|
|
|
+ const messages = messagesOrError.getValue()
|
|
|
|
+
|
|
|
|
+ const notificationsOrError = await this.getUserNotifications.execute({
|
|
|
|
+ userUuid: dto.userUuid,
|
|
|
|
+ lastSyncTime: getItemsResult.lastSyncTime ?? undefined,
|
|
|
|
+ })
|
|
|
|
+ if (notificationsOrError.isFailed()) {
|
|
|
|
+ return Result.fail(notificationsOrError.getError())
|
|
|
|
+ }
|
|
|
|
+ const notifications = notificationsOrError.getValue()
|
|
|
|
+
|
|
|
|
+ const syncResponse: SyncItemsResponse = {
|
|
|
|
+ retrievedItems,
|
|
|
|
+ syncToken: saveItemsResult.syncToken,
|
|
|
|
+ savedItems: saveItemsResult.savedItems,
|
|
|
|
+ conflicts: saveItemsResult.conflicts,
|
|
|
|
+ cursorToken: getItemsResult.cursorToken,
|
|
|
|
+ sharedVaultInvites,
|
|
|
|
+ sharedVaults,
|
|
|
|
+ messages,
|
|
|
|
+ notifications,
|
|
|
|
+ }
|
|
|
|
|
|
- const notificationsOrError = await this.getUserNotifications.execute({
|
|
|
|
- userUuid: dto.userUuid,
|
|
|
|
- lastSyncTime: getItemsResult.lastSyncTime ?? undefined,
|
|
|
|
- })
|
|
|
|
- if (notificationsOrError.isFailed()) {
|
|
|
|
- return Result.fail(notificationsOrError.getError())
|
|
|
|
- }
|
|
|
|
- const notifications = notificationsOrError.getValue()
|
|
|
|
-
|
|
|
|
- const syncResponse: SyncItemsResponse = {
|
|
|
|
- retrievedItems,
|
|
|
|
- syncToken: saveItemsResult.syncToken,
|
|
|
|
- savedItems: saveItemsResult.savedItems,
|
|
|
|
- conflicts: saveItemsResult.conflicts,
|
|
|
|
- cursorToken: getItemsResult.cursorToken,
|
|
|
|
- sharedVaultInvites,
|
|
|
|
- sharedVaults,
|
|
|
|
- messages,
|
|
|
|
- notifications,
|
|
|
|
|
|
+ return Result.ok(syncResponse)
|
|
|
|
+ } catch (error) {
|
|
|
|
+ const itemHashUuids = dto.itemHashes.map((itemHash) => itemHash.props.uuid)
|
|
|
|
+ this.logger.error(
|
|
|
|
+ `Sync error for user ${dto.userUuid} syncing items ${itemHashUuids.join(',')}: ${(error as Error).message}`,
|
|
|
|
+ )
|
|
|
|
+ throw error
|
|
}
|
|
}
|
|
-
|
|
|
|
- return Result.ok(syncResponse)
|
|
|
|
}
|
|
}
|
|
|
|
|
|
private isFirstSync(dto: SyncItemsDTO): boolean {
|
|
private isFirstSync(dto: SyncItemsDTO): boolean {
|