mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-02 18:17:46 +01:00
[PM-11404] Account Management: Prevent a verified user from purging their vault (#11411)
* 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 * Refactor userIsManagedByOrganization property to be non-nullable in organization data and response models * Refactor organization.data.spec.ts to include non-nullable userIsManagedByOrganization property
This commit is contained in:
parent
a5f856da2a
commit
97e195cd7b
@ -12,7 +12,13 @@
|
||||
<button type="button" bitButton buttonType="danger" (click)="deauthorizeSessions()">
|
||||
{{ "deauthorizeSessions" | i18n }}
|
||||
</button>
|
||||
<button type="button" bitButton buttonType="danger" [bitAction]="purgeVault">
|
||||
<button
|
||||
*ngIf="showPurgeVault$ | async"
|
||||
type="button"
|
||||
bitButton
|
||||
buttonType="danger"
|
||||
[bitAction]="purgeVault"
|
||||
>
|
||||
{{ "purgeVault" | i18n }}
|
||||
</button>
|
||||
<button type="button" bitButton buttonType="danger" [bitAction]="deleteAccount">
|
||||
|
@ -1,8 +1,11 @@
|
||||
import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
import { lastValueFrom } from "rxjs";
|
||||
import { lastValueFrom, map, Observable, of, switchMap } from "rxjs";
|
||||
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { PurgeVaultComponent } from "../../../vault/settings/purge-vault.component";
|
||||
@ -19,15 +22,32 @@ export class AccountComponent implements OnInit {
|
||||
deauthModalRef: ViewContainerRef;
|
||||
|
||||
showChangeEmail = true;
|
||||
showPurgeVault$: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
private modalService: ModalService,
|
||||
private dialogService: DialogService,
|
||||
private userVerificationService: UserVerificationService,
|
||||
private configService: ConfigService,
|
||||
private organizationService: OrganizationService,
|
||||
) {}
|
||||
|
||||
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),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
async deauthorizeSessions() {
|
||||
|
@ -57,6 +57,7 @@ describe("ORGANIZATIONS state", () => {
|
||||
limitCollectionCreationDeletion: false,
|
||||
allowAdminAccessToAllCollectionItems: false,
|
||||
familySponsorshipLastSyncDate: new Date(),
|
||||
userIsManagedByOrganization: false,
|
||||
},
|
||||
};
|
||||
const result = sut.deserializer(JSON.parse(JSON.stringify(expectedResult)));
|
||||
|
@ -57,6 +57,7 @@ export class OrganizationData {
|
||||
// Deprecated: https://bitwarden.atlassian.net/browse/PM-10863
|
||||
limitCollectionCreationDeletion: boolean;
|
||||
allowAdminAccessToAllCollectionItems: boolean;
|
||||
userIsManagedByOrganization: boolean;
|
||||
|
||||
constructor(
|
||||
response?: ProfileOrganizationResponse,
|
||||
@ -118,6 +119,7 @@ export class OrganizationData {
|
||||
// Deprecated: https://bitwarden.atlassian.net/browse/PM-10863
|
||||
this.limitCollectionCreationDeletion = response.limitCollectionCreationDeletion;
|
||||
this.allowAdminAccessToAllCollectionItems = response.allowAdminAccessToAllCollectionItems;
|
||||
this.userIsManagedByOrganization = response.userIsManagedByOrganization;
|
||||
|
||||
this.isMember = options.isMember;
|
||||
this.isProviderUser = options.isProviderUser;
|
||||
|
@ -77,6 +77,12 @@ export class Organization {
|
||||
* Refers to the ability for an owner/admin to access all collection items, regardless of assigned collections
|
||||
*/
|
||||
allowAdminAccessToAllCollectionItems: boolean;
|
||||
/**
|
||||
* Indicates if this organization manages the user.
|
||||
* A user is considered managed by an organization if their email domain
|
||||
* matches one of the verified domains of that organization, and the user is a member of it.
|
||||
*/
|
||||
userIsManagedByOrganization: boolean;
|
||||
|
||||
constructor(obj?: OrganizationData) {
|
||||
if (obj == null) {
|
||||
@ -134,6 +140,7 @@ export class Organization {
|
||||
// Deprecated: https://bitwarden.atlassian.net/browse/PM-10863
|
||||
this.limitCollectionCreationDeletion = obj.limitCollectionCreationDeletion;
|
||||
this.allowAdminAccessToAllCollectionItems = obj.allowAdminAccessToAllCollectionItems;
|
||||
this.userIsManagedByOrganization = obj.userIsManagedByOrganization;
|
||||
}
|
||||
|
||||
get canAccess() {
|
||||
|
@ -54,6 +54,7 @@ export class ProfileOrganizationResponse extends BaseResponse {
|
||||
// Deprecated: https://bitwarden.atlassian.net/browse/PM-10863
|
||||
limitCollectionCreationDeletion: boolean;
|
||||
allowAdminAccessToAllCollectionItems: boolean;
|
||||
userIsManagedByOrganization: boolean;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
@ -121,5 +122,6 @@ export class ProfileOrganizationResponse extends BaseResponse {
|
||||
this.allowAdminAccessToAllCollectionItems = this.getResponseProperty(
|
||||
"AllowAdminAccessToAllCollectionItems",
|
||||
);
|
||||
this.userIsManagedByOrganization = this.getResponseProperty("UserIsManagedByOrganization");
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ export class ProfileResponse extends BaseResponse {
|
||||
securityStamp: string;
|
||||
forcePasswordReset: boolean;
|
||||
usesKeyConnector: boolean;
|
||||
managedByOrganizationId?: string | null;
|
||||
organizations: ProfileOrganizationResponse[] = [];
|
||||
providers: ProfileProviderResponse[] = [];
|
||||
providerOrganizations: ProfileProviderOrganizationResponse[] = [];
|
||||
@ -43,7 +42,6 @@ export class ProfileResponse extends BaseResponse {
|
||||
this.securityStamp = this.getResponseProperty("SecurityStamp");
|
||||
this.forcePasswordReset = this.getResponseProperty("ForcePasswordReset") ?? false;
|
||||
this.usesKeyConnector = this.getResponseProperty("UsesKeyConnector") ?? false;
|
||||
this.managedByOrganizationId = this.getResponseProperty("ManagedByOrganizationId");
|
||||
|
||||
const organizations = this.getResponseProperty("Organizations");
|
||||
if (organizations != null) {
|
||||
|
Loading…
Reference in New Issue
Block a user