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

316 lines
11 KiB
TypeScript
Raw Normal View History

2021-12-17 15:57:11 +01:00
import { Component, NgZone, OnDestroy, OnInit, SecurityContext } from "@angular/core";
import { DomSanitizer } from "@angular/platform-browser";
import { NavigationEnd, Router } from "@angular/router";
import * as jq from "jquery";
import { IndividualConfig, ToastrService } from "ngx-toastr";
import Swal from "sweetalert2";
2018-06-05 05:10:41 +02:00
2021-12-17 15:57:11 +01:00
import { AuthService } from "jslib-common/abstractions/auth.service";
import { BroadcasterService } from "jslib-common/abstractions/broadcaster.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 { KeyConnectorService } from "jslib-common/abstractions/keyConnector.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 { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service";
2021-12-17 15:57:11 +01:00
import { DisableSendPolicy } from "./organizations/policies/disable-send.component";
import { MasterPasswordPolicy } from "./organizations/policies/master-password.component";
import { PasswordGeneratorPolicy } from "./organizations/policies/password-generator.component";
import { PersonalOwnershipPolicy } from "./organizations/policies/personal-ownership.component";
import { RequireSsoPolicy } from "./organizations/policies/require-sso.component";
import { ResetPasswordPolicy } from "./organizations/policies/reset-password.component";
import { SendOptionsPolicy } from "./organizations/policies/send-options.component";
import { SingleOrgPolicy } from "./organizations/policies/single-org.component";
import { TwoFactorAuthenticationPolicy } from "./organizations/policies/two-factor-authentication.component";
2022-02-24 12:10:07 +01:00
import { PolicyListService } from "./services/policy-list.service";
import { RouterService } from "./services/router.service";
2021-12-17 15:57:11 +01: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({
2021-12-17 15:57:11 +01:00
selector: "app-root",
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 {
2021-12-17 15:57:11 +01:00
private lastActivity: number = null;
private idleTimer: number = null;
private isIdle = false;
2021-12-17 15:57:11 +01:00
constructor(
private broadcasterService: BroadcasterService,
private tokenService: TokenService,
private folderService: FolderService,
private settingsService: SettingsService,
private syncService: SyncService,
private passwordGenerationService: PasswordGenerationService,
private cipherService: CipherService,
private authService: AuthService,
private router: Router,
private toastrService: ToastrService,
private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService,
private ngZone: NgZone,
private vaultTimeoutService: VaultTimeoutService,
private cryptoService: CryptoService,
private collectionService: CollectionService,
private sanitizer: DomSanitizer,
private searchService: SearchService,
private notificationsService: NotificationsService,
private routerService: RouterService,
private stateService: StateService,
private eventService: EventService,
private policyService: PolicyService,
protected policyListService: PolicyListService,
private keyConnectorService: KeyConnectorService
) {}
2018-06-08 23:08:19 +02:00
2021-12-17 15:57:11 +01: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();
});
2018-06-08 23:08:19 +02:00
2021-12-17 15:57:11 +01:00
this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => {
this.ngZone.run(async () => {
switch (message.command) {
case "loggedIn":
this.notificationsService.updateConnection(false);
break;
2021-12-17 15:57:11 +01:00
case "loggedOut":
this.routerService.setPreviousUrl(null);
this.notificationsService.updateConnection(false);
break;
2021-12-17 15:57:11 +01:00
case "unlocked":
this.notificationsService.updateConnection(false);
break;
case "authBlocked":
this.routerService.setPreviousUrl(message.url);
2021-12-17 15:57:11 +01:00
this.router.navigate(["/"]);
break;
case "logout":
this.logOut(!!message.expired);
break;
case "lockVault":
await this.vaultTimeoutService.lock();
break;
case "locked":
this.notificationsService.updateConnection(false);
this.router.navigate(["lock"]);
break;
case "lockedUrl":
this.routerService.setPreviousUrl(message.url);
2021-12-17 15:57:11 +01:00
break;
case "syncStarted":
break;
case "syncCompleted":
break;
2022-02-24 12:10:07 +01:00
case "upgradeOrganization": {
2021-12-17 15:57:11 +01:00
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;
2022-02-24 12:10:07 +01:00
}
case "premiumRequired": {
2021-12-17 15:57:11 +01:00
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;
2022-02-24 12:10:07 +01:00
}
case "emailVerificationRequired": {
2021-12-17 15:57:11 +01:00
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(
2022-01-31 20:11:27 +01:00
"https://bitwarden.com/help/create-bitwarden-account/"
2021-12-17 15:57:11 +01:00
);
}
break;
2022-02-24 12:10:07 +01:00
}
2021-12-17 15:57:11 +01:00
case "showToast":
this.showToast(message);
break;
case "setFullWidth":
this.setFullWidth();
break;
case "convertAccountToKeyConnector":
this.router.navigate(["/remove-password"]);
break;
default:
break;
}
});
});
2018-06-08 23:08:19 +02:00
2021-12-17 15:57:11 +01: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");
}
2021-12-17 15:57:11 +01:00
if (document.querySelector(".swal-modal") != null) {
Swal.close(undefined);
}
}
});
2021-12-17 15:57:11 +01:00
this.policyListService.addPolicies([
new TwoFactorAuthenticationPolicy(),
new MasterPasswordPolicy(),
new PasswordGeneratorPolicy(),
new SingleOrgPolicy(),
new RequireSsoPolicy(),
new PersonalOwnershipPolicy(),
new DisableSendPolicy(),
new SendOptionsPolicy(),
new ResetPasswordPolicy(),
]);
2022-03-09 17:16:53 +01:00
this.setFullWidth();
2021-12-17 15:57:11 +01:00
}
2021-12-17 15:57:11 +01:00
ngOnDestroy() {
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
}
2018-06-08 23:08:19 +02:00
2021-12-17 15:57:11 +01:00
private async logOut(expired: boolean) {
await this.eventService.uploadEvents();
const userId = await this.stateService.getUserId();
await Promise.all([
this.eventService.clearEvents(),
this.syncService.setLastSync(new Date(0)),
this.cryptoService.clearKeys(),
this.settingsService.clear(userId),
this.cipherService.clear(userId),
this.folderService.clear(userId),
this.collectionService.clear(userId),
this.policyService.clear(userId),
this.passwordGenerationService.clear(),
this.keyConnectorService.clear(),
]);
2018-06-08 23:08:19 +02:00
2021-12-17 15:57:11 +01:00
this.searchService.clearIndex();
this.authService.logOut(async () => {
if (expired) {
this.platformUtilsService.showToast(
"warning",
this.i18nService.t("loggedOut"),
this.i18nService.t("loginExpired")
);
}
2018-06-08 23:08:19 +02:00
2021-12-17 15:57:11 +01:00
await this.stateService.clean({ userId: userId });
Swal.close();
this.router.navigate(["/"]);
});
}
2021-12-17 15:57:11 +01:00
private async recordActivity() {
const now = new Date().getTime();
if (this.lastActivity != null && now - this.lastActivity < 250) {
return;
2018-06-08 23:08:19 +02:00
}
2021-12-17 15:57:11 +01:00
this.lastActivity = now;
this.stateService.setLastActive(now);
// Idle states
if (this.isIdle) {
this.isIdle = false;
this.idleStateChanged();
2018-08-23 04:37:55 +02:00
}
2021-12-17 15:57:11 +01:00
if (this.idleTimer != null) {
window.clearTimeout(this.idleTimer);
this.idleTimer = null;
}
this.idleTimer = window.setTimeout(() => {
if (!this.isIdle) {
this.isIdle = true;
this.idleStateChanged();
}
}, IdleTimeout);
}
2018-08-23 04:37:55 +02:00
2021-12-17 15:57:11 +01:00
private showToast(msg: any) {
let message = "";
2021-12-07 20:41:45 +01:00
2021-12-17 15:57:11 +01:00
const options: Partial<IndividualConfig> = {};
2021-12-07 20:41:45 +01:00
2021-12-17 15:57:11 +01:00
if (typeof msg.text === "string") {
message = msg.text;
} else if (msg.text.length === 1) {
message = msg.text[0];
} else {
msg.text.forEach(
(t: string) =>
(message += "<p>" + this.sanitizer.sanitize(SecurityContext.HTML, t) + "</p>")
);
options.enableHtml = true;
}
if (msg.options != null) {
if (msg.options.trustedHtml === true) {
options.enableHtml = true;
}
if (msg.options.timeout != null && msg.options.timeout > 0) {
options.timeOut = msg.options.timeout;
}
}
2021-12-17 15:57:11 +01:00
this.toastrService.show(message, msg.title, options, "toast-" + msg.type);
}
private idleStateChanged() {
if (this.isIdle) {
this.notificationsService.disconnectFromInactivity();
} else {
this.notificationsService.reconnectFromActivity();
2018-06-05 05:10:41 +02:00
}
2021-12-17 15:57:11 +01:00
}
2021-12-17 15:57:11 +01:00
private async setFullWidth() {
const enableFullWidth = await this.stateService.getEnableFullWidth();
if (enableFullWidth) {
document.body.classList.add("full-width");
} else {
document.body.classList.remove("full-width");
}
2021-12-17 15:57:11 +01:00
}
2018-06-05 05:10:41 +02:00
}