1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 00:03:56 +00:00

[PM-17563] Security task background synchronization (#14086)

* [PM-17563] Implement listenForTaskNotifications in default-task.service.ts

* [PM-17563] Update syncService to include userId in syncCompleted message payload

* [PM-17563] Update default-task.service to react to both pending task notifications and completed syncs

* [PM-17563] Add unit tests around task notification listening

* [PM-17563] Only check for at risk password tasks if tasks are enabled

* [PM-17563] Make userId required even if undefined

* [PM-17563] Use abstract TaskService instead of default implementation in MainBackground

* [PM-17563] Cleanup userId filtering
This commit is contained in:
Shane Melton
2025-04-04 13:42:44 -07:00
committed by GitHub
parent 1af8fe2012
commit a7fe4877d7
9 changed files with 400 additions and 39 deletions

View File

@@ -105,14 +105,14 @@ export abstract class CoreSyncService implements SyncService {
if (remoteFolder != null) {
await this.folderService.upsert(new FolderData(remoteFolder), userId);
this.messageSender.send("syncedUpsertedFolder", { folderId: notification.id });
return this.syncCompleted(true);
return this.syncCompleted(true, userId);
}
}
} catch (e) {
this.logService.error(e);
}
}
return this.syncCompleted(false);
return this.syncCompleted(false, userId);
}
async syncDeleteFolder(notification: SyncFolderNotification, userId: UserId): Promise<boolean> {
@@ -123,10 +123,10 @@ export abstract class CoreSyncService implements SyncService {
if (authStatus >= AuthenticationStatus.Locked) {
await this.folderService.delete(notification.id, userId);
this.messageSender.send("syncedDeletedFolder", { folderId: notification.id });
this.syncCompleted(true);
this.syncCompleted(true, userId);
return true;
}
return this.syncCompleted(false);
return this.syncCompleted(false, userId);
}
async syncUpsertCipher(
@@ -183,18 +183,18 @@ export abstract class CoreSyncService implements SyncService {
if (remoteCipher != null) {
await this.cipherService.upsert(new CipherData(remoteCipher));
this.messageSender.send("syncedUpsertedCipher", { cipherId: notification.id });
return this.syncCompleted(true);
return this.syncCompleted(true, userId);
}
}
} catch (e) {
if (e != null && e.statusCode === 404 && isEdit) {
await this.cipherService.delete(notification.id, userId);
this.messageSender.send("syncedDeletedCipher", { cipherId: notification.id });
return this.syncCompleted(true);
return this.syncCompleted(true, userId);
}
}
}
return this.syncCompleted(false);
return this.syncCompleted(false, userId);
}
async syncDeleteCipher(notification: SyncCipherNotification, userId: UserId): Promise<boolean> {
@@ -204,9 +204,9 @@ export abstract class CoreSyncService implements SyncService {
if (authStatus >= AuthenticationStatus.Locked) {
await this.cipherService.delete(notification.id, userId);
this.messageSender.send("syncedDeletedCipher", { cipherId: notification.id });
return this.syncCompleted(true);
return this.syncCompleted(true, userId);
}
return this.syncCompleted(false);
return this.syncCompleted(false, userId);
}
async syncUpsertSend(notification: SyncSendNotification, isEdit: boolean): Promise<boolean> {
@@ -234,14 +234,15 @@ export abstract class CoreSyncService implements SyncService {
if (remoteSend != null) {
await this.sendService.upsert(new SendData(remoteSend));
this.messageSender.send("syncedUpsertedSend", { sendId: notification.id });
return this.syncCompleted(true);
return this.syncCompleted(true, activeUserId);
}
}
} catch (e) {
this.logService.error(e);
}
}
return this.syncCompleted(false);
// TODO: Update syncCompleted userId when send service allows modification of non-active users
return this.syncCompleted(false, undefined);
}
async syncDeleteSend(notification: SyncSendNotification): Promise<boolean> {
@@ -249,10 +250,11 @@ export abstract class CoreSyncService implements SyncService {
if (await this.stateService.getIsAuthenticated()) {
await this.sendService.delete(notification.id);
this.messageSender.send("syncedDeletedSend", { sendId: notification.id });
this.syncCompleted(true);
// TODO: Update syncCompleted userId when send service allows modification of non-active users
this.syncCompleted(true, undefined);
return true;
}
return this.syncCompleted(false);
return this.syncCompleted(false, undefined);
}
// Helpers
@@ -262,9 +264,9 @@ export abstract class CoreSyncService implements SyncService {
this.messageSender.send("syncStarted");
}
protected syncCompleted(successfully: boolean): boolean {
protected syncCompleted(successfully: boolean, userId: UserId | undefined): boolean {
this.syncInProgress = false;
this.messageSender.send("syncCompleted", { successfully: successfully });
this.messageSender.send("syncCompleted", { successfully: successfully, userId });
return successfully;
}
}

View File

@@ -3,9 +3,9 @@
import { firstValueFrom, map } from "rxjs";
import {
CollectionService,
CollectionData,
CollectionDetailsResponse,
CollectionService,
} from "@bitwarden/admin-console/common";
import { KeyService } from "@bitwarden/key-management";
@@ -107,7 +107,7 @@ export class DefaultSyncService extends CoreSyncService {
this.syncStarted();
const authStatus = await firstValueFrom(this.authService.authStatusFor$(userId));
if (authStatus === AuthenticationStatus.LoggedOut) {
return this.syncCompleted(false);
return this.syncCompleted(false, userId);
}
const now = new Date();
@@ -116,14 +116,14 @@ export class DefaultSyncService extends CoreSyncService {
needsSync = await this.needsSyncing(forceSync);
} catch (e) {
if (allowThrowOnError) {
this.syncCompleted(false);
this.syncCompleted(false, userId);
throw e;
}
}
if (!needsSync) {
await this.setLastSync(now, userId);
return this.syncCompleted(false);
return this.syncCompleted(false, userId);
}
try {
@@ -139,13 +139,13 @@ export class DefaultSyncService extends CoreSyncService {
await this.syncPolicies(response.policies, response.profile.id);
await this.setLastSync(now, userId);
return this.syncCompleted(true);
return this.syncCompleted(true, userId);
} catch (e) {
if (allowThrowOnError) {
this.syncCompleted(false);
this.syncCompleted(false, userId);
throw e;
} else {
return this.syncCompleted(false);
return this.syncCompleted(false, userId);
}
}
}