1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-09 13:10:17 +00:00

Merge branch 'main' into auth/pm-9115/implement-view-data-persistence-in-2FA-flows

This commit is contained in:
Alec Rippberger
2025-04-17 13:04:28 -05:00
committed by GitHub
52 changed files with 947 additions and 147 deletions

View File

@@ -87,6 +87,7 @@ jobs:
os:
[
{ base: "linux", distro: "ubuntu-22.04", target_suffix: "" },
{ base: "linux", distro: "ubuntu-22.04-arm", target_suffix: "-arm64" },
{ base: "mac", distro: "macos-13", target_suffix: "" },
{ base: "mac", distro: "macos-14", target_suffix: "-arm64" }
]
@@ -130,7 +131,7 @@ jobs:
if: ${{ inputs.sdk_branch != '' && needs.setup.outputs.has_secrets == 'true' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
@@ -306,7 +307,7 @@ jobs:
if: ${{ inputs.sdk_branch != '' && needs.setup.outputs.has_secrets == 'true' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}

View File

@@ -201,7 +201,7 @@ jobs:
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
@@ -237,7 +237,7 @@ jobs:
TARGET: musl
run: |
rustup target add x86_64-unknown-linux-musl
node build.js cross-platform
node build.js --target=x86_64-unknown-linux-musl --release
- name: Build application
run: npm run dist:lin
@@ -298,6 +298,103 @@ jobs:
if-no-files-found: error
linux-arm64:
name: Linux ARM64 Build
# Note, before updating the ubuntu version of the workflow, ensure the snap base image
# is equal or greater than the new version. Otherwise there might be GLIBC version issues.
# The snap base for desktop is defined in `apps/desktop/electron-builder.json`
# We intentionally keep this runner on the oldest supported OS in GitHub Actions
# for maximum compatibility across GLIBC versions
runs-on: ubuntu-22.04-arm
needs: setup
env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
NODE_OPTIONS: --max_old_space_size=4096
defaults:
run:
working-directory: apps/desktop
steps:
- name: Check out repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: ${{ env._NODE_VERSION }}
- name: Set up environment
run: |
sudo apt-get update
sudo apt-get -y install pkg-config libxss-dev rpm musl-dev musl-tools flatpak flatpak-builder
- name: Print environment
run: |
node --version
npm --version
snap --version
snapcraft --version || echo 'snapcraft unavailable'
- name: Install Node dependencies
run: npm ci
working-directory: ./
- name: Download SDK Artifacts
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
artifacts: sdk-internal
repo: bitwarden/sdk-internal
path: ../sdk-internal
if_no_artifact_found: fail
- name: Override SDK
if: ${{ inputs.sdk_branch != '' }}
working-directory: ./
run: |
ls -l ../
npm link ../sdk-internal
- name: Cache Native Module
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
id: cache
with:
path: |
apps/desktop/desktop_native/napi/*.node
apps/desktop/desktop_native/dist/*
${{ env.RUNNER_TEMP }}/.cargo/registry
${{ env.RUNNER_TEMP }}/.cargo/git
key: rust-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('apps/desktop/desktop_native/**/*') }}
- name: Build Native Module
if: steps.cache.outputs.cache-hit != 'true'
working-directory: apps/desktop/desktop_native
env:
PKG_CONFIG_ALLOW_CROSS: true
PKG_CONFIG_ALL_STATIC: true
TARGET: musl
run: |
rustup target add aarch64-unknown-linux-musl
node build.js --target=aarch64-unknown-linux-musl --release
- name: Build application
run: npm run dist:lin:arm64
- name: Upload tar.gz artifact
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
with:
name: bitwarden_${{ env._PACKAGE_VERSION }}_arm64.tar.gz
path: apps/desktop/dist/bitwarden_desktop_arm64.tar.gz
if-no-files-found: error
windows:
name: Windows Build
runs-on: windows-2022
@@ -369,7 +466,7 @@ jobs:
if: ${{ inputs.sdk_branch != '' && needs.setup.outputs.has_secrets == 'true' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
@@ -705,7 +802,7 @@ jobs:
if: ${{ inputs.sdk_branch != '' && needs.setup.outputs.has_secrets == 'true' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
@@ -895,7 +992,7 @@ jobs:
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
@@ -1144,7 +1241,7 @@ jobs:
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}
@@ -1425,7 +1522,7 @@ jobs:
if: ${{ inputs.sdk_branch != '' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
github_token: ${{secrets.GITHUB_TOKEN}}
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build-wasm-internal.yml
workflow_conclusion: success
branch: ${{ inputs.sdk_branch }}

View File

@@ -4,7 +4,7 @@ import { html, TemplateResult } from "lit";
import { Theme } from "@bitwarden/common/platform/enums";
import { themes } from "../../../content/components/constants/styles";
import { Business, Users } from "../../../content/components/icons";
import { Business, Family } from "../../../content/components/icons";
import { OrganizationCategories, OrganizationCategory } from "./types";
@@ -13,7 +13,7 @@ const cipherIndicatorIconsMap: Record<
(args: { color: string; theme: Theme }) => TemplateResult
> = {
[OrganizationCategories.business]: Business,
[OrganizationCategories.family]: Users,
[OrganizationCategories.family]: Family,
};
export function CipherInfoIndicatorIcons({

View File

@@ -4,14 +4,14 @@ import { html } from "lit";
import { IconProps } from "../common-types";
import { buildIconColorRule, ruleNames, themes } from "../constants/styles";
export function Collection({ color, disabled, theme }: IconProps) {
export function CollectionShared({ color, disabled, theme }: IconProps) {
const shapeColor = disabled ? themes[theme].secondary["300"] : color || themes[theme].text.main;
return html`
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14" fill="none">
<path
class=${css(buildIconColorRule(shapeColor, ruleNames.fill))}
d="M3.5.75A.75.75 0 0 1 4.25 0h5.5a.75.75 0 0 1 0 1.5h-5.5A.75.75 0 0 1 3.5.75ZM2.25 2a.75.75 0 0 0 0 1.5h9.5a.75.75 0 0 0 0-1.5h-9.5Z"
d="M3.5.75A.75.75 0 0 1 4.25 0h5.5a.75.75 0 0 1 0 1.5h-5.5A.75.75 0 0 1 3.5.75ZM2.25 2a.75.75 0 0 0 0 1.5h9.5a.75.75 0 0 0 0-1.5h-9.5ZM6 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0ZM10 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0ZM7 11.46a1.928 1.928 0 0 0-.586-1.386 2.035 2.035 0 0 0-2.828 0A1.928 1.928 0 0 0 3 11.461c0 .298.241.539.54.539h2.92a.54.54 0 0 0 .54-.54ZM8 11.46a2.928 2.928 0 0 0-.371-1.426A2.005 2.005 0 0 1 9 9.5a2.035 2.035 0 0 1 1.414.574A1.928 1.928 0 0 1 11 11.461a.54.54 0 0 1-.54.539H7.904c.063-.168.097-.35.097-.54Z"
/>
<path
class=${css(buildIconColorRule(shapeColor, ruleNames.fill))}

View File

@@ -0,0 +1,19 @@
import { css } from "@emotion/css";
import { html } from "lit";
import { IconProps } from "../common-types";
import { buildIconColorRule, ruleNames, themes } from "../constants/styles";
export function Family({ color, disabled, theme }: IconProps) {
const shapeColor = disabled ? themes[theme].secondary["300"] : color || themes[theme].text.main;
return html`
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none">
<path
class=${css(buildIconColorRule(shapeColor, ruleNames.fill))}
fill-rule="evenodd"
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0Zm-1.5 0a6.47 6.47 0 0 1-.932 3.356 3.732 3.732 0 0 0-1.106-.784 3.547 3.547 0 0 0-.516-.19 2 2 0 1 0-3.444-1.297c-.323-.216-.681-.4-1.069-.536a2.5 2.5 0 1 0-3.065-.155 5.405 5.405 0 0 0-1.59.674 3.912 3.912 0 0 0-.977.893A6.5 6.5 0 1 1 14.5 8ZM2.531 11.514a.75.75 0 0 0 .103-.13c.276-.436.552-.801.942-1.047a3.837 3.837 0 0 1 1.177-.492 5.243 5.243 0 0 1 .845-.095h.007l.022.001h.023c.436 0 .865.07 1.262.205.381.13.733.335 1.037.584.175.143.324.3.448.465l.164.226a4.13 4.13 0 0 0-1.035 1.565 4.407 4.407 0 0 0-.276 1.537c0 .043.004.085.01.125a6.5 6.5 0 0 1-4.729-2.944Zm10.033.964.07.08a6.481 6.481 0 0 1-3.894 1.9.757.757 0 0 0 .01-.125c0-.35.062-.694.181-1.013a2.63 2.63 0 0 1 .505-.842c.213-.237.462-.42.73-.543.267-.123.55-.185.834-.185.284 0 .567.062.835.185.267.123.516.306.729.543ZM7 6.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0ZM11 9a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Z"
/>
</svg>
`;
}

View File

@@ -3,12 +3,12 @@ export { AngleUp } from "./angle-up";
export { BrandIconContainer } from "./brand-icon-container";
export { Business } from "./business";
export { Close } from "./close";
export { Collection } from "./collection";
export { CollectionShared } from "./collection-shared";
export { ExclamationTriangle } from "./exclamation-triangle";
export { ExternalLink } from "./external-link";
export { Family } from "./family";
export { Folder } from "./folder";
export { Globe } from "./globe";
export { PencilSquare } from "./pencil-square";
export { Shield } from "./shield";
export { User } from "./user";
export { Users } from "./users";

View File

@@ -1,18 +0,0 @@
import { css } from "@emotion/css";
import { html } from "lit";
import { IconProps } from "../common-types";
import { buildIconColorRule, ruleNames, themes } from "../constants/styles";
export function Users({ color, disabled, theme }: IconProps) {
const shapeColor = disabled ? themes[theme].secondary["300"] : color || themes[theme].text.main;
return html`
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 14" fill="none">
<path
class=${css(buildIconColorRule(shapeColor, ruleNames.fill))}
d="M6.5 2.5c0 .375-.082.73-.23 1.049A2.986 2.986 0 0 1 8 3c.644 0 1.241.203 1.73.549a2.5 2.5 0 1 1 3.925.825 4 4 0 0 1 1.173.846c.372.387.667.847.867 1.352.201.506.305 1.047.305 1.595 0 .46-.373.833-.833.833H11a4.987 4.987 0 0 1 1.62 2.087A5 5 0 0 1 13 13a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1 5 5 0 0 1 2-4H.833A.833.833 0 0 1 0 8.167c0-.548.103-1.09.304-1.595.202-.505.496-.965.868-1.352.339-.353.736-.64 1.173-.846A2.5 2.5 0 1 1 6.5 2.5ZM4 3.5a1 1 0 1 0 0-2 1 1 0 0 0 0 2Zm1.401 4a2.986 2.986 0 0 1-.389-1.771A2.404 2.404 0 0 0 4 5.5c-.32 0-.638.065-.936.194-.3.13-.575.32-.81.565A2.682 2.682 0 0 0 1.579 7.5h3.822Zm5.198 0h3.822a2.682 2.682 0 0 0-.674-1.24 2.493 2.493 0 0 0-.81-.566 2.362 2.362 0 0 0-1.95.035 2.987 2.987 0 0 1-.39 1.771ZM12 3.5a1 1 0 1 0 0-2 1 1 0 0 0 0 2Zm-4 4a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm3.464 5a3.5 3.5 0 0 0-6.928 0h6.928Z"
/>
</svg>
`;
}

View File

@@ -43,26 +43,23 @@ const createIconStory = (iconName: keyof typeof Icons): StoryObj<Args> => {
render: (args) => Template(args, Icons[iconName]),
} as StoryObj<Args>;
if (iconName !== "BrandIconContainer") {
story.argTypes = {
iconLink: { table: { disable: true } },
};
}
story.argTypes = {
iconLink: { table: { disable: true } },
};
return story;
};
export const AngleDownIcon = createIconStory("AngleDown");
export const AngleUpIcon = createIconStory("AngleUp");
export const BrandIcon = createIconStory("BrandIconContainer");
export const BusinessIcon = createIconStory("Business");
export const CloseIcon = createIconStory("Close");
export const CollectionIcon = createIconStory("Collection");
export const CollectionSharedIcon = createIconStory("CollectionShared");
export const ExclamationTriangleIcon = createIconStory("ExclamationTriangle");
export const ExternalLinkIcon = createIconStory("ExternalLink");
export const FamilyIcon = createIconStory("Family");
export const FolderIcon = createIconStory("Folder");
export const GlobeIcon = createIconStory("Globe");
export const PencilSquareIcon = createIconStory("PencilSquare");
export const ShieldIcon = createIconStory("Shield");
export const UserIcon = createIconStory("User");
export const UsersIcon = createIconStory("Users");

View File

@@ -4,14 +4,14 @@ import { ProductTierType } from "@bitwarden/common/billing/enums";
import { Theme } from "@bitwarden/common/platform/enums";
import { Option, OrgView, FolderView } from "../common-types";
import { Business, Users, Folder, User } from "../icons";
import { Business, Family, Folder, User } from "../icons";
import { ButtonRow } from "../rows/button-row";
function getVaultIconByProductTier(productTierType?: ProductTierType): Option["icon"] {
switch (productTierType) {
case ProductTierType.Free:
case ProductTierType.Families:
return Users;
return Family;
case ProductTierType.Teams:
case ProductTierType.Enterprise:
case ProductTierType.TeamsStarter:

View File

@@ -18,7 +18,11 @@ export class BackgroundCommunicationBackend implements CommunicationBackend {
return;
}
void this.queue.enqueue({ ...message.message, source: { Web: { id: sender.tab.id } } });
void this.queue.enqueue(
new IncomingMessage(message.message.payload, message.message.destination, {
Web: { id: sender.tab.id },
}),
);
});
}

View File

@@ -593,6 +593,7 @@ const routes: Routes = [
path: "intro-carousel",
component: ExtensionAnonLayoutWrapperComponent,
canActivate: [],
data: { elevation: 0, doNotSaveUrl: true } satisfies RouteDataProperties,
children: [
{
path: "",

View File

@@ -43,7 +43,7 @@
bitButton
buttonType="secondary"
(click)="navigateToLogin()"
class="tw-w-full tw-mt-4"
class="tw-w-full tw-mt-2"
>
{{ "logIn" | i18n }}
</button>

View File

@@ -34,18 +34,22 @@
"dist:oss:mac": "npm run build:oss:prod && npm run clean && npm run package:oss:mac",
"dist:oss:mac-arm64": "npm run build:oss:prod && npm run clean && npm run package:oss:mac-arm64",
"dist:oss:lin": "npm run build:oss:prod && npm run clean && npm run package:oss:lin",
"dist:oss:lin-arm64": "npm run build:oss:prod && npm run clean && npm run package:oss:lin-arm64",
"dist:bit:win": "npm run build:bit:prod && npm run clean && npm run package:bit:win",
"dist:bit:mac": "npm run build:bit:prod && npm run clean && npm run package:bit:mac",
"dist:bit:mac-arm64": "npm run build:bit:prod && npm run clean && npm run package:bit:mac-arm64",
"dist:bit:lin": "npm run build:bit:prod && npm run clean && npm run package:bit:lin",
"dist:bit:lin-arm64": "npm run build:bit:prod && npm run clean && npm run package:bit:lin-arm64",
"package:oss:win": "pkg . --targets win-x64 --output ./dist/oss/windows/bw.exe",
"package:oss:mac": "pkg . --targets macos-x64 --output ./dist/oss/macos/bw",
"package:oss:mac-arm64": "pkg . --targets macos-arm64 --output ./dist/oss/macos-arm64/bw",
"package:oss:lin": "pkg . --targets linux-x64 --output ./dist/oss/linux/bw",
"package:oss:lin-arm64": "pkg . --targets linux-arm64 --output ./dist/oss/linux-arm64/bw",
"package:bit:win": "pkg . --targets win-x64 --output ./dist/bit/windows/bw.exe",
"package:bit:mac": "pkg . --targets macos-x64 --output ./dist/bit/macos/bw",
"package:bit:mac-arm64": "pkg . --targets macos-arm64 --output ./dist/bit/macos-arm64/bw",
"package:bit:lin": "pkg . --targets linux-x64 --output ./dist/bit/linux/bw",
"package:bit:lin-arm64": "pkg . --targets linux-arm64 --output ./dist/bit/linux-arm64/bw",
"test": "jest",
"test:watch": "jest --watch",
"test:watch:all": "jest --watchAll"
@@ -72,7 +76,7 @@
"inquirer": "8.2.6",
"jsdom": "26.0.0",
"jszip": "3.10.1",
"koa": "2.15.4",
"koa": "2.16.1",
"koa-bodyparser": "4.4.1",
"koa-json": "2.0.2",
"lowdb": "1.0.0",

View File

@@ -10,8 +10,6 @@ import { PolicyType } from "@bitwarden/common/admin-console/enums";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { getUserId } from "@bitwarden/common/auth/services/account.service";
import { EventType } from "@bitwarden/common/enums";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import {
ExportFormat,
@@ -30,7 +28,6 @@ export class ExportCommand {
private policyService: PolicyService,
private eventCollectionService: EventCollectionService,
private accountService: AccountService,
private configService: ConfigService,
) {}
async run(options: OptionValues): Promise<Response> {
@@ -55,13 +52,6 @@ export class ExportCommand {
const format =
password && options.format == "json" ? "encrypted_json" : (options.format ?? "csv");
if (
format == "zip" &&
!(await this.configService.getFeatureFlag(FeatureFlag.ExportAttachments))
) {
return Response.badRequest("Exporting attachments is not supported in this environment.");
}
if (!this.isSupportedExportFormat(format)) {
return Response.badRequest(
`'${format}' is not a supported export format. Supported formats: ${EXPORT_FORMATS.join(

View File

@@ -464,7 +464,7 @@ export class VaultProgram extends BaseProgram {
private exportCommand(): Command {
return new Command("export")
.description("Export vault data to a CSV or JSON file.")
.description("Export vault data to a CSV, JSON or ZIP file.")
.option("--output <output>", "Output directory or filename.")
.option("--format <format>", "Export file format.")
.option(
@@ -476,7 +476,7 @@ export class VaultProgram extends BaseProgram {
writeLn("\n Notes:");
writeLn("");
writeLn(
" Valid formats are `csv`, `json`, and `encrypted_json`. Default format is `csv`.",
" Valid formats are `csv`, `json`, `encrypted_json` and zip. Default format is `csv`.",
);
writeLn("");
writeLn(
@@ -504,7 +504,6 @@ export class VaultProgram extends BaseProgram {
this.serviceContainer.policyService,
this.serviceContainer.eventCollectionService,
this.serviceContainer.accountService,
this.serviceContainer.configService,
);
const response = await command.run(options);
this.processResponse(response);

View File

@@ -3,6 +3,10 @@ const child_process = require("child_process");
const fs = require("fs");
const path = require("path");
const process = require("process");
const args = process.argv.slice(2); // Get arguments passed to the script
const mode = args.includes("--release") ? "release" : "debug";
const targetArg = args.find(arg => arg.startsWith("--target="));
const target = targetArg ? targetArg.split("=")[1] : null;
let crossPlatform = process.argv.length > 2 && process.argv[2] === "cross-platform";
@@ -18,10 +22,17 @@ function buildProxyBin(target, release = true) {
return child_process.execSync(`cargo build --bin desktop_proxy ${releaseArg} ${targetArg}`, {stdio: 'inherit', cwd: path.join(__dirname, "proxy")});
}
if (!crossPlatform) {
console.log("Building native modules in debug mode for the native architecture");
buildNapiModule(false, false);
buildProxyBin(false, false);
if (!crossPlatform && !target) {
console.log(`Building native modules in ${mode} mode for the native architecture`);
buildNapiModule(false, mode === "release");
buildProxyBin(false, mode === "release");
return;
}
if (target) {
console.log(`Building for target: ${target} in ${mode} mode`);
buildNapiModule(target, mode === "release");
buildProxyBin(target, mode === "release");
return;
}
@@ -47,7 +58,8 @@ switch (process.platform) {
default:
targets = [
['x86_64-unknown-linux-musl', 'x64']
['x86_64-unknown-linux-musl', 'x64'],
['aarch64-unknown-linux-musl', 'arm64']
];
process.env["PKG_CONFIG_ALLOW_CROSS"] = "1";

View File

@@ -36,6 +36,7 @@
"pack:dir": "npm run clean:dist && electron-builder --dir -p never",
"pack:lin:flatpak": "npm run clean:dist && electron-builder --dir -p never && flatpak-builder --repo=build/.repo build/.flatpak ./resources/com.bitwarden.desktop.devel.yaml --install-deps-from=flathub --force-clean && flatpak build-bundle ./build/.repo/ ./dist/com.bitwarden.desktop.flatpak com.bitwarden.desktop",
"pack:lin": "npm run clean:dist && electron-builder --linux --x64 -p never && export SNAP_FILE=$(realpath ./dist/bitwarden_*.snap) && unsquashfs -d ./dist/tmp-snap/ $SNAP_FILE && mkdir -p ./dist/tmp-snap/meta/polkit/ && cp ./resources/com.bitwarden.desktop.policy ./dist/tmp-snap/meta/polkit/polkit.com.bitwarden.desktop.policy && rm $SNAP_FILE && snapcraft pack ./dist/tmp-snap/ && mv ./*.snap ./dist/ && rm -rf ./dist/tmp-snap/",
"pack:lin:arm64": "npm run clean:dist && electron-builder --dir -p never && tar -czvf ./dist/bitwarden_desktop_arm64.tar.gz -C ./dist/linux-arm64-unpacked/ .",
"pack:mac": "npm run clean:dist && electron-builder --mac --universal -p never",
"pack:mac:arm64": "npm run clean:dist && electron-builder --mac --arm64 -p never",
"pack:mac:mas": "npm run clean:dist && electron-builder --mac mas --universal -p never",
@@ -45,6 +46,7 @@
"pack:win:ci": "npm run clean:dist && electron-builder --win --x64 --arm64 --ia32 -p never",
"dist:dir": "npm run build && npm run pack:dir",
"dist:lin": "npm run build && npm run pack:lin",
"dist:lin:arm64": "npm run build && npm run pack:lin:arm64",
"dist:mac": "npm run build && npm run pack:mac",
"dist:mac:mas": "npm run build && npm run pack:mac:mas",
"dist:mac:masdev": "npm run build && npm run pack:mac:masdev",

View File

@@ -3,9 +3,10 @@ import { RouterModule, Routes } from "@angular/router";
import { canAccessMembersTab } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { SponsoredFamiliesComponent } from "../../../billing/settings/sponsored-families.component";
import { FreeBitwardenFamiliesComponent } from "../../../billing/members/free-bitwarden-families.component";
import { organizationPermissionsGuard } from "../guards/org-permissions.guard";
import { canAccessSponsoredFamilies } from "./../../../billing/guards/can-access-sponsored-families.guard";
import { MembersComponent } from "./members.component";
const routes: Routes = [
@@ -19,8 +20,8 @@ const routes: Routes = [
},
{
path: "sponsored-families",
component: SponsoredFamiliesComponent,
canActivate: [organizationPermissionsGuard(canAccessMembersTab)],
component: FreeBitwardenFamiliesComponent,
canActivate: [organizationPermissionsGuard(canAccessMembersTab), canAccessSponsoredFamilies],
data: {
titleId: "sponsoredFamilies",
},

View File

@@ -43,6 +43,8 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit, OnDestroy {
value.plan = PlanType.FamiliesAnnually;
value.productTier = ProductTierType.Families;
value.acceptingSponsorship = true;
value.planSponsorshipType = PlanSponsorshipType.FamiliesForEnterprise;
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
value.onSuccess.subscribe(this.onOrganizationCreateSuccess.bind(this));
}

View File

@@ -0,0 +1,26 @@
import { inject } from "@angular/core";
import { ActivatedRouteSnapshot, CanActivateFn } from "@angular/router";
import { firstValueFrom, switchMap, filter } 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 { getUserId } from "@bitwarden/common/auth/services/account.service";
import { getById } from "@bitwarden/common/platform/misc";
import { FreeFamiliesPolicyService } from "../services/free-families-policy.service";
export const canAccessSponsoredFamilies: CanActivateFn = async (route: ActivatedRouteSnapshot) => {
const freeFamiliesPolicyService = inject(FreeFamiliesPolicyService);
const organizationService = inject(OrganizationService);
const accountService = inject(AccountService);
const org = accountService.activeAccount$.pipe(
getUserId,
switchMap((userId) => organizationService.organizations$(userId)),
getById(route.params.organizationId),
filter((org): org is Organization => org !== undefined),
);
return await firstValueFrom(freeFamiliesPolicyService.showSponsoredFamiliesDropdown$(org));
};

View File

@@ -0,0 +1,45 @@
<form>
<bit-dialog>
<span bitDialogTitle>{{ "addSponsorship" | i18n }}</span>
<div bitDialogContent>
<form [formGroup]="sponsorshipForm">
<div class="tw-grid tw-grid-cols-12 tw-gap-4">
<div class="tw-col-span-12">
<bit-form-field>
<bit-label>{{ "email" | i18n }}:</bit-label>
<input
bitInput
inputmode="email"
formControlName="sponsorshipEmail"
[attr.aria-invalid]="sponsorshipEmailControl.invalid"
appInputStripSpaces
/>
</bit-form-field>
</div>
<div class="tw-col-span-12">
<bit-form-field>
<bit-label>{{ "notes" | i18n }}:</bit-label>
<input
bitInput
inputmode="text"
formControlName="sponsorshipNote"
[attr.aria-invalid]="sponsorshipNoteControl.invalid"
appInputStripSpaces
/>
</bit-form-field>
</div>
</div>
</form>
</div>
<ng-container bitDialogFooter>
<button bitButton bitFormButton type="button" buttonType="primary" (click)="save()">
{{ "save" | i18n }}
</button>
<button bitButton type="button" buttonType="secondary" [bitDialogClose]="false">
{{ "cancel" | i18n }}
</button>
</ng-container>
</bit-dialog>
</form>

View File

@@ -0,0 +1,135 @@
import { DialogRef } from "@angular/cdk/dialog";
import { Component } from "@angular/core";
import {
AbstractControl,
FormBuilder,
FormControl,
FormGroup,
FormsModule,
ReactiveFormsModule,
ValidationErrors,
Validators,
} from "@angular/forms";
import { firstValueFrom, map } from "rxjs";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { ButtonModule, DialogModule, DialogService, FormFieldModule } from "@bitwarden/components";
interface RequestSponsorshipForm {
sponsorshipEmail: FormControl<string | null>;
sponsorshipNote: FormControl<string | null>;
}
export interface AddSponsorshipDialogResult {
action: AddSponsorshipDialogAction;
value: Partial<AddSponsorshipFormValue> | null;
}
interface AddSponsorshipFormValue {
sponsorshipEmail: string;
sponsorshipNote: string;
status: string;
}
enum AddSponsorshipDialogAction {
Saved = "saved",
Canceled = "canceled",
}
@Component({
templateUrl: "add-sponsorship-dialog.component.html",
standalone: true,
imports: [
JslibModule,
ButtonModule,
DialogModule,
FormsModule,
ReactiveFormsModule,
FormFieldModule,
],
})
export class AddSponsorshipDialogComponent {
sponsorshipForm: FormGroup<RequestSponsorshipForm>;
loading = false;
constructor(
private dialogRef: DialogRef<AddSponsorshipDialogResult>,
private formBuilder: FormBuilder,
private accountService: AccountService,
private i18nService: I18nService,
) {
this.sponsorshipForm = this.formBuilder.group<RequestSponsorshipForm>({
sponsorshipEmail: new FormControl<string | null>("", {
validators: [Validators.email, Validators.required],
asyncValidators: [this.validateNotCurrentUserEmail.bind(this)],
updateOn: "change",
}),
sponsorshipNote: new FormControl<string | null>("", {}),
});
}
static open(dialogService: DialogService): DialogRef<AddSponsorshipDialogResult> {
return dialogService.open<AddSponsorshipDialogResult>(AddSponsorshipDialogComponent);
}
protected async save() {
if (this.sponsorshipForm.invalid) {
return;
}
this.loading = true;
// TODO: This is a mockup implementation - needs to be updated with actual API integration
await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulate API call
const formValue = this.sponsorshipForm.getRawValue();
const dialogValue: Partial<AddSponsorshipFormValue> = {
status: "Sent",
sponsorshipEmail: formValue.sponsorshipEmail ?? "",
sponsorshipNote: formValue.sponsorshipNote ?? "",
};
this.dialogRef.close({
action: AddSponsorshipDialogAction.Saved,
value: dialogValue,
});
this.loading = false;
}
protected close = () => {
this.dialogRef.close({ action: AddSponsorshipDialogAction.Canceled, value: null });
};
get sponsorshipEmailControl() {
return this.sponsorshipForm.controls.sponsorshipEmail;
}
get sponsorshipNoteControl() {
return this.sponsorshipForm.controls.sponsorshipNote;
}
private async validateNotCurrentUserEmail(
control: AbstractControl,
): Promise<ValidationErrors | null> {
const value = control.value;
if (!value) {
return null;
}
const currentUserEmail = await firstValueFrom(
this.accountService.activeAccount$.pipe(map((a) => a?.email ?? "")),
);
if (!currentUserEmail) {
return null;
}
if (value.toLowerCase() === currentUserEmail.toLowerCase()) {
return { currentUserEmail: true };
}
return null;
}
}

View File

@@ -0,0 +1,23 @@
<app-header>
<button type="button" (click)="addSponsorship()" bitButton buttonType="primary">
<i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i>
{{ "addSponsorship" | i18n }}
</button>
</app-header>
<bit-tab-group [(selectedIndex)]="tabIndex">
<bit-tab [label]="'sponsoredBitwardenFamilies' | i18n">
<app-organization-sponsored-families
[sponsoredFamilies]="sponsoredFamilies"
(removeSponsorshipEvent)="removeSponsorhip($event)"
></app-organization-sponsored-families>
</bit-tab>
<bit-tab [label]="'memberFamilies' | i18n">
<app-organization-member-families
[memberFamilies]="sponsoredFamilies"
></app-organization-member-families>
</bit-tab>
</bit-tab-group>
<p class="tw-px-4" bitTypography="body2">{{ "sponsoredFamiliesRemoveActiveSponsorship" | i18n }}</p>

View File

@@ -0,0 +1,62 @@
import { DialogRef } from "@angular/cdk/dialog";
import { Component, OnInit } from "@angular/core";
import { Router } from "@angular/router";
import { firstValueFrom } from "rxjs";
import { DialogService } from "@bitwarden/components";
import { FreeFamiliesPolicyService } from "../services/free-families-policy.service";
import {
AddSponsorshipDialogComponent,
AddSponsorshipDialogResult,
} from "./add-sponsorship-dialog.component";
import { SponsoredFamily } from "./types/sponsored-family";
@Component({
selector: "app-free-bitwarden-families",
templateUrl: "free-bitwarden-families.component.html",
})
export class FreeBitwardenFamiliesComponent implements OnInit {
tabIndex = 0;
sponsoredFamilies: SponsoredFamily[] = [];
constructor(
private router: Router,
private dialogService: DialogService,
private freeFamiliesPolicyService: FreeFamiliesPolicyService,
) {}
async ngOnInit() {
await this.preventAccessToFreeFamiliesPage();
}
async addSponsorship() {
const addSponsorshipDialogRef: DialogRef<AddSponsorshipDialogResult> =
AddSponsorshipDialogComponent.open(this.dialogService);
const dialogRef = await firstValueFrom(addSponsorshipDialogRef.closed);
if (dialogRef?.value) {
this.sponsoredFamilies = [dialogRef.value, ...this.sponsoredFamilies];
}
}
removeSponsorhip(sponsorship: any) {
const index = this.sponsoredFamilies.findIndex(
(e) => e.sponsorshipEmail == sponsorship.sponsorshipEmail,
);
this.sponsoredFamilies.splice(index, 1);
}
private async preventAccessToFreeFamiliesPage() {
const showFreeFamiliesPage = await firstValueFrom(
this.freeFamiliesPolicyService.showFreeFamilies$,
);
if (!showFreeFamiliesPage) {
await this.router.navigate(["/"]);
return;
}
}
}

View File

@@ -0,0 +1,47 @@
<bit-container>
<ng-container>
<p bitTypography="body1">
{{ "membersWithSponsoredFamilies" | i18n }}
</p>
<h2 bitTypography="h2" class="">{{ "memberFamilies" | i18n }}</h2>
@if (loading) {
<ng-container>
<i class="bwi bwi-spinner bwi-spin tw-text-muted" title="{{ 'loading' | i18n }}"></i>
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
</ng-container>
}
@if (!loading && memberFamilies?.length > 0) {
<ng-container>
<bit-table>
<ng-container header>
<tr>
<th bitCell>{{ "member" | i18n }}</th>
<th bitCell>{{ "status" | i18n }}</th>
<th bitCell></th>
</tr>
</ng-container>
<ng-template body alignContent="middle">
@for (o of memberFamilies; let i = $index; track i) {
<ng-container>
<tr bitRow>
<td bitCell>{{ o.sponsorshipEmail }}</td>
<td bitCell class="tw-text-success">{{ o.status }}</td>
</tr>
</ng-container>
}
</ng-template>
</bit-table>
<hr class="mt-0" />
</ng-container>
} @else {
<div class="tw-my-5 tw-py-5 tw-flex tw-flex-col tw-items-center">
<img class="tw-w-32" src="./../../../images/search.svg" alt="Search" />
<h4 class="mt-3" bitTypography="h4">{{ "noMemberFamilies" | i18n }}</h4>
<p bitTypography="body2">{{ "noMemberFamiliesDescription" | i18n }}</p>
</div>
}
</ng-container>
</bit-container>

View File

@@ -0,0 +1,34 @@
import { Component, Input, OnDestroy, OnInit } from "@angular/core";
import { Subject } from "rxjs";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { SponsoredFamily } from "./types/sponsored-family";
@Component({
selector: "app-organization-member-families",
templateUrl: "organization-member-families.component.html",
})
export class OrganizationMemberFamiliesComponent implements OnInit, OnDestroy {
tabIndex = 0;
loading = false;
@Input() memberFamilies: SponsoredFamily[] = [];
private _destroy = new Subject<void>();
constructor(private platformUtilsService: PlatformUtilsService) {}
async ngOnInit() {
this.loading = false;
}
ngOnDestroy(): void {
this._destroy.next();
this._destroy.complete();
}
get isSelfHosted(): boolean {
return this.platformUtilsService.isSelfHost();
}
}

View File

@@ -0,0 +1,87 @@
<bit-container>
<ng-container>
<p bitTypography="body1">
{{ "sponsorFreeBitwardenFamilies" | i18n }}
</p>
<div bitTypography="body1">
{{ "sponsoredFamiliesInclude" | i18n }}:
<ul class="tw-list-outside">
<li>{{ "sponsoredFamiliesPremiumAccess" | i18n }}</li>
<li>{{ "sponsoredFamiliesSharedCollections" | i18n }}</li>
</ul>
</div>
<h2 bitTypography="h2" class="">{{ "sponsoredBitwardenFamilies" | i18n }}</h2>
@if (loading) {
<ng-container>
<i class="bwi bwi-spinner bwi-spin tw-text-muted" title="{{ 'loading' | i18n }}"></i>
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
</ng-container>
}
@if (!loading && sponsoredFamilies?.length > 0) {
<ng-container>
<bit-table>
<ng-container header>
<tr>
<th bitCell>{{ "recipient" | i18n }}</th>
<th bitCell>{{ "status" | i18n }}</th>
<th bitCell>{{ "notes" | i18n }}</th>
<th bitCell></th>
</tr>
</ng-container>
<ng-template body alignContent="middle">
@for (o of sponsoredFamilies; let i = $index; track i) {
<ng-container>
<tr bitRow>
<td bitCell>{{ o.sponsorshipEmail }}</td>
<td bitCell class="tw-text-success">{{ o.status }}</td>
<td bitCell>{{ o.sponsorshipNote }}</td>
<td bitCell>
<button
type="button"
bitIconButton="bwi-ellipsis-v"
buttonType="main"
[bitMenuTriggerFor]="appListDropdown"
appA11yTitle="{{ 'options' | i18n }}"
></button>
<bit-menu #appListDropdown>
<button
type="button"
bitMenuItem
[attr.aria-label]="'resendEmailLabel' | i18n"
>
<i aria-hidden="true" class="bwi bwi-envelope"></i>
{{ "resendInvitation" | i18n }}
</button>
<hr class="m-0" />
<button
type="button"
bitMenuItem
[attr.aria-label]="'revokeAccount' | i18n"
(click)="remove(o)"
>
<i aria-hidden="true" class="bwi bwi-close tw-text-danger"></i>
<span class="tw-text-danger pl-1">{{ "remove" | i18n }}</span>
</button>
</bit-menu>
</td>
</tr>
</ng-container>
}
</ng-template>
</bit-table>
<hr class="mt-0" />
</ng-container>
} @else {
<div class="tw-my-5 tw-py-5 tw-flex tw-flex-col tw-items-center">
<img class="tw-w-32" src="./../../../images/search.svg" alt="Search" />
<h4 class="mt-3" bitTypography="h4">{{ "noSponsoredFamilies" | i18n }}</h4>
<p bitTypography="body2">{{ "noSponsoredFamiliesDescription" | i18n }}</p>
</div>
}
</ng-container>
</bit-container>

View File

@@ -0,0 +1,39 @@
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
import { Subject } from "rxjs";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { SponsoredFamily } from "./types/sponsored-family";
@Component({
selector: "app-organization-sponsored-families",
templateUrl: "organization-sponsored-families.component.html",
})
export class OrganizationSponsoredFamiliesComponent implements OnInit, OnDestroy {
loading = false;
tabIndex = 0;
@Input() sponsoredFamilies: SponsoredFamily[] = [];
@Output() removeSponsorshipEvent = new EventEmitter<SponsoredFamily>();
private _destroy = new Subject<void>();
constructor(private platformUtilsService: PlatformUtilsService) {}
async ngOnInit() {
this.loading = false;
}
get isSelfHosted(): boolean {
return this.platformUtilsService.isSelfHost();
}
remove(sponsorship: SponsoredFamily) {
this.removeSponsorshipEvent.emit(sponsorship);
}
ngOnDestroy(): void {
this._destroy.next();
this._destroy.complete();
}
}

View File

@@ -0,0 +1,5 @@
export interface SponsoredFamily {
sponsorshipEmail?: string;
sponsorshipNote?: string;
status?: string;
}

View File

@@ -34,7 +34,12 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
import { getUserId } from "@bitwarden/common/auth/services/account.service";
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions";
import { TaxServiceAbstraction } from "@bitwarden/common/billing/abstractions/tax.service.abstraction";
import { PaymentMethodType, PlanType, ProductTierType } from "@bitwarden/common/billing/enums";
import {
PaymentMethodType,
PlanSponsorshipType,
PlanType,
ProductTierType,
} from "@bitwarden/common/billing/enums";
import { TaxInformation } from "@bitwarden/common/billing/models/domain";
import { ExpandedTaxInfoUpdateRequest } from "@bitwarden/common/billing/models/request/expanded-tax-info-update.request";
import { PreviewOrganizationInvoiceRequest } from "@bitwarden/common/billing/models/request/preview-organization-invoice.request";
@@ -83,6 +88,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy {
@Input() showFree = true;
@Input() showCancel = false;
@Input() acceptingSponsorship = false;
@Input() planSponsorshipType?: PlanSponsorshipType;
@Input() currentPlan: PlanResponse;
selectedFile: File;
@@ -682,11 +688,6 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy {
}
private refreshSalesTax(): void {
if (this.formGroup.controls.plan.value == PlanType.Free) {
this.estimatedTax = 0;
return;
}
if (!this.taxComponent.validate()) {
return;
}
@@ -696,6 +697,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy {
passwordManager: {
additionalStorage: this.formGroup.controls.additionalStorage.value,
plan: this.formGroup.controls.plan.value,
sponsoredPlan: this.planSponsorshipType,
seats: this.formGroup.controls.additionalSeats.value,
},
taxInformation: {

View File

@@ -19,7 +19,13 @@ export class WebCommunicationProvider implements CommunicationBackend {
return;
}
await this.queue.enqueue({ ...message.message, source: "BrowserBackground" });
void this.queue.enqueue(
new IncomingMessage(
message.message.payload,
message.message.destination,
"BrowserBackground",
),
);
});
}

View File

@@ -62,6 +62,9 @@ import { OrganizationBadgeModule } from "../vault/individual-vault/organization-
import { PipesModule } from "../vault/individual-vault/pipes/pipes.module";
import { PurgeVaultComponent } from "../vault/settings/purge-vault.component";
import { FreeBitwardenFamiliesComponent } from "./../billing/members/free-bitwarden-families.component";
import { OrganizationMemberFamiliesComponent } from "./../billing/members/organization-member-families.component";
import { OrganizationSponsoredFamiliesComponent } from "./../billing/members/organization-sponsored-families.component";
import { EnvironmentSelectorModule } from "./../components/environment-selector/environment-selector.module";
import { AccountFingerprintComponent } from "./components/account-fingerprint/account-fingerprint.component";
import { SharedModule } from "./shared.module";
@@ -128,6 +131,9 @@ import { SharedModule } from "./shared.module";
SelectableAvatarComponent,
SetPasswordComponent,
SponsoredFamiliesComponent,
OrganizationSponsoredFamiliesComponent,
OrganizationMemberFamiliesComponent,
FreeBitwardenFamiliesComponent,
SponsoringOrgRowComponent,
UpdatePasswordComponent,
UpdateTempPasswordComponent,
@@ -175,6 +181,9 @@ import { SharedModule } from "./shared.module";
SelectableAvatarComponent,
SetPasswordComponent,
SponsoredFamiliesComponent,
OrganizationSponsoredFamiliesComponent,
OrganizationMemberFamiliesComponent,
FreeBitwardenFamiliesComponent,
SponsoringOrgRowComponent,
UpdateTempPasswordComponent,
UpdatePasswordComponent,

View File

@@ -7,7 +7,7 @@
<bit-label>{{ "username" | i18n }}</bit-label>
<input id="username" type="text" formControlName="username" bitInput />
</bit-form-field>
<small class="form-text text-muted tw-mb-4">{{ "breachCheckUsernameEmail" | i18n }}</small>
<small class="tw-mb-4 tw-block tw-text-muted">{{ "breachCheckUsernameEmail" | i18n }}</small>
<button type="submit" buttonType="primary" bitButton [loading]="loading">
{{ "checkBreaches" | i18n }}
</button>
@@ -21,32 +21,33 @@
<bit-callout type="danger" title="{{ 'breachFound' | i18n }}" *ngIf="breachedAccounts.length">
{{ "breachUsernameFound" | i18n: checkedUsername : breachedAccounts.length }}
</bit-callout>
<ul class="list-group list-group-breach" *ngIf="breachedAccounts.length">
<li *ngFor="let a of breachedAccounts" class="list-group-item min-height-fix">
<div class="row">
<div class="col-2 tw-text-center">
<img [src]="a.logoPath" alt="" class="img-fluid" />
</div>
<div class="col-7">
<h3 class="tw-text-lg">{{ a.title }}</h3>
<p [innerHTML]="a.description"></p>
<p class="tw-mb-1">{{ "compromisedData" | i18n }}:</p>
<ul>
<li *ngFor="let d of a.dataClasses">{{ d }}</li>
</ul>
</div>
<div class="col-3">
<dl>
<dt>{{ "website" | i18n }}</dt>
<dd>{{ a.domain }}</dd>
<dt>{{ "affectedUsers" | i18n }}</dt>
<dd>{{ a.pwnCount | number }}</dd>
<dt>{{ "breachOccurred" | i18n }}</dt>
<dd>{{ a.breachDate | date: "mediumDate" }}</dd>
<dt>{{ "breachReported" | i18n }}</dt>
<dd>{{ a.addedDate | date: "mediumDate" }}</dd>
</dl>
</div>
<ul
class="tw-list-none tw-flex-col tw-divide-x-0 tw-divide-y tw-divide-solid tw-divide-secondary-300 tw-rounded tw-border tw-border-solid tw-border-secondary-300 tw-p-0"
*ngIf="breachedAccounts.length"
>
<li *ngFor="let a of breachedAccounts" class="tw-flex tw-gap-4 tw-p-4">
<div class="tw-w-32 tw-flex-none">
<img [src]="a.logoPath" alt="" class="tw-max-w-32 tw-items-stretch" />
</div>
<div class="tw-flex-auto">
<h3 class="tw-text-lg">{{ a.title }}</h3>
<p [innerHTML]="a.description"></p>
<p class="tw-mb-1">{{ "compromisedData" | i18n }}:</p>
<ul>
<li *ngFor="let d of a.dataClasses">{{ d }}</li>
</ul>
</div>
<div class="tw-w-48 tw-flex-none">
<dl>
<dt>{{ "website" | i18n }}</dt>
<dd>{{ a.domain }}</dd>
<dt>{{ "affectedUsers" | i18n }}</dt>
<dd>{{ a.pwnCount | number }}</dd>
<dt>{{ "breachOccurred" | i18n }}</dt>
<dd>{{ a.breachDate | date: "mediumDate" }}</dd>
<dt>{{ "breachReported" | i18n }}</dt>
<dd>{{ a.addedDate | date: "mediumDate" }}</dd>
</dl>
</div>
</li>
</ul>

View File

@@ -0,0 +1,12 @@
<svg width="97" height="97" viewBox="0 0 97 97" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M62.5 12.4604C63.6046 12.4604 64.5 13.3559 64.5 14.4604L64.5 90.4604C64.5 91.565 63.6046 92.4604 62.5 92.4604L6.5 92.4604C5.39543 92.4604 4.5 91.565 4.5 90.4604L4.5 14.4604C4.5 13.3559 5.39544 12.4604 6.5 12.4604L62.5 12.4604Z" fill="#99BAF4"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M62.5 90.4604L62.5 14.4604L6.5 14.4604L6.5 90.4604L62.5 90.4604ZM64.5 14.4604C64.5 13.3559 63.6046 12.4604 62.5 12.4604L6.5 12.4604C5.39544 12.4604 4.5 13.3559 4.5 14.4604L4.5 90.4604C4.5 91.565 5.39543 92.4604 6.5 92.4604L62.5 92.4604C63.6046 92.4604 64.5 91.565 64.5 90.4604L64.5 14.4604Z" fill="#0E3781"/>
<path d="M72.5 82.4604L72.5 6.46045C72.5 5.35588 71.6046 4.46045 70.5 4.46045L27.8284 4.46045C27.298 4.46045 26.7939 4.66655 26.4188 5.04162L13.0835 18.3769C12.7085 18.752 12.5 19.2584 12.5 19.7889L12.5 82.4604C12.5 83.565 13.3954 84.4604 14.5 84.4604L70.5 84.4604C71.6046 84.4604 72.5 83.565 72.5 82.4604Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M70.5 82.4604L70.5 6.46045L27.8284 6.46045L14.5 19.7889L14.5 82.4604L70.5 82.4604ZM27.833 6.45583C27.833 6.45583 27.8329 6.45595 27.8327 6.45617L27.833 6.45583ZM72.5 6.46045L72.5 82.4604C72.5 83.565 71.6046 84.4604 70.5 84.4604L14.5 84.4604C13.3954 84.4604 12.5 83.565 12.5 82.4604L12.5 19.7889C12.5 19.2584 12.7085 18.752 13.0835 18.3769L26.4188 5.04162C26.7939 4.66655 27.298 4.46045 27.8284 4.46045L70.5 4.46045C71.6046 4.46045 72.5 5.35588 72.5 6.46045Z" fill="#0E3781"/>
<path d="M84.5 48.4604C84.5 59.5061 75.5457 68.4604 64.5 68.4604C53.4543 68.4604 44.5 59.5061 44.5 48.4604C44.5 37.4148 53.4543 28.4604 64.5 28.4604C75.5457 28.4604 84.5 37.4148 84.5 48.4604Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M64.5 66.4604C74.4411 66.4604 82.5 58.4016 82.5 48.4604C82.5 38.5193 74.4411 30.4604 64.5 30.4604C54.5589 30.4604 46.5 38.5193 46.5 48.4604C46.5 58.4016 54.5589 66.4604 64.5 66.4604ZM64.5 68.4604C75.5457 68.4604 84.5 59.5061 84.5 48.4604C84.5 37.4148 75.5457 28.4604 64.5 28.4604C53.4543 28.4604 44.5 37.4148 44.5 48.4604C44.5 59.5061 53.4543 68.4604 64.5 68.4604Z" fill="#0E3781"/>
<path d="M79.5 48.4604C79.5 56.7447 72.7843 63.4604 64.5 63.4604C56.2157 63.4604 49.5 56.7447 49.5 48.4604C49.5 40.1762 56.2157 33.4604 64.5 33.4604C72.7843 33.4604 79.5 40.1762 79.5 48.4604Z" fill="#99BAF4"/>
<path d="M95.5038 77.5474L79 61.9604L77 63.9604L92.587 80.4643C93.3607 81.2836 94.6583 81.3021 95.4552 80.5053L95.5448 80.4156C96.3417 79.6188 96.3231 78.3212 95.5038 77.5474Z" fill="#0E3781"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M28.5 5.46045C29.0523 5.46045 29.5 5.90816 29.5 6.46045V21.4604H14.5C13.9477 21.4604 13.5 21.0127 13.5 20.4604C13.5 19.9082 13.9477 19.4604 14.5 19.4604H27.5V6.46045C27.5 5.90816 27.9477 5.46045 28.5 5.46045Z" fill="#0E3781"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.5 28.4604C19.9477 28.4604 19.5 28.9082 19.5 29.4604C19.5 30.0127 19.9477 30.4604 20.5 30.4604H30.5C31.0523 30.4604 31.5 30.0127 31.5 29.4604C31.5 28.9082 31.0523 28.4604 30.5 28.4604H20.5ZM34.5 28.4604C33.9477 28.4604 33.5 28.9082 33.5 29.4604C33.5 30.0127 33.9477 30.4604 34.5 30.4604H44.5C45.0523 30.4604 45.5 30.0127 45.5 29.4604C45.5 28.9082 45.0523 28.4604 44.5 28.4604H34.5ZM51.483 33.2759C51.3964 32.8118 50.9892 32.4604 50.5 32.4604H40.5C39.9477 32.4604 39.5 32.9082 39.5 33.4604C39.5 34.0127 39.9477 34.4604 40.5 34.4604H50.2171C50.6218 34.0477 51.0441 33.6524 51.483 33.2759ZM44.5246 49.4604C44.5579 50.1365 44.6247 50.8037 44.7235 51.4604H40.5C39.9477 51.4604 39.5 51.0127 39.5 50.4604C39.5 49.9082 39.9477 49.4604 40.5 49.4604H44.5246ZM44.7235 45.4605C44.6247 46.1172 44.5579 46.7844 44.5246 47.4605L37.5 47.4604C36.9477 47.4604 36.5 47.0127 36.5 46.4604C36.5 45.9082 36.9477 45.4604 37.5 45.4604L44.7235 45.4605ZM48.4985 36.4604C48.0192 37.0986 47.5772 37.7663 47.1756 38.4604L38.5 38.4604C37.9477 38.4604 37.5 38.0127 37.5 37.4604C37.5 36.9082 37.9477 36.4604 38.5 36.4604L48.4985 36.4604ZM64.5 28.4604C61.3707 28.4604 58.4093 29.1791 55.7717 30.4604L54.5 30.4604C53.9477 30.4604 53.5 30.0127 53.5 29.4604C53.5 28.9082 53.9477 28.4604 54.5 28.4604H64.5ZM48.5 28.4604C47.9477 28.4604 47.5 28.9082 47.5 29.4604C47.5 30.0127 47.9477 30.4604 48.5 30.4604H50.5C51.0523 30.4604 51.5 30.0127 51.5 29.4604C51.5 28.9082 51.0523 28.4604 50.5 28.4604H48.5ZM37.5 33.4604C37.5 32.9082 37.0523 32.4604 36.5 32.4604H34.5C33.9477 32.4604 33.5 32.9082 33.5 33.4604C33.5 34.0127 33.9477 34.4604 34.5 34.4604H36.5C37.0523 34.4604 37.5 34.0127 37.5 33.4604ZM34.5 38.4604C35.0523 38.4604 35.5 38.0127 35.5 37.4604C35.5 36.9082 35.0523 36.4604 34.5 36.4604H30.5C29.9477 36.4604 29.5 36.9082 29.5 37.4604C29.5 38.0127 29.9477 38.4604 30.5 38.4604H34.5ZM34.5 46.4604C34.5 47.0127 34.0523 47.4604 33.5 47.4604H27.5C26.9477 47.4604 26.5 47.0127 26.5 46.4604C26.5 45.9082 26.9477 45.4604 27.5 45.4604H33.5C34.0523 45.4604 34.5 45.9082 34.5 46.4604ZM36.5 51.4604C37.0523 51.4604 37.5 51.0127 37.5 50.4604C37.5 49.9082 37.0523 49.4604 36.5 49.4604H20.5C19.9477 49.4604 19.5 49.9082 19.5 50.4604C19.5 51.0127 19.9477 51.4604 20.5 51.4604H36.5ZM31.5 33.4604C31.5 32.9082 31.0523 32.4604 30.5 32.4604L20.5 32.4605C19.9477 32.4605 19.5 32.9082 19.5 33.4605C19.5 34.0127 19.9477 34.4605 20.5 34.4605L30.5 34.4604C31.0523 34.4604 31.5 34.0127 31.5 33.4604ZM26.5 38.4604C27.0523 38.4604 27.5 38.0127 27.5 37.4604C27.5 36.9082 27.0523 36.4604 26.5 36.4604H20.5C19.9477 36.4604 19.5 36.9082 19.5 37.4604C19.5 38.0127 19.9477 38.4604 20.5 38.4604H26.5ZM24.5 46.4604C24.5 47.0127 24.0523 47.4604 23.5 47.4604H20.5C19.9477 47.4604 19.5 47.0127 19.5 46.4604C19.5 45.9082 19.9477 45.4604 20.5 45.4604H23.5C24.0523 45.4604 24.5 45.9082 24.5 46.4604Z" fill="#FFBF00"/>
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -6306,6 +6306,21 @@
"sponsoredFamilies": {
"message": "Free Bitwarden Families"
},
"sponsoredBitwardenFamilies": {
"message": "Sponsored families"
},
"noSponsoredFamilies": {
"message": "No sponsored families"
},
"noSponsoredFamiliesDescription": {
"message": "Sponsored non-member families plans will display here"
},
"sponsorFreeBitwardenFamilies": {
"message": "Members of your organization are eligible for Free Bitwarden Families. You can sponsor Free Bitwarden Families for employees who are not a member of your Bitwarden organization. Sponsoring a non-member requires an available seat within your organization."
},
"sponsoredFamiliesRemoveActiveSponsorship": {
"message": "When you remove an active sponsorship, a seat within your organization will be available after the renewal date of the sponsored organization."
},
"sponsoredFamiliesEligible": {
"message": "You and your family are eligible for Free Bitwarden Families. Redeem with your personal email to keep your data secure even when you are not at work."
},
@@ -6321,6 +6336,18 @@
"sponsoredFamiliesSharedCollections": {
"message": "Shared collections for Family secrets"
},
"memberFamilies": {
"message": "Member families"
},
"noMemberFamilies": {
"message": "No member families"
},
"noMemberFamiliesDescription": {
"message": "Members who have redeemed family plans will display here"
},
"membersWithSponsoredFamilies": {
"message": "Members of your organization are eligible for Free Bitwarden Families. Here you can see members who have sponsored a Families organization."
},
"badToken": {
"message": "The link is no longer valid. Please have the sponsor resend the offer."
},
@@ -7984,6 +8011,9 @@
"inviteMember": {
"message": "Invite member"
},
"addSponsorship": {
"message": "Add sponsorship"
},
"needsConfirmation": {
"message": "Needs confirmation"
},

View File

@@ -536,6 +536,10 @@ export class LoginComponent implements OnInit, OnDestroy {
if (storedEmail) {
this.formGroup.controls.email.setValue(storedEmail);
this.formGroup.controls.rememberEmail.setValue(true);
// If we load an email into the form, we need to initialize it for the login process as well
// so that other login components can use it.
// We do this here as it's possible that a user doesn't edit the email field before submitting.
this.loginEmailService.setLoginEmail(storedEmail);
} else {
this.formGroup.controls.rememberEmail.setValue(false);
}

View File

@@ -6,4 +6,5 @@ export class OrganizationSponsorshipCreateRequest {
sponsoredEmail: string;
planSponsorshipType: PlanSponsorshipType;
friendlyName: string;
notes?: string;
}

View File

@@ -1,4 +1,4 @@
import { PlanType } from "../../enums";
import { PlanSponsorshipType, PlanType } from "../../enums";
export class PreviewOrganizationInvoiceRequest {
organizationId?: string;
@@ -21,6 +21,7 @@ export class PreviewOrganizationInvoiceRequest {
class PasswordManager {
plan: PlanType;
sponsoredPlan?: PlanSponsorshipType;
seats: number;
additionalStorage: number;

View File

@@ -46,7 +46,6 @@ export enum FeatureFlag {
CriticalApps = "pm-14466-risk-insights-critical-application",
EnableRiskInsightsNotifications = "enable-risk-insights-notifications",
DesktopSendUIRefresh = "desktop-send-ui-refresh",
ExportAttachments = "export-attachments",
/* Vault */
PM8851_BrowserOnboardingNudge = "pm-8851-browser-onboarding-nudge",
@@ -98,7 +97,6 @@ export const DefaultFeatureFlagValue = {
[FeatureFlag.CriticalApps]: FALSE,
[FeatureFlag.EnableRiskInsightsNotifications]: FALSE,
[FeatureFlag.DesktopSendUIRefresh]: FALSE,
[FeatureFlag.ExportAttachments]: FALSE,
/* Vault */
[FeatureFlag.PM8851_BrowserOnboardingNudge]: FALSE,

View File

@@ -39,8 +39,6 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { getUserId } from "@bitwarden/common/auth/services/account.service";
import { EventType } from "@bitwarden/common/enums";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@@ -184,10 +182,6 @@ export class ExportComponent implements OnInit, OnDestroy, AfterViewInit {
private onlyManagedCollections = true;
private onGenerate$ = new Subject<GenerateRequest>();
private isExportAttachmentsEnabled$ = this.configService.getFeatureFlag$(
FeatureFlag.ExportAttachments,
);
constructor(
protected i18nService: I18nService,
protected toastService: ToastService,
@@ -202,7 +196,6 @@ export class ExportComponent implements OnInit, OnDestroy, AfterViewInit {
protected organizationService: OrganizationService,
private accountService: AccountService,
private collectionService: CollectionService,
private configService: ConfigService,
) {}
async ngOnInit() {
@@ -225,17 +218,14 @@ export class ExportComponent implements OnInit, OnDestroy, AfterViewInit {
),
);
combineLatest([
this.exportForm.controls.vaultSelector.valueChanges,
this.isExportAttachmentsEnabled$,
])
this.exportForm.controls.vaultSelector.valueChanges
.pipe(takeUntil(this.destroy$))
.subscribe(([value, isExportAttachmentsEnabled]) => {
.subscribe(([value]) => {
this.organizationId = value !== "myVault" ? value : undefined;
this.formatOptions = this.formatOptions.filter((option) => option.value !== "zip");
this.exportForm.get("format").setValue("json");
if (value === "myVault" && isExportAttachmentsEnabled) {
if (value === "myVault") {
this.formatOptions.push({ name: ".zip (with attachments)", value: "zip" });
}
});

View File

@@ -1,6 +1,7 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { importProvidersFrom, signal } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { action } from "@storybook/addon-actions";
import {
applicationConfig,
@@ -225,6 +226,14 @@ export default {
getFeatureFlag: () => Promise.resolve(false),
},
},
{
provide: ActivatedRoute,
useValue: {
snapshot: {
queryParams: {},
},
},
},
],
}),
componentWrapperDecorator(

View File

@@ -83,4 +83,24 @@ describe("AddEditCustomFieldDialogComponent", () => {
expect.objectContaining({ value: FieldType.Linked }),
);
});
it("does not filter out 'Hidden' field type when 'disallowHiddenField' is false", () => {
dialogData.disallowHiddenField = false;
fixture = TestBed.createComponent(AddEditCustomFieldDialogComponent);
component = fixture.componentInstance;
expect(component.fieldTypeOptions).toContainEqual(
expect.objectContaining({ value: FieldType.Hidden }),
);
});
it("filers out 'Hidden' field type when 'disallowHiddenField' is true", () => {
dialogData.disallowHiddenField = true;
fixture = TestBed.createComponent(AddEditCustomFieldDialogComponent);
component = fixture.componentInstance;
expect(component.fieldTypeOptions).not.toContainEqual(
expect.objectContaining({ value: FieldType.Hidden }),
);
});
});

View File

@@ -25,6 +25,7 @@ export type AddEditCustomFieldDialogData = {
cipherType: CipherType;
/** When provided, dialog will display edit label variants */
editLabelConfig?: { index: number; label: string };
disallowHiddenField?: boolean;
};
@Component({
@@ -68,6 +69,9 @@ export class AddEditCustomFieldDialogComponent {
this.variant = data.editLabelConfig ? "edit" : "add";
this.fieldTypeOptions = this.fieldTypeOptions.filter((option) => {
if (this.data.disallowHiddenField && option.value === FieldType.Hidden) {
return false;
}
// Filter out the Linked field type for Secure Notes
if (this.data.cipherType === CipherType.SecureNote) {
return option.value !== FieldType.Linked;

View File

@@ -89,7 +89,7 @@
bitIconButton="bwi-pencil-square"
class="tw-self-center tw-mt-2"
data-testid="edit-custom-field-button"
*ngIf="!isPartialEdit"
*ngIf="canEdit(field.value.type)"
></button>
<button
@@ -100,7 +100,7 @@
[appA11yTitle]="'reorderToggleButton' | i18n: field.value.name"
(keydown)="handleKeyDown($event, field.value.name, i)"
data-testid="reorder-toggle-button"
*ngIf="!isPartialEdit"
*ngIf="canEdit(field.value.type)"
></button>
</div>

View File

@@ -45,7 +45,9 @@ describe("CustomFieldsComponent", () => {
announce = jest.fn().mockResolvedValue(null);
patchCipher = jest.fn();
originalCipherView = new CipherView();
config = {} as CipherFormConfig;
config = {
collections: [],
} as CipherFormConfig;
await TestBed.configureTestingModule({
imports: [CustomFieldsComponent],
@@ -463,5 +465,91 @@ describe("CustomFieldsComponent", () => {
// "reorder boolean label to position 4 of 4"
expect(announce).toHaveBeenCalledWith("reorderFieldDown boolean label 4 4", "assertive");
});
it("hides reorder buttons when in partial edit mode", () => {
originalCipherView.fields = mockFieldViews;
config.mode = "partial-edit";
component.ngOnInit();
fixture.detectChanges();
toggleItems = fixture.debugElement.queryAll(
By.css('button[data-testid="reorder-toggle-button"]'),
);
expect(toggleItems).toHaveLength(0);
});
});
it("shows all reorders button when in edit mode and viewPassword is true", () => {
originalCipherView.fields = mockFieldViews;
originalCipherView.viewPassword = true;
config.mode = "edit";
component.ngOnInit();
fixture.detectChanges();
const toggleItems = fixture.debugElement.queryAll(
By.css('button[data-testid="reorder-toggle-button"]'),
);
expect(toggleItems).toHaveLength(4);
});
it("shows all reorder buttons except for hidden fields when in edit mode and viewPassword is false", () => {
originalCipherView.fields = mockFieldViews;
originalCipherView.viewPassword = false;
config.mode = "edit";
component.ngOnInit();
fixture.detectChanges();
const toggleItems = fixture.debugElement.queryAll(
By.css('button[data-testid="reorder-toggle-button"]'),
);
expect(toggleItems).toHaveLength(3);
});
describe("edit button", () => {
it("hides the edit button when in partial-edit mode", () => {
originalCipherView.fields = mockFieldViews;
config.mode = "partial-edit";
component.ngOnInit();
fixture.detectChanges();
const editButtons = fixture.debugElement.queryAll(
By.css('button[data-testid="edit-custom-field-button"]'),
);
expect(editButtons).toHaveLength(0);
});
it("shows all the edit buttons when in edit mode and viewPassword is true", () => {
originalCipherView.fields = mockFieldViews;
originalCipherView.viewPassword = true;
config.mode = "edit";
component.ngOnInit();
fixture.detectChanges();
const editButtons = fixture.debugElement.queryAll(
By.css('button[data-testid="edit-custom-field-button"]'),
);
expect(editButtons).toHaveLength(4);
});
it("shows all the edit buttons except for hidden fields when in edit mode and viewPassword is false", () => {
originalCipherView.fields = mockFieldViews;
originalCipherView.viewPassword = false;
config.mode = "edit";
component.ngOnInit();
fixture.detectChanges();
const editButtons = fixture.debugElement.queryAll(
By.css('button[data-testid="edit-custom-field-button"]'),
);
expect(editButtons).toHaveLength(3);
});
});
});

View File

@@ -116,6 +116,8 @@ export class CustomFieldsComponent implements OnInit, AfterViewInit {
/** Emits when a new custom field should be focused */
private focusOnNewInput$ = new Subject<void>();
disallowHiddenField?: boolean;
destroyed$: DestroyRef;
FieldType = FieldType;
@@ -141,6 +143,13 @@ export class CustomFieldsComponent implements OnInit, AfterViewInit {
return this.customFieldsForm.controls.fields as FormArray;
}
canEdit(type: FieldType): boolean {
return (
!this.isPartialEdit &&
(type !== FieldType.Hidden || this.cipherFormContainer.originalCipherView?.viewPassword)
);
}
ngOnInit() {
const linkedFieldsOptionsForCipher = this.getLinkedFieldsOptionsForCipher();
const optionsArray = Array.from(linkedFieldsOptionsForCipher?.entries() ?? []);
@@ -210,6 +219,7 @@ export class CustomFieldsComponent implements OnInit, AfterViewInit {
/** Opens the add/edit custom field dialog */
openAddEditCustomFieldDialog(editLabelConfig?: AddEditCustomFieldDialogData["editLabelConfig"]) {
const { cipherType, mode, originalCipher } = this.cipherFormContainer.config;
this.dialogRef = this.dialogService.open<unknown, AddEditCustomFieldDialogData>(
AddEditCustomFieldDialogComponent,
{
@@ -217,8 +227,9 @@ export class CustomFieldsComponent implements OnInit, AfterViewInit {
addField: this.addField.bind(this),
updateLabel: this.updateLabel.bind(this),
removeField: this.removeField.bind(this),
cipherType: this.cipherFormContainer.config.cipherType,
cipherType,
editLabelConfig,
disallowHiddenField: mode === "edit" && !originalCipher.viewPassword,
},
},
);

View File

@@ -2,10 +2,10 @@ import { svgIcon } from "@bitwarden/components";
export const LoginCards = svgIcon`
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="150" fill="none">
<path class="tw-fill-background-alt4" fill-rule="evenodd" d="M134.152 32.493c0-.69.559-1.25 1.25-1.25h1.493a8.707 8.707 0 0 1 8.707 8.707v79.047a8.707 8.707 0 0 1-8.707 8.707H22.054c-4.81 0-8.707-3.906-8.707-8.713a1.25 1.25 0 1 1 2.5 0 6.212 6.212 0 0 0 6.207 6.213h114.841a6.207 6.207 0 0 0 6.207-6.207V39.95a6.207 6.207 0 0 0-6.207-6.207h-1.493a1.25 1.25 0 0 1-1.25-1.25Z" clip-rule="evenodd"/>
<path class="tw-fill-background-alt4" fill-rule="evenodd" d="M13.105 24.795a6.207 6.207 0 0 0-6.207 6.207v80.538a6.207 6.207 0 0 0 6.207 6.207h114.841a6.207 6.207 0 0 0 6.208-6.207V31.002a6.207 6.207 0 0 0-6.208-6.207H13.106Zm-8.707 6.207a8.707 8.707 0 0 1 8.707-8.707h114.841a8.708 8.708 0 0 1 8.708 8.707v80.538a8.708 8.708 0 0 1-8.708 8.707H13.106a8.707 8.707 0 0 1-8.708-8.707V31.002Z" clip-rule="evenodd"/>
<path class="tw-fill-background-alt4" fill-rule="evenodd" d="M120.964 75.915H20.766c-.819 0-1.483.664-1.483 1.483v8.949c0 .819.664 1.483 1.483 1.483h100.198c.819 0 1.483-.664 1.483-1.483v-8.95c0-.818-.664-1.482-1.483-1.482Zm-100.198-1.5a2.983 2.983 0 0 0-2.983 2.983v8.949a2.983 2.983 0 0 0 2.983 2.983h100.198a2.983 2.983 0 0 0 2.983-2.983v-8.95a2.983 2.983 0 0 0-2.983-2.982H20.766ZM120.964 96.794H20.766c-.819 0-1.483.664-1.483 1.483v8.948c0 .819.664 1.483 1.483 1.483h100.198c.819 0 1.483-.664 1.483-1.483v-8.948c0-.82-.664-1.483-1.483-1.483Zm-100.198-1.5a2.983 2.983 0 0 0-2.983 2.983v8.948a2.983 2.983 0 0 0 2.983 2.983h100.198a2.983 2.983 0 0 0 2.983-2.983v-8.948a2.983 2.983 0 0 0-2.983-2.983H20.766Z" clip-rule="evenodd"/>
<path class="tw-fill-art-primary" fill-rule="evenodd" d="M134.152 32.493c0-.69.559-1.25 1.25-1.25h1.493a8.707 8.707 0 0 1 8.707 8.707v79.047a8.707 8.707 0 0 1-8.707 8.707H22.054c-4.81 0-8.707-3.906-8.707-8.713a1.25 1.25 0 1 1 2.5 0 6.212 6.212 0 0 0 6.207 6.213h114.841a6.207 6.207 0 0 0 6.207-6.207V39.95a6.207 6.207 0 0 0-6.207-6.207h-1.493a1.25 1.25 0 0 1-1.25-1.25Z" clip-rule="evenodd"/>
<path class="tw-fill-art-primary" fill-rule="evenodd" d="M13.105 24.795a6.207 6.207 0 0 0-6.207 6.207v80.538a6.207 6.207 0 0 0 6.207 6.207h114.841a6.207 6.207 0 0 0 6.208-6.207V31.002a6.207 6.207 0 0 0-6.208-6.207H13.106Zm-8.707 6.207a8.707 8.707 0 0 1 8.707-8.707h114.841a8.708 8.708 0 0 1 8.708 8.707v80.538a8.708 8.708 0 0 1-8.708 8.707H13.106a8.707 8.707 0 0 1-8.708-8.707V31.002Z" clip-rule="evenodd"/>
<path class="tw-fill-art-primary" fill-rule="evenodd" d="M120.964 75.915H20.766c-.819 0-1.483.664-1.483 1.483v8.949c0 .819.664 1.483 1.483 1.483h100.198c.819 0 1.483-.664 1.483-1.483v-8.95c0-.818-.664-1.482-1.483-1.482Zm-100.198-1.5a2.983 2.983 0 0 0-2.983 2.983v8.949a2.983 2.983 0 0 0 2.983 2.983h100.198a2.983 2.983 0 0 0 2.983-2.983v-8.95a2.983 2.983 0 0 0-2.983-2.982H20.766ZM120.964 96.794H20.766c-.819 0-1.483.664-1.483 1.483v8.948c0 .819.664 1.483 1.483 1.483h100.198c.819 0 1.483-.664 1.483-1.483v-8.948c0-.82-.664-1.483-1.483-1.483Zm-100.198-1.5a2.983 2.983 0 0 0-2.983 2.983v8.948a2.983 2.983 0 0 0 2.983 2.983h100.198a2.983 2.983 0 0 0 2.983-2.983v-8.948a2.983 2.983 0 0 0-2.983-2.983H20.766Z" clip-rule="evenodd"/>
<path class="tw-fill-art-accent" fill-rule="evenodd" d="M22.795 81.712a.75.75 0 0 1 .75-.75H87.68a.75.75 0 0 1 0 1.5H23.545a.75.75 0 0 1-.75-.75ZM26.618 100.354a.75.75 0 0 0-1.5 0v1.426l-1.34-.439a.75.75 0 0 0-.466 1.426l1.353.443-.845 1.183a.75.75 0 0 0 1.221.872l.827-1.158.827 1.158a.75.75 0 0 0 1.22-.872l-.845-1.183 1.353-.443a.75.75 0 0 0-.466-1.426l-1.34.439v-1.426Zm9.584 0a.75.75 0 0 0-1.5 0v1.426l-1.339-.439a.75.75 0 0 0-.466 1.426l1.353.443-.845 1.183a.75.75 0 0 0 1.22.872l.827-1.158.827 1.158a.75.75 0 0 0 1.22-.872l-.844-1.183 1.353-.443a.75.75 0 0 0-.467-1.426l-1.339.439v-1.426Zm8.834-.75a.75.75 0 0 1 .75.75v1.426l1.339-.439a.75.75 0 0 1 .467 1.426l-1.353.443.845 1.183a.75.75 0 0 1-1.22.872l-.828-1.159-.827 1.159a.75.75 0 1 1-1.22-.872l.844-1.183-1.353-.443a.75.75 0 0 1 .467-1.426l1.339.439v-1.426a.75.75 0 0 1 .75-.75Zm10.334.75a.75.75 0 0 0-1.5 0v1.426l-1.339-.439a.75.75 0 0 0-.466 1.426l1.353.443-.845 1.183a.75.75 0 1 0 1.22.872l.828-1.159.827 1.159a.75.75 0 0 0 1.22-.872l-.845-1.183 1.353-.443a.75.75 0 0 0-.467-1.426l-1.339.439v-1.426Zm8.835-.75a.75.75 0 0 1 .75.75v1.426l1.338-.439a.75.75 0 0 1 .467 1.426l-1.352.443.845 1.183a.75.75 0 0 1-1.221.872l-.827-1.159-.828 1.159a.75.75 0 0 1-1.22-.872L63 103.21l-1.353-.443a.75.75 0 0 1 .467-1.426l1.34.439v-1.426a.75.75 0 0 1 .75-.75Zm10.334.75a.75.75 0 0 0-1.5 0v1.426l-1.34-.439a.75.75 0 0 0-.466 1.426l1.353.443-.845 1.183a.75.75 0 1 0 1.221.872l.827-1.158.827 1.158a.75.75 0 0 0 1.22-.872l-.844-1.183 1.352-.443a.75.75 0 0 0-.466-1.426l-1.34.439v-1.426ZM53.215 50.395c0-9.566 7.755-17.314 17.313-17.314 9.56 0 17.308 7.749 17.314 17.313 0 5.31-2.399 10.061-6.16 13.236l-.742.626-.418-.876c-1.785-3.736-5.584-6.324-9.994-6.324s-8.214 2.583-9.992 6.323l-.418.878-.743-.627c-3.761-3.175-6.16-7.92-6.16-13.236Zm13.8 5.66a12.594 12.594 0 0 0-7.373 5.801 15.759 15.759 0 0 1-4.927-11.462c0-8.736 7.083-15.813 15.813-15.813s15.808 7.077 15.814 15.814c0 4.51-1.895 8.58-4.928 11.462a12.623 12.623 0 0 0-7.373-5.802 6.659 6.659 0 0 0 3.149-5.66 6.663 6.663 0 0 0-6.662-6.662 6.663 6.663 0 0 0-6.66 6.662 6.659 6.659 0 0 0 3.147 5.66Zm3.513-10.822a5.163 5.163 0 0 0-5.16 5.162 5.163 5.163 0 0 0 5.16 5.16 5.163 5.163 0 0 0 5.162-5.16 5.163 5.163 0 0 0-5.162-5.162Z" clip-rule="evenodd"/>
<path class="tw-fill-background-alt4" fill-rule="evenodd" d="M70.528 34.57c-8.743 0-15.83 7.081-15.83 15.816s7.087 15.817 15.83 15.817c8.744 0 15.83-7.082 15.83-15.817S79.272 34.57 70.528 34.57Zm-17.33 15.816c0-9.564 7.76-17.317 17.33-17.317 9.571 0 17.33 7.753 17.33 17.317 0 9.565-7.759 17.317-17.33 17.317-9.57 0-17.33-7.752-17.33-17.317Z" clip-rule="evenodd"/>
<path class="tw-fill-art-primary" fill-rule="evenodd" d="M70.528 34.57c-8.743 0-15.83 7.081-15.83 15.816s7.087 15.817 15.83 15.817c8.744 0 15.83-7.082 15.83-15.817S79.272 34.57 70.528 34.57Zm-17.33 15.816c0-9.564 7.76-17.317 17.33-17.317 9.571 0 17.33 7.753 17.33 17.317 0 9.565-7.759 17.317-17.33 17.317-9.57 0-17.33-7.752-17.33-17.317Z" clip-rule="evenodd"/>
</svg>
`;

View File

@@ -3,14 +3,14 @@ import { svgIcon } from "@bitwarden/components";
export const SecureDevices = svgIcon`
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="150" fill="none">
<path class="tw-stroke-art-accent" stroke-width="1.5" d="M122.568 45.774v-3a5.176 5.176 0 0 0-5.176-5.175H34.094a5.176 5.176 0 0 0-5.176 5.176v10.432m67.636 39.392H33.378"/>
<path class="tw-stroke-background-alt4" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M53.446 111.924h43.108"/>
<path class="tw-stroke-background-alt4" stroke-linejoin="round" stroke-width="1.5" d="M68.118 98.72v13.204M82.96 98.72v13.204"/>
<path class="tw-stroke-background-alt4" stroke-width="2.5" d="M127.771 45.775v-3.026c0-5.718-4.635-10.352-10.352-10.352H34.068c-5.718 0-10.352 4.634-10.352 10.352v10.459m72.838 44.595H33.378"/>
<path class="tw-stroke-art-primary" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M53.446 111.924h43.108"/>
<path class="tw-stroke-art-primary" stroke-linejoin="round" stroke-width="1.5" d="M68.118 98.72v13.204M82.96 98.72v13.204"/>
<path class="tw-stroke-art-primary" stroke-width="2.5" d="M127.771 45.775v-3.026c0-5.718-4.635-10.352-10.352-10.352H34.068c-5.718 0-10.352 4.634-10.352 10.352v10.459m72.838 44.595H33.378"/>
<path class="tw-fill-art-accent" fill-rule="evenodd" d="M71.835 59.965C72.068 57.392 73.906 55.5 76 55.5s3.932 1.892 4.165 4.465h-8.33Zm-1.005.034c.224-3.015 2.388-5.499 5.17-5.499 2.781 0 4.946 2.484 5.17 5.5 1.6.232 2.83 1.61 2.83 3.275v6.62a3.31 3.31 0 0 1-3.31 3.311h-9.38a3.31 3.31 0 0 1-3.31-3.31v-6.62a3.311 3.311 0 0 1 2.83-3.277Zm.48.966h9.38a2.31 2.31 0 0 1 2.31 2.31v6.62a2.31 2.31 0 0 1-2.31 2.311h-9.38a2.31 2.31 0 0 1-2.31-2.31v-6.62a2.31 2.31 0 0 1 2.31-2.311Z" clip-rule="evenodd"/>
<path class="tw-fill-art-accent" fill-rule="evenodd" d="M75.448 67.482a1.103 1.103 0 0 1-.551-.956v-.215a1.103 1.103 0 1 1 2.206 0v.215c0 .408-.221.765-.551.956v1.594a.552.552 0 1 1-1.104 0v-1.594Z" clip-rule="evenodd"/>
<rect width="30.203" height="56.96" x="3.411" y="52.971" class="tw-stroke-background-alt4" stroke-width="2.5" rx="7.377"/>
<rect width="30.203" height="56.96" x="3.411" y="52.971" class="tw-stroke-art-primary" stroke-width="2.5" rx="7.377"/>
<path class="tw-stroke-art-accent" stroke-linecap="round" stroke-width="1.725" d="M18.164 58.148h.685"/>
<rect width="51.284" height="71.352" x="96.554" y="45.775" class="tw-stroke-background-alt4" stroke-width="2.5" rx="6.901"/>
<rect width="51.284" height="71.352" x="96.554" y="45.775" class="tw-stroke-art-primary" stroke-width="2.5" rx="6.901"/>
<circle cx="122.568" cy="111.924" r="1.486" class="tw-fill-art-accent"/>
</svg>
`;

View File

@@ -2,8 +2,8 @@ import { svgIcon } from "@bitwarden/components";
export const SecureUser = svgIcon`
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="150" fill="none">
<path class="tw-fill-background-alt4" fill-rule="evenodd" d="M96.538 35.676c-.85 0-1.538-.688-1.538-1.538v-.6a1.538 1.538 0 1 1 3.076 0v.6c0 .85-.688 1.538-1.538 1.538ZM103.737 35.676a1.538 1.538 0 0 1-1.538-1.538v-.6a1.538 1.538 0 0 1 3.076 0v.6c0 .85-.688 1.538-1.538 1.538ZM110.935 35.676a1.538 1.538 0 0 1-1.538-1.538v-.6a1.538 1.538 0 0 1 3.076 0v.6c0 .85-.689 1.538-1.538 1.538Z" clip-rule="evenodd"/>
<path class="tw-fill-background-alt4" fill-rule="evenodd" d="M12.708 26.798C7.346 26.798 3 31.145 3 36.508v58.446c0 5.362 4.347 9.71 9.71 9.71h9.567v-2.5h-9.568a7.21 7.21 0 0 1-7.209-7.21V39.451h112.272v5.666a21.936 21.936 0 0 0-8.466-1.688c-12.15 0-22 9.85-22 22 0 9.269 5.732 17.199 13.845 20.439-9.966 2.189-18.447 8.17-23.747 16.296H64.038v2.5H75.91a35.893 35.893 0 0 0-3.913 11.415c-.408 2.511.898 5.791 4.056 5.791h65.572c4.042 0 6.167-2.082 5.564-5.791-2.447-15.065-14.291-27.103-29.529-30.292 8.007-3.29 13.645-11.166 13.645-20.358 0-8.158-4.44-15.278-11.034-19.077v-9.845c0-5.362-4.347-9.71-9.71-9.71H12.708ZM117.771 37.95v-1.444a7.21 7.21 0 0 0-7.21-7.21H12.708a7.21 7.21 0 0 0-7.209 7.21v1.444h112.272Zm-38.837 66.713h-.144a33.454 33.454 0 0 0-4.326 11.816c-.118.732.03 1.578.376 2.164.292.494.65.726 1.213.726h65.572c1.649 0 2.42-.429 2.735-.751.252-.258.576-.819.361-2.139-2.662-16.39-17.328-29.024-35.128-29.024-13.09 0-24.486 6.833-30.659 16.968v.24Zm49.871-39.235c0 10.77-8.73 19.5-19.5 19.5s-19.5-8.73-19.5-19.5 8.73-19.5 19.5-19.5 19.5 8.73 19.5 19.5Z" clip-rule="evenodd"/>
<path class="tw-fill-art-primary" fill-rule="evenodd" d="M96.538 35.676c-.85 0-1.538-.688-1.538-1.538v-.6a1.538 1.538 0 1 1 3.076 0v.6c0 .85-.688 1.538-1.538 1.538ZM103.737 35.676a1.538 1.538 0 0 1-1.538-1.538v-.6a1.538 1.538 0 0 1 3.076 0v.6c0 .85-.688 1.538-1.538 1.538ZM110.935 35.676a1.538 1.538 0 0 1-1.538-1.538v-.6a1.538 1.538 0 0 1 3.076 0v.6c0 .85-.689 1.538-1.538 1.538Z" clip-rule="evenodd"/>
<path class="tw-fill-art-primary" fill-rule="evenodd" d="M12.708 26.798C7.346 26.798 3 31.145 3 36.508v58.446c0 5.362 4.347 9.71 9.71 9.71h9.567v-2.5h-9.568a7.21 7.21 0 0 1-7.209-7.21V39.451h112.272v5.666a21.936 21.936 0 0 0-8.466-1.688c-12.15 0-22 9.85-22 22 0 9.269 5.732 17.199 13.845 20.439-9.966 2.189-18.447 8.17-23.747 16.296H64.038v2.5H75.91a35.893 35.893 0 0 0-3.913 11.415c-.408 2.511.898 5.791 4.056 5.791h65.572c4.042 0 6.167-2.082 5.564-5.791-2.447-15.065-14.291-27.103-29.529-30.292 8.007-3.29 13.645-11.166 13.645-20.358 0-8.158-4.44-15.278-11.034-19.077v-9.845c0-5.362-4.347-9.71-9.71-9.71H12.708ZM117.771 37.95v-1.444a7.21 7.21 0 0 0-7.21-7.21H12.708a7.21 7.21 0 0 0-7.209 7.21v1.444h112.272Zm-38.837 66.713h-.144a33.454 33.454 0 0 0-4.326 11.816c-.118.732.03 1.578.376 2.164.292.494.65.726 1.213.726h65.572c1.649 0 2.42-.429 2.735-.751.252-.258.576-.819.361-2.139-2.662-16.39-17.328-29.024-35.128-29.024-13.09 0-24.486 6.833-30.659 16.968v.24Zm49.871-39.235c0 10.77-8.73 19.5-19.5 19.5s-19.5-8.73-19.5-19.5 8.73-19.5 19.5-19.5 19.5 8.73 19.5 19.5Z" clip-rule="evenodd"/>
<path class="tw-fill-art-accent" fill-rule="evenodd" d="M41.932 101.294a3.075 3.075 0 0 1-1.538-2.665v-.6a3.076 3.076 0 1 1 6.152 0v.6a3.075 3.075 0 0 1-1.538 2.665v4.444a1.538 1.538 0 0 1-3.076 0v-4.444Z" clip-rule="evenodd"/>
<path class="tw-fill-art-accent" fill-rule="evenodd" d="M31.715 80.342c.649-7.236 5.821-12.592 11.755-12.592 5.934 0 11.106 5.356 11.755 12.592h-23.51Zm-2.514.076C29.834 72.08 35.82 65.25 43.47 65.25c7.65 0 13.636 6.83 14.268 15.168 4.533.586 8.034 4.46 8.034 9.152v18.457a9.229 9.229 0 0 1-9.228 9.229H30.396a9.229 9.229 0 0 1-9.228-9.229V89.57c0-4.692 3.501-8.566 8.034-9.152Zm1.195 2.424h26.148a6.728 6.728 0 0 1 6.728 6.728v18.457a6.729 6.729 0 0 1-6.728 6.729H30.396a6.729 6.729 0 0 1-6.728-6.729V89.57a6.728 6.728 0 0 1 6.728-6.728Z" clip-rule="evenodd"/>
</svg>

View File

@@ -2,11 +2,11 @@ import { svgIcon } from "@bitwarden/components";
export const SecurityHandshake = svgIcon`
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="150" fill="none">
<path class="tw-fill-background-alt4" fill-rule="evenodd" d="M55.54 113.815c1.794.909 3.324 1.383 4.435 1.727l.015.005c.777.24 1.185.374 1.432.507.368.197.8.234 1.196.101.178-.059.34-.136.424-.176l.015-.007c.074-.035.111-.052.145-.066l.043-.016c.091-.023.18-.054.265-.093 1.521-.703 3.915-1.763 5.936-2.033a1.508 1.508 0 1 0-.4-2.989c-2.483.331-5.207 1.549-6.698 2.235a3.936 3.936 0 0 0-.205.071 19.521 19.521 0 0 0-1.259-.415m-5.344 1.149-7.071 12.092 10.526 5.46a1.508 1.508 0 1 1-1.392 2.677l-11.297-5.861a1.438 1.438 0 0 1-.086-.048c-1.192-.72-1.31-2.134-.741-3.096l7.824-13.379.006-.011a2.254 2.254 0 0 1 2.988-.846c1.819 1.003 3.36 1.483 4.587 1.863m30.235 16.5a1.511 1.511 0 0 1 2.097.401c.607.894.98 1.89.98 2.92 0 1.046-.387 2.014-1.104 2.799-.651.739-1.616 1.204-2.55 1.384-.396 1.524-1.314 2.468-2.166 2.927-.453.29-.949.482-1.457.579a4.34 4.34 0 0 1-.753 1.255c-.778 1.183-2.122 1.69-3.26 1.717-.528.684-1.278 1.183-2.103 1.523a1.378 1.378 0 0 1-.207.068c-.479.121-.86.121-1.15.12h-.031c-1.046 0-2.113-.377-2.97-.771a17.903 17.903 0 0 1-2.326-1.316 1.507 1.507 0 0 1-.425-2.09 1.512 1.512 0 0 1 2.092-.425c.54.357 1.225.771 1.921 1.091.729.335 1.319.495 1.708.495.158 0 .232 0 .297-.005a.5.5 0 0 0 .057-.006c.642-.289.817-.592.864-.75a1.509 1.509 0 0 1 2.019-.963.34.34 0 0 0 .035.013l.006.001h.118c.425 0 .74-.204.844-.378.052-.087.112-.169.18-.244.233-.255.341-.534.351-.854a1.508 1.508 0 0 1 1.765-1.439.995.995 0 0 0 .183.016c.228 0 .45-.066.634-.19.052-.035.106-.067.162-.095.135-.068.748-.467.788-1.786a1.506 1.506 0 0 1 1.77-1.439c.056.009.122.015.19.015.46 0 .97-.241 1.148-.447l.03-.033c.233-.253.32-.506.32-.772 0-.291-.106-.707-.459-1.226a1.507 1.507 0 0 1 .402-2.095Z" clip-rule="evenodd"/>
<path class="tw-fill-background-alt4" fill-rule="evenodd" d="M72 112.173c-1.273.841-2.725 2.355-4.115 5.058l-.01.017-.008.017c-.151.275-.17.673.06 1.112.223.352.93.775 2.136.148l.002-.001c1.492-.774 2.61-1.589 3.249-2.055l.27-.196.394-.28h.483c1.04 0 1.622-.069 1.973-.127l1.176-.195.463 1.096c.27.638.738 1.674 1.75 2.722 1.003 1.039 2.605 2.153 5.227 2.823l.379.097 6.936 6.552 9.308-5.228-6.9-11.821-8.164 3.699-9.407-4.142-.055-.019a5.217 5.217 0 0 1-.143-.052 4.902 4.902 0 0 0-1.654-.284c-.92 0-2.086.225-3.35 1.059Zm-1.665-2.515c1.808-1.195 3.566-1.56 5.014-1.56a7.942 7.942 0 0 1 2.62.442h.067l8.555 3.767 7.51-3.403c.622-.295 1.275-.21 1.71-.065a2.269 2.269 0 0 1 1.288 1.069l7.663 13.128.041.102c.447 1.114-.052 2.174-.793 2.728l-.079.059-10.628 5.969-.034.017a2.14 2.14 0 0 1-.611.203c-.186.031-.36.03-.42.03h-.013a2.308 2.308 0 0 1-1.566-.644l-6.743-6.369c-2.938-.818-4.923-2.157-6.267-3.548a11.163 11.163 0 0 1-1.879-2.613c-.241.016-.51.028-.81.034a27.07 27.07 0 0 1-3.503 2.196c-2.178 1.133-4.872.843-6.142-1.31l-.013-.021-.012-.021c-.64-1.17-.807-2.672-.084-4.011 1.569-3.044 3.333-4.993 5.129-6.179ZM57.94 130.702c.891-1.069 2.069-1.933 3.664-1.8l.008.001.01.001c.935.089 1.694.495 2.265.942.338-.144.68-.255 1.02-.329.627-.138 1.35-.175 2.03.051l.01.004.01.004c.977.341 1.645 1.027 2.088 1.686.1.002.202.008.305.017 1.872.175 2.963 1.224 3.556 2.131.99.251 1.717.81 2.216 1.488.572.777.794 1.647.905 2.123.353 1.346.505 3.585.005 5.75l-.012.052-.016.052c-.523 1.697-2.08 2.624-3.747 2.624-1.286 0-2.644-.473-3.66-1.359-1.753-.177-3.254-.773-4.257-1.985a5.169 5.169 0 0 1-3.062-1.144l-.03-.025-.03-.026a4.962 4.962 0 0 1-1.3-1.834 7.301 7.301 0 0 1-1.28-.677c-.767-.513-1.61-1.319-2.011-2.519-.59-1.766-.012-3.553 1.287-5.197l.013-.016.013-.015Zm2.332 1.915c-.918 1.168-.934 1.9-.78 2.359.118.355.396.679.827.968.43.287.91.469 1.226.561l.843.246.203.853c.13.545.38.869.605 1.076.441.341.906.462 1.33.462.1 0 .185-.012.26-.028l1.153-.253.524 1.056c.026.051.053.101.083.151.305.466.902.901 2.221 1.056l.848-.401.748.917c.401.493 1.156.843 1.894.843.531 0 .763-.234.848-.457.37-1.661.23-3.382-.003-4.254l-.007-.025-.005-.025c-.098-.423-.212-.781-.402-1.039-.135-.183-.335-.366-.838-.395l-.93-.054-.37-.855c-.189-.439-.584-1.013-1.482-1.097a.998.998 0 0 0-.402.042l-1.315.417-.533-1.272a2.837 2.837 0 0 0-.41-.7c-.156-.188-.302-.291-.43-.34-.02-.003-.153-.026-.421.033a3.292 3.292 0 0 0-.967.405l-.097.065-1.137.789-.885-1.063a2.803 2.803 0 0 0-.562-.523 1.255 1.255 0 0 0-.565-.228c-.189-.014-.494.023-1.072.71Z" clip-rule="evenodd"/>
<path class="tw-fill-background-alt4" fill-rule="evenodd" d="M65.358 131.532a.754.754 0 0 1-.246 1.038l-.103.062c-.269.163-.767.464-1.28.884-.602.495-1.119 1.074-1.317 1.666-.137.411-.148.939-.064 1.485.083.542.25 1.032.4 1.333a.754.754 0 0 1-1.35.674 6.278 6.278 0 0 1-.543-1.777c-.104-.679-.116-1.471.125-2.191.334-1.002 1.12-1.804 1.79-2.355.605-.496 1.201-.855 1.463-1.012l.087-.053a.756.756 0 0 1 1.038.246ZM68.873 132.736c.19.37.044.825-.326 1.015-.456.234-1.697 1.226-2.23 3.049-.556 1.904-.188 3.039-.072 3.236a.754.754 0 1 1-1.305.76c-.38-.653-.708-2.24-.072-4.418.66-2.26 2.202-3.564 2.988-3.968a.754.754 0 0 1 1.017.326ZM72.056 135.181c.191.37.045.825-.326 1.015-.141.073-.415.314-.724.782a6.358 6.358 0 0 0-.77 1.693c-.187.637-.246 1.364-.225 1.989.01.31.04.58.077.788.034.182.065.271.074.295.002.007.002.008 0 .005a.755.755 0 0 1-1.304.76c-.132-.226-.208-.527-.255-.792a7.079 7.079 0 0 1-.1-1.006c-.025-.737.04-1.631.283-2.461a7.84 7.84 0 0 1 .96-2.102c.365-.553.814-1.046 1.294-1.292a.756.756 0 0 1 1.016.326ZM77.04 136.44l.01.008.027.025.11.101a54.371 54.371 0 0 0 1.782 1.551c1.106.921 2.391 1.905 3.282 2.35a.754.754 0 1 1-.675 1.349c-1.068-.534-2.477-1.628-3.574-2.541a57.15 57.15 0 0 1-1.833-1.595l-.114-.105-.03-.028-.012-.01.514-.553-.514.553a.754.754 0 1 1 1.027-1.105ZM78.495 132.514l.012.011.038.034.15.13a74.33 74.33 0 0 0 2.44 2.015c1.507 1.19 3.281 2.483 4.53 3.075a.753.753 0 1 1-.648 1.362c-1.422-.674-3.32-2.071-4.819-3.254-.76-.6-1.433-1.159-1.918-1.569-.242-.204-.438-.372-.572-.488l-.156-.135-.04-.036-.015-.013.499-.566-.5.566a.756.756 0 0 1 .998-1.132ZM81.422 128.595l.014.012.044.037.17.142c.15.124.366.303.635.522.54.439 1.29 1.038 2.133 1.679 1.707 1.297 3.727 2.715 5.154 3.366a.753.753 0 1 1-.627 1.372c-1.6-.73-3.742-2.247-5.441-3.538a87.058 87.058 0 0 1-2.82-2.242l-.176-.147-.046-.039-.016-.014.488-.575-.488.575a.754.754 0 1 1 .976-1.15ZM134.303 48.211a61.447 61.447 0 0 1-.856 38.597 61.76 61.76 0 0 1-23.725 30.537 1.511 1.511 0 0 1-2.096-.409 1.507 1.507 0 0 1 .408-2.093 58.736 58.736 0 0 0 22.567-29.045 58.431 58.431 0 0 0 .814-36.704 58.696 58.696 0 0 0-21.256-30.008 59.167 59.167 0 0 0-35.015-11.57 59.17 59.17 0 0 0-35.071 11.4A58.707 58.707 0 0 0 18.669 48.82a58.433 58.433 0 0 0 .634 36.708 58.733 58.733 0 0 0 22.424 29.154c.69.469.868 1.407.399 2.095a1.51 1.51 0 0 1-2.098.398 61.752 61.752 0 0 1-23.575-30.652 61.446 61.446 0 0 1-.667-38.6 61.723 61.723 0 0 1 22.502-31.44A62.192 62.192 0 0 1 75.153 4.5a62.188 62.188 0 0 1 36.803 12.161 61.714 61.714 0 0 1 22.348 31.55Z" clip-rule="evenodd"/>
<path class="tw-fill-art-primary" fill-rule="evenodd" d="M55.54 113.815c1.794.909 3.324 1.383 4.435 1.727l.015.005c.777.24 1.185.374 1.432.507.368.197.8.234 1.196.101.178-.059.34-.136.424-.176l.015-.007c.074-.035.111-.052.145-.066l.043-.016c.091-.023.18-.054.265-.093 1.521-.703 3.915-1.763 5.936-2.033a1.508 1.508 0 1 0-.4-2.989c-2.483.331-5.207 1.549-6.698 2.235a3.936 3.936 0 0 0-.205.071 19.521 19.521 0 0 0-1.259-.415m-5.344 1.149-7.071 12.092 10.526 5.46a1.508 1.508 0 1 1-1.392 2.677l-11.297-5.861a1.438 1.438 0 0 1-.086-.048c-1.192-.72-1.31-2.134-.741-3.096l7.824-13.379.006-.011a2.254 2.254 0 0 1 2.988-.846c1.819 1.003 3.36 1.483 4.587 1.863m30.235 16.5a1.511 1.511 0 0 1 2.097.401c.607.894.98 1.89.98 2.92 0 1.046-.387 2.014-1.104 2.799-.651.739-1.616 1.204-2.55 1.384-.396 1.524-1.314 2.468-2.166 2.927-.453.29-.949.482-1.457.579a4.34 4.34 0 0 1-.753 1.255c-.778 1.183-2.122 1.69-3.26 1.717-.528.684-1.278 1.183-2.103 1.523a1.378 1.378 0 0 1-.207.068c-.479.121-.86.121-1.15.12h-.031c-1.046 0-2.113-.377-2.97-.771a17.903 17.903 0 0 1-2.326-1.316 1.507 1.507 0 0 1-.425-2.09 1.512 1.512 0 0 1 2.092-.425c.54.357 1.225.771 1.921 1.091.729.335 1.319.495 1.708.495.158 0 .232 0 .297-.005a.5.5 0 0 0 .057-.006c.642-.289.817-.592.864-.75a1.509 1.509 0 0 1 2.019-.963.34.34 0 0 0 .035.013l.006.001h.118c.425 0 .74-.204.844-.378.052-.087.112-.169.18-.244.233-.255.341-.534.351-.854a1.508 1.508 0 0 1 1.765-1.439.995.995 0 0 0 .183.016c.228 0 .45-.066.634-.19.052-.035.106-.067.162-.095.135-.068.748-.467.788-1.786a1.506 1.506 0 0 1 1.77-1.439c.056.009.122.015.19.015.46 0 .97-.241 1.148-.447l.03-.033c.233-.253.32-.506.32-.772 0-.291-.106-.707-.459-1.226a1.507 1.507 0 0 1 .402-2.095Z" clip-rule="evenodd"/>
<path class="tw-fill-art-primary" fill-rule="evenodd" d="M72 112.173c-1.273.841-2.725 2.355-4.115 5.058l-.01.017-.008.017c-.151.275-.17.673.06 1.112.223.352.93.775 2.136.148l.002-.001c1.492-.774 2.61-1.589 3.249-2.055l.27-.196.394-.28h.483c1.04 0 1.622-.069 1.973-.127l1.176-.195.463 1.096c.27.638.738 1.674 1.75 2.722 1.003 1.039 2.605 2.153 5.227 2.823l.379.097 6.936 6.552 9.308-5.228-6.9-11.821-8.164 3.699-9.407-4.142-.055-.019a5.217 5.217 0 0 1-.143-.052 4.902 4.902 0 0 0-1.654-.284c-.92 0-2.086.225-3.35 1.059Zm-1.665-2.515c1.808-1.195 3.566-1.56 5.014-1.56a7.942 7.942 0 0 1 2.62.442h.067l8.555 3.767 7.51-3.403c.622-.295 1.275-.21 1.71-.065a2.269 2.269 0 0 1 1.288 1.069l7.663 13.128.041.102c.447 1.114-.052 2.174-.793 2.728l-.079.059-10.628 5.969-.034.017a2.14 2.14 0 0 1-.611.203c-.186.031-.36.03-.42.03h-.013a2.308 2.308 0 0 1-1.566-.644l-6.743-6.369c-2.938-.818-4.923-2.157-6.267-3.548a11.163 11.163 0 0 1-1.879-2.613c-.241.016-.51.028-.81.034a27.07 27.07 0 0 1-3.503 2.196c-2.178 1.133-4.872.843-6.142-1.31l-.013-.021-.012-.021c-.64-1.17-.807-2.672-.084-4.011 1.569-3.044 3.333-4.993 5.129-6.179ZM57.94 130.702c.891-1.069 2.069-1.933 3.664-1.8l.008.001.01.001c.935.089 1.694.495 2.265.942.338-.144.68-.255 1.02-.329.627-.138 1.35-.175 2.03.051l.01.004.01.004c.977.341 1.645 1.027 2.088 1.686.1.002.202.008.305.017 1.872.175 2.963 1.224 3.556 2.131.99.251 1.717.81 2.216 1.488.572.777.794 1.647.905 2.123.353 1.346.505 3.585.005 5.75l-.012.052-.016.052c-.523 1.697-2.08 2.624-3.747 2.624-1.286 0-2.644-.473-3.66-1.359-1.753-.177-3.254-.773-4.257-1.985a5.169 5.169 0 0 1-3.062-1.144l-.03-.025-.03-.026a4.962 4.962 0 0 1-1.3-1.834 7.301 7.301 0 0 1-1.28-.677c-.767-.513-1.61-1.319-2.011-2.519-.59-1.766-.012-3.553 1.287-5.197l.013-.016.013-.015Zm2.332 1.915c-.918 1.168-.934 1.9-.78 2.359.118.355.396.679.827.968.43.287.91.469 1.226.561l.843.246.203.853c.13.545.38.869.605 1.076.441.341.906.462 1.33.462.1 0 .185-.012.26-.028l1.153-.253.524 1.056c.026.051.053.101.083.151.305.466.902.901 2.221 1.056l.848-.401.748.917c.401.493 1.156.843 1.894.843.531 0 .763-.234.848-.457.37-1.661.23-3.382-.003-4.254l-.007-.025-.005-.025c-.098-.423-.212-.781-.402-1.039-.135-.183-.335-.366-.838-.395l-.93-.054-.37-.855c-.189-.439-.584-1.013-1.482-1.097a.998.998 0 0 0-.402.042l-1.315.417-.533-1.272a2.837 2.837 0 0 0-.41-.7c-.156-.188-.302-.291-.43-.34-.02-.003-.153-.026-.421.033a3.292 3.292 0 0 0-.967.405l-.097.065-1.137.789-.885-1.063a2.803 2.803 0 0 0-.562-.523 1.255 1.255 0 0 0-.565-.228c-.189-.014-.494.023-1.072.71Z" clip-rule="evenodd"/>
<path class="tw-fill-art-primary" fill-rule="evenodd" d="M65.358 131.532a.754.754 0 0 1-.246 1.038l-.103.062c-.269.163-.767.464-1.28.884-.602.495-1.119 1.074-1.317 1.666-.137.411-.148.939-.064 1.485.083.542.25 1.032.4 1.333a.754.754 0 0 1-1.35.674 6.278 6.278 0 0 1-.543-1.777c-.104-.679-.116-1.471.125-2.191.334-1.002 1.12-1.804 1.79-2.355.605-.496 1.201-.855 1.463-1.012l.087-.053a.756.756 0 0 1 1.038.246ZM68.873 132.736c.19.37.044.825-.326 1.015-.456.234-1.697 1.226-2.23 3.049-.556 1.904-.188 3.039-.072 3.236a.754.754 0 1 1-1.305.76c-.38-.653-.708-2.24-.072-4.418.66-2.26 2.202-3.564 2.988-3.968a.754.754 0 0 1 1.017.326ZM72.056 135.181c.191.37.045.825-.326 1.015-.141.073-.415.314-.724.782a6.358 6.358 0 0 0-.77 1.693c-.187.637-.246 1.364-.225 1.989.01.31.04.58.077.788.034.182.065.271.074.295.002.007.002.008 0 .005a.755.755 0 0 1-1.304.76c-.132-.226-.208-.527-.255-.792a7.079 7.079 0 0 1-.1-1.006c-.025-.737.04-1.631.283-2.461a7.84 7.84 0 0 1 .96-2.102c.365-.553.814-1.046 1.294-1.292a.756.756 0 0 1 1.016.326ZM77.04 136.44l.01.008.027.025.11.101a54.371 54.371 0 0 0 1.782 1.551c1.106.921 2.391 1.905 3.282 2.35a.754.754 0 1 1-.675 1.349c-1.068-.534-2.477-1.628-3.574-2.541a57.15 57.15 0 0 1-1.833-1.595l-.114-.105-.03-.028-.012-.01.514-.553-.514.553a.754.754 0 1 1 1.027-1.105ZM78.495 132.514l.012.011.038.034.15.13a74.33 74.33 0 0 0 2.44 2.015c1.507 1.19 3.281 2.483 4.53 3.075a.753.753 0 1 1-.648 1.362c-1.422-.674-3.32-2.071-4.819-3.254-.76-.6-1.433-1.159-1.918-1.569-.242-.204-.438-.372-.572-.488l-.156-.135-.04-.036-.015-.013.499-.566-.5.566a.756.756 0 0 1 .998-1.132ZM81.422 128.595l.014.012.044.037.17.142c.15.124.366.303.635.522.54.439 1.29 1.038 2.133 1.679 1.707 1.297 3.727 2.715 5.154 3.366a.753.753 0 1 1-.627 1.372c-1.6-.73-3.742-2.247-5.441-3.538a87.058 87.058 0 0 1-2.82-2.242l-.176-.147-.046-.039-.016-.014.488-.575-.488.575a.754.754 0 1 1 .976-1.15ZM134.303 48.211a61.447 61.447 0 0 1-.856 38.597 61.76 61.76 0 0 1-23.725 30.537 1.511 1.511 0 0 1-2.096-.409 1.507 1.507 0 0 1 .408-2.093 58.736 58.736 0 0 0 22.567-29.045 58.431 58.431 0 0 0 .814-36.704 58.696 58.696 0 0 0-21.256-30.008 59.167 59.167 0 0 0-35.015-11.57 59.17 59.17 0 0 0-35.071 11.4A58.707 58.707 0 0 0 18.669 48.82a58.433 58.433 0 0 0 .634 36.708 58.733 58.733 0 0 0 22.424 29.154c.69.469.868 1.407.399 2.095a1.51 1.51 0 0 1-2.098.398 61.752 61.752 0 0 1-23.575-30.652 61.446 61.446 0 0 1-.667-38.6 61.723 61.723 0 0 1 22.502-31.44A62.192 62.192 0 0 1 75.153 4.5a62.188 62.188 0 0 1 36.803 12.161 61.714 61.714 0 0 1 22.348 31.55Z" clip-rule="evenodd"/>
<path class="tw-fill-art-accent" fill-rule="evenodd" d="M128.53 49.913a55.343 55.343 0 0 1-.771 34.77 55.64 55.64 0 0 1-21.378 27.512.755.755 0 0 1-.844-1.25 54.131 54.131 0 0 0 20.799-26.766 53.85 53.85 0 0 0 .751-33.825 54.094 54.094 0 0 0-19.592-27.653 54.534 54.534 0 0 0-32.27-10.66 54.537 54.537 0 0 0-32.322 10.503 54.1 54.1 0 0 0-19.727 27.558 53.841 53.841 0 0 0 .585 33.828 54.125 54.125 0 0 0 20.667 26.866.754.754 0 1 1-.85 1.247 55.637 55.637 0 0 1-21.243-27.616 55.347 55.347 0 0 1-.6-34.774A55.608 55.608 0 0 1 42.01 21.328a56.05 56.05 0 0 1 33.218-10.796 56.044 56.044 0 0 1 33.164 10.957 55.597 55.597 0 0 1 20.137 28.424Z" clip-rule="evenodd"/>
<path class="tw-fill-background-alt4" fill-rule="evenodd" d="M61.17 48.3c.727-8.197 6.577-14.301 13.33-14.301 6.754 0 12.604 6.104 13.33 14.3a12.392 12.392 0 0 0-.35-.004H61.52c-.117 0-.234.002-.35.005Zm-2.53.343c.6-9.417 7.306-17.144 15.86-17.144 8.555 0 15.26 7.727 15.862 17.144 5.247 1.291 9.138 6.028 9.138 11.673v17.412c0 6.64-5.382 12.022-12.02 12.022H61.52c-6.639 0-12.02-5.383-12.02-12.022V60.316c0-5.646 3.891-10.382 9.138-11.673Zm2.881 2.152H87.48A9.521 9.521 0 0 1 97 60.316v17.412a9.521 9.521 0 0 1-9.52 9.522H61.52a9.521 9.521 0 0 1-9.52-9.522V60.316a9.521 9.521 0 0 1 9.52-9.521Z" clip-rule="evenodd"/>
<path class="tw-fill-art-primary" fill-rule="evenodd" d="M61.17 48.3c.727-8.197 6.577-14.301 13.33-14.301 6.754 0 12.604 6.104 13.33 14.3a12.392 12.392 0 0 0-.35-.004H61.52c-.117 0-.234.002-.35.005Zm-2.53.343c.6-9.417 7.306-17.144 15.86-17.144 8.555 0 15.26 7.727 15.862 17.144 5.247 1.291 9.138 6.028 9.138 11.673v17.412c0 6.64-5.382 12.022-12.02 12.022H61.52c-6.639 0-12.02-5.383-12.02-12.022V60.316c0-5.646 3.891-10.382 9.138-11.673Zm2.881 2.152H87.48A9.521 9.521 0 0 1 97 60.316v17.412a9.521 9.521 0 0 1-9.52 9.522H61.52a9.521 9.521 0 0 1-9.52-9.522V60.316a9.521 9.521 0 0 1 9.52-9.521Z" clip-rule="evenodd"/>
<path class="tw-fill-art-accent" fill-rule="evenodd" d="M72.741 71.859a3.499 3.499 0 0 1-1.74-3.027v-.674a3.5 3.5 0 1 1 7 0v.674c0 1.292-.7 2.42-1.742 3.027v4.956a1.76 1.76 0 1 1-3.518 0V71.86Z" clip-rule="evenodd"/>
</svg>
`;

18
package-lock.json generated
View File

@@ -24,7 +24,7 @@
"@angular/platform-browser": "18.2.13",
"@angular/platform-browser-dynamic": "18.2.13",
"@angular/router": "18.2.13",
"@bitwarden/sdk-internal": "0.2.0-main.133",
"@bitwarden/sdk-internal": "0.2.0-main.137",
"@electron/fuses": "1.8.0",
"@emotion/css": "11.13.5",
"@koa/multer": "3.0.2",
@@ -48,7 +48,7 @@
"jquery": "3.7.1",
"jsdom": "26.0.0",
"jszip": "3.10.1",
"koa": "2.15.4",
"koa": "2.16.1",
"koa-bodyparser": "4.4.1",
"koa-json": "2.0.2",
"lit": "3.2.1",
@@ -210,7 +210,7 @@
"inquirer": "8.2.6",
"jsdom": "26.0.0",
"jszip": "3.10.1",
"koa": "2.15.4",
"koa": "2.16.1",
"koa-bodyparser": "4.4.1",
"koa-json": "2.0.2",
"lowdb": "1.0.0",
@@ -4700,9 +4700,9 @@
"link": true
},
"node_modules/@bitwarden/sdk-internal": {
"version": "0.2.0-main.133",
"resolved": "https://registry.npmjs.org/@bitwarden/sdk-internal/-/sdk-internal-0.2.0-main.133.tgz",
"integrity": "sha512-KzKJGf9cKlcQzfRmqkAwVGBN1kDpcRFkTMm7nrphZSrjfaWJWI1lBEJ0DhnkbMMHJXhQavGyoVk5TIn/Y8ylmw==",
"version": "0.2.0-main.137",
"resolved": "https://registry.npmjs.org/@bitwarden/sdk-internal/-/sdk-internal-0.2.0-main.137.tgz",
"integrity": "sha512-Df0pB5tOEc4WiMjskunTrqHulPzenFv8C61sqsBhHfy80xcf5kU5JyPd4asbf3e4uNS6QGXptd8imp09AuiFEA==",
"license": "GPL-3.0"
},
"node_modules/@bitwarden/send-ui": {
@@ -24789,9 +24789,9 @@
}
},
"node_modules/koa": {
"version": "2.15.4",
"resolved": "https://registry.npmjs.org/koa/-/koa-2.15.4.tgz",
"integrity": "sha512-7fNBIdrU2PEgLljXoPWoyY4r1e+ToWCmzS/wwMPbUNs7X+5MMET1ObhJBlUkF5uZG9B6QhM2zS1TsH6adegkiQ==",
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/koa/-/koa-2.16.1.tgz",
"integrity": "sha512-umfX9d3iuSxTQP4pnzLOz0HKnPg0FaUUIKcye2lOiz3KPu1Y3M3xlz76dISdFPQs37P9eJz1wUpcTS6KDPn9fA==",
"license": "MIT",
"dependencies": {
"accepts": "^1.3.5",

View File

@@ -156,7 +156,7 @@
"@angular/platform-browser": "18.2.13",
"@angular/platform-browser-dynamic": "18.2.13",
"@angular/router": "18.2.13",
"@bitwarden/sdk-internal": "0.2.0-main.133",
"@bitwarden/sdk-internal": "0.2.0-main.137",
"@electron/fuses": "1.8.0",
"@emotion/css": "11.13.5",
"@koa/multer": "3.0.2",
@@ -180,7 +180,7 @@
"jquery": "3.7.1",
"jsdom": "26.0.0",
"jszip": "3.10.1",
"koa": "2.15.4",
"koa": "2.16.1",
"koa-bodyparser": "4.4.1",
"koa-json": "2.0.2",
"lit": "3.2.1",