1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 16:53:34 +00:00

Merge branch 'main' into vault/pm-5273

# Conflicts:
#	libs/common/src/platform/abstractions/state.service.ts
#	libs/common/src/platform/services/state.service.ts
#	libs/common/src/state-migrations/migrate.ts
This commit is contained in:
Carlos Gonçalves
2024-03-25 18:38:10 +00:00
364 changed files with 9254 additions and 2586 deletions

View File

@@ -149,6 +149,7 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit,
this.captchaToken,
null,
);
this.formPromise = this.loginStrategyService.logIn(credentials);
const response = await this.formPromise;
this.setFormValues();
@@ -302,6 +303,9 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit,
async saveEmailSettings() {
this.setFormValues();
await this.loginService.saveEmailSettings();
// Save off email for SSO
await this.ssoLoginService.setSsoEmail(this.formGroup.value.email);
}
// Legacy accounts used the master key to encrypt data. Migration is required

View File

@@ -182,11 +182,14 @@ export class SsoComponent {
private async logIn(code: string, codeVerifier: string, orgSsoIdentifier: string): Promise<void> {
this.loggingIn = true;
try {
const email = await this.ssoLoginService.getSsoEmail();
const credentials = new SsoLoginCredentials(
code,
codeVerifier,
this.redirectUri,
orgSsoIdentifier,
email,
);
this.formPromise = this.loginStrategyService.logIn(credentials);
const authResult = await this.formPromise;

View File

@@ -3,6 +3,7 @@ import { Router } from "@angular/router";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@@ -19,6 +20,7 @@ export class TwoFactorOptionsComponent implements OnInit {
protected i18nService: I18nService,
protected platformUtilsService: PlatformUtilsService,
protected win: Window,
protected environmentService: EnvironmentService,
) {}
ngOnInit() {
@@ -30,7 +32,8 @@ export class TwoFactorOptionsComponent implements OnInit {
}
recover() {
this.platformUtilsService.launchUri("https://vault.bitwarden.com/#/recover-2fa");
const webVault = this.environmentService.getWebVaultUrl();
this.platformUtilsService.launchUri(webVault + "/#/recover-2fa");
this.onRecoverSelected.emit();
}
}

View File

@@ -1,6 +1,7 @@
import { Directive, OnInit, TemplateRef, ViewContainerRef } from "@angular/core";
import { firstValueFrom } from "rxjs";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
/**
* Hides the element if the user has premium.
@@ -12,11 +13,13 @@ export class NotPremiumDirective implements OnInit {
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef,
private stateService: StateService,
private billingAccountProfileStateService: BillingAccountProfileStateService,
) {}
async ngOnInit(): Promise<void> {
const premium = await this.stateService.getCanAccessPremium();
const premium = await firstValueFrom(
this.billingAccountProfileStateService.hasPremiumFromAnySource$,
);
if (premium) {
this.viewContainer.clear();

View File

@@ -1,6 +1,7 @@
import { Directive, OnInit, TemplateRef, ViewContainerRef } from "@angular/core";
import { Directive, OnDestroy, OnInit, TemplateRef, ViewContainerRef } from "@angular/core";
import { Subject, takeUntil } from "rxjs";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
/**
* Only shows the element if the user has premium.
@@ -8,20 +9,29 @@ import { StateService } from "@bitwarden/common/platform/abstractions/state.serv
@Directive({
selector: "[appPremium]",
})
export class PremiumDirective implements OnInit {
export class PremiumDirective implements OnInit, OnDestroy {
private directiveIsDestroyed$ = new Subject<boolean>();
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef,
private stateService: StateService,
private billingAccountProfileStateService: BillingAccountProfileStateService,
) {}
async ngOnInit(): Promise<void> {
const premium = await this.stateService.getCanAccessPremium();
this.billingAccountProfileStateService.hasPremiumFromAnySource$
.pipe(takeUntil(this.directiveIsDestroyed$))
.subscribe((premium: boolean) => {
if (premium) {
this.viewContainer.clear();
} else {
this.viewContainer.createEmbeddedView(this.templateRef);
}
});
}
if (premium) {
this.viewContainer.createEmbeddedView(this.templateRef);
} else {
this.viewContainer.clear();
}
ngOnDestroy() {
this.directiveIsDestroyed$.next(true);
this.directiveIsDestroyed$.complete();
}
}

View File

@@ -42,6 +42,7 @@ export const LOGOUT_CALLBACK = new SafeInjectionToken<
export const LOCKED_CALLBACK = new SafeInjectionToken<(userId?: string) => Promise<void>>(
"LOCKED_CALLBACK",
);
export const SUPPORTS_SECURE_STORAGE = new SafeInjectionToken<boolean>("SUPPORTS_SECURE_STORAGE");
export const LOCALES_DIRECTORY = new SafeInjectionToken<string>("LOCALES_DIRECTORY");
export const SYSTEM_LANGUAGE = new SafeInjectionToken<string>("SYSTEM_LANGUAGE");
export const LOG_MAC_FAILURES = new SafeInjectionToken<boolean>("LOG_MAC_FAILURES");

View File

@@ -9,14 +9,12 @@ import {
LoginStrategyServiceAbstraction,
LoginStrategyService,
} from "@bitwarden/auth/common";
import { AvatarUpdateService as AccountUpdateServiceAbstraction } from "@bitwarden/common/abstractions/account/avatar-update.service";
import { ApiService as ApiServiceAbstraction } from "@bitwarden/common/abstractions/api.service";
import { AuditService as AuditServiceAbstraction } from "@bitwarden/common/abstractions/audit.service";
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service";
import { NotificationsService as NotificationsServiceAbstraction } from "@bitwarden/common/abstractions/notifications.service";
import { SearchService as SearchServiceAbstraction } from "@bitwarden/common/abstractions/search.service";
import { SettingsService as SettingsServiceAbstraction } from "@bitwarden/common/abstractions/settings.service";
import { VaultTimeoutSettingsService as VaultTimeoutSettingsServiceAbstraction } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
@@ -29,6 +27,7 @@ import {
OrgDomainInternalServiceAbstraction,
OrgDomainServiceAbstraction,
} from "@bitwarden/common/admin-console/abstractions/organization-domain/org-domain.service.abstraction";
import { OrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/abstractions/organization-management-preferences/organization-management-preferences.service";
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
import {
@@ -40,6 +39,7 @@ import { OrganizationApiService } from "@bitwarden/common/admin-console/services
import { OrganizationService } from "@bitwarden/common/admin-console/services/organization/organization.service";
import { OrgDomainApiService } from "@bitwarden/common/admin-console/services/organization-domain/org-domain-api.service";
import { OrgDomainService } from "@bitwarden/common/admin-console/services/organization-domain/org-domain.service";
import { DefaultOrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/services/organization-management-preferences/default-organization-management-preferences.service";
import { OrganizationUserServiceImplementation } from "@bitwarden/common/admin-console/services/organization-user/organization-user.service.implementation";
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
@@ -51,6 +51,7 @@ import {
} from "@bitwarden/common/auth/abstractions/account.service";
import { AnonymousHubService as AnonymousHubServiceAbstraction } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth.service";
import { AvatarService as AvatarServiceAbstraction } from "@bitwarden/common/auth/abstractions/avatar.service";
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
@@ -69,6 +70,7 @@ import { AccountApiServiceImplementation } from "@bitwarden/common/auth/services
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
import { AnonymousHubService } from "@bitwarden/common/auth/services/anonymous-hub.service";
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
import { AvatarService } from "@bitwarden/common/auth/services/avatar.service";
import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device-trust-crypto.service.implementation";
import { DevicesServiceImplementation } from "@bitwarden/common/auth/services/devices/devices.service.implementation";
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
@@ -95,9 +97,11 @@ import {
DomainSettingsService,
DefaultDomainSettingsService,
} from "@bitwarden/common/autofill/services/domain-settings.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billilng-api.service.abstraction";
import { OrganizationBillingServiceAbstraction } from "@bitwarden/common/billing/abstractions/organization-billing.service";
import { PaymentMethodWarningsServiceAbstraction } from "@bitwarden/common/billing/abstractions/payment-method-warnings-service.abstraction";
import { DefaultBillingAccountProfileStateService } from "@bitwarden/common/billing/services/account/billing-account-profile-state.service";
import { BillingApiService } from "@bitwarden/common/billing/services/billing-api.service";
import { OrganizationBillingService } from "@bitwarden/common/billing/services/organization-billing.service";
import { PaymentMethodWarningsService } from "@bitwarden/common/billing/services/payment-method-warnings.service";
@@ -163,14 +167,12 @@ import {
DefaultThemeStateService,
ThemeStateService,
} from "@bitwarden/common/platform/theming/theme-state.service";
import { AvatarUpdateService } from "@bitwarden/common/services/account/avatar-update.service";
import { ApiService } from "@bitwarden/common/services/api.service";
import { AuditService } from "@bitwarden/common/services/audit.service";
import { EventCollectionService } from "@bitwarden/common/services/event/event-collection.service";
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
import { NotificationsService } from "@bitwarden/common/services/notifications.service";
import { SearchService } from "@bitwarden/common/services/search.service";
import { SettingsService } from "@bitwarden/common/services/settings.service";
import { VaultTimeoutSettingsService } from "@bitwarden/common/services/vault-timeout/vault-timeout-settings.service";
import { VaultTimeoutService } from "@bitwarden/common/services/vault-timeout/vault-timeout.service";
import {
@@ -250,6 +252,7 @@ import {
SECURE_STORAGE,
STATE_FACTORY,
STATE_SERVICE_USE_CACHE,
SUPPORTS_SECURE_STORAGE,
SYSTEM_LANGUAGE,
SYSTEM_THEME_OBSERVABLE,
WINDOW,
@@ -272,6 +275,12 @@ const typesafeProviders: Array<SafeProvider> = [
useFactory: (i18nService: I18nServiceAbstraction) => i18nService.translationLocale,
deps: [I18nServiceAbstraction],
}),
safeProvider({
provide: SUPPORTS_SECURE_STORAGE,
useFactory: (platformUtilsService: PlatformUtilsServiceAbstraction) =>
platformUtilsService.supportsSecureStorage(),
deps: [PlatformUtilsServiceAbstraction],
}),
safeProvider({
provide: LOCALES_DIRECTORY,
useValue: "./locales",
@@ -361,6 +370,7 @@ const typesafeProviders: Array<SafeProvider> = [
DeviceTrustCryptoServiceAbstraction,
AuthRequestServiceAbstraction,
GlobalStateProvider,
BillingAccountProfileStateService,
],
}),
safeProvider({
@@ -454,9 +464,9 @@ const typesafeProviders: Array<SafeProvider> = [
useExisting: InternalAccountService,
}),
safeProvider({
provide: AccountUpdateServiceAbstraction,
useClass: AvatarUpdateService,
deps: [ApiServiceAbstraction, StateServiceAbstraction],
provide: AvatarServiceAbstraction,
useClass: AvatarService,
deps: [ApiServiceAbstraction, StateProvider],
}),
safeProvider({ provide: LogService, useFactory: () => new ConsoleLogService(false), deps: [] }),
safeProvider({
@@ -477,7 +487,12 @@ const typesafeProviders: Array<SafeProvider> = [
safeProvider({
provide: TokenServiceAbstraction,
useClass: TokenService,
deps: [StateServiceAbstraction],
deps: [
SingleUserStateProvider,
GlobalStateProvider,
SUPPORTS_SECURE_STORAGE,
AbstractStorageService,
],
}),
safeProvider({
provide: KeyGenerationServiceAbstraction,
@@ -521,6 +536,7 @@ const typesafeProviders: Array<SafeProvider> = [
PlatformUtilsServiceAbstraction,
EnvironmentServiceAbstraction,
AppIdServiceAbstraction,
StateServiceAbstraction,
LOGOUT_CALLBACK,
],
}),
@@ -563,15 +579,12 @@ const typesafeProviders: Array<SafeProvider> = [
FolderApiServiceAbstraction,
InternalOrganizationServiceAbstraction,
SendApiServiceAbstraction,
AvatarServiceAbstraction,
LOGOUT_CALLBACK,
BillingAccountProfileStateService,
],
}),
safeProvider({ provide: BroadcasterServiceAbstraction, useClass: BroadcasterService, deps: [] }),
safeProvider({
provide: SettingsServiceAbstraction,
useClass: SettingsService,
deps: [StateServiceAbstraction],
}),
safeProvider({
provide: VaultTimeoutSettingsServiceAbstraction,
useClass: VaultTimeoutSettingsService,
@@ -622,6 +635,7 @@ const typesafeProviders: Array<SafeProvider> = [
STATE_FACTORY,
AccountServiceAbstraction,
EnvironmentServiceAbstraction,
TokenServiceAbstraction,
MigrationRunner,
STATE_SERVICE_USE_CACHE,
],
@@ -704,16 +718,17 @@ const typesafeProviders: Array<SafeProvider> = [
safeProvider({
provide: EventUploadServiceAbstraction,
useClass: EventUploadService,
deps: [ApiServiceAbstraction, StateServiceAbstraction, LogService],
deps: [ApiServiceAbstraction, StateProvider, LogService, AccountServiceAbstraction],
}),
safeProvider({
provide: EventCollectionServiceAbstraction,
useClass: EventCollectionService,
deps: [
CipherServiceAbstraction,
StateServiceAbstraction,
StateProvider,
OrganizationServiceAbstraction,
EventUploadServiceAbstraction,
AccountServiceAbstraction,
],
}),
safeProvider({
@@ -761,7 +776,7 @@ const typesafeProviders: Array<SafeProvider> = [
safeProvider({
provide: InternalOrganizationServiceAbstraction,
useClass: OrganizationService,
deps: [StateServiceAbstraction, StateProvider],
deps: [StateProvider],
}),
safeProvider({
provide: OrganizationServiceAbstraction,
@@ -955,7 +970,7 @@ const typesafeProviders: Array<SafeProvider> = [
safeProvider({
provide: ActiveUserStateProvider,
useClass: DefaultActiveUserStateProvider,
deps: [AccountServiceAbstraction, StorageServiceProvider, StateEventRegistrarService],
deps: [AccountServiceAbstraction, SingleUserStateProvider],
}),
safeProvider({
provide: SingleUserStateProvider,
@@ -1032,6 +1047,16 @@ const typesafeProviders: Array<SafeProvider> = [
useClass: PaymentMethodWarningsService,
deps: [BillingApiServiceAbstraction, StateProvider],
}),
safeProvider({
provide: BillingAccountProfileStateService,
useClass: DefaultBillingAccountProfileStateService,
deps: [ActiveUserStateProvider],
}),
safeProvider({
provide: OrganizationManagementPreferencesService,
useClass: DefaultOrganizationManagementPreferencesService,
deps: [StateProvider],
}),
];
function encryptServiceFactory(

View File

@@ -34,7 +34,7 @@ export class ExportScopeCalloutComponent implements OnInit {
) {}
async ngOnInit(): Promise<void> {
if (!this.organizationService.hasOrganizations()) {
if (!(await this.organizationService.hasOrganizations())) {
return;
}
@@ -48,7 +48,7 @@ export class ExportScopeCalloutComponent implements OnInit {
? {
title: "exportingOrganizationVaultTitle",
description: "exportingOrganizationVaultDesc",
scopeIdentifier: this.organizationService.get(organizationId).name,
scopeIdentifier: (await this.organizationService.get(organizationId)).name,
}
: {
title: "exportingPersonalVaultTitle",

View File

@@ -25,8 +25,10 @@ export class ExportComponent implements OnInit, OnDestroy {
@Output() onSaved = new EventEmitter();
@ViewChild(PasswordStrengthComponent) passwordStrengthComponent: PasswordStrengthComponent;
encryptedExportType = EncryptedExportType;
protected showFilePassword: boolean;
filePasswordValue: string = null;
formPromise: Promise<string>;
private _disabledByPolicy = false;
protected organizationId: string = null;
@@ -126,10 +128,23 @@ export class ExportComponent implements OnInit, OnDestroy {
return this.format === "encrypted_json";
}
get isFileEncryptedExport() {
return (
this.format === "encrypted_json" &&
this.fileEncryptionType === EncryptedExportType.FileEncrypted
);
}
get isAccountEncryptedExport() {
return (
this.format === "encrypted_json" &&
this.fileEncryptionType === EncryptedExportType.AccountEncrypted
);
}
protected async doExport() {
try {
this.formPromise = this.getExportData();
const data = await this.formPromise;
const data = await this.getExportData();
this.downloadFile(data);
this.saved();
await this.collectEvent();

View File

@@ -5,6 +5,7 @@ import { BehaviorSubject, Subject, concatMap, firstValueFrom, map, takeUntil } f
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { PolicyType } from "@bitwarden/common/admin-console/enums";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@@ -116,6 +117,7 @@ export class AddEditComponent implements OnInit, OnDestroy {
protected sendApiService: SendApiService,
protected dialogService: DialogService,
protected formBuilder: FormBuilder,
protected billingAccountProfileStateService: BillingAccountProfileStateService,
) {
this.typeOptions = [
{ name: i18nService.t("sendTypeFile"), value: SendType.File, premium: true },
@@ -188,6 +190,12 @@ export class AddEditComponent implements OnInit, OnDestroy {
}
});
this.billingAccountProfileStateService.hasPremiumFromAnySource$
.pipe(takeUntil(this.destroy$))
.subscribe((hasPremiumFromAnySource) => {
this.canAccessPremium = hasPremiumFromAnySource;
});
await this.load();
}
@@ -205,7 +213,6 @@ export class AddEditComponent implements OnInit, OnDestroy {
}
async load() {
this.canAccessPremium = await this.stateService.getCanAccessPremium();
this.emailVerified = await this.stateService.getEmailVerified();
this.type = !this.canAccessPremium || !this.emailVerified ? SendType.Text : SendType.File;

View File

@@ -1,6 +1,8 @@
import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core";
import { firstValueFrom } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
@@ -42,6 +44,7 @@ export class AttachmentsComponent implements OnInit {
protected stateService: StateService,
protected fileDownloadService: FileDownloadService,
protected dialogService: DialogService,
protected billingAccountProfileStateService: BillingAccountProfileStateService,
) {}
async ngOnInit() {
@@ -185,7 +188,9 @@ export class AttachmentsComponent implements OnInit {
await this.cipherService.getKeyForCipherKeyDecryption(this.cipherDomain),
);
const canAccessPremium = await this.stateService.getCanAccessPremium();
const canAccessPremium = await firstValueFrom(
this.billingAccountProfileStateService.hasPremiumFromAnySource$,
);
this.canAccessAttachments = canAccessPremium || this.cipher.organizationId != null;
if (!this.canAccessAttachments) {

View File

@@ -8,7 +8,7 @@ import {
Observable,
} from "rxjs";
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { buildCipherIcon } from "@bitwarden/common/vault/icon/build-cipher-icon";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
@@ -35,15 +35,15 @@ export class IconComponent implements OnInit {
constructor(
private environmentService: EnvironmentService,
private settingsService: SettingsService,
private domainSettingsService: DomainSettingsService,
) {}
async ngOnInit() {
const iconsUrl = this.environmentService.getIconsUrl();
this.data$ = combineLatest([
this.settingsService.disableFavicon$.pipe(distinctUntilChanged()),
this.domainSettingsService.showFavicons$.pipe(distinctUntilChanged()),
this.cipher$.pipe(filter((c) => c !== undefined)),
]).pipe(map(([disableFavicon, cipher]) => buildCipherIcon(iconsUrl, cipher, disableFavicon)));
]).pipe(map(([showFavicon, cipher]) => buildCipherIcon(iconsUrl, cipher, showFavicon)));
}
}

View File

@@ -1,6 +1,8 @@
import { Directive, OnInit } from "@angular/core";
import { Directive } from "@angular/core";
import { Observable, Subject } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@@ -9,11 +11,12 @@ import { StateService } from "@bitwarden/common/platform/abstractions/state.serv
import { DialogService } from "@bitwarden/components";
@Directive()
export class PremiumComponent implements OnInit {
isPremium = false;
export class PremiumComponent {
isPremium$: Observable<boolean>;
price = 10;
refreshPromise: Promise<any>;
cloudWebVaultUrl: string;
private directiveIsDestroyed$ = new Subject<boolean>();
constructor(
protected i18nService: I18nService,
@@ -22,13 +25,11 @@ export class PremiumComponent implements OnInit {
private logService: LogService,
protected stateService: StateService,
protected dialogService: DialogService,
private environmentService: EnvironmentService,
environmentService: EnvironmentService,
billingAccountProfileStateService: BillingAccountProfileStateService,
) {
this.cloudWebVaultUrl = this.environmentService.getCloudWebVaultUrl();
}
async ngOnInit() {
this.isPremium = await this.stateService.getCanAccessPremium();
this.cloudWebVaultUrl = environmentService.getCloudWebVaultUrl();
this.isPremium$ = billingAccountProfileStateService.hasPremiumFromAnySource$;
}
async refresh() {
@@ -36,7 +37,6 @@ export class PremiumComponent implements OnInit {
this.refreshPromise = this.apiService.refreshIdentityToken();
await this.refreshPromise;
this.platformUtilsService.showToast("success", null, this.i18nService.t("refreshComplete"));
this.isPremium = await this.stateService.getCanAccessPremium();
} catch (e) {
this.logService.error(e);
}

View File

@@ -9,12 +9,13 @@ import {
OnInit,
Output,
} from "@angular/core";
import { firstValueFrom } from "rxjs";
import { firstValueFrom, Subject, takeUntil } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { EventType } from "@bitwarden/common/enums";
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
@@ -68,6 +69,7 @@ export class ViewComponent implements OnDestroy, OnInit {
private totpInterval: any;
private previousCipherId: string;
private passwordReprompted = false;
private directiveIsDestroyed$ = new Subject<boolean>();
get fido2CredentialCreationDateValue(): string {
const dateCreated = this.i18nService.t("dateCreated");
@@ -99,6 +101,7 @@ export class ViewComponent implements OnDestroy, OnInit {
protected fileDownloadService: FileDownloadService,
protected dialogService: DialogService,
protected datePipe: DatePipe,
private billingAccountProfileStateService: BillingAccountProfileStateService,
) {}
ngOnInit() {
@@ -116,11 +119,19 @@ export class ViewComponent implements OnDestroy, OnInit {
}
});
});
this.billingAccountProfileStateService.hasPremiumFromAnySource$
.pipe(takeUntil(this.directiveIsDestroyed$))
.subscribe((canAccessPremium: boolean) => {
this.canAccessPremium = canAccessPremium;
});
}
ngOnDestroy() {
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
this.cleanUp();
this.directiveIsDestroyed$.next(true);
this.directiveIsDestroyed$.complete();
}
async load() {
@@ -130,7 +141,6 @@ export class ViewComponent implements OnDestroy, OnInit {
this.cipher = await cipher.decrypt(
await this.cipherService.getKeyForCipherKeyDecryption(cipher),
);
this.canAccessPremium = await this.stateService.getCanAccessPremium();
this.showPremiumRequiredTotp =
this.cipher.login.totp && !this.canAccessPremium && !this.cipher.organizationUseTotp;