bitwarden-estensione-browser/src/app/app.component.ts

281 lines
11 KiB
TypeScript
Raw Normal View History

import * as jq from 'jquery';
import Swal from 'sweetalert2';
2018-06-05 05:10:41 +02:00
import {
BodyOutputType,
Toast,
2018-06-05 05:10:41 +02:00
ToasterConfig,
2018-06-08 23:08:19 +02:00
ToasterService,
2018-06-05 05:10:41 +02:00
} from 'angular2-toaster';
import {
Component,
2018-06-08 23:08:19 +02:00
NgZone,
OnDestroy,
OnInit,
SecurityContext,
2018-06-05 05:10:41 +02:00
} from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import {
NavigationEnd,
Router,
} from '@angular/router';
2018-06-05 05:10:41 +02:00
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
import { StorageService } from 'jslib-common/abstractions/storage.service';
import { AuthService } from 'jslib-common/abstractions/auth.service';
import { CipherService } from 'jslib-common/abstractions/cipher.service';
import { CollectionService } from 'jslib-common/abstractions/collection.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { EventService } from 'jslib-common/abstractions/event.service';
import { FolderService } from 'jslib-common/abstractions/folder.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { NotificationsService } from 'jslib-common/abstractions/notifications.service';
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { PolicyService } from 'jslib-common/abstractions/policy.service';
import { SearchService } from 'jslib-common/abstractions/search.service';
import { SettingsService } from 'jslib-common/abstractions/settings.service';
import { StateService } from 'jslib-common/abstractions/state.service';
import { SyncService } from 'jslib-common/abstractions/sync.service';
import { TokenService } from 'jslib-common/abstractions/token.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service';
import { ConstantsService } from 'jslib-common/services/constants.service';
2018-06-08 23:08:19 +02:00
2018-06-10 04:40:53 +02:00
import { RouterService } from './services/router.service';
2018-06-08 23:08:19 +02:00
const BroadcasterSubscriptionId = 'AppComponent';
2018-08-23 04:56:00 +02:00
const IdleTimeout = 60000 * 10; // 10 minutes
2018-06-08 23:08:19 +02:00
2018-06-05 05:10:41 +02:00
@Component({
selector: 'app-root',
2018-06-06 15:43:28 +02:00
templateUrl: 'app.component.html',
2018-06-05 05:10:41 +02:00
})
2018-06-08 23:08:19 +02:00
export class AppComponent implements OnDestroy, OnInit {
2018-06-05 21:46:26 +02:00
toasterConfig: ToasterConfig = new ToasterConfig({
showCloseButton: true,
mouseoverTimerStop: true,
animation: 'flyRight',
limit: 5,
});
2018-06-08 23:08:19 +02:00
private lastActivity: number = null;
2018-08-23 04:37:55 +02:00
private idleTimer: number = null;
private isIdle = false;
2018-06-08 23:08:19 +02:00
constructor(
2018-07-18 18:57:20 +02:00
private broadcasterService: BroadcasterService, private userService: UserService,
2018-06-08 23:08:19 +02:00
private tokenService: TokenService, private folderService: FolderService,
private settingsService: SettingsService, private syncService: SyncService,
private passwordGenerationService: PasswordGenerationService, private cipherService: CipherService,
private authService: AuthService, private router: Router,
2018-06-08 23:08:19 +02:00
private toasterService: ToasterService, private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService, private ngZone: NgZone,
private vaultTimeoutService: VaultTimeoutService, private storageService: StorageService,
2018-06-10 04:40:53 +02:00
private cryptoService: CryptoService, private collectionService: CollectionService,
private sanitizer: DomSanitizer, private searchService: SearchService,
2019-07-02 14:44:29 +02:00
private notificationsService: NotificationsService, private routerService: RouterService,
private stateService: StateService, private eventService: EventService,
private policyService: PolicyService) { }
2018-06-08 23:08:19 +02:00
ngOnInit() {
this.ngZone.runOutsideAngular(() => {
window.onmousemove = () => this.recordActivity();
window.onmousedown = () => this.recordActivity();
window.ontouchstart = () => this.recordActivity();
window.onclick = () => this.recordActivity();
window.onscroll = () => this.recordActivity();
window.onkeypress = () => this.recordActivity();
});
this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => {
this.ngZone.run(async () => {
switch (message.command) {
case 'loggedIn':
case 'loggedOut':
2018-08-21 04:21:13 +02:00
case 'unlocked':
2018-08-23 14:56:45 +02:00
this.notificationsService.updateConnection(false);
2018-06-08 23:08:19 +02:00
break;
2019-04-18 16:11:04 +02:00
case 'authBlocked':
this.router.navigate(['/']);
break;
2018-06-08 23:08:19 +02:00
case 'logout':
this.logOut(!!message.expired);
break;
case 'lockVault':
await this.vaultTimeoutService.lock();
2018-06-08 23:08:19 +02:00
break;
case 'locked':
2018-08-23 14:56:45 +02:00
this.notificationsService.updateConnection(false);
2018-06-09 20:55:34 +02:00
this.router.navigate(['lock']);
2018-06-08 23:08:19 +02:00
break;
2019-02-22 19:17:10 +01:00
case 'lockedUrl':
window.setTimeout(() => this.routerService.setPreviousUrl(message.url), 500);
break;
2018-06-08 23:08:19 +02:00
case 'syncStarted':
break;
case 'syncCompleted':
break;
2018-07-18 15:21:23 +02:00
case 'upgradeOrganization':
const upgradeConfirmed = await this.platformUtilsService.showDialog(
this.i18nService.t('upgradeOrganizationDesc'), this.i18nService.t('upgradeOrganization'),
this.i18nService.t('upgradeOrganization'), this.i18nService.t('cancel'));
if (upgradeConfirmed) {
this.router.navigate(['organizations', message.organizationId, 'settings', 'billing']);
}
break;
case 'premiumRequired':
const premiumConfirmed = await this.platformUtilsService.showDialog(
this.i18nService.t('premiumRequiredDesc'), this.i18nService.t('premiumRequired'),
this.i18nService.t('learnMore'), this.i18nService.t('cancel'));
if (premiumConfirmed) {
this.router.navigate(['settings/premium']);
}
break;
case 'emailVerificationRequired':
const emailVerificationConfirmed = await this.platformUtilsService.showDialog(
this.i18nService.t('emailVerificationRequiredDesc'),
this.i18nService.t('emailVerificationRequired'),
this.i18nService.t('learnMore'), this.i18nService.t('cancel'));
if (emailVerificationConfirmed) {
this.platformUtilsService.launchUri('https://bitwarden.com/help/article/create-bitwarden-account/');
}
break;
case 'showToast':
this.showToast(message);
break;
case 'setFullWidth':
this.setFullWidth();
break;
2018-06-08 23:08:19 +02:00
default:
2018-07-18 15:21:23 +02:00
break;
2018-06-08 23:08:19 +02:00
}
});
});
this.router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
const modals = Array.from(document.querySelectorAll('.modal'));
for (const modal of modals) {
(jq(modal) as any).modal('hide');
}
if (document.querySelector('.swal-modal') != null) {
Swal.close(undefined);
}
}
});
this.setFullWidth();
2018-06-08 23:08:19 +02:00
}
ngOnDestroy() {
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
}
private async logOut(expired: boolean) {
await this.eventService.uploadEvents();
2018-06-08 23:08:19 +02:00
const userId = await this.userService.getUserId();
await Promise.all([
this.eventService.clearEvents(),
2018-06-08 23:08:19 +02:00
this.syncService.setLastSync(new Date(0)),
this.tokenService.clearToken(),
this.cryptoService.clearKeys(),
this.userService.clear(),
this.settingsService.clear(userId),
this.cipherService.clear(userId),
this.folderService.clear(userId),
this.collectionService.clear(userId),
this.policyService.clear(userId),
2018-06-08 23:08:19 +02:00
this.passwordGenerationService.clear(),
2019-07-02 14:44:29 +02:00
this.stateService.purge(),
2018-06-08 23:08:19 +02:00
]);
2018-08-13 22:27:17 +02:00
this.searchService.clearIndex();
2018-06-08 23:08:19 +02:00
this.authService.logOut(async () => {
if (expired) {
this.toasterService.popAsync('warning', this.i18nService.t('loggedOut'),
this.i18nService.t('loginExpired'));
}
Swal.close();
2018-06-10 04:02:45 +02:00
this.router.navigate(['/']);
2018-06-08 23:08:19 +02:00
});
}
private async recordActivity() {
const now = (new Date()).getTime();
if (this.lastActivity != null && now - this.lastActivity < 250) {
return;
}
this.lastActivity = now;
this.storageService.save(ConstantsService.lastActiveKey, now);
2018-08-23 04:37:55 +02:00
// Idle states
if (this.isIdle) {
this.isIdle = false;
this.idleStateChanged();
}
if (this.idleTimer != null) {
window.clearTimeout(this.idleTimer);
this.idleTimer = null;
}
this.idleTimer = window.setTimeout(() => {
if (!this.isIdle) {
this.isIdle = true;
this.idleStateChanged();
}
}, IdleTimeout);
}
private showToast(msg: any) {
const toast: Toast = {
type: msg.type,
title: msg.title,
};
if (typeof (msg.text) === 'string') {
toast.body = msg.text;
} else if (msg.text.length === 1) {
toast.body = msg.text[0];
} else {
let message = '';
msg.text.forEach((t: string) =>
message += ('<p>' + this.sanitizer.sanitize(SecurityContext.HTML, t) + '</p>'));
toast.body = message;
toast.bodyOutputType = BodyOutputType.TrustedHtml;
}
if (msg.options != null) {
if (msg.options.trustedHtml === true) {
toast.bodyOutputType = BodyOutputType.TrustedHtml;
}
if (msg.options.timeout != null && msg.options.timeout > 0) {
toast.timeout = msg.options.timeout;
}
}
this.toasterService.popAsync(toast);
}
2018-08-23 04:37:55 +02:00
private idleStateChanged() {
if (this.isIdle) {
this.notificationsService.disconnectFromInactivity();
} else {
this.notificationsService.reconnectFromActivity();
}
2018-06-05 05:10:41 +02:00
}
private async setFullWidth() {
const enableFullWidth = await this.storageService.get<boolean>('enableFullWidth');
if (enableFullWidth) {
document.body.classList.add('full-width');
} else {
document.body.classList.remove('full-width');
}
}
2018-06-05 05:10:41 +02:00
}