bitwarden-estensione-browser/src/popup/settings/settings.component.ts

283 lines
12 KiB
TypeScript
Raw Normal View History

2018-04-10 22:20:49 +02:00
import { Angulartics2 } from 'angulartics2';
2018-04-12 23:28:33 +02:00
import swal from 'sweetalert';
2018-04-10 22:20:49 +02:00
import {
Component,
ElementRef,
2018-04-10 22:20:49 +02:00
OnInit,
ViewChild,
2018-04-10 22:20:49 +02:00
} from '@angular/core';
import { Router } from '@angular/router';
import { BrowserApi } from '../../browser/browserApi';
import { DeviceType } from 'jslib/enums/deviceType';
import { ConstantsService } from 'jslib/services/constants.service';
2018-11-16 17:08:36 +01:00
import { CryptoService } from 'jslib/abstractions/crypto.service';
2018-06-25 14:06:38 +02:00
import { EnvironmentService } from 'jslib/abstractions/environment.service';
2018-04-10 22:20:49 +02:00
import { I18nService } from 'jslib/abstractions/i18n.service';
import { LockService } from 'jslib/abstractions/lock.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { StorageService } from 'jslib/abstractions/storage.service';
2018-11-16 17:08:36 +01:00
import { UserService } from 'jslib/abstractions/user.service';
2018-04-10 22:20:49 +02:00
const RateUrls = {
2018-07-09 15:12:41 +02:00
[DeviceType.ChromeExtension]:
2018-04-10 22:20:49 +02:00
'https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/reviews',
2018-07-09 15:12:41 +02:00
[DeviceType.FirefoxExtension]:
2018-04-10 22:20:49 +02:00
'https://addons.mozilla.org/en-US/firefox/addon/bitwarden-password-manager/#reviews',
2018-07-09 15:12:41 +02:00
[DeviceType.OperaExtension]:
2018-04-10 22:20:49 +02:00
'https://addons.opera.com/en/extensions/details/bitwarden-free-password-manager/#feedback-container',
2018-07-09 15:12:41 +02:00
[DeviceType.EdgeExtension]:
2018-04-10 22:20:49 +02:00
'https://www.microsoft.com/store/p/bitwarden-free-password-manager/9p6kxl0svnnl',
2018-07-09 15:12:41 +02:00
[DeviceType.VivaldiExtension]:
2018-04-10 22:20:49 +02:00
'https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/reviews',
2018-07-09 15:12:41 +02:00
[DeviceType.SafariExtension]:
2018-04-10 22:20:49 +02:00
'https://itunes.apple.com/app/bitwarden-password-manager/id1137397744',
};
2018-04-09 23:35:16 +02:00
@Component({
selector: 'app-settings',
templateUrl: 'settings.component.html',
})
2018-04-10 22:20:49 +02:00
export class SettingsComponent implements OnInit {
@ViewChild('lockOptionsSelect', { read: ElementRef }) lockOptionsSelectRef: ElementRef;
2018-04-10 22:20:49 +02:00
lockOptions: any[];
lockOption: number = null;
2019-02-13 05:53:04 +01:00
pin: boolean = null;
previousLockOption: number = null;
2018-04-10 22:20:49 +02:00
constructor(private platformUtilsService: PlatformUtilsService, private i18nService: I18nService,
private analytics: Angulartics2, private lockService: LockService,
private storageService: StorageService, public messagingService: MessagingService,
2018-11-16 17:08:36 +01:00
private router: Router, private environmentService: EnvironmentService,
private cryptoService: CryptoService, private userService: UserService) {
2018-04-10 22:20:49 +02:00
}
async ngOnInit() {
const showOnLocked = !this.platformUtilsService.isFirefox() && !this.platformUtilsService.isEdge()
&& !this.platformUtilsService.isSafari();
this.lockOptions = [
{ name: this.i18nService.t('immediately'), value: 0 },
{ name: this.i18nService.t('oneMinute'), value: 1 },
{ name: this.i18nService.t('fiveMinutes'), value: 5 },
{ name: this.i18nService.t('fifteenMinutes'), value: 15 },
{ name: this.i18nService.t('thirtyMinutes'), value: 30 },
{ name: this.i18nService.t('oneHour'), value: 60 },
{ name: this.i18nService.t('fourHours'), value: 240 },
// { name: i18nService.t('onIdle'), value: -4 },
// { name: i18nService.t('onSleep'), value: -3 },
];
if (showOnLocked) {
this.lockOptions.push({ name: this.i18nService.t('onLocked'), value: -2 });
}
this.lockOptions.push({ name: this.i18nService.t('onRestart'), value: -1 });
this.lockOptions.push({ name: this.i18nService.t('never'), value: null });
let option = await this.storageService.get<number>(ConstantsService.lockOptionKey);
if (option != null) {
if (option === -2 && !showOnLocked) {
option = -1;
}
this.lockOption = option;
}
this.previousLockOption = this.lockOption;
2019-02-13 05:53:04 +01:00
const pinSet = await this.lockService.isPinLockSet();
this.pin = pinSet[0] || pinSet[1];
2018-04-10 22:20:49 +02:00
}
async saveLockOption(newValue: number) {
2018-10-04 04:49:59 +02:00
if (newValue == null && !this.platformUtilsService.isSafari()) {
const confirmed = await this.platformUtilsService.showDialog(
this.i18nService.t('neverLockWarning'), null,
this.i18nService.t('yes'), this.i18nService.t('cancel'), 'warning');
if (!confirmed) {
this.lockOptions.forEach((option: any, i) => {
if (option.value === this.lockOption) {
this.lockOptionsSelectRef.nativeElement.value = i + ': ' + this.lockOption;
}
});
return;
}
}
this.previousLockOption = this.lockOption;
this.lockOption = newValue;
2018-04-10 22:20:49 +02:00
await this.lockService.setLockOption(this.lockOption != null ? this.lockOption : null);
if (this.previousLockOption == null) {
this.messagingService.send('bgReseedStorage');
}
2018-04-10 22:20:49 +02:00
}
2019-02-13 05:53:04 +01:00
async updatePin() {
if (this.pin) {
const div = document.createElement('div');
const label = document.createElement('label');
label.className = 'checkbox';
const checkboxText = document.createElement('span');
const restartText = document.createTextNode(this.i18nService.t('lockWithMasterPassOnRestart'));
checkboxText.appendChild(restartText);
label.innerHTML = '<input type="checkbox" id="master-pass-restart" checked>';
label.appendChild(checkboxText);
div.innerHTML = '<input type="text" class="swal-content__input" id="pin-val">';
(div.querySelector('#pin-val') as HTMLInputElement).placeholder = this.i18nService.t('pin');
div.appendChild(label);
const submitted = await swal({
2019-02-13 05:53:04 +01:00
text: this.i18nService.t('setYourPinCode'),
content: { element: div },
2019-02-13 05:53:04 +01:00
buttons: [this.i18nService.t('cancel'), this.i18nService.t('submit')],
});
let pin: string = null;
let masterPassOnRestart: boolean = null;
if (submitted) {
pin = (document.getElementById('pin-val') as HTMLInputElement).value;
masterPassOnRestart = (document.getElementById('master-pass-restart') as HTMLInputElement).checked;
}
2019-02-13 05:53:04 +01:00
if (pin != null && pin.trim() !== '') {
if (masterPassOnRestart) {
const encPin = await this.cryptoService.encrypt(pin);
await this.storageService.save(ConstantsService.protectedPin, encPin.encryptedString);
} else {
const kdf = await this.userService.getKdf();
const kdfIterations = await this.userService.getKdfIterations();
const email = await this.userService.getEmail();
const pinKey = await this.cryptoService.makePinKey(pin, email, kdf, kdfIterations);
const key = await this.cryptoService.getKey();
const pinProtectedKey = await this.cryptoService.encrypt(key.key, pinKey);
await this.storageService.save(ConstantsService.pinProtectedKey, pinProtectedKey.encryptedString);
}
2019-02-13 05:53:04 +01:00
} else {
this.pin = false;
}
}
if (!this.pin) {
await this.storageService.remove(ConstantsService.pinProtectedKey);
await this.storageService.remove(ConstantsService.protectedPin);
2019-02-13 05:53:04 +01:00
}
}
2018-04-10 22:20:49 +02:00
async lock() {
this.analytics.eventTrack.next({ action: 'Lock Now' });
await this.lockService.lock(true);
2018-04-10 22:20:49 +02:00
this.router.navigate(['lock']);
}
async logOut() {
const confirmed = await this.platformUtilsService.showDialog(
this.i18nService.t('logOutConfirmation'), this.i18nService.t('logOut'),
this.i18nService.t('yes'), this.i18nService.t('cancel'));
if (confirmed) {
this.messagingService.send('logout');
}
}
async changePassword() {
this.analytics.eventTrack.next({ action: 'Clicked Change Password' });
const confirmed = await this.platformUtilsService.showDialog(
this.i18nService.t('changeMasterPasswordConfirmation'), this.i18nService.t('changeMasterPassword'),
this.i18nService.t('yes'), this.i18nService.t('cancel'));
if (confirmed) {
BrowserApi.createNewTab('https://help.bitwarden.com/article/change-your-master-password/');
}
}
async twoStep() {
this.analytics.eventTrack.next({ action: 'Clicked Two-step Login' });
const confirmed = await this.platformUtilsService.showDialog(
this.i18nService.t('twoStepLoginConfirmation'), this.i18nService.t('twoStepLogin'),
this.i18nService.t('yes'), this.i18nService.t('cancel'));
if (confirmed) {
BrowserApi.createNewTab('https://help.bitwarden.com/article/setup-two-step-login/');
}
}
async share() {
this.analytics.eventTrack.next({ action: 'Clicked Share Vault' });
const confirmed = await this.platformUtilsService.showDialog(
this.i18nService.t('shareVaultConfirmation'), this.i18nService.t('shareVault'),
this.i18nService.t('yes'), this.i18nService.t('cancel'));
if (confirmed) {
BrowserApi.createNewTab('https://help.bitwarden.com/article/what-is-an-organization/');
}
}
async webVault() {
this.analytics.eventTrack.next({ action: 'Clicked Web Vault' });
2018-06-25 14:06:38 +02:00
let url = this.environmentService.getWebVaultUrl();
if (url == null) {
url = 'https://vault.bitwarden.com';
}
BrowserApi.createNewTab(url);
2018-04-10 22:20:49 +02:00
}
import() {
this.analytics.eventTrack.next({ action: 'Clicked Import Items' });
BrowserApi.createNewTab('https://help.bitwarden.com/article/import-data/');
}
2018-04-14 04:18:21 +02:00
export() {
if (this.platformUtilsService.isEdge()) {
BrowserApi.createNewTab('https://help.bitwarden.com/article/export-your-data/');
return;
}
this.router.navigate(['/export']);
}
2018-04-12 23:28:33 +02:00
help() {
this.analytics.eventTrack.next({ action: 'Clicked Help and Feedback' });
BrowserApi.createNewTab('https://help.bitwarden.com/');
}
about() {
this.analytics.eventTrack.next({ action: 'Clicked About' });
2018-04-19 15:45:51 +02:00
const year = (new Date()).getFullYear();
2018-04-12 23:28:33 +02:00
const versionText = document.createTextNode(
this.i18nService.t('version') + ': ' + BrowserApi.getApplicationVersion());
const div = document.createElement('div');
2018-04-19 15:45:51 +02:00
div.innerHTML = `<p class="text-center"><i class="fa fa-shield fa-3x"></i></p>
<p class="text-center"><b>Bitwarden</b><br>&copy; 8bit Solutions LLC 2015-` + year + `</p>`;
2018-04-12 23:28:33 +02:00
div.appendChild(versionText);
swal({
content: { element: div },
buttons: [this.i18nService.t('close'), false],
});
}
2018-11-16 17:08:36 +01:00
async fingerprint() {
this.analytics.eventTrack.next({ action: 'Clicked Fingerprint' });
const fingerprint = await this.cryptoService.getFingerprint(await this.userService.getUserId());
const p = document.createElement('p');
p.innerText = this.i18nService.t('yourAccountsFingerprint') + ':';
const p2 = document.createElement('p');
p2.innerText = fingerprint.join('-');
const div = document.createElement('div');
div.appendChild(p);
div.appendChild(p2);
const result = await swal({
content: { element: div },
buttons: [this.i18nService.t('close'), this.i18nService.t('learnMore')],
});
if (result) {
2018-11-16 17:17:16 +01:00
this.platformUtilsService.launchUri('https://help.bitwarden.com/article/fingerprint-phrase/');
2018-11-16 17:08:36 +01:00
}
}
2018-04-10 22:20:49 +02:00
rate() {
this.analytics.eventTrack.next({ action: 'Rate Extension' });
BrowserApi.createNewTab((RateUrls as any)[this.platformUtilsService.getDevice()]);
}
}