update enc key
This commit is contained in:
parent
d1395e37fd
commit
49f948844f
2
jslib
2
jslib
|
@ -1 +1 @@
|
|||
Subproject commit 3354f0b8180c319b4ae72c062874e9f8f5a1fe61
|
||||
Subproject commit f35ecf0cd8bd1b91f2544e07bb7b766d227f54ff
|
|
@ -92,6 +92,7 @@ import { TwoFactorSetupComponent } from './settings/two-factor-setup.component';
|
|||
import { TwoFactorU2fComponent } from './settings/two-factor-u2f.component';
|
||||
import { TwoFactorVerifyComponent } from './settings/two-factor-verify.component';
|
||||
import { TwoFactorYubiKeyComponent } from './settings/two-factor-yubikey.component';
|
||||
import { UpdateKeyComponent } from './settings/update-key.component';
|
||||
import { UpdateLicenseComponent } from './settings/update-license.component';
|
||||
import { UserBillingComponent } from './settings/user-billing.component';
|
||||
import { VerifyEmailComponent } from './settings/verify-email.component';
|
||||
|
@ -241,6 +242,7 @@ import { SearchPipe } from 'jslib/angular/pipes/search.pipe';
|
|||
TwoFactorU2fComponent,
|
||||
TwoFactorVerifyComponent,
|
||||
TwoFactorYubiKeyComponent,
|
||||
UpdateKeyComponent,
|
||||
UpdateLicenseComponent,
|
||||
UserBillingComponent,
|
||||
UserLayoutComponent,
|
||||
|
@ -280,6 +282,7 @@ import { SearchPipe } from 'jslib/angular/pipes/search.pipe';
|
|||
TwoFactorRecoveryComponent,
|
||||
TwoFactorU2fComponent,
|
||||
TwoFactorYubiKeyComponent,
|
||||
UpdateKeyComponent,
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<div class="modal fade">
|
||||
<div class="modal-dialog">
|
||||
<form class="modal-content" #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate>
|
||||
<div class="modal-header">
|
||||
<h2 class="modal-title">{{'updateEncryptionKey' | i18n}}</h2>
|
||||
<button type="button" class="close" data-dismiss="modal" attr.aria-label="{{'close' | i18n}}">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>{{'updateEncryptionKeyShortDesc' | i18n}} {{'updateEncryptionKeyDesc' | i18n}}
|
||||
<a href="https://help.bitwarden.com/article/update-encryption-key/" target="_blank" rel="noopener">{{'learnMore' | i18n}}</a>
|
||||
</p>
|
||||
<app-callout type="warning">{{'updateEncryptionKeyWarning' | i18n}}</app-callout>
|
||||
<label for="masterPassword">{{'masterPass' | i18n}}</label>
|
||||
<input id="masterPassword" type="password" name="MasterPasswordHash" class="form-control" [(ngModel)]="masterPassword" required
|
||||
appAutofocus appInputVerbatim>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button appBlurClick type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
|
||||
<i class="fa fa-spinner fa-spin"></i>
|
||||
<span>{{'updateEncryptionKey' | i18n}}</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">{{'close' | i18n}}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,98 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
import {
|
||||
Toast,
|
||||
ToasterService,
|
||||
} from 'angular2-toaster';
|
||||
import { Angulartics2 } from 'angulartics2';
|
||||
|
||||
import { ApiService } from 'jslib/abstractions/api.service';
|
||||
import { CipherService } from 'jslib/abstractions/cipher.service';
|
||||
import { CryptoService } from 'jslib/abstractions/crypto.service';
|
||||
import { FolderService } from 'jslib/abstractions/folder.service';
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
import { MessagingService } from 'jslib/abstractions/messaging.service';
|
||||
import { SyncService } from 'jslib/abstractions/sync.service';
|
||||
|
||||
import { CipherString } from 'jslib/models/domain/cipherString';
|
||||
|
||||
import { CipherWithIdRequest } from 'jslib/models/request/cipherWithIdRequest';
|
||||
import { FolderWithIdRequest } from 'jslib/models/request/folderWithIdRequest';
|
||||
import { UpdateKeyRequest } from 'jslib/models/request/updateKeyRequest';
|
||||
|
||||
@Component({
|
||||
selector: 'app-update-key',
|
||||
templateUrl: 'update-key.component.html',
|
||||
})
|
||||
export class UpdateKeyComponent {
|
||||
masterPassword: string;
|
||||
formPromise: Promise<any>;
|
||||
|
||||
constructor(private apiService: ApiService, private i18nService: I18nService,
|
||||
private analytics: Angulartics2, private toasterService: ToasterService,
|
||||
private cryptoService: CryptoService, private messagingService: MessagingService,
|
||||
private syncService: SyncService, private folderService: FolderService,
|
||||
private cipherService: CipherService) { }
|
||||
|
||||
async submit() {
|
||||
const hasEncKey = await this.cryptoService.hasEncKey();
|
||||
if (hasEncKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.masterPassword == null || this.masterPassword === '') {
|
||||
this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'),
|
||||
this.i18nService.t('masterPassRequired'));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.formPromise = this.makeRequest().then((request) => {
|
||||
return this.apiService.postAccountKey(request);
|
||||
});
|
||||
await this.formPromise;
|
||||
this.analytics.eventTrack.next({ action: 'Key Updated' });
|
||||
const toast: Toast = {
|
||||
type: 'success',
|
||||
title: this.i18nService.t('keyUpdated'),
|
||||
body: this.i18nService.t('logBackInOthersToo'),
|
||||
timeout: 15000,
|
||||
};
|
||||
this.toasterService.popAsync(toast);
|
||||
this.messagingService.send('logout');
|
||||
} catch { }
|
||||
}
|
||||
|
||||
private async makeRequest(): Promise<UpdateKeyRequest> {
|
||||
const key = await this.cryptoService.getKey();
|
||||
const encKey = await this.cryptoService.makeEncKey(key);
|
||||
const privateKey = await this.cryptoService.getPrivateKey();
|
||||
let encPrivateKey: CipherString = null;
|
||||
if (privateKey != null) {
|
||||
encPrivateKey = await this.cryptoService.encrypt(privateKey, encKey[0]);
|
||||
}
|
||||
const request = new UpdateKeyRequest();
|
||||
request.privateKey = encPrivateKey != null ? encPrivateKey.encryptedString : null;
|
||||
request.key = encKey[1].encryptedString;
|
||||
request.masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, null);
|
||||
|
||||
await this.syncService.fullSync(true);
|
||||
|
||||
const folders = await this.folderService.getAllDecrypted();
|
||||
for (let i = 0; i < folders.length; i++) {
|
||||
const folder = await this.folderService.encrypt(folders[i], encKey[0]);
|
||||
request.folders.push(new FolderWithIdRequest(folder));
|
||||
}
|
||||
|
||||
const ciphers = await this.cipherService.getAllDecrypted();
|
||||
for (let i = 0; i < ciphers.length; i++) {
|
||||
if (ciphers[i].organizationId != null) {
|
||||
continue;
|
||||
}
|
||||
const cipher = await this.cipherService.encrypt(ciphers[i], encKey[0]);
|
||||
request.ciphers.push(new CipherWithIdRequest(cipher));
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
|
@ -61,6 +61,17 @@
|
|||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card border-warning mb-4" *ngIf="showUpdateKey">
|
||||
<div class="card-header bg-warning text-white">
|
||||
<i class="fa fa-warning fa-fw"></i> {{'updateKeyTitle' | i18n}}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>{{'updateEncryptionKeyShortDesc' | i18n}}</p>
|
||||
<button class="btn btn-block btn-outline-secondary" type="button" (click)="updateKey()">
|
||||
{{'updateEncryptionKey' | i18n}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
{{'organizations' | i18n}}
|
||||
|
@ -80,3 +91,4 @@
|
|||
<ng-template #bulkDeleteTemplate></ng-template>
|
||||
<ng-template #bulkMoveTemplate></ng-template>
|
||||
<ng-template #bulkShareTemplate></ng-template>
|
||||
<ng-template #updateKeyTemplate></ng-template>
|
||||
|
|
|
@ -18,6 +18,7 @@ import { CipherView } from 'jslib/models/view/cipherView';
|
|||
import { ModalComponent } from '../modal.component';
|
||||
|
||||
import { OrganizationsComponent } from '../settings/organizations.component';
|
||||
import { UpdateKeyComponent } from '../settings/update-key.component';
|
||||
import { AddEditComponent } from './add-edit.component';
|
||||
import { AttachmentsComponent } from './attachments.component';
|
||||
import { BulkDeleteComponent } from './bulk-delete.component';
|
||||
|
@ -50,6 +51,7 @@ export class VaultComponent implements OnInit {
|
|||
@ViewChild('bulkDeleteTemplate', { read: ViewContainerRef }) bulkDeleteModalRef: ViewContainerRef;
|
||||
@ViewChild('bulkMoveTemplate', { read: ViewContainerRef }) bulkMoveModalRef: ViewContainerRef;
|
||||
@ViewChild('bulkShareTemplate', { read: ViewContainerRef }) bulkShareModalRef: ViewContainerRef;
|
||||
@ViewChild('updateKeyTemplate', { read: ViewContainerRef }) updateKeyModalRef: ViewContainerRef;
|
||||
|
||||
favorites: boolean = false;
|
||||
type: CipherType = null;
|
||||
|
@ -70,7 +72,7 @@ export class VaultComponent implements OnInit {
|
|||
this.showVerifyEmail = !(await this.tokenService.getEmailVerified());
|
||||
this.showBrowserOutdated = window.navigator.userAgent.indexOf('MSIE') !== -1;
|
||||
const hasEncKey = await this.cryptoService.hasEncKey();
|
||||
this.showUpdateKey = !this.showVerifyEmail && hasEncKey;
|
||||
this.showUpdateKey = !hasEncKey;
|
||||
|
||||
this.route.queryParams.subscribe(async (params) => {
|
||||
await this.syncService.fullSync(false);
|
||||
|
@ -363,6 +365,20 @@ export class VaultComponent implements OnInit {
|
|||
this.ciphersComponent.selectAll(select);
|
||||
}
|
||||
|
||||
updateKey() {
|
||||
if (this.modal != null) {
|
||||
this.modal.close();
|
||||
}
|
||||
|
||||
const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
|
||||
this.modal = this.updateKeyModalRef.createComponent(factory).instance;
|
||||
this.modal.show<UpdateKeyComponent>(UpdateKeyComponent, this.updateKeyModalRef);
|
||||
|
||||
this.modal.onClosed.subscribe(() => {
|
||||
this.modal = null;
|
||||
});
|
||||
}
|
||||
|
||||
private clearFilters() {
|
||||
this.folderId = null;
|
||||
this.collectionId = null;
|
||||
|
|
|
@ -837,6 +837,9 @@
|
|||
"logBackIn": {
|
||||
"message": "Please log back in."
|
||||
},
|
||||
"logBackInOthersToo": {
|
||||
"message": "Please log back in. If you are using other Bitwarden applications log out and back in to those as well."
|
||||
},
|
||||
"changeMasterPassword": {
|
||||
"message": "Change Master Password"
|
||||
},
|
||||
|
@ -2273,5 +2276,23 @@
|
|||
"example": "15"
|
||||
}
|
||||
}
|
||||
},
|
||||
"keyUpdated": {
|
||||
"message": "Key Updated"
|
||||
},
|
||||
"updateKeyTitle": {
|
||||
"message": "Update Key"
|
||||
},
|
||||
"updateEncryptionKey": {
|
||||
"message": "Update Encryption Key"
|
||||
},
|
||||
"updateEncryptionKeyShortDesc": {
|
||||
"message": "You are currently using an outdated encryption scheme."
|
||||
},
|
||||
"updateEncryptionKeyDesc": {
|
||||
"message": "We've moved to larger encryption keys that provide better security and access to newer features. Updating your encryption key is quick and easy. Just type your master password below. This update will eventually become mandatory."
|
||||
},
|
||||
"updateEncryptionKeyWarning": {
|
||||
"message": "After updating your encryption key, you are required to log out and back in to all Bitwarden applications that you are currently using (such as the mobile app or browser extensions). Failure to log out and back in (which downloads your new encryption key) may result in data corruption. We will attempt to log you out automatically, however, it may be delayed."
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue