1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 15:53:27 +00:00

[PM-10294] Remove FC v1 from Clients (#10422)

* chore: remove fc v1 from org.canEditAnyCollection and update callers, refs PM-10294

* chore: remove fc v1 from collectionView.canEdit and update callers, refs PM-10294

* chore: remove fc v1 from organization.canEditAllCiphers and update callers, refs PM-10294

* chore: remove fc v1 from canDeleteAnyCollection, collection views, update callers, refs PM-10294

* chore: remove fc v1 from canEditUser/GroupAccess, refs PM-10294

* chore: remove fc v1 from canViewCollectionInfo, refs PM-10294

* chore: remove fc v1 from account component, refs PM-10294

* fix: remove fc v1 from collections component, refs PM-10294

* fix: update vault-items component, refs PM-10294

* fix: remove fc v1 from collection-dialog and collections components, refs PM-10294

* chore: remove ConfigService from group-add-edit and account components, refs PM-10294

* chore: change canEditAnyCollection to getter and update callers, refs PM-10294

* chore: change canEditUnmanagedCollections to getter and update callers, refs PM-10294

* chore: change canDeleteAnyCollection to getter and update callers, refs PM-10294

* chore: remove deprecated observable and update comments with v1, refs PM-10294

* chore: remove ununsed ConfigService from collection-dialog component, refs PM-10294

* chore: remove final fc v1 ref for vault-collection-row, refs PM-10294
This commit is contained in:
Vincent Salucci
2024-08-13 10:45:41 -05:00
committed by GitHub
parent 43da67ee51
commit 471dd3bd7b
27 changed files with 254 additions and 717 deletions

View File

@@ -24,7 +24,6 @@ export class CollectionsComponent implements OnInit {
collectionIds: string[];
collections: CollectionView[] = [];
organization: Organization;
flexibleCollectionsV1Enabled: boolean;
restrictProviderAccess: boolean;
protected cipherDomain: Cipher;
@@ -40,9 +39,6 @@ export class CollectionsComponent implements OnInit {
) {}
async ngOnInit() {
this.flexibleCollectionsV1Enabled = await this.configService.getFeatureFlag(
FeatureFlag.FlexibleCollectionsV1,
);
this.restrictProviderAccess = await this.configService.getFeatureFlag(
FeatureFlag.RestrictProviderAccess,
);
@@ -72,12 +68,7 @@ export class CollectionsComponent implements OnInit {
async submit(): Promise<boolean> {
const selectedCollectionIds = this.collections
.filter((c) => {
if (
this.organization.canEditAllCiphers(
this.flexibleCollectionsV1Enabled,
this.restrictProviderAccess,
)
) {
if (this.organization.canEditAllCiphers(this.restrictProviderAccess)) {
return !!(c as any).checked;
} else {
return !!(c as any).checked && c.readOnly == null;

View File

@@ -90,7 +90,6 @@ export class AddEditComponent implements OnInit, OnDestroy {
private personalOwnershipPolicyAppliesToActiveUser: boolean;
private previousCipherId: string;
protected flexibleCollectionsV1Enabled = false;
protected restrictProviderAccess = false;
get fido2CredentialCreationDateValue(): string {
@@ -181,9 +180,6 @@ export class AddEditComponent implements OnInit, OnDestroy {
}
async ngOnInit() {
this.flexibleCollectionsV1Enabled = await this.configService.getFeatureFlag(
FeatureFlag.FlexibleCollectionsV1,
);
this.restrictProviderAccess = await this.configService.getFeatureFlag(
FeatureFlag.RestrictProviderAccess,
);
@@ -674,10 +670,7 @@ export class AddEditComponent implements OnInit, OnDestroy {
protected saveCipher(cipher: Cipher) {
const isNotClone = this.editMode && !this.cloneMode;
let orgAdmin = this.organization?.canEditAllCiphers(
this.flexibleCollectionsV1Enabled,
this.restrictProviderAccess,
);
let orgAdmin = this.organization?.canEditAllCiphers(this.restrictProviderAccess);
// if a cipher is unassigned we want to check if they are an admin or have permission to edit any collection
if (!cipher.collectionIds) {
@@ -690,20 +683,14 @@ export class AddEditComponent implements OnInit, OnDestroy {
}
protected deleteCipher() {
const asAdmin = this.organization?.canEditAllCiphers(
this.flexibleCollectionsV1Enabled,
this.restrictProviderAccess,
);
const asAdmin = this.organization?.canEditAllCiphers(this.restrictProviderAccess);
return this.cipher.isDeleted
? this.cipherService.deleteWithServer(this.cipher.id, asAdmin)
: this.cipherService.softDeleteWithServer(this.cipher.id, asAdmin);
}
protected restoreCipher() {
const asAdmin = this.organization?.canEditAllCiphers(
this.flexibleCollectionsV1Enabled,
this.restrictProviderAccess,
);
const asAdmin = this.organization?.canEditAllCiphers(this.restrictProviderAccess);
return this.cipherService.restoreWithServer(this.cipher.id, asAdmin);
}

View File

@@ -168,13 +168,8 @@ export class Organization {
);
}
canEditAnyCollection(flexibleCollectionsV1Enabled: boolean) {
if (!flexibleCollectionsV1Enabled) {
// Pre-Flexible Collections v1 logic
return this.isAdmin || this.permissions.editAnyCollection;
}
// Post Flexible Collections V1, the allowAdminAccessToAllCollectionItems flag can restrict admins
get canEditAnyCollection() {
// The allowAdminAccessToAllCollectionItems flag can restrict admins
// Providers and custom users with canEditAnyCollection are not affected by allowAdminAccessToAllCollectionItems flag
return (
this.isProviderUser ||
@@ -183,7 +178,7 @@ export class Organization {
);
}
canEditUnmanagedCollections() {
get canEditUnmanagedCollections() {
// Any admin or custom user with editAnyCollection permission can edit unmanaged collections
return this.isAdmin || this.permissions.editAnyCollection;
}
@@ -203,15 +198,7 @@ export class Organization {
);
}
canEditAllCiphers(
flexibleCollectionsV1Enabled: boolean,
restrictProviderAccessFlagEnabled: boolean,
) {
// Before Flexible Collections V1, any admin or anyone with editAnyCollection permission could edit all ciphers
if (!flexibleCollectionsV1Enabled) {
return this.isAdmin || this.permissions.editAnyCollection;
}
canEditAllCiphers(restrictProviderAccessFlagEnabled: boolean) {
// Providers can access items until the restrictProviderAccess flag is enabled
// After the flag is enabled and removed, this block will be deleted
// so that they permanently lose access to items
@@ -219,7 +206,7 @@ export class Organization {
return true;
}
// Post Flexible Collections V1, the allowAdminAccessToAllCollectionItems flag can restrict admins
// The allowAdminAccessToAllCollectionItems flag can restrict admins
// Custom users with canEditAnyCollection are not affected by allowAdminAccessToAllCollectionItems flag
return (
(this.type === OrganizationUserType.Custom && this.permissions.editAnyCollection) ||
@@ -229,10 +216,9 @@ export class Organization {
}
/**
* @param flexibleCollectionsV1Enabled - Whether or not the V1 Flexible Collection feature flag is enabled
* @returns True if the user can delete any collection
*/
canDeleteAnyCollection(flexibleCollectionsV1Enabled: boolean) {
get canDeleteAnyCollection() {
// Providers and Users with DeleteAnyCollection permission can always delete collections
if (this.isProviderUser || this.permissions.deleteAnyCollection) {
return true;
@@ -240,7 +226,7 @@ export class Organization {
// If AllowAdminAccessToAllCollectionItems is true, Owners and Admins can delete any collection, regardless of LimitCollectionCreationDeletion setting
// Using explicit type checks because provider users are handled above and this mimics the server's permission checks closely
if (!flexibleCollectionsV1Enabled || this.allowAdminAccessToAllCollectionItems) {
if (this.allowAdminAccessToAllCollectionItems) {
return this.type == OrganizationUserType.Owner || this.type == OrganizationUserType.Admin;
}

View File

@@ -38,11 +38,7 @@ export class CollectionView implements View, ITreeNodeObject {
}
}
canEditItems(
org: Organization,
v1FlexibleCollections: boolean,
restrictProviderAccess: boolean,
): boolean {
canEditItems(org: Organization, restrictProviderAccess: boolean): boolean {
if (org != null && org.id !== this.organizationId) {
throw new Error(
"Id of the organization provided does not match the org id of the collection.",
@@ -50,7 +46,7 @@ export class CollectionView implements View, ITreeNodeObject {
}
return (
org?.canEditAllCiphers(v1FlexibleCollections, restrictProviderAccess) ||
org?.canEditAllCiphers(restrictProviderAccess) ||
this.manage ||
(this.assigned && !this.readOnly)
);
@@ -58,28 +54,23 @@ export class CollectionView implements View, ITreeNodeObject {
/**
* Returns true if the user can edit a collection (including user and group access) from the individual vault.
* After FCv1, does not include admin permissions - see {@link CollectionAdminView.canEdit}.
* Does not include admin permissions - see {@link CollectionAdminView.canEdit}.
*/
canEdit(org: Organization, flexibleCollectionsV1Enabled: boolean): boolean {
canEdit(org: Organization): boolean {
if (org != null && org.id !== this.organizationId) {
throw new Error(
"Id of the organization provided does not match the org id of the collection.",
);
}
if (flexibleCollectionsV1Enabled) {
// Only use individual permissions, not admin permissions
return this.manage;
}
return org?.canEditAnyCollection(flexibleCollectionsV1Enabled) || this.manage;
return this.manage;
}
/**
* Returns true if the user can delete a collection from the individual vault.
* After FCv1, does not include admin permissions - see {@link CollectionAdminView.canDelete}.
* Does not include admin permissions - see {@link CollectionAdminView.canDelete}.
*/
canDelete(org: Organization, flexibleCollectionsV1Enabled: boolean): boolean {
canDelete(org: Organization): boolean {
if (org != null && org.id !== this.organizationId) {
throw new Error(
"Id of the organization provided does not match the org id of the collection.",
@@ -88,24 +79,14 @@ export class CollectionView implements View, ITreeNodeObject {
const canDeleteManagedCollections = !org?.limitCollectionCreationDeletion || org.isAdmin;
if (flexibleCollectionsV1Enabled) {
// Only use individual permissions, not admin permissions
return canDeleteManagedCollections && this.manage;
}
return (
org?.canDeleteAnyCollection(flexibleCollectionsV1Enabled) ||
(canDeleteManagedCollections && this.manage)
);
// Only use individual permissions, not admin permissions
return canDeleteManagedCollections && this.manage;
}
/**
* Returns true if the user can view collection info and access in a read-only state from the individual vault
*/
canViewCollectionInfo(
org: Organization | undefined,
flexibleCollectionsV1Enabled: boolean,
): boolean {
canViewCollectionInfo(org: Organization | undefined): boolean {
return false;
}

View File

@@ -175,7 +175,6 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI
) {}
async ngOnInit() {
const v1FCEnabled = await this.configService.getFeatureFlag(FeatureFlag.FlexibleCollectionsV1);
const restrictProviderAccess = await this.configService.getFeatureFlag(
FeatureFlag.RestrictProviderAccess,
);
@@ -186,7 +185,7 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI
this.showOrgSelector = true;
}
await this.initializeItems(this.selectedOrgId, v1FCEnabled, restrictProviderAccess);
await this.initializeItems(this.selectedOrgId, restrictProviderAccess);
if (this.selectedOrgId && this.selectedOrgId !== MY_VAULT_ID) {
await this.handleOrganizationCiphers();
@@ -332,11 +331,7 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI
}
}
private async initializeItems(
organizationId: OrganizationId,
v1FCEnabled: boolean,
restrictProviderAccess: boolean,
) {
private async initializeItems(organizationId: OrganizationId, restrictProviderAccess: boolean) {
this.totalItemCount = this.params.ciphers.length;
// If organizationId is not present or organizationId is MyVault, then all ciphers are considered personal items
@@ -351,7 +346,7 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI
const org = await this.organizationService.get(organizationId);
this.orgName = org.name;
this.editableItems = org.canEditAllCiphers(v1FCEnabled, restrictProviderAccess)
this.editableItems = org.canEditAllCiphers(restrictProviderAccess)
? this.params.ciphers
: this.params.ciphers.filter((c) => c.edit);