mirror of
https://github.com/bitwarden/browser
synced 2026-02-12 14:34:02 +00:00
Merge branch 'main' into pm-15808-Show-suspended-org-modals-for-orgs-in-unpaid-and-canceled-status
This commit is contained in:
@@ -14,11 +14,11 @@
|
||||
"build:watch:firefox": "npm run build:firefox -- --watch",
|
||||
"build:watch:opera": "npm run build:opera -- --watch",
|
||||
"build:watch:safari": "npm run build:safari -- --watch",
|
||||
"build:prod:chrome": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build:chrome",
|
||||
"build:prod:edge": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build:edge",
|
||||
"build:prod:firefox": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build:firefox",
|
||||
"build:prod:opera": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build:opera",
|
||||
"build:prod:safari": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build:safari",
|
||||
"build:prod:chrome": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=8192\" npm run build:chrome",
|
||||
"build:prod:edge": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=8192\" npm run build:edge",
|
||||
"build:prod:firefox": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=8192\" npm run build:firefox",
|
||||
"build:prod:opera": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=8192\" npm run build:opera",
|
||||
"build:prod:safari": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=8192\" npm run build:safari",
|
||||
"dist:chrome": "npm run build:prod:chrome && mkdir -p dist && ./scripts/compress.ps1 dist-chrome.zip",
|
||||
"dist:edge": "npm run build:prod:edge && mkdir -p dist && ./scripts/compress.ps1 dist-edge.zip",
|
||||
"dist:firefox": "npm run build:prod:firefox && mkdir -p dist && ./scripts/compress.ps1 dist-firefox.zip",
|
||||
|
||||
@@ -2813,6 +2813,254 @@ exports[`AutofillInlineMenuList initAutofillInlineMenuList the list of ciphers f
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`AutofillInlineMenuList initAutofillInlineMenuList the list of ciphers for an authenticated user renders correctly when there are multiple TOTP elements with username displayed 1`] = `
|
||||
<div
|
||||
class="inline-menu-list-container theme_light"
|
||||
>
|
||||
<ul
|
||||
class="inline-menu-list-actions"
|
||||
role="list"
|
||||
>
|
||||
<li
|
||||
class="inline-menu-list-actions-item"
|
||||
role="listitem"
|
||||
>
|
||||
<div
|
||||
class="cipher-container"
|
||||
>
|
||||
<button
|
||||
aria-description="username: user1"
|
||||
aria-label="fillCredentialsFor website login 1"
|
||||
class="fill-cipher-button inline-menu-list-action"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="cipher-icon"
|
||||
>
|
||||
<div
|
||||
style="position: relative;"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
viewBox="0 0 29 29"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
|
||||
|
||||
<circle
|
||||
class="circle-color"
|
||||
cx="14.5"
|
||||
cy="14.5"
|
||||
fill="none"
|
||||
r="12.5"
|
||||
stroke-dasharray="78.5"
|
||||
stroke-dashoffset="78.5"
|
||||
stroke-width="3"
|
||||
style="stroke-dashoffset: NaN;"
|
||||
transform="rotate(-90 14.5 14.5)"
|
||||
/>
|
||||
|
||||
|
||||
<circle
|
||||
class="circle-color"
|
||||
cx="14.5"
|
||||
cy="14.5"
|
||||
fill="none"
|
||||
r="14"
|
||||
stroke-width="1"
|
||||
/>
|
||||
|
||||
|
||||
</svg>
|
||||
<span
|
||||
aria-label=""
|
||||
bittypography="helper"
|
||||
class="totp-sec-span"
|
||||
>
|
||||
NaN
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
<div
|
||||
class="cipher-details"
|
||||
>
|
||||
<span
|
||||
aria-label=""
|
||||
class="cipher-name"
|
||||
/>
|
||||
<span
|
||||
class="cipher-subtitle"
|
||||
title="user1"
|
||||
>
|
||||
user1
|
||||
</span>
|
||||
<span
|
||||
aria-label=""
|
||||
class="cipher-subtitle"
|
||||
data-testid="totp-code"
|
||||
>
|
||||
123 456
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
aria-label="view website login 1, opensInANewWindow"
|
||||
class="view-cipher-button"
|
||||
tabindex="-1"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
width="20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g
|
||||
clip-path="url(#a)"
|
||||
>
|
||||
<path
|
||||
d="M16.587 7.932H5.9a.455.455 0 0 1-.31-.12.393.393 0 0 1-.127-.287c0-.108.046-.211.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.076.128.179.128.287a.393.393 0 0 1-.128.288.455.455 0 0 1-.31.119Zm0 2.474H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm0 2.468H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm2.163-8.103v10.457H1.25V4.771h17.5Zm0-1.162H1.25a1.3 1.3 0 0 0-.884.34A1.122 1.122 0 0 0 0 4.772v10.457c0 .308.132.604.366.822a1.3 1.3 0 0 0 .884.34h17.5a1.3 1.3 0 0 0 .884-.34c.234-.218.366-.514.366-.822V4.771c0-.308-.132-.603-.366-.821a1.3 1.3 0 0 0-.884-.34ZM3.213 8.01c.287 0 .52-.217.52-.484s-.234-.483-.52-.483c-.288 0-.52.216-.52.483s.233.483.52.483Zm0 4.903c.287 0 .52-.217.52-.484 0-.266-.234-.483-.52-.483-.287 0-.52.216-.52.483s.233.484.52.484Zm0-2.452c.287 0 .52-.216.52-.483 0-.268-.234-.484-.52-.484-.288 0-.52.216-.52.484 0 .267.233.483.52.483Z"
|
||||
fill="#175DDC"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clippath
|
||||
id="a"
|
||||
>
|
||||
<path
|
||||
d="M0 .113h20v19.773H0z"
|
||||
fill="#fff"
|
||||
/>
|
||||
</clippath>
|
||||
</defs>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="inline-menu-list-actions-item"
|
||||
role="listitem"
|
||||
>
|
||||
<div
|
||||
class="cipher-container"
|
||||
>
|
||||
<button
|
||||
aria-description="username: user2"
|
||||
aria-label="fillCredentialsFor website login 2"
|
||||
class="fill-cipher-button inline-menu-list-action"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="cipher-icon"
|
||||
>
|
||||
<div
|
||||
style="position: relative;"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
viewBox="0 0 29 29"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
|
||||
|
||||
<circle
|
||||
class="circle-color"
|
||||
cx="14.5"
|
||||
cy="14.5"
|
||||
fill="none"
|
||||
r="12.5"
|
||||
stroke-dasharray="78.5"
|
||||
stroke-dashoffset="78.5"
|
||||
stroke-width="3"
|
||||
style="stroke-dashoffset: NaN;"
|
||||
transform="rotate(-90 14.5 14.5)"
|
||||
/>
|
||||
|
||||
|
||||
<circle
|
||||
class="circle-color"
|
||||
cx="14.5"
|
||||
cy="14.5"
|
||||
fill="none"
|
||||
r="14"
|
||||
stroke-width="1"
|
||||
/>
|
||||
|
||||
|
||||
</svg>
|
||||
<span
|
||||
aria-label=""
|
||||
bittypography="helper"
|
||||
class="totp-sec-span"
|
||||
>
|
||||
NaN
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
<div
|
||||
class="cipher-details"
|
||||
>
|
||||
<span
|
||||
aria-label=""
|
||||
class="cipher-name"
|
||||
/>
|
||||
<span
|
||||
class="cipher-subtitle"
|
||||
title="user2"
|
||||
>
|
||||
user2
|
||||
</span>
|
||||
<span
|
||||
aria-label=""
|
||||
class="cipher-subtitle"
|
||||
data-testid="totp-code"
|
||||
>
|
||||
654 321
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
aria-label="view website login 2, opensInANewWindow"
|
||||
class="view-cipher-button"
|
||||
tabindex="-1"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
width="20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g
|
||||
clip-path="url(#a)"
|
||||
>
|
||||
<path
|
||||
d="M16.587 7.932H5.9a.455.455 0 0 1-.31-.12.393.393 0 0 1-.127-.287c0-.108.046-.211.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.076.128.179.128.287a.393.393 0 0 1-.128.288.455.455 0 0 1-.31.119Zm0 2.474H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm0 2.468H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm2.163-8.103v10.457H1.25V4.771h17.5Zm0-1.162H1.25a1.3 1.3 0 0 0-.884.34A1.122 1.122 0 0 0 0 4.772v10.457c0 .308.132.604.366.822a1.3 1.3 0 0 0 .884.34h17.5a1.3 1.3 0 0 0 .884-.34c.234-.218.366-.514.366-.822V4.771c0-.308-.132-.603-.366-.821a1.3 1.3 0 0 0-.884-.34ZM3.213 8.01c.287 0 .52-.217.52-.484s-.234-.483-.52-.483c-.288 0-.52.216-.52.483s.233.483.52.483Zm0 4.903c.287 0 .52-.217.52-.484 0-.266-.234-.483-.52-.483-.287 0-.52.216-.52.483s.233.484.52.484Zm0-2.452c.287 0 .52-.216.52-.483 0-.268-.234-.484-.52-.484-.288 0-.52.216-.52.484 0 .267.233.483.52.483Z"
|
||||
fill="#175DDC"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clippath
|
||||
id="a"
|
||||
>
|
||||
<path
|
||||
d="M0 .113h20v19.773H0z"
|
||||
fill="#fff"
|
||||
/>
|
||||
</clippath>
|
||||
</defs>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`AutofillInlineMenuList initAutofillInlineMenuList the locked inline menu for an unauthenticated user creates the views for the locked inline menu 1`] = `
|
||||
<div
|
||||
class="inline-menu-list-container theme_light"
|
||||
|
||||
@@ -140,6 +140,47 @@ describe("AutofillInlineMenuList", () => {
|
||||
expect(autofillInlineMenuList["inlineMenuListContainer"]).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders correctly when there are multiple TOTP elements with username displayed", async () => {
|
||||
const totpCipher1 = createAutofillOverlayCipherDataMock(1, {
|
||||
type: CipherType.Login,
|
||||
login: {
|
||||
totp: "123456",
|
||||
totpField: true,
|
||||
username: "user1",
|
||||
},
|
||||
});
|
||||
|
||||
const totpCipher2 = createAutofillOverlayCipherDataMock(2, {
|
||||
type: CipherType.Login,
|
||||
login: {
|
||||
totp: "654321",
|
||||
totpField: true,
|
||||
username: "user2",
|
||||
},
|
||||
});
|
||||
|
||||
postWindowMessage(
|
||||
createInitAutofillInlineMenuListMessageMock({
|
||||
inlineMenuFillType: CipherType.Login,
|
||||
ciphers: [totpCipher1, totpCipher2],
|
||||
}),
|
||||
);
|
||||
|
||||
await flushPromises();
|
||||
const checkSubtitleElement = (username: string) => {
|
||||
const subtitleElement = autofillInlineMenuList["inlineMenuListContainer"].querySelector(
|
||||
`span.cipher-subtitle[title="${username}"]`,
|
||||
);
|
||||
expect(subtitleElement).not.toBeNull();
|
||||
expect(subtitleElement.textContent).toBe(username);
|
||||
};
|
||||
|
||||
checkSubtitleElement("user1");
|
||||
checkSubtitleElement("user2");
|
||||
|
||||
expect(autofillInlineMenuList["inlineMenuListContainer"]).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("creates the view for a totp field", () => {
|
||||
postWindowMessage(
|
||||
createInitAutofillInlineMenuListMessageMock({
|
||||
|
||||
@@ -1163,7 +1163,7 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {
|
||||
}
|
||||
|
||||
if (cipher.login?.totpField && cipher.login?.totp) {
|
||||
return this.buildTotpElement(cipher.login?.totp);
|
||||
return this.buildTotpElement(cipher.login?.totp, cipher.login?.username);
|
||||
}
|
||||
const subTitleText = this.getSubTitleText(cipher);
|
||||
const cipherSubtitleElement = this.buildCipherSubtitleElement(subTitleText);
|
||||
@@ -1174,13 +1174,24 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {
|
||||
return cipherDetailsElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there is more than one TOTP element being displayed.
|
||||
*
|
||||
* @returns {boolean} - Returns true if more than one TOTP element is displayed, otherwise false.
|
||||
*/
|
||||
private multipleTotpElements(): boolean {
|
||||
return (
|
||||
this.ciphers.filter((cipher) => cipher.login?.totpField && cipher.login?.totp).length > 1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a TOTP element for a given TOTP code.
|
||||
*
|
||||
* @param totp - The TOTP code to display.
|
||||
*/
|
||||
|
||||
private buildTotpElement(totpCode: string): HTMLDivElement | null {
|
||||
private buildTotpElement(totpCode: string, username?: string): HTMLDivElement | null {
|
||||
if (!totpCode) {
|
||||
return null;
|
||||
}
|
||||
@@ -1196,12 +1207,17 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {
|
||||
|
||||
containerElement.appendChild(totpHeading);
|
||||
|
||||
const subtitleElement = document.createElement("span");
|
||||
subtitleElement.classList.add("cipher-subtitle");
|
||||
subtitleElement.textContent = formattedTotpCode;
|
||||
subtitleElement.setAttribute("aria-label", this.getTranslation("totpCodeAria"));
|
||||
subtitleElement.setAttribute("data-testid", "totp-code");
|
||||
containerElement.appendChild(subtitleElement);
|
||||
if (this.multipleTotpElements() && username) {
|
||||
const usernameSubtitle = this.buildCipherSubtitleElement(username);
|
||||
containerElement.appendChild(usernameSubtitle);
|
||||
}
|
||||
|
||||
const totpCodeSpan = document.createElement("span");
|
||||
totpCodeSpan.classList.add("cipher-subtitle");
|
||||
totpCodeSpan.textContent = formattedTotpCode;
|
||||
totpCodeSpan.setAttribute("aria-label", this.getTranslation("totpCodeAria"));
|
||||
totpCodeSpan.setAttribute("data-testid", "totp-code");
|
||||
containerElement.appendChild(totpCodeSpan);
|
||||
|
||||
return containerElement;
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
"license": "SEE LICENSE IN LICENSE.txt",
|
||||
"scripts": {
|
||||
"clean": "rimraf dist",
|
||||
"build:oss": "webpack",
|
||||
"build:oss": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" webpack",
|
||||
"build:oss:debug": "npm run build:oss && node --inspect ./build/bw.js",
|
||||
"build:oss:watch": "webpack --watch",
|
||||
"build:oss:prod": "cross-env NODE_ENV=production webpack",
|
||||
"build:oss:prod:watch": "cross-env NODE_ENV=production webpack --watch",
|
||||
"debug": "node --inspect ./build/bw.js",
|
||||
"publish:npm": "npm run build:oss:prod && npm publish --access public",
|
||||
"build:bit": "webpack -c ../../bitwarden_license/bit-cli/webpack.config.js",
|
||||
"build:bit": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" webpack -c ../../bitwarden_license/bit-cli/webpack.config.js",
|
||||
"build:bit:debug": "npm run build:bit && node --inspect ./build/bw.js",
|
||||
"build:bit:watch": "webpack --watch -c ../../bitwarden_license/bit-cli/webpack.config.js",
|
||||
"build:bit:prod": "cross-env NODE_ENV=production npm run build:bit",
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"postinstall": "electron-rebuild",
|
||||
"start": "cross-env ELECTRON_IS_DEV=0 ELECTRON_NO_UPDATER=1 electron ./build",
|
||||
"build-native": "cd desktop_native && node build.js",
|
||||
"build": "concurrently -n Main,Rend,Prel -c yellow,cyan \"npm run build:main\" \"npm run build:renderer\" \"npm run build:preload\"",
|
||||
"build": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" concurrently -n Main,Rend,Prel -c yellow,cyan \"npm run build:main\" \"npm run build:renderer\" \"npm run build:preload\"",
|
||||
"build:dev": "concurrently -n Main,Rend -c yellow,cyan \"npm run build:main:dev\" \"npm run build:renderer:dev\"",
|
||||
"build:preload": "cross-env NODE_ENV=production webpack --config webpack.preload.js",
|
||||
"build:preload:watch": "cross-env NODE_ENV=production webpack --config webpack.preload.js --watch",
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "@bitwarden/web-vault",
|
||||
"version": "2024.12.1",
|
||||
"scripts": {
|
||||
"build:oss": "webpack",
|
||||
"build:bit": "webpack -c ../../bitwarden_license/bit-web/webpack.config.js",
|
||||
"build:oss": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" webpack",
|
||||
"build:bit": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" webpack -c ../../bitwarden_license/bit-web/webpack.config.js",
|
||||
"build:oss:watch": "webpack serve",
|
||||
"build:bit:watch": "webpack serve -c ../../bitwarden_license/bit-web/webpack.config.js",
|
||||
"build:bit:dev": "cross-env ENV=development npm run build:bit",
|
||||
|
||||
Reference in New Issue
Block a user