From 203a7b0c01efa7f0e7008a9c9629e33d01c9a1b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rui=20Tom=C3=A9?= <108268980+r-tome@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:12:16 +0000 Subject: [PATCH] [PM-11405] Account Management: Prevent a verified user from changing their email address (#11486) * Update AccountService to include a method for setting the managedByOrganizationId * Update AccountComponent to conditionally show the purgeVault button based on a feature flag and if the user is managed by an organization * Add missing method to FakeAccountService * Remove the setAccountManagedByOrganizationId method from the AccountService abstract class. * Refactor AccountComponent to use OrganizationService to check for managing organization * Rename managesActiveUser to userIsManagedByOrganization * Hide the change email section if the user is managed by an organization * Refactor userIsManagedByOrganization property to be non-nullable in organization data and response models * Refactor organization.data.spec.ts to include non-nullable userIsManagedByOrganization property * Refactor account component initialization logic * Remove opening modal that was added by mistake --- .../settings/account/account.component.html | 2 +- .../settings/account/account.component.ts | 49 ++++++++++++------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/apps/web/src/app/auth/settings/account/account.component.html b/apps/web/src/app/auth/settings/account/account.component.html index 71508f7ae9..a5e5329fce 100644 --- a/apps/web/src/app/auth/settings/account/account.component.html +++ b/apps/web/src/app/auth/settings/account/account.component.html @@ -3,7 +3,7 @@ -
+

{{ "changeEmail" | i18n }}

diff --git a/apps/web/src/app/auth/settings/account/account.component.ts b/apps/web/src/app/auth/settings/account/account.component.ts index dd8dc881f6..51bf427696 100644 --- a/apps/web/src/app/auth/settings/account/account.component.ts +++ b/apps/web/src/app/auth/settings/account/account.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core"; -import { lastValueFrom, map, Observable, of, switchMap } from "rxjs"; +import { combineLatest, from, lastValueFrom, map, Observable } from "rxjs"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; @@ -21,7 +21,7 @@ export class AccountComponent implements OnInit { @ViewChild("deauthorizeSessionsTemplate", { read: ViewContainerRef, static: true }) deauthModalRef: ViewContainerRef; - showChangeEmail = true; + showChangeEmail$: Observable; showPurgeVault$: Observable; constructor( @@ -33,21 +33,36 @@ export class AccountComponent implements OnInit { ) {} async ngOnInit() { - this.showChangeEmail = await this.userVerificationService.hasMasterPassword(); - this.showPurgeVault$ = this.configService - .getFeatureFlag$(FeatureFlag.AccountDeprovisioning) - .pipe( - switchMap((isAccountDeprovisioningEnabled) => - isAccountDeprovisioningEnabled - ? this.organizationService.organizations$.pipe( - map( - (organizations) => - !organizations.some((o) => o.userIsManagedByOrganization === true), - ), - ) - : of(true), - ), - ); + const isAccountDeprovisioningEnabled$ = this.configService.getFeatureFlag$( + FeatureFlag.AccountDeprovisioning, + ); + + const userIsManagedByOrganization$ = this.organizationService.organizations$.pipe( + map((organizations) => organizations.some((o) => o.userIsManagedByOrganization === true)), + ); + + const hasMasterPassword$ = from(this.userVerificationService.hasMasterPassword()); + + this.showChangeEmail$ = combineLatest([ + hasMasterPassword$, + isAccountDeprovisioningEnabled$, + userIsManagedByOrganization$, + ]).pipe( + map( + ([hasMasterPassword, isAccountDeprovisioningEnabled, userIsManagedByOrganization]) => + hasMasterPassword && (!isAccountDeprovisioningEnabled || !userIsManagedByOrganization), + ), + ); + + this.showPurgeVault$ = combineLatest([ + isAccountDeprovisioningEnabled$, + userIsManagedByOrganization$, + ]).pipe( + map( + ([isAccountDeprovisioningEnabled, userIsManagedByOrganization]) => + !isAccountDeprovisioningEnabled || !userIsManagedByOrganization, + ), + ); } async deauthorizeSessions() {