mirror of
https://github.com/bitwarden/browser
synced 2025-12-14 15:23:33 +00:00
Merge branch 'main' into auth/pm-14369/hide-account-switcher-if-on-login-page-and-not-logged-in
This commit is contained in:
@@ -257,12 +257,9 @@ import { BrowserPlatformUtilsService } from "../platform/services/platform-utils
|
|||||||
import { PopupViewCacheBackgroundService } from "../platform/services/popup-view-cache-background.service";
|
import { PopupViewCacheBackgroundService } from "../platform/services/popup-view-cache-background.service";
|
||||||
import { BrowserSdkClientFactory } from "../platform/services/sdk/browser-sdk-client-factory";
|
import { BrowserSdkClientFactory } from "../platform/services/sdk/browser-sdk-client-factory";
|
||||||
import { BackgroundTaskSchedulerService } from "../platform/services/task-scheduler/background-task-scheduler.service";
|
import { BackgroundTaskSchedulerService } from "../platform/services/task-scheduler/background-task-scheduler.service";
|
||||||
import { ForegroundTaskSchedulerService } from "../platform/services/task-scheduler/foreground-task-scheduler.service";
|
|
||||||
import { BackgroundMemoryStorageService } from "../platform/storage/background-memory-storage.service";
|
import { BackgroundMemoryStorageService } from "../platform/storage/background-memory-storage.service";
|
||||||
import { BrowserStorageServiceProvider } from "../platform/storage/browser-storage-service.provider";
|
import { BrowserStorageServiceProvider } from "../platform/storage/browser-storage-service.provider";
|
||||||
import { ForegroundMemoryStorageService } from "../platform/storage/foreground-memory-storage.service";
|
|
||||||
import { OffscreenStorageService } from "../platform/storage/offscreen-storage.service";
|
import { OffscreenStorageService } from "../platform/storage/offscreen-storage.service";
|
||||||
import { ForegroundSyncService } from "../platform/sync/foreground-sync.service";
|
|
||||||
import { SyncServiceListener } from "../platform/sync/sync-service.listener";
|
import { SyncServiceListener } from "../platform/sync/sync-service.listener";
|
||||||
import { fromChromeRuntimeMessaging } from "../platform/utils/from-chrome-runtime-messaging";
|
import { fromChromeRuntimeMessaging } from "../platform/utils/from-chrome-runtime-messaging";
|
||||||
import VaultTimeoutService from "../services/vault-timeout/vault-timeout.service";
|
import VaultTimeoutService from "../services/vault-timeout/vault-timeout.service";
|
||||||
@@ -401,7 +398,7 @@ export default class MainBackground {
|
|||||||
|
|
||||||
private popupViewCacheBackgroundService: PopupViewCacheBackgroundService;
|
private popupViewCacheBackgroundService: PopupViewCacheBackgroundService;
|
||||||
|
|
||||||
constructor(public popupOnlyContext: boolean = false) {
|
constructor() {
|
||||||
// Services
|
// Services
|
||||||
const lockedCallback = async (userId?: string) => {
|
const lockedCallback = async (userId?: string) => {
|
||||||
if (this.notificationsService != null) {
|
if (this.notificationsService != null) {
|
||||||
@@ -460,45 +457,6 @@ export default class MainBackground {
|
|||||||
this.offscreenDocumentService,
|
this.offscreenDocumentService,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Creates a session key for mv3 storage of large memory items
|
|
||||||
const sessionKey = new Lazy(async () => {
|
|
||||||
// Key already in session storage
|
|
||||||
const sessionStorage = new BrowserMemoryStorageService();
|
|
||||||
const existingKey = await sessionStorage.get<SymmetricCryptoKey>("session-key");
|
|
||||||
if (existingKey) {
|
|
||||||
if (sessionStorage.valuesRequireDeserialization) {
|
|
||||||
return SymmetricCryptoKey.fromJSON(existingKey);
|
|
||||||
}
|
|
||||||
return existingKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
// New key
|
|
||||||
const { derivedKey } = await this.keyGenerationService.createKeyWithPurpose(
|
|
||||||
128,
|
|
||||||
"ephemeral",
|
|
||||||
"bitwarden-ephemeral",
|
|
||||||
);
|
|
||||||
await sessionStorage.save("session-key", derivedKey);
|
|
||||||
return derivedKey;
|
|
||||||
});
|
|
||||||
|
|
||||||
const mv3MemoryStorageCreator = () => {
|
|
||||||
if (this.popupOnlyContext) {
|
|
||||||
return new ForegroundMemoryStorageService();
|
|
||||||
}
|
|
||||||
|
|
||||||
// For local backed session storage, we expect that the encrypted data on disk will persist longer than the encryption key in memory
|
|
||||||
// and failures to decrypt because of that are completely expected. For this reason, we pass in `false` to the `EncryptServiceImplementation`
|
|
||||||
// so that MAC failures are not logged.
|
|
||||||
return new LocalBackedSessionStorageService(
|
|
||||||
sessionKey,
|
|
||||||
this.storageService,
|
|
||||||
new EncryptServiceImplementation(this.cryptoFunctionService, this.logService, false),
|
|
||||||
this.platformUtilsService,
|
|
||||||
this.logService,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.secureStorageService = this.storageService; // secure storage is not supported in browsers, so we use local storage and warn users when it is used
|
this.secureStorageService = this.storageService; // secure storage is not supported in browsers, so we use local storage and warn users when it is used
|
||||||
|
|
||||||
if (BrowserApi.isManifestVersion(3)) {
|
if (BrowserApi.isManifestVersion(3)) {
|
||||||
@@ -506,18 +464,47 @@ export default class MainBackground {
|
|||||||
this.memoryStorageForStateProviders = new BrowserMemoryStorageService(); // mv3 stores to storage.session
|
this.memoryStorageForStateProviders = new BrowserMemoryStorageService(); // mv3 stores to storage.session
|
||||||
this.memoryStorageService = this.memoryStorageForStateProviders;
|
this.memoryStorageService = this.memoryStorageForStateProviders;
|
||||||
} else {
|
} else {
|
||||||
if (popupOnlyContext) {
|
this.memoryStorageForStateProviders = new BackgroundMemoryStorageService(); // mv2 stores to memory
|
||||||
this.memoryStorageForStateProviders = new ForegroundMemoryStorageService();
|
this.memoryStorageService = this.memoryStorageForStateProviders;
|
||||||
this.memoryStorageService = new ForegroundMemoryStorageService();
|
|
||||||
} else {
|
|
||||||
this.memoryStorageForStateProviders = new BackgroundMemoryStorageService(); // mv2 stores to memory
|
|
||||||
this.memoryStorageService = this.memoryStorageForStateProviders;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.largeObjectMemoryStorageForStateProviders = BrowserApi.isManifestVersion(3)
|
if (BrowserApi.isManifestVersion(3)) {
|
||||||
? mv3MemoryStorageCreator() // mv3 stores to local-backed session storage
|
// Creates a session key for mv3 storage of large memory items
|
||||||
: this.memoryStorageForStateProviders; // mv2 stores to the same location
|
const sessionKey = new Lazy(async () => {
|
||||||
|
// Key already in session storage
|
||||||
|
const sessionStorage = new BrowserMemoryStorageService();
|
||||||
|
const existingKey = await sessionStorage.get<SymmetricCryptoKey>("session-key");
|
||||||
|
if (existingKey) {
|
||||||
|
if (sessionStorage.valuesRequireDeserialization) {
|
||||||
|
return SymmetricCryptoKey.fromJSON(existingKey);
|
||||||
|
}
|
||||||
|
return existingKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New key
|
||||||
|
const { derivedKey } = await this.keyGenerationService.createKeyWithPurpose(
|
||||||
|
128,
|
||||||
|
"ephemeral",
|
||||||
|
"bitwarden-ephemeral",
|
||||||
|
);
|
||||||
|
await sessionStorage.save("session-key", derivedKey);
|
||||||
|
return derivedKey;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.largeObjectMemoryStorageForStateProviders = new LocalBackedSessionStorageService(
|
||||||
|
sessionKey,
|
||||||
|
this.storageService,
|
||||||
|
// For local backed session storage, we expect that the encrypted data on disk will persist longer than the encryption key in memory
|
||||||
|
// and failures to decrypt because of that are completely expected. For this reason, we pass in `false` to the `EncryptServiceImplementation`
|
||||||
|
// so that MAC failures are not logged.
|
||||||
|
new EncryptServiceImplementation(this.cryptoFunctionService, this.logService, false),
|
||||||
|
this.platformUtilsService,
|
||||||
|
this.logService,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// mv2 stores to the same location
|
||||||
|
this.largeObjectMemoryStorageForStateProviders = this.memoryStorageForStateProviders;
|
||||||
|
}
|
||||||
|
|
||||||
const localStorageStorageService = BrowserApi.isManifestVersion(3)
|
const localStorageStorageService = BrowserApi.isManifestVersion(3)
|
||||||
? new OffscreenStorageService(this.offscreenDocumentService)
|
? new OffscreenStorageService(this.offscreenDocumentService)
|
||||||
@@ -575,9 +562,10 @@ export default class MainBackground {
|
|||||||
this.derivedStateProvider,
|
this.derivedStateProvider,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.taskSchedulerService = this.popupOnlyContext
|
this.taskSchedulerService = new BackgroundTaskSchedulerService(
|
||||||
? new ForegroundTaskSchedulerService(this.logService, this.stateProvider)
|
this.logService,
|
||||||
: new BackgroundTaskSchedulerService(this.logService, this.stateProvider);
|
this.stateProvider,
|
||||||
|
);
|
||||||
this.taskSchedulerService.registerTaskHandler(ScheduledTaskNames.scheduleNextSyncInterval, () =>
|
this.taskSchedulerService.registerTaskHandler(ScheduledTaskNames.scheduleNextSyncInterval, () =>
|
||||||
this.fullSync(),
|
this.fullSync(),
|
||||||
);
|
);
|
||||||
@@ -873,26 +861,24 @@ export default class MainBackground {
|
|||||||
|
|
||||||
this.vaultSettingsService = new VaultSettingsService(this.stateProvider);
|
this.vaultSettingsService = new VaultSettingsService(this.stateProvider);
|
||||||
|
|
||||||
if (!this.popupOnlyContext) {
|
this.vaultTimeoutService = new VaultTimeoutService(
|
||||||
this.vaultTimeoutService = new VaultTimeoutService(
|
this.accountService,
|
||||||
this.accountService,
|
this.masterPasswordService,
|
||||||
this.masterPasswordService,
|
this.cipherService,
|
||||||
this.cipherService,
|
this.folderService,
|
||||||
this.folderService,
|
this.collectionService,
|
||||||
this.collectionService,
|
this.platformUtilsService,
|
||||||
this.platformUtilsService,
|
this.messagingService,
|
||||||
this.messagingService,
|
this.searchService,
|
||||||
this.searchService,
|
this.stateService,
|
||||||
this.stateService,
|
this.authService,
|
||||||
this.authService,
|
this.vaultTimeoutSettingsService,
|
||||||
this.vaultTimeoutSettingsService,
|
this.stateEventRunnerService,
|
||||||
this.stateEventRunnerService,
|
this.taskSchedulerService,
|
||||||
this.taskSchedulerService,
|
this.logService,
|
||||||
this.logService,
|
lockedCallback,
|
||||||
lockedCallback,
|
logoutCallback,
|
||||||
logoutCallback,
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
this.containerService = new ContainerService(this.keyService, this.encryptService);
|
this.containerService = new ContainerService(this.keyService, this.encryptService);
|
||||||
|
|
||||||
this.sendStateProvider = new SendStateProvider(this.stateProvider);
|
this.sendStateProvider = new SendStateProvider(this.stateProvider);
|
||||||
@@ -913,59 +899,41 @@ export default class MainBackground {
|
|||||||
|
|
||||||
this.providerService = new ProviderService(this.stateProvider);
|
this.providerService = new ProviderService(this.stateProvider);
|
||||||
|
|
||||||
if (this.popupOnlyContext) {
|
this.syncService = new DefaultSyncService(
|
||||||
this.syncService = new ForegroundSyncService(
|
this.masterPasswordService,
|
||||||
this.stateService,
|
this.accountService,
|
||||||
this.folderService,
|
this.apiService,
|
||||||
this.folderApiService,
|
this.domainSettingsService,
|
||||||
this.messagingService,
|
this.folderService,
|
||||||
this.logService,
|
this.cipherService,
|
||||||
this.cipherService,
|
this.keyService,
|
||||||
this.collectionService,
|
this.collectionService,
|
||||||
this.apiService,
|
this.messagingService,
|
||||||
this.accountService,
|
this.policyService,
|
||||||
this.authService,
|
this.sendService,
|
||||||
this.sendService,
|
this.logService,
|
||||||
this.sendApiService,
|
this.keyConnectorService,
|
||||||
messageListener,
|
this.stateService,
|
||||||
this.stateProvider,
|
this.providerService,
|
||||||
);
|
this.folderApiService,
|
||||||
} else {
|
this.organizationService,
|
||||||
this.syncService = new DefaultSyncService(
|
this.sendApiService,
|
||||||
this.masterPasswordService,
|
this.userDecryptionOptionsService,
|
||||||
this.accountService,
|
this.avatarService,
|
||||||
this.apiService,
|
logoutCallback,
|
||||||
this.domainSettingsService,
|
this.billingAccountProfileStateService,
|
||||||
this.folderService,
|
this.tokenService,
|
||||||
this.cipherService,
|
this.authService,
|
||||||
this.keyService,
|
this.stateProvider,
|
||||||
this.collectionService,
|
);
|
||||||
this.messagingService,
|
|
||||||
this.policyService,
|
this.syncServiceListener = new SyncServiceListener(
|
||||||
this.sendService,
|
this.syncService,
|
||||||
this.logService,
|
messageListener,
|
||||||
this.keyConnectorService,
|
this.messagingService,
|
||||||
this.stateService,
|
this.logService,
|
||||||
this.providerService,
|
);
|
||||||
this.folderApiService,
|
|
||||||
this.organizationService,
|
|
||||||
this.sendApiService,
|
|
||||||
this.userDecryptionOptionsService,
|
|
||||||
this.avatarService,
|
|
||||||
logoutCallback,
|
|
||||||
this.billingAccountProfileStateService,
|
|
||||||
this.tokenService,
|
|
||||||
this.authService,
|
|
||||||
this.stateProvider,
|
|
||||||
);
|
|
||||||
|
|
||||||
this.syncServiceListener = new SyncServiceListener(
|
|
||||||
this.syncService,
|
|
||||||
messageListener,
|
|
||||||
this.messagingService,
|
|
||||||
this.logService,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
this.eventUploadService = new EventUploadService(
|
this.eventUploadService = new EventUploadService(
|
||||||
this.apiService,
|
this.apiService,
|
||||||
this.stateProvider,
|
this.stateProvider,
|
||||||
@@ -1112,122 +1080,128 @@ export default class MainBackground {
|
|||||||
this.isSafari = this.platformUtilsService.isSafari();
|
this.isSafari = this.platformUtilsService.isSafari();
|
||||||
|
|
||||||
// Background
|
// Background
|
||||||
if (!this.popupOnlyContext) {
|
|
||||||
this.fido2Background = new Fido2Background(
|
|
||||||
this.logService,
|
|
||||||
this.fido2ActiveRequestManager,
|
|
||||||
this.fido2ClientService,
|
|
||||||
this.vaultSettingsService,
|
|
||||||
this.scriptInjectorService,
|
|
||||||
this.configService,
|
|
||||||
this.authService,
|
|
||||||
);
|
|
||||||
|
|
||||||
const lockService = new DefaultLockService(this.accountService, this.vaultTimeoutService);
|
this.fido2Background = new Fido2Background(
|
||||||
|
this.logService,
|
||||||
|
this.fido2ActiveRequestManager,
|
||||||
|
this.fido2ClientService,
|
||||||
|
this.vaultSettingsService,
|
||||||
|
this.scriptInjectorService,
|
||||||
|
this.configService,
|
||||||
|
this.authService,
|
||||||
|
);
|
||||||
|
|
||||||
this.runtimeBackground = new RuntimeBackground(
|
const lockService = new DefaultLockService(this.accountService, this.vaultTimeoutService);
|
||||||
this,
|
|
||||||
this.autofillService,
|
|
||||||
this.platformUtilsService as BrowserPlatformUtilsService,
|
|
||||||
this.notificationsService,
|
|
||||||
this.autofillSettingsService,
|
|
||||||
this.processReloadService,
|
|
||||||
this.environmentService,
|
|
||||||
this.messagingService,
|
|
||||||
this.logService,
|
|
||||||
this.configService,
|
|
||||||
messageListener,
|
|
||||||
this.accountService,
|
|
||||||
lockService,
|
|
||||||
);
|
|
||||||
this.nativeMessagingBackground = new NativeMessagingBackground(
|
|
||||||
this.keyService,
|
|
||||||
this.encryptService,
|
|
||||||
this.cryptoFunctionService,
|
|
||||||
this.runtimeBackground,
|
|
||||||
this.messagingService,
|
|
||||||
this.appIdService,
|
|
||||||
this.platformUtilsService,
|
|
||||||
this.logService,
|
|
||||||
this.authService,
|
|
||||||
this.biometricStateService,
|
|
||||||
this.accountService,
|
|
||||||
);
|
|
||||||
this.commandsBackground = new CommandsBackground(
|
|
||||||
this,
|
|
||||||
this.platformUtilsService,
|
|
||||||
this.vaultTimeoutService,
|
|
||||||
this.authService,
|
|
||||||
() => this.generatePasswordToClipboard(),
|
|
||||||
);
|
|
||||||
this.notificationBackground = new NotificationBackground(
|
|
||||||
this.autofillService,
|
|
||||||
this.cipherService,
|
|
||||||
this.authService,
|
|
||||||
this.policyService,
|
|
||||||
this.folderService,
|
|
||||||
this.userNotificationSettingsService,
|
|
||||||
this.domainSettingsService,
|
|
||||||
this.environmentService,
|
|
||||||
this.logService,
|
|
||||||
this.themeStateService,
|
|
||||||
this.configService,
|
|
||||||
this.accountService,
|
|
||||||
);
|
|
||||||
|
|
||||||
this.overlayNotificationsBackground = new OverlayNotificationsBackground(
|
this.runtimeBackground = new RuntimeBackground(
|
||||||
this.logService,
|
this,
|
||||||
this.configService,
|
this.autofillService,
|
||||||
this.notificationBackground,
|
this.platformUtilsService as BrowserPlatformUtilsService,
|
||||||
);
|
this.notificationsService,
|
||||||
|
this.autofillSettingsService,
|
||||||
|
this.processReloadService,
|
||||||
|
this.environmentService,
|
||||||
|
this.messagingService,
|
||||||
|
this.logService,
|
||||||
|
this.configService,
|
||||||
|
messageListener,
|
||||||
|
this.accountService,
|
||||||
|
lockService,
|
||||||
|
);
|
||||||
|
this.nativeMessagingBackground = new NativeMessagingBackground(
|
||||||
|
this.keyService,
|
||||||
|
this.encryptService,
|
||||||
|
this.cryptoFunctionService,
|
||||||
|
this.runtimeBackground,
|
||||||
|
this.messagingService,
|
||||||
|
this.appIdService,
|
||||||
|
this.platformUtilsService,
|
||||||
|
this.logService,
|
||||||
|
this.authService,
|
||||||
|
this.biometricStateService,
|
||||||
|
this.accountService,
|
||||||
|
);
|
||||||
|
this.commandsBackground = new CommandsBackground(
|
||||||
|
this,
|
||||||
|
this.platformUtilsService,
|
||||||
|
this.vaultTimeoutService,
|
||||||
|
this.authService,
|
||||||
|
() => this.generatePasswordToClipboard(),
|
||||||
|
);
|
||||||
|
this.notificationBackground = new NotificationBackground(
|
||||||
|
this.autofillService,
|
||||||
|
this.cipherService,
|
||||||
|
this.authService,
|
||||||
|
this.policyService,
|
||||||
|
this.folderService,
|
||||||
|
this.userNotificationSettingsService,
|
||||||
|
this.domainSettingsService,
|
||||||
|
this.environmentService,
|
||||||
|
this.logService,
|
||||||
|
this.themeStateService,
|
||||||
|
this.configService,
|
||||||
|
this.accountService,
|
||||||
|
);
|
||||||
|
|
||||||
this.filelessImporterBackground = new FilelessImporterBackground(
|
this.overlayNotificationsBackground = new OverlayNotificationsBackground(
|
||||||
this.configService,
|
this.logService,
|
||||||
this.authService,
|
this.configService,
|
||||||
this.policyService,
|
this.notificationBackground,
|
||||||
this.notificationBackground,
|
);
|
||||||
this.importService,
|
|
||||||
this.syncService,
|
|
||||||
this.scriptInjectorService,
|
|
||||||
);
|
|
||||||
|
|
||||||
this.autoSubmitLoginBackground = new AutoSubmitLoginBackground(
|
this.filelessImporterBackground = new FilelessImporterBackground(
|
||||||
this.logService,
|
this.configService,
|
||||||
this.autofillService,
|
this.authService,
|
||||||
this.scriptInjectorService,
|
this.policyService,
|
||||||
this.authService,
|
this.notificationBackground,
|
||||||
this.configService,
|
this.importService,
|
||||||
this.platformUtilsService,
|
this.syncService,
|
||||||
this.policyService,
|
this.scriptInjectorService,
|
||||||
);
|
);
|
||||||
|
|
||||||
const contextMenuClickedHandler = new ContextMenuClickedHandler(
|
this.autoSubmitLoginBackground = new AutoSubmitLoginBackground(
|
||||||
(options) => this.platformUtilsService.copyToClipboard(options.text),
|
this.logService,
|
||||||
async () => this.generatePasswordToClipboard(),
|
this.autofillService,
|
||||||
async (tab, cipher) => {
|
this.scriptInjectorService,
|
||||||
this.loginToAutoFill = cipher;
|
this.authService,
|
||||||
if (tab == null) {
|
this.configService,
|
||||||
return;
|
this.platformUtilsService,
|
||||||
}
|
this.policyService,
|
||||||
|
);
|
||||||
|
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
const contextMenuClickedHandler = new ContextMenuClickedHandler(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
(options) => this.platformUtilsService.copyToClipboard(options.text),
|
||||||
BrowserApi.tabSendMessage(tab, {
|
async (_tab) => {
|
||||||
command: "collectPageDetails",
|
const options = (await this.passwordGenerationService.getOptions())?.[0] ?? {};
|
||||||
tab: tab,
|
const password = await this.passwordGenerationService.generatePassword(options);
|
||||||
sender: "contextMenu",
|
this.platformUtilsService.copyToClipboard(password);
|
||||||
});
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
},
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
this.authService,
|
this.passwordGenerationService.addHistory(password);
|
||||||
this.cipherService,
|
},
|
||||||
this.totpService,
|
async (tab, cipher) => {
|
||||||
this.eventCollectionService,
|
this.loginToAutoFill = cipher;
|
||||||
this.userVerificationService,
|
if (tab == null) {
|
||||||
this.accountService,
|
return;
|
||||||
);
|
}
|
||||||
|
|
||||||
this.contextMenusBackground = new ContextMenusBackground(contextMenuClickedHandler);
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
}
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
BrowserApi.tabSendMessage(tab, {
|
||||||
|
command: "collectPageDetails",
|
||||||
|
tab: tab,
|
||||||
|
sender: "contextMenu",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
this.authService,
|
||||||
|
this.cipherService,
|
||||||
|
this.totpService,
|
||||||
|
this.eventCollectionService,
|
||||||
|
this.userVerificationService,
|
||||||
|
this.accountService,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.contextMenusBackground = new ContextMenusBackground(contextMenuClickedHandler);
|
||||||
|
|
||||||
this.idleBackground = new IdleBackground(
|
this.idleBackground = new IdleBackground(
|
||||||
this.vaultTimeoutService,
|
this.vaultTimeoutService,
|
||||||
@@ -1246,29 +1220,27 @@ export default class MainBackground {
|
|||||||
this.stateProvider,
|
this.stateProvider,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!this.popupOnlyContext) {
|
this.mainContextMenuHandler = new MainContextMenuHandler(
|
||||||
this.mainContextMenuHandler = new MainContextMenuHandler(
|
this.stateService,
|
||||||
this.stateService,
|
this.autofillSettingsService,
|
||||||
this.autofillSettingsService,
|
this.i18nService,
|
||||||
this.i18nService,
|
this.logService,
|
||||||
this.logService,
|
this.billingAccountProfileStateService,
|
||||||
this.billingAccountProfileStateService,
|
);
|
||||||
);
|
|
||||||
|
|
||||||
this.cipherContextMenuHandler = new CipherContextMenuHandler(
|
this.cipherContextMenuHandler = new CipherContextMenuHandler(
|
||||||
this.mainContextMenuHandler,
|
this.mainContextMenuHandler,
|
||||||
this.authService,
|
this.authService,
|
||||||
|
this.cipherService,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (chrome.webRequest != null && chrome.webRequest.onAuthRequired != null) {
|
||||||
|
this.webRequestBackground = new WebRequestBackground(
|
||||||
|
this.platformUtilsService,
|
||||||
this.cipherService,
|
this.cipherService,
|
||||||
|
this.authService,
|
||||||
|
chrome.webRequest,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (chrome.webRequest != null && chrome.webRequest.onAuthRequired != null) {
|
|
||||||
this.webRequestBackground = new WebRequestBackground(
|
|
||||||
this.platformUtilsService,
|
|
||||||
this.cipherService,
|
|
||||||
this.authService,
|
|
||||||
chrome.webRequest,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.userAutoUnlockKeyService = new UserAutoUnlockKeyService(this.keyService);
|
this.userAutoUnlockKeyService = new UserAutoUnlockKeyService(this.keyService);
|
||||||
@@ -1283,7 +1255,7 @@ export default class MainBackground {
|
|||||||
this.containerService.attachToGlobal(self);
|
this.containerService.attachToGlobal(self);
|
||||||
|
|
||||||
// Only the "true" background should run migrations
|
// Only the "true" background should run migrations
|
||||||
await this.stateService.init({ runMigrations: !this.popupOnlyContext });
|
await this.stateService.init({ runMigrations: true });
|
||||||
|
|
||||||
// This is here instead of in in the InitService b/c we don't plan for
|
// This is here instead of in in the InitService b/c we don't plan for
|
||||||
// side effects to run in the Browser InitService.
|
// side effects to run in the Browser InitService.
|
||||||
@@ -1305,10 +1277,6 @@ export default class MainBackground {
|
|||||||
|
|
||||||
this.popupViewCacheBackgroundService.startObservingTabChanges();
|
this.popupViewCacheBackgroundService.startObservingTabChanges();
|
||||||
|
|
||||||
if (this.popupOnlyContext) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.vaultTimeoutService.init(true);
|
await this.vaultTimeoutService.init(true);
|
||||||
this.fido2Background.init();
|
this.fido2Background.init();
|
||||||
await this.runtimeBackground.init();
|
await this.runtimeBackground.init();
|
||||||
@@ -1637,7 +1605,6 @@ export default class MainBackground {
|
|||||||
*/
|
*/
|
||||||
async initOverlayAndTabsBackground() {
|
async initOverlayAndTabsBackground() {
|
||||||
if (
|
if (
|
||||||
this.popupOnlyContext ||
|
|
||||||
this.overlayBackground ||
|
this.overlayBackground ||
|
||||||
this.tabsBackground ||
|
this.tabsBackground ||
|
||||||
(await firstValueFrom(this.authService.activeAccountStatus$)) ===
|
(await firstValueFrom(this.authService.activeAccountStatus$)) ===
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ import {
|
|||||||
LockComponentService,
|
LockComponentService,
|
||||||
} from "@bitwarden/auth/angular";
|
} from "@bitwarden/auth/angular";
|
||||||
import { LockService, LoginEmailService, PinServiceAbstraction } from "@bitwarden/auth/common";
|
import { LockService, LoginEmailService, PinServiceAbstraction } from "@bitwarden/auth/common";
|
||||||
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
|
|
||||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
@@ -92,9 +92,15 @@ import { InlineDerivedStateProvider } from "@bitwarden/common/platform/state/imp
|
|||||||
import { PrimarySecondaryStorageService } from "@bitwarden/common/platform/storage/primary-secondary-storage.service";
|
import { PrimarySecondaryStorageService } from "@bitwarden/common/platform/storage/primary-secondary-storage.service";
|
||||||
import { WindowStorageService } from "@bitwarden/common/platform/storage/window-storage.service";
|
import { WindowStorageService } from "@bitwarden/common/platform/storage/window-storage.service";
|
||||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||||
|
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||||
|
import { InternalSendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||||
import { VaultTimeoutStringType } from "@bitwarden/common/types/vault-timeout.type";
|
import { VaultTimeoutStringType } from "@bitwarden/common/types/vault-timeout.type";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { FolderService as FolderServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction";
|
||||||
|
import {
|
||||||
|
FolderService as FolderServiceAbstraction,
|
||||||
|
InternalFolderService,
|
||||||
|
} from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||||
import { TotpService as TotpServiceAbstraction } from "@bitwarden/common/vault/abstractions/totp.service";
|
import { TotpService as TotpServiceAbstraction } from "@bitwarden/common/vault/abstractions/totp.service";
|
||||||
import { TotpService } from "@bitwarden/common/vault/services/totp.service";
|
import { TotpService } from "@bitwarden/common/vault/services/totp.service";
|
||||||
import { DialogService, ToastService } from "@bitwarden/components";
|
import { DialogService, ToastService } from "@bitwarden/components";
|
||||||
@@ -107,7 +113,6 @@ import { ExtensionAnonLayoutWrapperDataService } from "../../auth/popup/extensio
|
|||||||
import { ExtensionLoginComponentService } from "../../auth/popup/login/extension-login-component.service";
|
import { ExtensionLoginComponentService } from "../../auth/popup/login/extension-login-component.service";
|
||||||
import { AutofillService as AutofillServiceAbstraction } from "../../autofill/services/abstractions/autofill.service";
|
import { AutofillService as AutofillServiceAbstraction } from "../../autofill/services/abstractions/autofill.service";
|
||||||
import AutofillService from "../../autofill/services/autofill.service";
|
import AutofillService from "../../autofill/services/autofill.service";
|
||||||
import MainBackground from "../../background/main.background";
|
|
||||||
import { ForegroundBrowserBiometricsService } from "../../key-management/biometrics/foreground-browser-biometrics";
|
import { ForegroundBrowserBiometricsService } from "../../key-management/biometrics/foreground-browser-biometrics";
|
||||||
import { BrowserKeyService } from "../../key-management/browser-key.service";
|
import { BrowserKeyService } from "../../key-management/browser-key.service";
|
||||||
import { BrowserApi } from "../../platform/browser/browser-api";
|
import { BrowserApi } from "../../platform/browser/browser-api";
|
||||||
@@ -117,12 +122,12 @@ import { ChromeMessageSender } from "../../platform/messaging/chrome-message.sen
|
|||||||
/* eslint-enable no-restricted-imports */
|
/* eslint-enable no-restricted-imports */
|
||||||
import { OffscreenDocumentService } from "../../platform/offscreen-document/abstractions/offscreen-document";
|
import { OffscreenDocumentService } from "../../platform/offscreen-document/abstractions/offscreen-document";
|
||||||
import { DefaultOffscreenDocumentService } from "../../platform/offscreen-document/offscreen-document.service";
|
import { DefaultOffscreenDocumentService } from "../../platform/offscreen-document/offscreen-document.service";
|
||||||
import BrowserPopupUtils from "../../platform/popup/browser-popup-utils";
|
|
||||||
import { BrowserFileDownloadService } from "../../platform/popup/services/browser-file-download.service";
|
import { BrowserFileDownloadService } from "../../platform/popup/services/browser-file-download.service";
|
||||||
import { PopupViewCacheService } from "../../platform/popup/view-cache/popup-view-cache.service";
|
import { PopupViewCacheService } from "../../platform/popup/view-cache/popup-view-cache.service";
|
||||||
import { ScriptInjectorService } from "../../platform/services/abstractions/script-injector.service";
|
import { ScriptInjectorService } from "../../platform/services/abstractions/script-injector.service";
|
||||||
import { BrowserEnvironmentService } from "../../platform/services/browser-environment.service";
|
import { BrowserEnvironmentService } from "../../platform/services/browser-environment.service";
|
||||||
import BrowserLocalStorageService from "../../platform/services/browser-local-storage.service";
|
import BrowserLocalStorageService from "../../platform/services/browser-local-storage.service";
|
||||||
|
import BrowserMemoryStorageService from "../../platform/services/browser-memory-storage.service";
|
||||||
import { BrowserScriptInjectorService } from "../../platform/services/browser-script-injector.service";
|
import { BrowserScriptInjectorService } from "../../platform/services/browser-script-injector.service";
|
||||||
import I18nService from "../../platform/services/i18n.service";
|
import I18nService from "../../platform/services/i18n.service";
|
||||||
import { ForegroundPlatformUtilsService } from "../../platform/services/platform-utils/foreground-platform-utils.service";
|
import { ForegroundPlatformUtilsService } from "../../platform/services/platform-utils/foreground-platform-utils.service";
|
||||||
@@ -130,6 +135,7 @@ import { BrowserSdkClientFactory } from "../../platform/services/sdk/browser-sdk
|
|||||||
import { ForegroundTaskSchedulerService } from "../../platform/services/task-scheduler/foreground-task-scheduler.service";
|
import { ForegroundTaskSchedulerService } from "../../platform/services/task-scheduler/foreground-task-scheduler.service";
|
||||||
import { BrowserStorageServiceProvider } from "../../platform/storage/browser-storage-service.provider";
|
import { BrowserStorageServiceProvider } from "../../platform/storage/browser-storage-service.provider";
|
||||||
import { ForegroundMemoryStorageService } from "../../platform/storage/foreground-memory-storage.service";
|
import { ForegroundMemoryStorageService } from "../../platform/storage/foreground-memory-storage.service";
|
||||||
|
import { ForegroundSyncService } from "../../platform/sync/foreground-sync.service";
|
||||||
import { fromChromeRuntimeMessaging } from "../../platform/utils/from-chrome-runtime-messaging";
|
import { fromChromeRuntimeMessaging } from "../../platform/utils/from-chrome-runtime-messaging";
|
||||||
import { ExtensionLockComponentService } from "../../services/extension-lock-component.service";
|
import { ExtensionLockComponentService } from "../../services/extension-lock-component.service";
|
||||||
import { ForegroundVaultTimeoutService } from "../../services/vault-timeout/foreground-vault-timeout.service";
|
import { ForegroundVaultTimeoutService } from "../../services/vault-timeout/foreground-vault-timeout.service";
|
||||||
@@ -151,26 +157,6 @@ const DISK_BACKUP_LOCAL_STORAGE = new SafeInjectionToken<
|
|||||||
AbstractStorageService & ObservableStorageService
|
AbstractStorageService & ObservableStorageService
|
||||||
>("DISK_BACKUP_LOCAL_STORAGE");
|
>("DISK_BACKUP_LOCAL_STORAGE");
|
||||||
|
|
||||||
const needsBackgroundInit = BrowserPopupUtils.backgroundInitializationRequired();
|
|
||||||
const mainBackground: MainBackground = needsBackgroundInit
|
|
||||||
? createLocalBgService()
|
|
||||||
: BrowserApi.getBackgroundPage().bitwardenMain;
|
|
||||||
|
|
||||||
function createLocalBgService() {
|
|
||||||
const localBgService = new MainBackground(true);
|
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
localBgService.bootstrap();
|
|
||||||
return localBgService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @deprecated This method needs to be removed as part of MV3 conversion. Please do not add more and actively try to remove usages */
|
|
||||||
function getBgService<T>(service: keyof MainBackground) {
|
|
||||||
return (): T => {
|
|
||||||
return mainBackground ? (mainBackground[service] as any as T) : null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provider definitions used in the ngModule.
|
* Provider definitions used in the ngModule.
|
||||||
* Add your provider definition here using the safeProvider function as a wrapper. This will give you type safety.
|
* Add your provider definition here using the safeProvider function as a wrapper. This will give you type safety.
|
||||||
@@ -307,8 +293,23 @@ const safeProviders: SafeProvider[] = [
|
|||||||
}),
|
}),
|
||||||
safeProvider({
|
safeProvider({
|
||||||
provide: SyncService,
|
provide: SyncService,
|
||||||
useFactory: getBgService<SyncService>("syncService"),
|
useClass: ForegroundSyncService,
|
||||||
deps: [],
|
deps: [
|
||||||
|
StateService,
|
||||||
|
InternalFolderService,
|
||||||
|
FolderApiServiceAbstraction,
|
||||||
|
MessageSender,
|
||||||
|
LogService,
|
||||||
|
CipherService,
|
||||||
|
CollectionService,
|
||||||
|
ApiService,
|
||||||
|
AccountServiceAbstraction,
|
||||||
|
AuthService,
|
||||||
|
InternalSendService,
|
||||||
|
SendApiService,
|
||||||
|
MessageListener,
|
||||||
|
StateProvider,
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
safeProvider({
|
safeProvider({
|
||||||
provide: DomainSettingsService,
|
provide: DomainSettingsService,
|
||||||
@@ -358,11 +359,6 @@ const safeProviders: SafeProvider[] = [
|
|||||||
useClass: ForegroundVaultTimeoutService,
|
useClass: ForegroundVaultTimeoutService,
|
||||||
deps: [MessagingServiceAbstraction],
|
deps: [MessagingServiceAbstraction],
|
||||||
}),
|
}),
|
||||||
safeProvider({
|
|
||||||
provide: NotificationsService,
|
|
||||||
useFactory: getBgService<NotificationsService>("notificationsService"),
|
|
||||||
deps: [],
|
|
||||||
}),
|
|
||||||
safeProvider({
|
safeProvider({
|
||||||
provide: VaultFilterService,
|
provide: VaultFilterService,
|
||||||
useClass: VaultFilterService,
|
useClass: VaultFilterService,
|
||||||
@@ -382,8 +378,8 @@ const safeProviders: SafeProvider[] = [
|
|||||||
}),
|
}),
|
||||||
safeProvider({
|
safeProvider({
|
||||||
provide: MEMORY_STORAGE,
|
provide: MEMORY_STORAGE,
|
||||||
useFactory: getBgService<AbstractStorageService>("memoryStorageService"),
|
useFactory: (memoryStorage: AbstractStorageService) => memoryStorage,
|
||||||
deps: [],
|
deps: [OBSERVABLE_MEMORY_STORAGE],
|
||||||
}),
|
}),
|
||||||
safeProvider({
|
safeProvider({
|
||||||
provide: OBSERVABLE_MEMORY_STORAGE,
|
provide: OBSERVABLE_MEMORY_STORAGE,
|
||||||
@@ -392,9 +388,7 @@ const safeProviders: SafeProvider[] = [
|
|||||||
return new ForegroundMemoryStorageService();
|
return new ForegroundMemoryStorageService();
|
||||||
}
|
}
|
||||||
|
|
||||||
return getBgService<AbstractStorageService & ObservableStorageService>(
|
return new BrowserMemoryStorageService();
|
||||||
"memoryStorageForStateProviders",
|
|
||||||
)();
|
|
||||||
},
|
},
|
||||||
deps: [],
|
deps: [],
|
||||||
}),
|
}),
|
||||||
@@ -407,9 +401,7 @@ const safeProviders: SafeProvider[] = [
|
|||||||
return regularMemoryStorageService;
|
return regularMemoryStorageService;
|
||||||
}
|
}
|
||||||
|
|
||||||
return getBgService<AbstractStorageService & ObservableStorageService>(
|
return new ForegroundMemoryStorageService();
|
||||||
"largeObjectMemoryStorageForStateProviders",
|
|
||||||
)();
|
|
||||||
},
|
},
|
||||||
deps: [OBSERVABLE_MEMORY_STORAGE],
|
deps: [OBSERVABLE_MEMORY_STORAGE],
|
||||||
}),
|
}),
|
||||||
@@ -494,15 +486,7 @@ const safeProviders: SafeProvider[] = [
|
|||||||
}),
|
}),
|
||||||
safeProvider({
|
safeProvider({
|
||||||
provide: INTRAPROCESS_MESSAGING_SUBJECT,
|
provide: INTRAPROCESS_MESSAGING_SUBJECT,
|
||||||
useFactory: () => {
|
useFactory: () => new Subject<Message<Record<string, unknown>>>(),
|
||||||
if (BrowserPopupUtils.backgroundInitializationRequired()) {
|
|
||||||
// There is no persistent main background which means we have one in memory,
|
|
||||||
// we need the same instance that our in memory background is utilizing.
|
|
||||||
return getBgService("intraprocessMessagingSubject")();
|
|
||||||
} else {
|
|
||||||
return new Subject<Message<Record<string, unknown>>>();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
deps: [],
|
deps: [],
|
||||||
}),
|
}),
|
||||||
safeProvider({
|
safeProvider({
|
||||||
@@ -514,23 +498,6 @@ const safeProviders: SafeProvider[] = [
|
|||||||
),
|
),
|
||||||
deps: [INTRAPROCESS_MESSAGING_SUBJECT, LogService],
|
deps: [INTRAPROCESS_MESSAGING_SUBJECT, LogService],
|
||||||
}),
|
}),
|
||||||
safeProvider({
|
|
||||||
provide: INTRAPROCESS_MESSAGING_SUBJECT,
|
|
||||||
useFactory: () => {
|
|
||||||
if (needsBackgroundInit) {
|
|
||||||
// We will have created a popup within this context, in that case
|
|
||||||
// we want to make sure we have the same subject as that context so we
|
|
||||||
// can message with it.
|
|
||||||
return getBgService("intraprocessMessagingSubject")();
|
|
||||||
} else {
|
|
||||||
// There isn't a locally created background so we will communicate with
|
|
||||||
// the true background through chrome apis, in that case, we can just create
|
|
||||||
// one for ourself.
|
|
||||||
return new Subject<Message<Record<string, unknown>>>();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
deps: [],
|
|
||||||
}),
|
|
||||||
safeProvider({
|
safeProvider({
|
||||||
provide: DISK_BACKUP_LOCAL_STORAGE,
|
provide: DISK_BACKUP_LOCAL_STORAGE,
|
||||||
useFactory: (diskStorage: AbstractStorageService & ObservableStorageService) =>
|
useFactory: (diskStorage: AbstractStorageService & ObservableStorageService) =>
|
||||||
@@ -572,13 +539,7 @@ const safeProviders: SafeProvider[] = [
|
|||||||
}),
|
}),
|
||||||
safeProvider({
|
safeProvider({
|
||||||
provide: ForegroundTaskSchedulerService,
|
provide: ForegroundTaskSchedulerService,
|
||||||
useFactory: (logService: LogService, stateProvider: StateProvider) => {
|
useClass: ForegroundTaskSchedulerService,
|
||||||
if (needsBackgroundInit) {
|
|
||||||
return getBgService<ForegroundTaskSchedulerService>("taskSchedulerService")();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ForegroundTaskSchedulerService(logService, stateProvider);
|
|
||||||
},
|
|
||||||
deps: [LogService, StateProvider],
|
deps: [LogService, StateProvider],
|
||||||
}),
|
}),
|
||||||
safeProvider({
|
safeProvider({
|
||||||
|
|||||||
@@ -486,7 +486,7 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
|
|||||||
const enableUpgradePasswordManagerSub = await firstValueFrom(
|
const enableUpgradePasswordManagerSub = await firstValueFrom(
|
||||||
this.enableUpgradePasswordManagerSub$,
|
this.enableUpgradePasswordManagerSub$,
|
||||||
);
|
);
|
||||||
if (enableUpgradePasswordManagerSub) {
|
if (enableUpgradePasswordManagerSub && this.organization.canEditSubscription) {
|
||||||
const reference = openChangePlanDialog(this.dialogService, {
|
const reference = openChangePlanDialog(this.dialogService, {
|
||||||
data: {
|
data: {
|
||||||
organizationId: this.organization.id,
|
organizationId: this.organization.id,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
{{ "refresh" | i18n }}
|
{{ "refresh" | i18n }}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<bit-tab-group [(selectedIndex)]="tabIndex">
|
<bit-tab-group [(selectedIndex)]="tabIndex" (selectedIndexChange)="onTabChange($event)">
|
||||||
<bit-tab label="{{ 'allApplicationsWithCount' | i18n: apps.length }}">
|
<bit-tab label="{{ 'allApplicationsWithCount' | i18n: apps.length }}">
|
||||||
<tools-all-applications></tools-all-applications>
|
<tools-all-applications></tools-all-applications>
|
||||||
</bit-tab>
|
</bit-tab>
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { CommonModule } from "@angular/common";
|
import { CommonModule } from "@angular/common";
|
||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { first } from "rxjs";
|
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { AsyncActionsModule, ButtonModule, TabsModule } from "@bitwarden/components";
|
import { AsyncActionsModule, ButtonModule, TabsModule } from "@bitwarden/components";
|
||||||
@@ -18,7 +17,7 @@ import { PasswordHealthComponent } from "./password-health.component";
|
|||||||
|
|
||||||
export enum AccessIntelligenceTabType {
|
export enum AccessIntelligenceTabType {
|
||||||
AllApps = 0,
|
AllApps = 0,
|
||||||
PriorityApps = 1,
|
CriticalApps = 1,
|
||||||
NotifiedMembers = 2,
|
NotifiedMembers = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,8 +57,19 @@ export class AccessIntelligenceComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(route: ActivatedRoute) {
|
onTabChange = async (newIndex: number) => {
|
||||||
route.queryParams.pipe(takeUntilDestroyed(), first()).subscribe(({ tabIndex }) => {
|
await this.router.navigate([], {
|
||||||
|
relativeTo: this.route,
|
||||||
|
queryParams: { tabIndex: newIndex },
|
||||||
|
queryParamsHandling: "merge",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected route: ActivatedRoute,
|
||||||
|
private router: Router,
|
||||||
|
) {
|
||||||
|
route.queryParams.pipe(takeUntilDestroyed()).subscribe(({ tabIndex }) => {
|
||||||
this.tabIndex = !isNaN(tabIndex) ? tabIndex : AccessIntelligenceTabType.AllApps;
|
this.tabIndex = !isNaN(tabIndex) ? tabIndex : AccessIntelligenceTabType.AllApps;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,13 +14,15 @@
|
|||||||
</h2>
|
</h2>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container slot="description">
|
<ng-container slot="description">
|
||||||
<p class="tw-text-muted">
|
<div class="tw-flex tw-flex-col tw-mb-2">
|
||||||
{{ "noAppsInOrgDescription" | i18n }}
|
<span class="tw-text-muted">
|
||||||
|
{{ "noAppsInOrgDescription" | i18n }}
|
||||||
|
</span>
|
||||||
<a class="text-primary" routerLink="/login">{{ "learnMore" | i18n }}</a>
|
<a class="text-primary" routerLink="/login">{{ "learnMore" | i18n }}</a>
|
||||||
</p>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container slot="button">
|
<ng-container slot="button">
|
||||||
<button bitButton buttonType="primary" type="button">
|
<button (click)="goToCreateNewLoginItem()" bitButton buttonType="primary" type="button">
|
||||||
{{ "createNewLoginItem" | i18n }}
|
{{ "createNewLoginItem" | i18n }}
|
||||||
</button>
|
</button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
@@ -50,7 +52,15 @@
|
|||||||
class="tw-grow"
|
class="tw-grow"
|
||||||
[formControl]="searchControl"
|
[formControl]="searchControl"
|
||||||
></bit-search>
|
></bit-search>
|
||||||
<button class="tw-rounded-lg" type="button" buttonType="secondary" bitButton>
|
<button
|
||||||
|
class="tw-rounded-lg"
|
||||||
|
type="button"
|
||||||
|
buttonType="secondary"
|
||||||
|
bitButton
|
||||||
|
[disabled]="!selectedIds.size"
|
||||||
|
[loading]="markingAsCritical"
|
||||||
|
(click)="markAppsAsCritical()"
|
||||||
|
>
|
||||||
<i class="bwi bwi-star-f tw-mr-2"></i>
|
<i class="bwi bwi-star-f tw-mr-2"></i>
|
||||||
{{ "markAppAsCritical" | i18n }}
|
{{ "markAppAsCritical" | i18n }}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ export class AllApplicationsComponent implements OnInit {
|
|||||||
protected loading = false;
|
protected loading = false;
|
||||||
protected organization: Organization;
|
protected organization: Organization;
|
||||||
noItemsIcon = Icons.Security;
|
noItemsIcon = Icons.Security;
|
||||||
|
protected markingAsCritical = false;
|
||||||
|
|
||||||
// MOCK DATA
|
// MOCK DATA
|
||||||
protected mockData = applicationTableMockData;
|
protected mockData = applicationTableMockData;
|
||||||
@@ -76,8 +77,18 @@ export class AllApplicationsComponent implements OnInit {
|
|||||||
.subscribe((v) => (this.dataSource.filter = v));
|
.subscribe((v) => (this.dataSource.filter = v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goToCreateNewLoginItem = async () => {
|
||||||
|
// TODO: implement
|
||||||
|
this.toastService.showToast({
|
||||||
|
variant: "warning",
|
||||||
|
title: null,
|
||||||
|
message: "Not yet implemented",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
markAppsAsCritical = async () => {
|
markAppsAsCritical = async () => {
|
||||||
// TODO: Send to API once implemented
|
// TODO: Send to API once implemented
|
||||||
|
this.markingAsCritical = true;
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.selectedIds.clear();
|
this.selectedIds.clear();
|
||||||
@@ -87,6 +98,7 @@ export class AllApplicationsComponent implements OnInit {
|
|||||||
message: this.i18nService.t("appsMarkedAsCritical"),
|
message: this.i18nService.t("appsMarkedAsCritical"),
|
||||||
});
|
});
|
||||||
resolve(true);
|
resolve(true);
|
||||||
|
this.markingAsCritical = false;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,7 +19,9 @@
|
|||||||
</p>
|
</p>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container slot="button">
|
<ng-container slot="button">
|
||||||
<button bitButton buttonType="primary" type="button">{{ "markCriticalApps" | i18n }}</button>
|
<button (click)="goToAllAppsTab()" bitButton buttonType="primary" type="button">
|
||||||
|
{{ "markCriticalApps" | i18n }}
|
||||||
|
</button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</bit-no-items>
|
</bit-no-items>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Component, DestroyRef, inject, OnInit } from "@angular/core";
|
import { Component, DestroyRef, inject, OnInit } from "@angular/core";
|
||||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||||
import { FormControl } from "@angular/forms";
|
import { FormControl } from "@angular/forms";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { debounceTime, map } from "rxjs";
|
import { debounceTime, map } from "rxjs";
|
||||||
|
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@@ -12,6 +12,7 @@ import { HeaderModule } from "../../layouts/header/header.module";
|
|||||||
import { SharedModule } from "../../shared";
|
import { SharedModule } from "../../shared";
|
||||||
import { PipesModule } from "../../vault/individual-vault/pipes/pipes.module";
|
import { PipesModule } from "../../vault/individual-vault/pipes/pipes.module";
|
||||||
|
|
||||||
|
import { AccessIntelligenceTabType } from "./access-intelligence.component";
|
||||||
import { applicationTableMockData } from "./application-table.mock";
|
import { applicationTableMockData } from "./application-table.mock";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -26,8 +27,10 @@ export class CriticalApplicationsComponent implements OnInit {
|
|||||||
protected searchControl = new FormControl("", { nonNullable: true });
|
protected searchControl = new FormControl("", { nonNullable: true });
|
||||||
private destroyRef = inject(DestroyRef);
|
private destroyRef = inject(DestroyRef);
|
||||||
protected loading = false;
|
protected loading = false;
|
||||||
|
protected organizationId: string;
|
||||||
noItemsIcon = Icons.Security;
|
noItemsIcon = Icons.Security;
|
||||||
// MOCK DATA
|
// MOCK DATA
|
||||||
|
protected mockData = applicationTableMockData;
|
||||||
protected mockAtRiskMembersCount = 0;
|
protected mockAtRiskMembersCount = 0;
|
||||||
protected mockAtRiskAppsCount = 0;
|
protected mockAtRiskAppsCount = 0;
|
||||||
protected mockTotalMembersCount = 0;
|
protected mockTotalMembersCount = 0;
|
||||||
@@ -38,18 +41,26 @@ export class CriticalApplicationsComponent implements OnInit {
|
|||||||
.pipe(
|
.pipe(
|
||||||
takeUntilDestroyed(this.destroyRef),
|
takeUntilDestroyed(this.destroyRef),
|
||||||
map(async (params) => {
|
map(async (params) => {
|
||||||
// const organizationId = params.get("organizationId");
|
this.organizationId = params.get("organizationId");
|
||||||
// TODO: use organizationId to fetch data
|
// TODO: use organizationId to fetch data
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goToAllAppsTab = async () => {
|
||||||
|
await this.router.navigate([`organizations/${this.organizationId}/access-intelligence`], {
|
||||||
|
queryParams: { tabIndex: AccessIntelligenceTabType.AllApps },
|
||||||
|
queryParamsHandling: "merge",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected i18nService: I18nService,
|
protected i18nService: I18nService,
|
||||||
protected activatedRoute: ActivatedRoute,
|
protected activatedRoute: ActivatedRoute,
|
||||||
|
protected router: Router,
|
||||||
) {
|
) {
|
||||||
this.dataSource.data = applicationTableMockData;
|
this.dataSource.data = []; //applicationTableMockData;
|
||||||
this.searchControl.valueChanges
|
this.searchControl.valueChanges
|
||||||
.pipe(debounceTime(200), takeUntilDestroyed())
|
.pipe(debounceTime(200), takeUntilDestroyed())
|
||||||
.subscribe((v) => (this.dataSource.filter = v));
|
.subscribe((v) => (this.dataSource.filter = v));
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ describe("UserVerificationService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("returns if verification is successful", async () => {
|
it("returns if verification is successful", async () => {
|
||||||
keyService.compareAndUpdateKeyHash.mockResolvedValueOnce(true);
|
keyService.compareKeyHash.mockResolvedValueOnce(true);
|
||||||
|
|
||||||
const result = await sut.verifyUserByMasterPassword(
|
const result = await sut.verifyUserByMasterPassword(
|
||||||
{
|
{
|
||||||
@@ -227,7 +227,7 @@ describe("UserVerificationService", () => {
|
|||||||
"email",
|
"email",
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(keyService.compareAndUpdateKeyHash).toHaveBeenCalled();
|
expect(keyService.compareKeyHash).toHaveBeenCalled();
|
||||||
expect(masterPasswordService.setMasterKeyHash).toHaveBeenCalledWith(
|
expect(masterPasswordService.setMasterKeyHash).toHaveBeenCalledWith(
|
||||||
"localHash",
|
"localHash",
|
||||||
mockUserId,
|
mockUserId,
|
||||||
@@ -240,7 +240,7 @@ describe("UserVerificationService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("throws if verification fails", async () => {
|
it("throws if verification fails", async () => {
|
||||||
keyService.compareAndUpdateKeyHash.mockResolvedValueOnce(false);
|
keyService.compareKeyHash.mockResolvedValueOnce(false);
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
sut.verifyUserByMasterPassword(
|
sut.verifyUserByMasterPassword(
|
||||||
@@ -253,7 +253,7 @@ describe("UserVerificationService", () => {
|
|||||||
),
|
),
|
||||||
).rejects.toThrow("Invalid master password");
|
).rejects.toThrow("Invalid master password");
|
||||||
|
|
||||||
expect(keyService.compareAndUpdateKeyHash).toHaveBeenCalled();
|
expect(keyService.compareKeyHash).toHaveBeenCalled();
|
||||||
expect(masterPasswordService.setMasterKeyHash).not.toHaveBeenCalledWith();
|
expect(masterPasswordService.setMasterKeyHash).not.toHaveBeenCalledWith();
|
||||||
expect(masterPasswordService.setMasterKey).not.toHaveBeenCalledWith();
|
expect(masterPasswordService.setMasterKey).not.toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
@@ -285,7 +285,7 @@ describe("UserVerificationService", () => {
|
|||||||
"email",
|
"email",
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(keyService.compareAndUpdateKeyHash).not.toHaveBeenCalled();
|
expect(keyService.compareKeyHash).not.toHaveBeenCalled();
|
||||||
expect(masterPasswordService.setMasterKeyHash).toHaveBeenCalledWith(
|
expect(masterPasswordService.setMasterKeyHash).toHaveBeenCalledWith(
|
||||||
"localHash",
|
"localHash",
|
||||||
mockUserId,
|
mockUserId,
|
||||||
@@ -318,7 +318,7 @@ describe("UserVerificationService", () => {
|
|||||||
),
|
),
|
||||||
).rejects.toThrow("Invalid master password");
|
).rejects.toThrow("Invalid master password");
|
||||||
|
|
||||||
expect(keyService.compareAndUpdateKeyHash).not.toHaveBeenCalled();
|
expect(keyService.compareKeyHash).not.toHaveBeenCalled();
|
||||||
expect(masterPasswordService.setMasterKeyHash).not.toHaveBeenCalledWith();
|
expect(masterPasswordService.setMasterKeyHash).not.toHaveBeenCalledWith();
|
||||||
expect(masterPasswordService.setMasterKey).not.toHaveBeenCalledWith();
|
expect(masterPasswordService.setMasterKey).not.toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -206,9 +206,10 @@ export class UserVerificationService implements UserVerificationServiceAbstracti
|
|||||||
let policyOptions: MasterPasswordPolicyResponse | null;
|
let policyOptions: MasterPasswordPolicyResponse | null;
|
||||||
// Client-side verification
|
// Client-side verification
|
||||||
if (await this.hasMasterPasswordAndMasterKeyHash(userId)) {
|
if (await this.hasMasterPasswordAndMasterKeyHash(userId)) {
|
||||||
const passwordValid = await this.keyService.compareAndUpdateKeyHash(
|
const passwordValid = await this.keyService.compareKeyHash(
|
||||||
verification.secret,
|
verification.secret,
|
||||||
masterKey,
|
masterKey,
|
||||||
|
userId,
|
||||||
);
|
);
|
||||||
if (!passwordValid) {
|
if (!passwordValid) {
|
||||||
throw new Error(this.i18nService.t("invalidMasterPassword"));
|
throw new Error(this.i18nService.t("invalidMasterPassword"));
|
||||||
|
|||||||
@@ -204,14 +204,18 @@ export abstract class KeyService {
|
|||||||
hashPurpose?: HashPurpose,
|
hashPurpose?: HashPurpose,
|
||||||
): Promise<string>;
|
): Promise<string>;
|
||||||
/**
|
/**
|
||||||
* Compares the provided master password to the stored password hash and server password hash.
|
* Compares the provided master password to the stored password hash.
|
||||||
* Updates the stored hash if outdated.
|
|
||||||
* @param masterPassword The user's master password
|
* @param masterPassword The user's master password
|
||||||
* @param key The user's master key
|
* @param key The user's master key
|
||||||
|
* @param userId The id of the user to do the operation for.
|
||||||
* @returns True if the provided master password matches either the stored
|
* @returns True if the provided master password matches either the stored
|
||||||
* key hash or the server key hash
|
* key hash or the server key hash
|
||||||
*/
|
*/
|
||||||
abstract compareAndUpdateKeyHash(masterPassword: string, masterKey: MasterKey): Promise<boolean>;
|
abstract compareKeyHash(
|
||||||
|
masterPassword: string,
|
||||||
|
masterKey: MasterKey,
|
||||||
|
userId: UserId,
|
||||||
|
): Promise<boolean>;
|
||||||
/**
|
/**
|
||||||
* Stores the encrypted organization keys and clears any decrypted
|
* Stores the encrypted organization keys and clears any decrypted
|
||||||
* organization keys currently in memory
|
* organization keys currently in memory
|
||||||
|
|||||||
@@ -733,4 +733,63 @@ describe("keyService", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("compareKeyHash", () => {
|
||||||
|
type TestCase = {
|
||||||
|
masterKey: MasterKey;
|
||||||
|
masterPassword: string | null;
|
||||||
|
storedMasterKeyHash: string;
|
||||||
|
mockReturnedHash: string;
|
||||||
|
expectedToMatch: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const data: TestCase[] = [
|
||||||
|
{
|
||||||
|
masterKey: makeSymmetricCryptoKey(64),
|
||||||
|
masterPassword: "my_master_password",
|
||||||
|
storedMasterKeyHash: "bXlfaGFzaA==",
|
||||||
|
mockReturnedHash: "bXlfaGFzaA==",
|
||||||
|
expectedToMatch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
masterKey: makeSymmetricCryptoKey(64),
|
||||||
|
masterPassword: null,
|
||||||
|
storedMasterKeyHash: "bXlfaGFzaA==",
|
||||||
|
mockReturnedHash: "bXlfaGFzaA==",
|
||||||
|
expectedToMatch: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
masterKey: makeSymmetricCryptoKey(64),
|
||||||
|
masterPassword: null,
|
||||||
|
storedMasterKeyHash: null,
|
||||||
|
mockReturnedHash: "bXlfaGFzaA==",
|
||||||
|
expectedToMatch: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
it.each(data)(
|
||||||
|
"returns expected match value when calculated hash equals stored hash",
|
||||||
|
async ({
|
||||||
|
masterKey,
|
||||||
|
masterPassword,
|
||||||
|
storedMasterKeyHash,
|
||||||
|
mockReturnedHash,
|
||||||
|
expectedToMatch,
|
||||||
|
}) => {
|
||||||
|
masterPasswordService.masterKeyHashSubject.next(storedMasterKeyHash);
|
||||||
|
|
||||||
|
cryptoFunctionService.pbkdf2
|
||||||
|
.calledWith(masterKey.key, masterPassword, "sha256", 2)
|
||||||
|
.mockResolvedValue(Utils.fromB64ToArray(mockReturnedHash));
|
||||||
|
|
||||||
|
const actualDidMatch = await keyService.compareKeyHash(
|
||||||
|
masterPassword,
|
||||||
|
masterKey,
|
||||||
|
mockUserId,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(actualDidMatch).toBe(expectedToMatch);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -319,34 +319,43 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move to MasterPasswordService
|
// TODO: move to MasterPasswordService
|
||||||
async compareAndUpdateKeyHash(masterPassword: string, masterKey: MasterKey): Promise<boolean> {
|
async compareKeyHash(
|
||||||
const userId = await firstValueFrom(this.stateProvider.activeUserId$);
|
masterPassword: string,
|
||||||
|
masterKey: MasterKey,
|
||||||
|
userId: UserId,
|
||||||
|
): Promise<boolean> {
|
||||||
|
if (masterKey == null) {
|
||||||
|
throw new Error("'masterKey' is required to be non-null.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (masterPassword == null) {
|
||||||
|
// If they don't give us a master password, we can't hash it, and therefore
|
||||||
|
// it will never match what we have stored.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the current password hash
|
||||||
const storedPasswordHash = await firstValueFrom(
|
const storedPasswordHash = await firstValueFrom(
|
||||||
this.masterPasswordService.masterKeyHash$(userId),
|
this.masterPasswordService.masterKeyHash$(userId),
|
||||||
);
|
);
|
||||||
if (masterPassword != null && storedPasswordHash != null) {
|
|
||||||
const localKeyHash = await this.hashMasterKey(
|
|
||||||
masterPassword,
|
|
||||||
masterKey,
|
|
||||||
HashPurpose.LocalAuthorization,
|
|
||||||
);
|
|
||||||
if (localKeyHash != null && storedPasswordHash === localKeyHash) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: remove serverKeyHash check in 1-2 releases after everyone's keyHash has been updated
|
if (storedPasswordHash == null) {
|
||||||
const serverKeyHash = await this.hashMasterKey(
|
return false;
|
||||||
masterPassword,
|
|
||||||
masterKey,
|
|
||||||
HashPurpose.ServerAuthorization,
|
|
||||||
);
|
|
||||||
if (serverKeyHash != null && storedPasswordHash === serverKeyHash) {
|
|
||||||
await this.masterPasswordService.setMasterKeyHash(localKeyHash, userId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
// Hash the key for local use
|
||||||
|
const localKeyHash = await this.hashMasterKey(
|
||||||
|
masterPassword,
|
||||||
|
masterKey,
|
||||||
|
HashPurpose.LocalAuthorization,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if the stored hash is already equal to the hash we create locally
|
||||||
|
if (localKeyHash == null || storedPasswordHash !== localKeyHash) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async setOrgKeys(
|
async setOrgKeys(
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { DialogRef } from "@angular/cdk/dialog";
|
import { DialogRef } from "@angular/cdk/dialog";
|
||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
|
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
|
||||||
|
import { firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import {
|
import {
|
||||||
@@ -43,16 +45,25 @@ export class PasswordRepromptComponent {
|
|||||||
protected i18nService: I18nService,
|
protected i18nService: I18nService,
|
||||||
protected formBuilder: FormBuilder,
|
protected formBuilder: FormBuilder,
|
||||||
protected dialogRef: DialogRef,
|
protected dialogRef: DialogRef,
|
||||||
|
protected accountService: AccountService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
submit = async () => {
|
submit = async () => {
|
||||||
|
const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(map((a) => a?.id)));
|
||||||
|
|
||||||
|
if (userId == null) {
|
||||||
|
throw new Error("An active user is expected while doing password reprompt.");
|
||||||
|
}
|
||||||
|
|
||||||
const storedMasterKey = await this.keyService.getOrDeriveMasterKey(
|
const storedMasterKey = await this.keyService.getOrDeriveMasterKey(
|
||||||
this.formGroup.value.masterPassword,
|
this.formGroup.value.masterPassword,
|
||||||
|
userId,
|
||||||
);
|
);
|
||||||
if (
|
if (
|
||||||
!(await this.keyService.compareAndUpdateKeyHash(
|
!(await this.keyService.compareKeyHash(
|
||||||
this.formGroup.value.masterPassword,
|
this.formGroup.value.masterPassword,
|
||||||
storedMasterKey,
|
storedMasterKey,
|
||||||
|
userId,
|
||||||
))
|
))
|
||||||
) {
|
) {
|
||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
|
|||||||
10
package-lock.json
generated
10
package-lock.json
generated
@@ -69,7 +69,7 @@
|
|||||||
"rxjs": "7.8.1",
|
"rxjs": "7.8.1",
|
||||||
"tabbable": "6.2.0",
|
"tabbable": "6.2.0",
|
||||||
"tldts": "6.1.58",
|
"tldts": "6.1.58",
|
||||||
"utf-8-validate": "6.0.4",
|
"utf-8-validate": "6.0.5",
|
||||||
"zone.js": "0.14.10",
|
"zone.js": "0.14.10",
|
||||||
"zxcvbn": "4.4.2"
|
"zxcvbn": "4.4.2"
|
||||||
},
|
},
|
||||||
@@ -319,6 +319,7 @@
|
|||||||
"license": "GPL-3.0"
|
"license": "GPL-3.0"
|
||||||
},
|
},
|
||||||
"libs/tools/export/vault-export/vault-export-core": {
|
"libs/tools/export/vault-export/vault-export-core": {
|
||||||
|
"name": "@bitwarden/vault-export-core",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -34702,10 +34703,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/utf-8-validate": {
|
"node_modules/utf-8-validate": {
|
||||||
"version": "6.0.4",
|
"version": "6.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.5.tgz",
|
||||||
"integrity": "sha512-xu9GQDeFp+eZ6LnCywXN/zBancWvOpUMzgjLPSjy4BRHSmTelvn2E0DG0o1sTiw5hkCKBHo8rwSKncfRfv2EEQ==",
|
"integrity": "sha512-EYZR+OpIXp9Y1eG1iueg8KRsY8TuT8VNgnanZ0uA3STqhHQTLwbl+WX76/9X5OY12yQubymBpaBSmMPkSTQcKA==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-gyp-build": "^4.3.0"
|
"node-gyp-build": "^4.3.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -203,7 +203,7 @@
|
|||||||
"rxjs": "7.8.1",
|
"rxjs": "7.8.1",
|
||||||
"tabbable": "6.2.0",
|
"tabbable": "6.2.0",
|
||||||
"tldts": "6.1.58",
|
"tldts": "6.1.58",
|
||||||
"utf-8-validate": "6.0.4",
|
"utf-8-validate": "6.0.5",
|
||||||
"zone.js": "0.14.10",
|
"zone.js": "0.14.10",
|
||||||
"zxcvbn": "4.4.2"
|
"zxcvbn": "4.4.2"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user