From db9003458b81beaaa6242d387917065ee9f93ef5 Mon Sep 17 00:00:00 2001
From: Nick Krantz <125900171+nick-livefront@users.noreply.github.com>
Date: Wed, 11 Sep 2024 11:29:53 -0500
Subject: [PATCH 1/5] [PM-11436] New "+" button (#10907)
* replace icon in "new" button on admin-console
* replace icon in "new" button on secrets manager
* reduce flash of "new item" button by checking the availability of the organization
---
.../vault-header/vault-header.component.html | 8 ++++++--
.../secrets-manager/shared/new-menu.component.html | 11 +++--------
2 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.html b/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.html
index f583055687c..72b1284b86a 100644
--- a/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.html
+++ b/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.html
@@ -100,7 +100,10 @@
[placeholder]="'searchCollection' | i18n"
>
-
+
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/new-menu.component.html b/bitwarden_license/bit-web/src/app/secrets-manager/shared/new-menu.component.html
index 457eff37fac..2238fa9fc87 100644
--- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/new-menu.component.html
+++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/new-menu.component.html
@@ -1,11 +1,6 @@
-
diff --git a/apps/web/src/app/vault/org-vault/vault.component.ts b/apps/web/src/app/vault/org-vault/vault.component.ts
index f9652fe08ca..add1ecbe3e5 100644
--- a/apps/web/src/app/vault/org-vault/vault.component.ts
+++ b/apps/web/src/app/vault/org-vault/vault.component.ts
@@ -43,9 +43,7 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { EventType } from "@bitwarden/common/enums";
-import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@@ -172,17 +170,8 @@ export class VaultComponent implements OnInit, OnDestroy {
protected orgRevokedUsers: OrganizationUserUserDetailsResponse[];
- private _restrictProviderAccessFlagEnabled: boolean;
- protected get restrictProviderAccessEnabled(): boolean {
- return this._restrictProviderAccessFlagEnabled;
- }
-
protected get hideVaultFilters(): boolean {
- return (
- this.restrictProviderAccessEnabled &&
- this.organization?.isProviderUser &&
- !this.organization?.isMember
- );
+ return this.organization?.isProviderUser && !this.organization?.isMember;
}
private searchText$ = new Subject();
@@ -218,7 +207,6 @@ export class VaultComponent implements OnInit, OnDestroy {
private apiService: ApiService,
private collectionService: CollectionService,
private organizationUserApiService: OrganizationUserApiService,
- protected configService: ConfigService,
private toastService: ToastService,
private accountService: AccountService,
) {}
@@ -230,10 +218,6 @@ export class VaultComponent implements OnInit, OnDestroy {
: "trashCleanupWarning",
);
- this._restrictProviderAccessFlagEnabled = await this.configService.getFeatureFlag(
- FeatureFlag.RestrictProviderAccess,
- );
-
const filter$ = this.routedVaultFilterService.filter$;
const organizationId$ = filter$.pipe(
map((filter) => filter.organizationId),
@@ -325,7 +309,7 @@ export class VaultComponent implements OnInit, OnDestroy {
this.editableCollections$ = this.allCollectionsWithoutUnassigned$.pipe(
map((collections) => {
// Users that can edit all ciphers can implicitly add to / edit within any collection
- if (this.organization.canEditAllCiphers(this.restrictProviderAccessEnabled)) {
+ if (this.organization.canEditAllCiphers) {
return collections;
}
// The user is only allowed to add/edit items to assigned collections that are not readonly
@@ -362,16 +346,12 @@ export class VaultComponent implements OnInit, OnDestroy {
// Restricted providers (who are not members) do not have access org cipher endpoint below
// Return early to avoid 404 response
- if (
- this.restrictProviderAccessEnabled &&
- !organization.isMember &&
- organization.isProviderUser
- ) {
+ if (!organization.isMember && organization.isProviderUser) {
return [];
}
// If the user can edit all ciphers for the organization then fetch them ALL.
- if (organization.canEditAllCiphers(this.restrictProviderAccessEnabled)) {
+ if (organization.canEditAllCiphers) {
ciphers = await this.cipherService.getAllFromApiForOrganization(organization.id);
} else {
// Otherwise, only fetch ciphers they have access to (includes unassigned for admins).
@@ -476,11 +456,8 @@ export class VaultComponent implements OnInit, OnDestroy {
]).pipe(
map(([filter, collection, organization]) => {
return (
- (filter.collectionId === Unassigned &&
- !organization.canEditUnassignedCiphers(this.restrictProviderAccessEnabled)) ||
- (!organization.canEditAllCiphers(this.restrictProviderAccessEnabled) &&
- collection != undefined &&
- !collection.node.assigned)
+ (filter.collectionId === Unassigned && !organization.canEditUnassignedCiphers) ||
+ (!organization.canEditAllCiphers && collection != undefined && !collection.node.assigned)
);
}),
shareReplay({ refCount: true, bufferSize: 1 }),
@@ -525,7 +502,7 @@ export class VaultComponent implements OnInit, OnDestroy {
}
const canEditCipher =
- organization.canEditAllCiphers(this.restrictProviderAccessEnabled) ||
+ organization.canEditAllCiphers ||
(await firstValueFrom(allCipherMap$))[cipherId] != undefined;
if (canEditCipher) {
@@ -758,15 +735,9 @@ export class VaultComponent implements OnInit, OnDestroy {
this.allCollectionsWithoutUnassigned$.pipe(
map((c) => {
return c.sort((a, b) => {
- if (
- a.canEditItems(this.organization, this.restrictProviderAccessEnabled) &&
- !b.canEditItems(this.organization, this.restrictProviderAccessEnabled)
- ) {
+ if (a.canEditItems(this.organization) && !b.canEditItems(this.organization)) {
return -1;
- } else if (
- !a.canEditItems(this.organization, this.restrictProviderAccessEnabled) &&
- b.canEditItems(this.organization, this.restrictProviderAccessEnabled)
- ) {
+ } else if (!a.canEditItems(this.organization) && b.canEditItems(this.organization)) {
return 1;
} else {
return a.name.localeCompare(b.name);
@@ -1001,9 +972,7 @@ export class VaultComponent implements OnInit, OnDestroy {
const unassignedCiphers: string[] = [];
// If user has edit all Access no need to check for unassigned ciphers
- const canEditAll = this.organization.canEditAllCiphers(this.restrictProviderAccessEnabled);
-
- if (canEditAll) {
+ if (this.organization.canEditAllCiphers) {
ciphers.map((cipher) => {
editAccessCiphers.push(cipher.id);
});
@@ -1042,7 +1011,7 @@ export class VaultComponent implements OnInit, OnDestroy {
}
async deleteCipher(c: CipherView): Promise {
- if (!c.edit && !this.organization.canEditAllCiphers(this.restrictProviderAccessEnabled)) {
+ if (!c.edit && !this.organization.canEditAllCiphers) {
this.showMissingPermissionsError();
return;
}
@@ -1146,9 +1115,7 @@ export class VaultComponent implements OnInit, OnDestroy {
const canDeleteCollections =
collections == null || collections.every((c) => c.canDelete(organization));
const canDeleteCiphers =
- ciphers == null ||
- ciphers.every((c) => c.edit) ||
- this.organization.canEditAllCiphers(this.restrictProviderAccessEnabled);
+ ciphers == null || ciphers.every((c) => c.edit) || this.organization.canEditAllCiphers;
if (!canDeleteCiphers || !canDeleteCollections) {
this.showMissingPermissionsError();
@@ -1351,8 +1318,7 @@ export class VaultComponent implements OnInit, OnDestroy {
}
protected deleteCipherWithServer(id: string, permanent: boolean, isUnassigned: boolean) {
- const asAdmin =
- this.organization?.canEditAllCiphers(this.restrictProviderAccessEnabled) || isUnassigned;
+ const asAdmin = this.organization?.canEditAllCiphers || isUnassigned;
return permanent
? this.cipherService.deleteWithServer(id, asAdmin)
: this.cipherService.softDeleteWithServer(id, asAdmin);
diff --git a/libs/angular/src/admin-console/components/collections.component.ts b/libs/angular/src/admin-console/components/collections.component.ts
index 4f166286184..d6801aa155e 100644
--- a/libs/angular/src/admin-console/components/collections.component.ts
+++ b/libs/angular/src/admin-console/components/collections.component.ts
@@ -4,8 +4,6 @@ import { firstValueFrom, map } from "rxjs";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
-import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@@ -27,7 +25,6 @@ export class CollectionsComponent implements OnInit {
collectionIds: string[];
collections: CollectionView[] = [];
organization: Organization;
- restrictProviderAccess: boolean;
protected cipherDomain: Cipher;
@@ -38,15 +35,11 @@ export class CollectionsComponent implements OnInit {
protected cipherService: CipherService,
protected organizationService: OrganizationService,
private logService: LogService,
- private configService: ConfigService,
private accountService: AccountService,
private toastService: ToastService,
) {}
async ngOnInit() {
- this.restrictProviderAccess = await this.configService.getFeatureFlag(
- FeatureFlag.RestrictProviderAccess,
- );
await this.load();
}
@@ -76,7 +69,7 @@ export class CollectionsComponent implements OnInit {
async submit(): Promise {
const selectedCollectionIds = this.collections
.filter((c) => {
- if (this.organization.canEditAllCiphers(this.restrictProviderAccess)) {
+ if (this.organization.canEditAllCiphers) {
return !!(c as any).checked;
} else {
return !!(c as any).checked && c.readOnly == null;
diff --git a/libs/angular/src/vault/components/add-edit.component.ts b/libs/angular/src/vault/components/add-edit.component.ts
index 96589fd2b07..45475440d0a 100644
--- a/libs/angular/src/vault/components/add-edit.component.ts
+++ b/libs/angular/src/vault/components/add-edit.component.ts
@@ -13,7 +13,6 @@ import { OrganizationUserStatusType, PolicyType } from "@bitwarden/common/admin-
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { EventType } from "@bitwarden/common/enums";
-import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { UriMatchStrategy } from "@bitwarden/common/models/domain/domain-service";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@@ -92,8 +91,6 @@ export class AddEditComponent implements OnInit, OnDestroy {
private personalOwnershipPolicyAppliesToActiveUser: boolean;
private previousCipherId: string;
- protected restrictProviderAccess = false;
-
get fido2CredentialCreationDateValue(): string {
const dateCreated = this.i18nService.t("dateCreated");
const creationDate = this.datePipe.transform(
@@ -182,10 +179,6 @@ export class AddEditComponent implements OnInit, OnDestroy {
}
async ngOnInit() {
- this.restrictProviderAccess = await this.configService.getFeatureFlag(
- FeatureFlag.RestrictProviderAccess,
- );
-
this.policyService
.policyAppliesToActiveUser$(PolicyType.PersonalOwnership)
.pipe(
@@ -683,11 +676,11 @@ export class AddEditComponent implements OnInit, OnDestroy {
protected saveCipher(cipher: Cipher) {
const isNotClone = this.editMode && !this.cloneMode;
- let orgAdmin = this.organization?.canEditAllCiphers(this.restrictProviderAccess);
+ let orgAdmin = this.organization?.canEditAllCiphers;
// if a cipher is unassigned we want to check if they are an admin or have permission to edit any collection
if (!cipher.collectionIds) {
- orgAdmin = this.organization?.canEditUnassignedCiphers(this.restrictProviderAccess);
+ orgAdmin = this.organization?.canEditUnassignedCiphers;
}
return this.cipher.id == null
@@ -696,14 +689,14 @@ export class AddEditComponent implements OnInit, OnDestroy {
}
protected deleteCipher() {
- const asAdmin = this.organization?.canEditAllCiphers(this.restrictProviderAccess);
+ const asAdmin = this.organization?.canEditAllCiphers;
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.restrictProviderAccess);
+ const asAdmin = this.organization?.canEditAllCiphers;
return this.cipherService.restoreWithServer(this.cipher.id, asAdmin);
}
diff --git a/libs/common/src/admin-console/models/domain/organization.ts b/libs/common/src/admin-console/models/domain/organization.ts
index 490c799ad18..8c28bcb4935 100644
--- a/libs/common/src/admin-console/models/domain/organization.ts
+++ b/libs/common/src/admin-console/models/domain/organization.ts
@@ -183,14 +183,7 @@ export class Organization {
return this.isAdmin || this.permissions.editAnyCollection;
}
- canEditUnassignedCiphers(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
- if (this.isProviderUser && !restrictProviderAccessFlagEnabled) {
- return true;
- }
-
+ get canEditUnassignedCiphers() {
return (
this.type === OrganizationUserType.Admin ||
this.type === OrganizationUserType.Owner ||
@@ -198,14 +191,7 @@ export class Organization {
);
}
- 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
- if (this.isProviderUser && !restrictProviderAccessFlagEnabled) {
- return true;
- }
-
+ get canEditAllCiphers() {
// The allowAdminAccessToAllCollectionItems flag can restrict admins
// Custom users with canEditAnyCollection are not affected by allowAdminAccessToAllCollectionItems flag
return (
diff --git a/libs/common/src/enums/feature-flag.enum.ts b/libs/common/src/enums/feature-flag.enum.ts
index 53baea14c5c..e7ece5b36a7 100644
--- a/libs/common/src/enums/feature-flag.enum.ts
+++ b/libs/common/src/enums/feature-flag.enum.ts
@@ -12,7 +12,6 @@ export enum FeatureFlag {
EnableDeleteProvider = "AC-1218-delete-provider",
ExtensionRefresh = "extension-refresh",
PersistPopupView = "persist-popup-view",
- RestrictProviderAccess = "restrict-provider-access",
PM4154_BulkEncryptionService = "PM-4154-bulk-encryption-service",
UseTreeWalkerApiForPageDetailsCollection = "use-tree-walker-api-for-page-details-collection",
EmailVerification = "email-verification",
@@ -59,7 +58,6 @@ export const DefaultFeatureFlagValue = {
[FeatureFlag.EnableDeleteProvider]: FALSE,
[FeatureFlag.ExtensionRefresh]: FALSE,
[FeatureFlag.PersistPopupView]: FALSE,
- [FeatureFlag.RestrictProviderAccess]: FALSE,
[FeatureFlag.PM4154_BulkEncryptionService]: FALSE,
[FeatureFlag.UseTreeWalkerApiForPageDetailsCollection]: FALSE,
[FeatureFlag.EmailVerification]: FALSE,
diff --git a/libs/common/src/vault/models/view/collection.view.ts b/libs/common/src/vault/models/view/collection.view.ts
index 0a05007b66f..873f538ca64 100644
--- a/libs/common/src/vault/models/view/collection.view.ts
+++ b/libs/common/src/vault/models/view/collection.view.ts
@@ -38,18 +38,14 @@ export class CollectionView implements View, ITreeNodeObject {
}
}
- canEditItems(org: Organization, restrictProviderAccess: boolean): boolean {
+ canEditItems(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.",
);
}
- return (
- org?.canEditAllCiphers(restrictProviderAccess) ||
- this.manage ||
- (this.assigned && !this.readOnly)
- );
+ return org?.canEditAllCiphers || this.manage || (this.assigned && !this.readOnly);
}
/**
diff --git a/libs/vault/src/components/assign-collections.component.ts b/libs/vault/src/components/assign-collections.component.ts
index 188fc543eff..db4d61691c9 100644
--- a/libs/vault/src/components/assign-collections.component.ts
+++ b/libs/vault/src/components/assign-collections.component.ts
@@ -11,12 +11,12 @@ import {
} from "@angular/core";
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
import {
- Observable,
- Subject,
combineLatest,
firstValueFrom,
map,
+ Observable,
shareReplay,
+ Subject,
switchMap,
takeUntil,
tap,
@@ -27,8 +27,6 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/enums";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
-import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { CipherId, CollectionId, OrganizationId, UserId } from "@bitwarden/common/types/guid";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
@@ -170,7 +168,6 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI
constructor(
private cipherService: CipherService,
private i18nService: I18nService,
- private configService: ConfigService,
private organizationService: OrganizationService,
private collectionService: CollectionService,
private formBuilder: FormBuilder,
@@ -179,10 +176,6 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI
) {}
async ngOnInit() {
- const restrictProviderAccess = await this.configService.getFeatureFlag(
- FeatureFlag.RestrictProviderAccess,
- );
-
this.activeUserId = await firstValueFrom(
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
);
@@ -193,7 +186,7 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI
this.showOrgSelector = true;
}
- await this.initializeItems(this.selectedOrgId, restrictProviderAccess);
+ await this.initializeItems(this.selectedOrgId);
if (this.selectedOrgId && this.selectedOrgId !== MY_VAULT_ID) {
await this.handleOrganizationCiphers();
@@ -339,7 +332,7 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI
}
}
- private async initializeItems(organizationId: OrganizationId, restrictProviderAccess: boolean) {
+ private async initializeItems(organizationId: OrganizationId) {
this.totalItemCount = this.params.ciphers.length;
// If organizationId is not present or organizationId is MyVault, then all ciphers are considered personal items
@@ -354,7 +347,7 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI
const org = await this.organizationService.get(organizationId);
this.orgName = org.name;
- this.editableItems = org.canEditAllCiphers(restrictProviderAccess)
+ this.editableItems = org.canEditAllCiphers
? this.params.ciphers
: this.params.ciphers.filter((c) => c.edit);
From a0a0a7ae1368262850d6fbe14a860077ffe4afd1 Mon Sep 17 00:00:00 2001
From: Victoria League
Date: Wed, 11 Sep 2024 14:54:07 -0400
Subject: [PATCH 3/5] [CL-395] Add and use art colors in svgs (#10990)
---
.../vault-ui-onboarding.component.ts | 14 ++++----
libs/auth/src/angular/icons/lock.icon.ts | 22 ++++++-------
libs/components/src/icon/icons/no-results.ts | 22 ++++++-------
libs/components/src/tw-theme.css | 6 ++++
libs/components/tailwind.config.base.js | 4 +++
.../send/send-ui/src/icons/no-send.icon.ts | 14 ++++----
.../send-ui/src/icons/send-created.icon.ts | 12 +++----
libs/vault/src/icons/deactivated-org.ts | 32 +++++++++----------
libs/vault/src/icons/empty-trash.ts | 20 ++++++------
libs/vault/src/icons/no-folders.ts | 26 +++++++--------
libs/vault/src/icons/vault.ts | 18 +++++------
11 files changed, 100 insertions(+), 90 deletions(-)
diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-ui-onboarding/vault-ui-onboarding.component.ts b/apps/browser/src/vault/popup/components/vault-v2/vault-ui-onboarding/vault-ui-onboarding.component.ts
index 9022a3b0489..20b39c5a88d 100644
--- a/apps/browser/src/vault/popup/components/vault-v2/vault-ui-onboarding/vault-ui-onboarding.component.ts
+++ b/apps/browser/src/vault/popup/components/vault-v2/vault-ui-onboarding/vault-ui-onboarding.component.ts
@@ -13,13 +13,13 @@ import {
const announcementIcon = svgIcon`