diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json
index 60b5b313ac0..f03b003ba2b 100644
--- a/apps/web/src/locales/en/messages.json
+++ b/apps/web/src/locales/en/messages.json
@@ -8523,6 +8523,14 @@
},
"noInvoicesToList": {
"message": "There are no invoices to list",
- "description": "A paragraph on the Billing History page of the Provider Portal letting users know they can download a CSV report for their invoices that does not include prorations."
+ "description": "A paragraph on the Billing History page of the Provider Portal letting users know they can download a CSV report for their invoices that does not include prorations."
+ },
+ "providerClientVaultPrivacyNotification": {
+ "message": "Notice: Later this month, client vault privacy will be improved and provider members will no longer have direct access to client vault items. For questions,",
+ "description": "This will be displayed as part of a larger sentence. The whole sentence reads: 'Notice: Later this month, client vault privacy will be improved and provider members will no longer have direct access to client vault items. For questions, please contact Bitwarden support'."
+ },
+ "contactBitwardenSupport": {
+ "message": "contact Bitwarden support.",
+ "description": "This will be displayed as part of a larger sentence. The whole sentence reads: 'Notice: Later this month, client vault privacy will be improved and provider members will no longer have direct access to client vault items. For questions, please contact Bitwarden support'. 'Bitwarden' should not be translated"
}
}
diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/providers-layout.component.html b/bitwarden_license/bit-web/src/app/admin-console/providers/providers-layout.component.html
index 5a46b49f24e..9ed71f157c5 100644
--- a/bitwarden_license/bit-web/src/app/admin-console/providers/providers-layout.component.html
+++ b/bitwarden_license/bit-web/src/app/admin-console/providers/providers-layout.component.html
@@ -45,7 +45,26 @@
-
+
+ {{ "providerClientVaultPrivacyNotification" | i18n }}
+
+ {{ "contactBitwardenSupport" | i18n }} .
+
diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/providers-layout.component.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/providers-layout.component.ts
index d4abea087f1..65175fb51f7 100644
--- a/bitwarden_license/bit-web/src/app/admin-console/providers/providers-layout.component.ts
+++ b/bitwarden_license/bit-web/src/app/admin-console/providers/providers-layout.component.ts
@@ -10,12 +10,20 @@ import { Provider } from "@bitwarden/common/admin-console/models/domain/provider
import { hasConsolidatedBilling } from "@bitwarden/common/billing/abstractions/provider-billing.service.abstraction";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
-import { IconModule, LayoutComponent, NavigationModule } from "@bitwarden/components";
+import {
+ BannerModule,
+ IconModule,
+ LayoutComponent,
+ LinkModule,
+ NavigationModule,
+} from "@bitwarden/components";
import { ProviderPortalLogo } from "@bitwarden/web-vault/app/admin-console/icons/provider-portal-logo";
import { PaymentMethodWarningsModule } from "@bitwarden/web-vault/app/billing/shared";
import { ProductSwitcherModule } from "@bitwarden/web-vault/app/layouts/product-switcher/product-switcher.module";
import { ToggleWidthComponent } from "@bitwarden/web-vault/app/layouts/toggle-width.component";
+import { ProviderClientVaultPrivacyBannerService } from "./services/provider-client-vault-privacy-banner.service";
+
@Component({
selector: "providers-layout",
templateUrl: "providers-layout.component.html",
@@ -30,6 +38,8 @@ import { ToggleWidthComponent } from "@bitwarden/web-vault/app/layouts/toggle-wi
PaymentMethodWarningsModule,
ToggleWidthComponent,
ProductSwitcherModule,
+ BannerModule,
+ LinkModule,
],
})
export class ProvidersLayoutComponent implements OnInit, OnDestroy {
@@ -45,10 +55,15 @@ export class ProvidersLayoutComponent implements OnInit, OnDestroy {
FeatureFlag.ShowPaymentMethodWarningBanners,
);
+ protected showProviderClientVaultPrivacyWarningBanner$ = this.configService.getFeatureFlag$(
+ FeatureFlag.ProviderClientVaultPrivacyBanner,
+ );
+
constructor(
private route: ActivatedRoute,
private providerService: ProviderService,
private configService: ConfigService,
+ protected providerClientVaultPrivacyBannerService: ProviderClientVaultPrivacyBannerService,
) {}
ngOnInit() {
diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/services/provider-client-vault-privacy-banner.service.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/services/provider-client-vault-privacy-banner.service.ts
new file mode 100644
index 00000000000..c347f5c2aae
--- /dev/null
+++ b/bitwarden_license/bit-web/src/app/admin-console/providers/services/provider-client-vault-privacy-banner.service.ts
@@ -0,0 +1,31 @@
+import { Injectable } from "@angular/core";
+
+import {
+ StateProvider,
+ AC_BANNERS_DISMISSED_DISK,
+ UserKeyDefinition,
+} from "@bitwarden/common/platform/state";
+
+export const SHOW_BANNER_KEY = new UserKeyDefinition(
+ AC_BANNERS_DISMISSED_DISK,
+ "showProviderClientVaultPrivacyBanner",
+ {
+ deserializer: (b) => b,
+ clearOn: [],
+ },
+);
+
+/** Displays a banner warning provider users that client organization vaults
+ * will soon become inaccessible directly. */
+@Injectable({ providedIn: "root" })
+export class ProviderClientVaultPrivacyBannerService {
+ private _showBanner = this.stateProvider.getActive(SHOW_BANNER_KEY);
+
+ showBanner$ = this._showBanner.state$;
+
+ constructor(private stateProvider: StateProvider) {}
+
+ async hideBanner() {
+ await this._showBanner.update(() => false);
+ }
+}
diff --git a/libs/common/src/enums/feature-flag.enum.ts b/libs/common/src/enums/feature-flag.enum.ts
index 2ed70efb81d..25c4c492e91 100644
--- a/libs/common/src/enums/feature-flag.enum.ts
+++ b/libs/common/src/enums/feature-flag.enum.ts
@@ -22,6 +22,7 @@ export enum FeatureFlag {
MemberAccessReport = "ac-2059-member-access-report",
EnableTimeThreshold = "PM-5864-dollar-threshold",
GroupsComponentRefactor = "groups-component-refactor",
+ ProviderClientVaultPrivacyBanner = "ac-2833-provider-client-vault-privacy-banner",
}
export type AllowedFeatureFlagTypes = boolean | number | string;
@@ -54,6 +55,7 @@ export const DefaultFeatureFlagValue = {
[FeatureFlag.MemberAccessReport]: FALSE,
[FeatureFlag.EnableTimeThreshold]: FALSE,
[FeatureFlag.GroupsComponentRefactor]: FALSE,
+ [FeatureFlag.ProviderClientVaultPrivacyBanner]: FALSE,
} satisfies Record;
export type DefaultFeatureFlagValueType = typeof DefaultFeatureFlagValue;
diff --git a/libs/common/src/platform/state/state-definitions.ts b/libs/common/src/platform/state/state-definitions.ts
index e22763e6fb7..6cc2b181b64 100644
--- a/libs/common/src/platform/state/state-definitions.ts
+++ b/libs/common/src/platform/state/state-definitions.ts
@@ -29,6 +29,9 @@ export const ORGANIZATION_MANAGEMENT_PREFERENCES_DISK = new StateDefinition(
web: "disk-local",
},
);
+export const AC_BANNERS_DISMISSED_DISK = new StateDefinition("acBannersDismissed", "disk", {
+ web: "disk-local",
+});
// Billing
export const BILLING_DISK = new StateDefinition("billing", "disk");