1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

handle PersonalOwnership policy and vault selector with only one option (#14530)

This commit is contained in:
Jonathan Prusik
2025-04-29 11:13:08 -04:00
committed by GitHub
parent 3694903a2a
commit 708bc78802
4 changed files with 66 additions and 26 deletions

View File

@@ -24,7 +24,11 @@ function getVaultIconByProductTier(productTierType?: ProductTierType): Option["i
}
}
// Value represents default selector state outside of data-driven state
const defaultNoneSelectValue = "0";
export type NotificationButtonRowProps = {
collections?: CollectionView[];
folders?: FolderView[];
i18n: { [key: string]: string };
organizations?: OrgView[];
@@ -32,40 +36,44 @@ export type NotificationButtonRowProps = {
text: string;
handlePrimaryButtonClick: (args: any) => void;
};
collections?: CollectionView[];
personalVaultIsAllowed: boolean;
theme: Theme;
};
export function NotificationButtonRow({
folders,
collections,
folders,
i18n,
organizations,
primaryButton,
personalVaultIsAllowed,
theme,
}: NotificationButtonRowProps) {
const currentUserVaultOption: Option = {
icon: User,
default: true,
text: i18n.myVault,
value: "0",
value: defaultNoneSelectValue,
};
const organizationOptions: Option[] = organizations?.length
? organizations.reduce(
(options, { id, name, productTierType }: OrgView) => {
const icon = getVaultIconByProductTier(productTierType);
return [
...options,
{
icon,
text: name,
value: id,
},
];
},
[currentUserVaultOption],
)
: ([] as Option[]);
// Do not include user vault if disallowed by org policy
const initialVaultOptions = [
...(personalVaultIsAllowed ? [currentUserVaultOption] : []),
] as Option[];
const vaultOptions: Option[] = organizations?.length
? organizations.reduce((options, { id, name, productTierType }: OrgView) => {
const icon = getVaultIconByProductTier(productTierType);
return [
...options,
{
icon,
text: name,
value: id,
},
];
}, initialVaultOptions)
: initialVaultOptions;
const folderOptions: Option[] = folders?.length
? folders.reduce<Option[]>(
@@ -74,7 +82,7 @@ export function NotificationButtonRow({
{
icon: Folder,
text: name,
value: id === null ? "0" : id,
value: id === null ? defaultNoneSelectValue : id,
default: id === null,
},
],
@@ -89,7 +97,7 @@ export function NotificationButtonRow({
{
icon: CollectionShared,
text: name,
value: id === null ? "0" : id,
value: id === null ? defaultNoneSelectValue : id,
default: id === null,
},
],
@@ -97,17 +105,31 @@ export function NotificationButtonRow({
)
: [];
if (vaultOptions.length === 1) {
selectedVaultSignal?.set(vaultOptions[0].value);
// If the individual vault is disabled by a vault policy,
// a collection selection is required
if (
!personalVaultIsAllowed &&
collections?.length &&
selectedCollectionSignal.get() === defaultNoneSelectValue
) {
selectedCollectionSignal?.set(collections[0].id);
}
}
return html`
${ButtonRow({
theme,
primaryButton,
selectButtons: [
...(organizationOptions.length > 1
...(vaultOptions.length > 1
? [
{
id: "organization",
label: i18n.vault,
options: organizationOptions,
options: vaultOptions,
selectedSignal: selectedVaultSignal,
},
]

View File

@@ -29,6 +29,7 @@ export type NotificationContainerProps = NotificationBarIframeInitData & {
folders?: FolderView[];
i18n: { [key: string]: string };
organizations?: OrgView[];
personalVaultIsAllowed?: boolean;
type: NotificationType; // @TODO typing override for generic `NotificationBarIframeInitData.type`
};
@@ -41,6 +42,7 @@ export function NotificationContainer({
folders,
i18n,
organizations,
personalVaultIsAllowed = true,
theme = ThemeTypes.Light,
type,
}: NotificationContainerProps) {
@@ -71,6 +73,7 @@ export function NotificationContainer({
i18n,
notificationType: type,
organizations,
personalVaultIsAllowed,
theme,
})}
</div>

View File

@@ -18,6 +18,7 @@ export type NotificationFooterProps = {
i18n: { [key: string]: string };
notificationType?: NotificationType;
organizations?: OrgView[];
personalVaultIsAllowed: boolean;
theme: Theme;
handleSaveAction: (e: Event) => void;
};
@@ -28,6 +29,7 @@ export function NotificationFooter({
i18n,
notificationType,
organizations,
personalVaultIsAllowed,
theme,
handleSaveAction,
}: NotificationFooterProps) {
@@ -46,6 +48,7 @@ export function NotificationFooter({
handlePrimaryButtonClick: handleSaveAction,
text: primaryButtonText,
},
personalVaultIsAllowed,
theme,
})
: nothing}

View File

@@ -135,7 +135,11 @@ async function initNotificationBar(message: NotificationBarWindowMessage) {
}
notificationBarIframeInitData = initData;
const { isVaultLocked, theme } = notificationBarIframeInitData;
const {
isVaultLocked,
removeIndividualVault: personalVaultDisallowed, // renamed to avoid local method collision
theme,
} = notificationBarIframeInitData;
const i18n = getI18n();
const resolvedTheme = getResolvedTheme(theme ?? ThemeTypes.Light);
@@ -172,6 +176,7 @@ async function initNotificationBar(message: NotificationBarWindowMessage) {
...notificationBarIframeInitData,
type: notificationBarIframeInitData.type as NotificationType,
theme: resolvedTheme,
personalVaultIsAllowed: !personalVaultDisallowed,
handleCloseNotification,
handleSaveAction,
handleEditOrUpdateAction,
@@ -266,7 +271,10 @@ function handleSaveAction(e: Event) {
const selectedFolder = selectedFolderSignal.get();
if (selectedVault.length > 1) {
openAddEditVaultItemPopout(e, { organizationId: selectedVault, folder: selectedFolder });
openAddEditVaultItemPopout(e, {
organizationId: selectedVault,
folder: selectedFolder,
});
handleCloseNotification(e);
return;
}
@@ -370,7 +378,11 @@ function handleSaveCipherAttemptCompletedMessage(message: NotificationBarWindowM
function openAddEditVaultItemPopout(
e: Event,
options: { cipherId?: string; organizationId?: string; folder?: string },
options: {
cipherId?: string;
organizationId?: string;
folder?: string;
},
) {
e.preventDefault();
sendPlatformMessage({