mirror of
https://github.com/bitwarden/browser
synced 2026-02-13 23:13:36 +00:00
add submitOld() to ChangePasswordComponent and rotateUserKeyClicked() to InputPasswordComponent
This commit is contained in:
@@ -23,4 +23,11 @@ export class WebChangePasswordService
|
||||
hint,
|
||||
);
|
||||
}
|
||||
|
||||
override async rotateUserKeyAndEncryptedDataLegacy(
|
||||
newPassword: string,
|
||||
user: Account,
|
||||
): Promise<void | null> {
|
||||
await this.userKeyRotationService.rotateUserKeyAndEncryptedDataLegacy(newPassword, user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,15 @@ import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/mod
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
|
||||
import { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { HashPurpose } from "@bitwarden/common/platform/enums";
|
||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
import { KdfConfigService, KeyService } from "@bitwarden/key-management";
|
||||
|
||||
@@ -34,6 +37,7 @@ export class ChangeExistingPasswordComponent implements OnInit {
|
||||
email?: string;
|
||||
masterPasswordPolicyOptions?: MasterPasswordPolicyOptions;
|
||||
userkeyRotationV2 = false;
|
||||
formPromise: Promise<any>;
|
||||
|
||||
constructor(
|
||||
private accountService: AccountService,
|
||||
@@ -100,8 +104,77 @@ export class ChangeExistingPasswordComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
async submitOld(passwordInputResult: PasswordInputResult) {}
|
||||
async submitOld(passwordInputResult: PasswordInputResult) {
|
||||
if (passwordInputResult.rotateUserKey) {
|
||||
await this.syncService.fullSync(true);
|
||||
}
|
||||
|
||||
const masterKey = await this.keyService.makeMasterKey(
|
||||
passwordInputResult.currentPassword,
|
||||
await firstValueFrom(this.accountService.activeAccount$.pipe(map((a) => a?.email))),
|
||||
await this.kdfConfigService.getKdfConfig(),
|
||||
);
|
||||
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
const newLocalKeyHash = await this.keyService.hashMasterKey(
|
||||
passwordInputResult.newPassword,
|
||||
passwordInputResult.masterKey,
|
||||
HashPurpose.LocalAuthorization,
|
||||
);
|
||||
|
||||
const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(masterKey, userId);
|
||||
if (userKey == null) {
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("invalidMasterPassword"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const request = new PasswordRequest();
|
||||
request.masterPasswordHash = await this.keyService.hashMasterKey(
|
||||
passwordInputResult.currentPassword,
|
||||
masterKey,
|
||||
);
|
||||
request.masterPasswordHint = passwordInputResult.hint;
|
||||
request.newMasterPasswordHash = passwordInputResult.serverMasterKeyHash;
|
||||
// request.key = newUserKey[1].encryptedString;
|
||||
|
||||
try {
|
||||
if (passwordInputResult.rotateUserKey) {
|
||||
this.formPromise = this.masterPasswordApiService.postPassword(request).then(async () => {
|
||||
// we need to save this for local masterkey verification during rotation
|
||||
await this.masterPasswordService.setMasterKeyHash(newLocalKeyHash, userId as UserId);
|
||||
await this.masterPasswordService.setMasterKey(
|
||||
passwordInputResult.masterKey,
|
||||
userId as UserId,
|
||||
);
|
||||
return this.updateKey(passwordInputResult.newPassword);
|
||||
});
|
||||
} else {
|
||||
this.formPromise = this.masterPasswordApiService.postPassword(request);
|
||||
}
|
||||
|
||||
await this.formPromise;
|
||||
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: this.i18nService.t("masterPasswordChanged"),
|
||||
message: this.i18nService.t("logBackIn"),
|
||||
});
|
||||
this.messagingService.send("logout");
|
||||
} catch {
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("errorOccurred"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// todo: move this to a service
|
||||
// https://bitwarden.atlassian.net/browse/PM-17108
|
||||
async updatePassword(currentPassword: string, newPassword: string, hint: string) {
|
||||
const { userId, email } = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => ({ userId: a?.id, email: a?.email }))),
|
||||
@@ -155,4 +228,9 @@ export class ChangeExistingPasswordComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async updateKey(newPassword: string) {
|
||||
const user = await firstValueFrom(this.accountService.activeAccount$);
|
||||
await this.changePasswordService.rotateUserKeyAndEncryptedDataLegacy(newPassword, user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,10 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { MasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { HashPurpose } from "@bitwarden/common/platform/enums";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import {
|
||||
AsyncActionsModule,
|
||||
ButtonModule,
|
||||
@@ -158,12 +160,14 @@ export class InputPasswordComponent implements OnInit {
|
||||
constructor(
|
||||
private accountService: AccountService,
|
||||
private auditService: AuditService,
|
||||
private cipherService: CipherService,
|
||||
private dialogService: DialogService,
|
||||
private formBuilder: FormBuilder,
|
||||
private i18nService: I18nService,
|
||||
private kdfConfigService: KdfConfigService,
|
||||
private keyService: KeyService,
|
||||
private masterPasswordService: MasterPasswordServiceAbstraction,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private policyService: PolicyService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
@@ -385,4 +389,55 @@ export class InputPasswordComponent implements OnInit {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async rotateUserKeyClicked() {
|
||||
if (this.rotateUserKey) {
|
||||
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
|
||||
|
||||
const ciphers = await this.cipherService.getAllDecrypted(activeUserId);
|
||||
let hasOldAttachments = false;
|
||||
if (ciphers != null) {
|
||||
for (let i = 0; i < ciphers.length; i++) {
|
||||
if (ciphers[i].organizationId == null && ciphers[i].hasOldAttachments) {
|
||||
hasOldAttachments = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasOldAttachments) {
|
||||
const learnMore = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "warning" },
|
||||
content: { key: "oldAttachmentsNeedFixDesc" },
|
||||
acceptButtonText: { key: "learnMore" },
|
||||
cancelButtonText: { key: "close" },
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (learnMore) {
|
||||
this.platformUtilsService.launchUri(
|
||||
"https://bitwarden.com/help/attachments/#add-storage-space",
|
||||
);
|
||||
}
|
||||
|
||||
this.formGroup.controls.rotateUserKey.setValue(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "rotateEncKeyTitle" },
|
||||
content:
|
||||
this.i18nService.t("updateEncryptionKeyWarning") +
|
||||
" " +
|
||||
this.i18nService.t("updateEncryptionKeyExportWarning") +
|
||||
" " +
|
||||
this.i18nService.t("rotateEncKeyConfirmation"),
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
this.formGroup.controls.rotateUserKey.setValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,4 +7,9 @@ export abstract class ChangePasswordService {
|
||||
user: Account,
|
||||
hint: string,
|
||||
): Promise<void | null>;
|
||||
|
||||
abstract rotateUserKeyAndEncryptedDataLegacy(
|
||||
newPassword: string,
|
||||
user: Account,
|
||||
): Promise<void | null>;
|
||||
}
|
||||
|
||||
@@ -11,4 +11,11 @@ export class DefaultChangePasswordService implements ChangePasswordService {
|
||||
): Promise<void | null> {
|
||||
return null;
|
||||
}
|
||||
|
||||
async rotateUserKeyAndEncryptedDataLegacy(
|
||||
newPassword: string,
|
||||
user: Account,
|
||||
): Promise<void | null> {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user