mirror of
https://github.com/bitwarden/browser
synced 2026-02-12 06:23:38 +00:00
Merge branch 'main' into km/beeep/fido2-deps
This commit is contained in:
15
.github/CODEOWNERS
vendored
15
.github/CODEOWNERS
vendored
@@ -83,6 +83,19 @@ apps/web/src/utils/ @bitwarden/team-platform-dev
|
||||
apps/web/src/app/core @bitwarden/team-platform-dev
|
||||
apps/web/src/app/shared @bitwarden/team-platform-dev
|
||||
apps/web/src/translation-constants.ts @bitwarden/team-platform-dev
|
||||
# Workflows
|
||||
.github/workflows/brew-bump-desktop.yml @bitwarden/team-platform-dev
|
||||
.github/workflows/build-browser.yml @bitwarden/team-platform-dev
|
||||
.github/workflows/build-cli.yml @bitwarden/team-platform-dev
|
||||
.github/workflows/build-desktop.yml @bitwarden/team-platform-dev
|
||||
.github/workflows/build-web.yml @bitwarden/team-platform-dev
|
||||
.github/workflows/chromatic.yml @bitwarden/team-platform-dev
|
||||
.github/workflows/lint.yml @bitwarden/team-platform-dev
|
||||
.github/workflows/locales-lint.yml @bitwarden/team-platform-dev
|
||||
.github/workflows/repository-management.yml @bitwarden/team-platform-dev
|
||||
.github/workflows/scan.yml @bitwarden/team-platform-dev
|
||||
.github/workflows/test.yml @bitwarden/team-platform-dev
|
||||
.github/workflows/version-auto-bump.yml @bitwarden/team-platform-dev
|
||||
|
||||
## Autofill team files ##
|
||||
apps/browser/src/autofill @bitwarden/team-autofill-dev
|
||||
@@ -143,8 +156,6 @@ apps/desktop/desktop_native/core/src/ssh_agent @bitwarden/team-platform-dev @bit
|
||||
.github/workflows/release-desktop-beta.yml
|
||||
.github/workflows/release-desktop.yml
|
||||
.github/workflows/release-web.yml
|
||||
.github/workflows/version-auto-bump.yml
|
||||
.github/workflows/version-bump.yml
|
||||
|
||||
## Docker files have shared ownership ##
|
||||
**/Dockerfile
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import * as fet from "node-fetch";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
|
||||
import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-array-buffer";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
@@ -10,16 +9,36 @@ import { Response } from "../models/response";
|
||||
import { FileResponse } from "../models/response/file.response";
|
||||
import { CliUtils } from "../utils";
|
||||
|
||||
/**
|
||||
* Used to download and save attachments
|
||||
*/
|
||||
export abstract class DownloadCommand {
|
||||
constructor(protected encryptService: EncryptService) {}
|
||||
/**
|
||||
* @param encryptService - Needed for decryption of the retrieved attachment
|
||||
* @param apiService - Needed to override the existing nativeFetch which is available as of Node 18, to support proxies
|
||||
*/
|
||||
constructor(
|
||||
protected encryptService: EncryptService,
|
||||
protected apiService: ApiService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Fetches an attachment via the url, decrypts it's content and saves it to a file
|
||||
* @param url - url used to retrieve the attachment
|
||||
* @param key - SymmetricCryptoKey to decrypt the file contents
|
||||
* @param fileName - filename used when written to disk
|
||||
* @param output - If output is empty or `--raw` was passed to the initial command the content is output onto stdout
|
||||
* @returns Promise<FileResponse>
|
||||
*/
|
||||
protected async saveAttachmentToFile(
|
||||
url: string,
|
||||
key: SymmetricCryptoKey,
|
||||
fileName: string,
|
||||
output?: string,
|
||||
) {
|
||||
const response = await fet.default(new fet.Request(url, { headers: { cache: "no-cache" } }));
|
||||
const response = await this.apiService.nativeFetch(
|
||||
new Request(url, { headers: { cache: "no-cache" } }),
|
||||
);
|
||||
if (response.status !== 200) {
|
||||
return Response.error(
|
||||
"A " + response.status + " error occurred while downloading the attachment.",
|
||||
|
||||
@@ -60,13 +60,13 @@ export class GetCommand extends DownloadCommand {
|
||||
private keyService: KeyService,
|
||||
encryptService: EncryptService,
|
||||
private searchService: SearchService,
|
||||
private apiService: ApiService,
|
||||
protected apiService: ApiService,
|
||||
private organizationService: OrganizationService,
|
||||
private eventCollectionService: EventCollectionService,
|
||||
private accountProfileService: BillingAccountProfileStateService,
|
||||
private accountService: AccountService,
|
||||
) {
|
||||
super(encryptService);
|
||||
super(encryptService, apiService);
|
||||
}
|
||||
|
||||
async run(object: string, id: string, cmdOptions: Record<string, any>): Promise<Response> {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import * as fetch from "node-fetch";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
|
||||
import { Response } from "../models/response";
|
||||
@@ -14,12 +13,15 @@ const UPDATE_COMMAND = "npm install -g @bitwarden/cli";
|
||||
export class UpdateCommand {
|
||||
inPkg = false;
|
||||
|
||||
constructor(private platformUtilsService: PlatformUtilsService) {
|
||||
constructor(
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
protected apiService: ApiService,
|
||||
) {
|
||||
this.inPkg = !!(process as any).pkg;
|
||||
}
|
||||
|
||||
async run(): Promise<Response> {
|
||||
const response = await fetch.default(CLIENTS_RELEASE_LIST_ENDPOINT);
|
||||
const response = await this.apiService.nativeFetch(new Request(CLIENTS_RELEASE_LIST_ENDPOINT));
|
||||
if (response.status !== 200) {
|
||||
return Response.error("Error contacting update API: " + response.status);
|
||||
}
|
||||
|
||||
@@ -157,6 +157,7 @@ export class OssServeConfigurator {
|
||||
this.serviceContainer.environmentService,
|
||||
this.serviceContainer.searchService,
|
||||
this.serviceContainer.encryptService,
|
||||
this.serviceContainer.apiService,
|
||||
);
|
||||
this.sendEditCommand = new SendEditCommand(
|
||||
this.serviceContainer.sendService,
|
||||
|
||||
@@ -428,7 +428,10 @@ export class Program extends BaseProgram {
|
||||
writeLn("", true);
|
||||
})
|
||||
.action(async () => {
|
||||
const command = new UpdateCommand(this.serviceContainer.platformUtilsService);
|
||||
const command = new UpdateCommand(
|
||||
this.serviceContainer.platformUtilsService,
|
||||
this.serviceContainer.apiService,
|
||||
);
|
||||
const response = await command.run();
|
||||
this.processResponse(response);
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { OptionValues } from "commander";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
@@ -20,8 +21,9 @@ export class SendGetCommand extends DownloadCommand {
|
||||
private environmentService: EnvironmentService,
|
||||
private searchService: SearchService,
|
||||
encryptService: EncryptService,
|
||||
apiService: ApiService,
|
||||
) {
|
||||
super(encryptService);
|
||||
super(encryptService, apiService);
|
||||
}
|
||||
|
||||
async run(id: string, options: OptionValues) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { OptionValues } from "commander";
|
||||
import * as inquirer from "inquirer";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
|
||||
@@ -35,8 +36,9 @@ export class SendReceiveCommand extends DownloadCommand {
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private environmentService: EnvironmentService,
|
||||
private sendApiService: SendApiService,
|
||||
apiService: ApiService,
|
||||
) {
|
||||
super(encryptService);
|
||||
super(encryptService, apiService);
|
||||
}
|
||||
|
||||
async run(url: string, options: OptionValues): Promise<Response> {
|
||||
|
||||
@@ -108,6 +108,7 @@ export class SendProgram extends BaseProgram {
|
||||
this.serviceContainer.platformUtilsService,
|
||||
this.serviceContainer.environmentService,
|
||||
this.serviceContainer.sendApiService,
|
||||
this.serviceContainer.apiService,
|
||||
);
|
||||
const response = await cmd.run(url, options);
|
||||
this.processResponse(response);
|
||||
@@ -190,6 +191,7 @@ export class SendProgram extends BaseProgram {
|
||||
this.serviceContainer.environmentService,
|
||||
this.serviceContainer.searchService,
|
||||
this.serviceContainer.encryptService,
|
||||
this.serviceContainer.apiService,
|
||||
);
|
||||
const response = await cmd.run(id, options);
|
||||
this.processResponse(response);
|
||||
@@ -249,6 +251,7 @@ export class SendProgram extends BaseProgram {
|
||||
this.serviceContainer.environmentService,
|
||||
this.serviceContainer.searchService,
|
||||
this.serviceContainer.encryptService,
|
||||
this.serviceContainer.apiService,
|
||||
);
|
||||
const cmd = new SendEditCommand(
|
||||
this.serviceContainer.sendService,
|
||||
|
||||
71
apps/desktop/desktop_native/Cargo.lock
generated
71
apps/desktop/desktop_native/Cargo.lock
generated
@@ -338,7 +338,7 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
[[package]]
|
||||
name = "bitwarden-russh"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/bitwarden/bitwarden-russh.git?rev=b4e7f2fedbe3df8c35545feb000176d3e7b2bc32#b4e7f2fedbe3df8c35545feb000176d3e7b2bc32"
|
||||
source = "git+https://github.com/bitwarden/bitwarden-russh.git?rev=23b50e3bbe6d56ef19ab0e98e8bb1462cb6d77ae#23b50e3bbe6d56ef19ab0e98e8bb1462cb6d77ae"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byteorder",
|
||||
@@ -584,6 +584,25 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.20"
|
||||
@@ -773,6 +792,7 @@ dependencies = [
|
||||
"sha2",
|
||||
"ssh-encoding",
|
||||
"ssh-key",
|
||||
"sysinfo",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
@@ -903,6 +923,12 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "embed_plist"
|
||||
version = "1.2.2"
|
||||
@@ -1490,6 +1516,15 @@ dependencies = [
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.3"
|
||||
@@ -2051,6 +2086,26 @@ dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "recvmsg"
|
||||
version = "1.0.0"
|
||||
@@ -2453,6 +2508,20 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3b5ae3f4f7d64646c46c4cae4e3f01d1c5d255c7406fdd7c7f999a94e488791"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"memchr",
|
||||
"ntapi",
|
||||
"rayon",
|
||||
"windows 0.57.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.14.0"
|
||||
|
||||
@@ -49,7 +49,7 @@ ssh-key = { version = "=0.6.7", default-features = false, features = [
|
||||
"rsa",
|
||||
"getrandom",
|
||||
] }
|
||||
bitwarden-russh = { git = "https://github.com/bitwarden/bitwarden-russh.git", rev = "b4e7f2fedbe3df8c35545feb000176d3e7b2bc32" }
|
||||
bitwarden-russh = { git = "https://github.com/bitwarden/bitwarden-russh.git", rev = "23b50e3bbe6d56ef19ab0e98e8bb1462cb6d77ae" }
|
||||
tokio = { version = "=1.41.1", features = ["io-util", "sync", "macros", "net"] }
|
||||
tokio-stream = { version = "=0.1.15", features = ["net"] }
|
||||
tokio-util = { version = "=0.7.12", features = ["codec"] }
|
||||
@@ -59,6 +59,7 @@ rand_chacha = "=0.3.1"
|
||||
pkcs8 = { version = "=0.10.2", features = ["alloc", "encryption", "pem"] }
|
||||
rsa = "=0.9.6"
|
||||
ed25519 = { version = "=2.2.3", features = ["pkcs8"] }
|
||||
sysinfo = { version = "0.32.0", features = ["windows"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
widestring = { version = "=1.1.0", optional = true }
|
||||
@@ -72,6 +73,7 @@ windows = { version = "=0.58.0", features = [
|
||||
"Win32_System_WinRT",
|
||||
"Win32_UI_Input_KeyboardAndMouse",
|
||||
"Win32_UI_WindowsAndMessaging",
|
||||
"Win32_System_Pipes",
|
||||
], optional = true }
|
||||
|
||||
[target.'cfg(windows)'.dev-dependencies]
|
||||
|
||||
@@ -310,12 +310,16 @@ mod tests {
|
||||
os_key_part_b64: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=".to_owned(),
|
||||
client_key_part_b64: Some("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=".to_owned()),
|
||||
};
|
||||
crate::password::set_password(test, test, secret).await.unwrap();
|
||||
crate::password::set_password(test, test, secret)
|
||||
.await
|
||||
.unwrap();
|
||||
let result =
|
||||
<Biometric as BiometricTrait>::get_biometric_secret(test, test, Some(key_material))
|
||||
.await
|
||||
.unwrap();
|
||||
crate::password::delete_password("test", "test").await.unwrap();
|
||||
crate::password::delete_password("test", "test")
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(result, secret);
|
||||
}
|
||||
|
||||
@@ -328,19 +332,24 @@ mod tests {
|
||||
os_key_part_b64: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=".to_owned(),
|
||||
client_key_part_b64: Some("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=".to_owned()),
|
||||
};
|
||||
crate::password::set_password(test, test, &secret.to_string()).await.unwrap();
|
||||
crate::password::set_password(test, test, &secret.to_string())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let result =
|
||||
<Biometric as BiometricTrait>::get_biometric_secret(test, test, Some(key_material))
|
||||
.await
|
||||
.unwrap();
|
||||
crate::password::delete_password("test", "test").await.unwrap();
|
||||
crate::password::delete_password("test", "test")
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(result, "secret");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn set_biometric_secret_requires_key() {
|
||||
let result = <Biometric as BiometricTrait>::set_biometric_secret("", "", "", None, "").await;
|
||||
let result =
|
||||
<Biometric as BiometricTrait>::set_biometric_secret("", "", "", None, "").await;
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
result.unwrap_err().to_string(),
|
||||
|
||||
@@ -28,12 +28,18 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test() {
|
||||
set_password("BitwardenTest", "BitwardenTest", "Random").await.unwrap();
|
||||
set_password("BitwardenTest", "BitwardenTest", "Random")
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
"Random",
|
||||
get_password("BitwardenTest", "BitwardenTest").await.unwrap()
|
||||
get_password("BitwardenTest", "BitwardenTest")
|
||||
.await
|
||||
.unwrap()
|
||||
);
|
||||
delete_password("BitwardenTest", "BitwardenTest").await.unwrap();
|
||||
delete_password("BitwardenTest", "BitwardenTest")
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Ensure password is deleted
|
||||
match get_password("BitwardenTest", "BitwardenTest").await {
|
||||
|
||||
@@ -5,9 +5,7 @@ use std::collections::HashMap;
|
||||
pub async fn get_password(service: &str, account: &str) -> Result<String> {
|
||||
match get_password_new(service, account).await {
|
||||
Ok(res) => Ok(res),
|
||||
Err(_) => {
|
||||
get_password_legacy(service, account).await
|
||||
}
|
||||
Err(_) => get_password_legacy(service, account).await,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +18,8 @@ async fn get_password_new(service: &str, account: &str) -> Result<String> {
|
||||
Some(res) => {
|
||||
let secret = res.secret().await?;
|
||||
Ok(String::from_utf8(secret.to_vec())?)
|
||||
},
|
||||
None => Err(anyhow!("no result"))
|
||||
}
|
||||
None => Err(anyhow!("no result")),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,20 +35,30 @@ async fn get_password_legacy(service: &str, account: &str) -> Result<String> {
|
||||
match res {
|
||||
Some(res) => {
|
||||
let secret = res.secret().await?;
|
||||
println!("deleting legacy secret service entry {} {}", service, account);
|
||||
println!(
|
||||
"deleting legacy secret service entry {} {}",
|
||||
service, account
|
||||
);
|
||||
keyring.delete(&attributes).await?;
|
||||
let secret_string = String::from_utf8(secret.to_vec())?;
|
||||
set_password(service, account, &secret_string).await?;
|
||||
Ok(secret_string)
|
||||
},
|
||||
None => Err(anyhow!("no result"))
|
||||
}
|
||||
None => Err(anyhow!("no result")),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn set_password(service: &str, account: &str, password: &str) -> Result<()> {
|
||||
let keyring = oo7::Keyring::new().await?;
|
||||
let attributes = HashMap::from([("service", service), ("account", account)]);
|
||||
keyring.create_item("org.freedesktop.Secret.Generic", &attributes, password, true).await?;
|
||||
keyring
|
||||
.create_item(
|
||||
"org.freedesktop.Secret.Generic",
|
||||
&attributes,
|
||||
password,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -74,22 +82,25 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test() {
|
||||
set_password("BitwardenTest", "BitwardenTest", "Random").await.unwrap();
|
||||
set_password("BitwardenTest", "BitwardenTest", "Random")
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
"Random",
|
||||
get_password("BitwardenTest", "BitwardenTest").await.unwrap()
|
||||
get_password("BitwardenTest", "BitwardenTest")
|
||||
.await
|
||||
.unwrap()
|
||||
);
|
||||
delete_password("BitwardenTest", "BitwardenTest").await.unwrap();
|
||||
delete_password("BitwardenTest", "BitwardenTest")
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Ensure password is deleted
|
||||
match get_password("BitwardenTest", "BitwardenTest").await {
|
||||
Ok(_) => {
|
||||
panic!("Got a result")
|
||||
}
|
||||
Err(e) => assert_eq!(
|
||||
"no result",
|
||||
e.to_string()
|
||||
),
|
||||
Err(e) => assert_eq!("no result", e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,10 +108,7 @@ mod tests {
|
||||
async fn test_error_no_password() {
|
||||
match get_password("Unknown", "Unknown").await {
|
||||
Ok(_) => panic!("Got a result"),
|
||||
Err(e) => assert_eq!(
|
||||
"no result",
|
||||
e.to_string()
|
||||
),
|
||||
Err(e) => assert_eq!("no result", e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,12 +112,18 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test() {
|
||||
set_password("BitwardenTest", "BitwardenTest", "Random").await.unwrap();
|
||||
set_password("BitwardenTest", "BitwardenTest", "Random")
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
"Random",
|
||||
get_password("BitwardenTest", "BitwardenTest").await.unwrap()
|
||||
get_password("BitwardenTest", "BitwardenTest")
|
||||
.await
|
||||
.unwrap()
|
||||
);
|
||||
delete_password("BitwardenTest", "BitwardenTest").await.unwrap();
|
||||
delete_password("BitwardenTest", "BitwardenTest")
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Ensure password is deleted
|
||||
match get_password("BitwardenTest", "BitwardenTest").await {
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, AtomicU32},
|
||||
Arc,
|
||||
};
|
||||
|
||||
use tokio::sync::Mutex;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
@@ -10,34 +13,52 @@ use bitwarden_russh::ssh_agent::{self, Key};
|
||||
#[cfg_attr(target_os = "linux", path = "unix.rs")]
|
||||
mod platform_ssh_agent;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
mod peercred_unix_listener_stream;
|
||||
|
||||
pub mod generator;
|
||||
pub mod importer;
|
||||
|
||||
pub mod peerinfo;
|
||||
#[derive(Clone)]
|
||||
pub struct BitwardenDesktopAgent {
|
||||
keystore: ssh_agent::KeyStore,
|
||||
cancellation_token: CancellationToken,
|
||||
show_ui_request_tx: tokio::sync::mpsc::Sender<(u32, (String, bool))>,
|
||||
show_ui_request_tx: tokio::sync::mpsc::Sender<SshAgentUIRequest>,
|
||||
get_ui_response_rx: Arc<Mutex<tokio::sync::broadcast::Receiver<(u32, bool)>>>,
|
||||
request_id: Arc<Mutex<u32>>,
|
||||
request_id: Arc<AtomicU32>,
|
||||
/// before first unlock, or after account switching, listing keys should require an unlock to get a list of public keys
|
||||
needs_unlock: Arc<Mutex<bool>>,
|
||||
is_running: Arc<tokio::sync::Mutex<bool>>,
|
||||
needs_unlock: Arc<AtomicBool>,
|
||||
is_running: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl ssh_agent::Agent for BitwardenDesktopAgent {
|
||||
async fn confirm(&self, ssh_key: Key) -> bool {
|
||||
if !*self.is_running.lock().await {
|
||||
pub struct SshAgentUIRequest {
|
||||
pub request_id: u32,
|
||||
pub cipher_id: Option<String>,
|
||||
pub process_name: String,
|
||||
pub is_list: bool,
|
||||
}
|
||||
|
||||
impl ssh_agent::Agent<peerinfo::models::PeerInfo> for BitwardenDesktopAgent {
|
||||
async fn confirm(&self, ssh_key: Key, info: &peerinfo::models::PeerInfo) -> bool {
|
||||
if !self.is_running() {
|
||||
println!("[BitwardenDesktopAgent] Agent is not running, but tried to call confirm");
|
||||
return false;
|
||||
}
|
||||
|
||||
let request_id = self.get_request_id().await;
|
||||
println!(
|
||||
"[SSH Agent] Confirming request from application: {}",
|
||||
info.process_name()
|
||||
);
|
||||
|
||||
let mut rx_channel = self.get_ui_response_rx.lock().await.resubscribe();
|
||||
let message = (request_id, (ssh_key.cipher_uuid.clone(), false));
|
||||
self.show_ui_request_tx
|
||||
.send(message)
|
||||
.send(SshAgentUIRequest {
|
||||
request_id,
|
||||
cipher_id: Some(ssh_key.cipher_uuid.clone()),
|
||||
process_name: info.process_name().to_string(),
|
||||
is_list: false,
|
||||
})
|
||||
.await
|
||||
.expect("Should send request to ui");
|
||||
while let Ok((id, response)) = rx_channel.recv().await {
|
||||
@@ -48,15 +69,20 @@ impl ssh_agent::Agent for BitwardenDesktopAgent {
|
||||
false
|
||||
}
|
||||
|
||||
async fn can_list(&self) -> bool {
|
||||
if !*self.needs_unlock.lock().await{
|
||||
async fn can_list(&self, info: &peerinfo::models::PeerInfo) -> bool {
|
||||
if !self.needs_unlock.load(std::sync::atomic::Ordering::Relaxed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let request_id = self.get_request_id().await;
|
||||
|
||||
let mut rx_channel = self.get_ui_response_rx.lock().await.resubscribe();
|
||||
let message = (request_id, ("".to_string(), true));
|
||||
let message = SshAgentUIRequest {
|
||||
request_id,
|
||||
cipher_id: None,
|
||||
process_name: info.process_name().to_string(),
|
||||
is_list: true,
|
||||
};
|
||||
self.show_ui_request_tx
|
||||
.send(message)
|
||||
.await
|
||||
@@ -72,13 +98,13 @@ impl ssh_agent::Agent for BitwardenDesktopAgent {
|
||||
|
||||
impl BitwardenDesktopAgent {
|
||||
pub fn stop(&self) {
|
||||
if !*self.is_running.blocking_lock() {
|
||||
if !self.is_running() {
|
||||
println!("[BitwardenDesktopAgent] Tried to stop agent while it is not running");
|
||||
return;
|
||||
}
|
||||
|
||||
*self.is_running.blocking_lock() = false;
|
||||
self.cancellation_token.cancel();
|
||||
self.is_running
|
||||
.store(false, std::sync::atomic::Ordering::Relaxed);
|
||||
self.keystore
|
||||
.0
|
||||
.write()
|
||||
@@ -90,7 +116,7 @@ impl BitwardenDesktopAgent {
|
||||
&mut self,
|
||||
new_keys: Vec<(String, String, String)>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
if !*self.is_running.blocking_lock() {
|
||||
if !self.is_running() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"[BitwardenDesktopAgent] Tried to set keys while agent is not running"
|
||||
));
|
||||
@@ -99,7 +125,8 @@ impl BitwardenDesktopAgent {
|
||||
let keystore = &mut self.keystore;
|
||||
keystore.0.write().expect("RwLock is not poisoned").clear();
|
||||
|
||||
*self.needs_unlock.blocking_lock() = false;
|
||||
self.needs_unlock
|
||||
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
for (key, name, cipher_id) in new_keys.iter() {
|
||||
match parse_key_safe(&key) {
|
||||
@@ -127,7 +154,7 @@ impl BitwardenDesktopAgent {
|
||||
}
|
||||
|
||||
pub fn lock(&mut self) -> Result<(), anyhow::Error> {
|
||||
if !*self.is_running.blocking_lock() {
|
||||
if !self.is_running() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"[BitwardenDesktopAgent] Tried to lock agent, but it is not running"
|
||||
));
|
||||
@@ -148,24 +175,26 @@ impl BitwardenDesktopAgent {
|
||||
pub fn clear_keys(&mut self) -> Result<(), anyhow::Error> {
|
||||
let keystore = &mut self.keystore;
|
||||
keystore.0.write().expect("RwLock is not poisoned").clear();
|
||||
*self.needs_unlock.blocking_lock() = true;
|
||||
self.needs_unlock
|
||||
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_request_id(&self) -> u32 {
|
||||
if !*self.is_running.lock().await {
|
||||
if !self.is_running() {
|
||||
println!("[BitwardenDesktopAgent] Agent is not running, but tried to get request id");
|
||||
return 0;
|
||||
}
|
||||
|
||||
let mut request_id = self.request_id.lock().await;
|
||||
*request_id += 1;
|
||||
*request_id
|
||||
let request_id = self
|
||||
.request_id
|
||||
.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
request_id
|
||||
}
|
||||
|
||||
pub fn is_running(self) -> bool {
|
||||
return self.is_running.blocking_lock().clone();
|
||||
pub fn is_running(&self) -> bool {
|
||||
self.is_running.load(std::sync::atomic::Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,32 @@
|
||||
use std::{
|
||||
io, pin::Pin, sync::Arc, task::{Context, Poll}
|
||||
};
|
||||
|
||||
use futures::Stream;
|
||||
use std::os::windows::prelude::AsRawHandle as _;
|
||||
use std::{
|
||||
io,
|
||||
pin::Pin,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
},
|
||||
task::{Context, Poll},
|
||||
};
|
||||
use tokio::{
|
||||
net::windows::named_pipe::{NamedPipeServer, ServerOptions},
|
||||
select,
|
||||
};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use windows::Win32::{Foundation::HANDLE, System::Pipes::GetNamedPipeClientProcessId};
|
||||
|
||||
use crate::ssh_agent::peerinfo::{self, models::PeerInfo};
|
||||
|
||||
const PIPE_NAME: &str = r"\\.\pipe\openssh-ssh-agent";
|
||||
|
||||
#[pin_project::pin_project]
|
||||
pub struct NamedPipeServerStream {
|
||||
rx: tokio::sync::mpsc::Receiver<NamedPipeServer>,
|
||||
rx: tokio::sync::mpsc::Receiver<(NamedPipeServer, PeerInfo)>,
|
||||
}
|
||||
|
||||
impl NamedPipeServerStream {
|
||||
pub fn new(cancellation_token: CancellationToken, is_running: Arc<tokio::sync::Mutex<bool>>) -> Self {
|
||||
pub fn new(cancellation_token: CancellationToken, is_running: Arc<AtomicBool>) -> Self {
|
||||
let (tx, rx) = tokio::sync::mpsc::channel(16);
|
||||
tokio::spawn(async move {
|
||||
println!(
|
||||
@@ -30,7 +39,7 @@ impl NamedPipeServerStream {
|
||||
println!("[SSH Agent Native Module] Encountered an error creating the first pipe. The system's openssh service must likely be disabled");
|
||||
println!("[SSH Agent Natvie Module] error: {}", err);
|
||||
cancellation_token.cancel();
|
||||
*is_running.lock().await = false;
|
||||
is_running.store(false, Ordering::Relaxed);
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -43,14 +52,32 @@ impl NamedPipeServerStream {
|
||||
}
|
||||
_ = listener.connect() => {
|
||||
println!("[SSH Agent Native Module] Incoming connection");
|
||||
tx.send(listener).await.unwrap();
|
||||
let handle = HANDLE(listener.as_raw_handle());
|
||||
let mut pid = 0;
|
||||
unsafe {
|
||||
if let Err(e) = GetNamedPipeClientProcessId(handle, &mut pid) {
|
||||
println!("Error getting named pipe client process id {}", e);
|
||||
continue
|
||||
}
|
||||
};
|
||||
|
||||
let peer_info = peerinfo::gather::get_peer_info(pid as u32);
|
||||
let peer_info = match peer_info {
|
||||
Err(err) => {
|
||||
println!("Failed getting process info for pid {} {}", pid, err);
|
||||
continue
|
||||
},
|
||||
Ok(info) => info,
|
||||
};
|
||||
|
||||
tx.send((listener, peer_info)).await.unwrap();
|
||||
|
||||
listener = match ServerOptions::new().create(PIPE_NAME) {
|
||||
Ok(pipe) => pipe,
|
||||
Err(err) => {
|
||||
println!("[SSH Agent Native Module] Encountered an error creating a new pipe {}", err);
|
||||
cancellation_token.cancel();
|
||||
*is_running.lock().await = false;
|
||||
is_running.store(false, Ordering::Relaxed);
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -63,12 +90,12 @@ impl NamedPipeServerStream {
|
||||
}
|
||||
|
||||
impl Stream for NamedPipeServerStream {
|
||||
type Item = io::Result<NamedPipeServer>;
|
||||
type Item = io::Result<(NamedPipeServer, PeerInfo)>;
|
||||
|
||||
fn poll_next(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<io::Result<NamedPipeServer>>> {
|
||||
) -> Poll<Option<io::Result<(NamedPipeServer, PeerInfo)>>> {
|
||||
let this = self.project();
|
||||
|
||||
this.rx.poll_recv(cx).map(|v| v.map(Ok))
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
use futures::Stream;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use tokio::net::{UnixListener, UnixStream};
|
||||
|
||||
use super::peerinfo;
|
||||
use super::peerinfo::models::PeerInfo;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PeercredUnixListenerStream {
|
||||
inner: UnixListener,
|
||||
}
|
||||
|
||||
impl PeercredUnixListenerStream {
|
||||
pub fn new(listener: UnixListener) -> Self {
|
||||
Self { inner: listener }
|
||||
}
|
||||
}
|
||||
|
||||
impl Stream for PeercredUnixListenerStream {
|
||||
type Item = io::Result<(UnixStream, PeerInfo)>;
|
||||
|
||||
fn poll_next(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<io::Result<(UnixStream, PeerInfo)>>> {
|
||||
match self.inner.poll_accept(cx) {
|
||||
Poll::Ready(Ok((stream, _))) => {
|
||||
let pid = match stream.peer_cred() {
|
||||
Ok(peer) => match peer.pid() {
|
||||
Some(pid) => pid,
|
||||
None => {
|
||||
return Poll::Ready(Some(Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Failed to get peer PID",
|
||||
))));
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
return Poll::Ready(Some(Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("Failed to get peer credentials: {}", err),
|
||||
))));
|
||||
}
|
||||
};
|
||||
let peer_info = peerinfo::gather::get_peer_info(pid as u32);
|
||||
match peer_info {
|
||||
Ok(info) => Poll::Ready(Some(Ok((stream, info)))),
|
||||
Err(err) => Poll::Ready(Some(Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("Failed to get peer info: {}", err),
|
||||
)))),
|
||||
}
|
||||
}
|
||||
Poll::Ready(Err(err)) => Poll::Ready(Some(Err(err))),
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<UnixListener> for PeercredUnixListenerStream {
|
||||
fn as_ref(&self) -> &UnixListener {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<UnixListener> for PeercredUnixListenerStream {
|
||||
fn as_mut(&mut self) -> &mut UnixListener {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
use sysinfo::{Pid, System};
|
||||
|
||||
use super::models::PeerInfo;
|
||||
|
||||
pub fn get_peer_info(peer_pid: u32) -> Result<PeerInfo, String> {
|
||||
let s = System::new_all();
|
||||
if let Some(process) = s.process(Pid::from_u32(peer_pid)) {
|
||||
let peer_process_name = match process.name().to_str() {
|
||||
Some(name) => name.to_string(),
|
||||
None => {
|
||||
return Err("Failed to get process name".to_string());
|
||||
}
|
||||
};
|
||||
|
||||
return Ok(PeerInfo::new(
|
||||
peer_pid,
|
||||
process.pid().as_u32(),
|
||||
peer_process_name,
|
||||
));
|
||||
}
|
||||
|
||||
Err("Failed to get process".to_string())
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod gather;
|
||||
pub mod models;
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Peerinfo represents the information of a peer process connecting over a socket.
|
||||
* This can be later extended to include more information (icon, app name) for the corresponding application.
|
||||
*/
|
||||
#[derive(Debug)]
|
||||
pub struct PeerInfo {
|
||||
uid: u32,
|
||||
pid: u32,
|
||||
process_name: String,
|
||||
}
|
||||
|
||||
impl PeerInfo {
|
||||
pub fn new(uid: u32, pid: u32, process_name: String) -> Self {
|
||||
Self {
|
||||
uid,
|
||||
pid,
|
||||
process_name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uid(&self) -> u32 {
|
||||
self.uid
|
||||
}
|
||||
|
||||
pub fn pid(&self) -> u32 {
|
||||
self.pid
|
||||
}
|
||||
|
||||
pub fn process_name(&self) -> &str {
|
||||
&self.process_name
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,10 @@ use std::{
|
||||
collections::HashMap,
|
||||
fs,
|
||||
os::unix::fs::PermissionsExt,
|
||||
sync::{Arc, RwLock},
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicU32},
|
||||
Arc, RwLock,
|
||||
},
|
||||
};
|
||||
|
||||
use bitwarden_russh::ssh_agent;
|
||||
@@ -10,11 +13,13 @@ use homedir::my_home;
|
||||
use tokio::{net::UnixListener, sync::Mutex};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use super::BitwardenDesktopAgent;
|
||||
use crate::ssh_agent::peercred_unix_listener_stream::PeercredUnixListenerStream;
|
||||
|
||||
use super::{BitwardenDesktopAgent, SshAgentUIRequest};
|
||||
|
||||
impl BitwardenDesktopAgent {
|
||||
pub async fn start_server(
|
||||
auth_request_tx: tokio::sync::mpsc::Sender<(u32, (String, bool))>,
|
||||
auth_request_tx: tokio::sync::mpsc::Sender<SshAgentUIRequest>,
|
||||
auth_response_rx: Arc<Mutex<tokio::sync::broadcast::Receiver<(u32, bool)>>>,
|
||||
) -> Result<Self, anyhow::Error> {
|
||||
let agent = BitwardenDesktopAgent {
|
||||
@@ -22,9 +27,9 @@ impl BitwardenDesktopAgent {
|
||||
cancellation_token: CancellationToken::new(),
|
||||
show_ui_request_tx: auth_request_tx,
|
||||
get_ui_response_rx: auth_response_rx,
|
||||
request_id: Arc::new(tokio::sync::Mutex::new(0)),
|
||||
needs_unlock: Arc::new(tokio::sync::Mutex::new(true)),
|
||||
is_running: Arc::new(tokio::sync::Mutex::new(false)),
|
||||
request_id: Arc::new(AtomicU32::new(0)),
|
||||
needs_unlock: Arc::new(AtomicBool::new(false)),
|
||||
is_running: Arc::new(AtomicBool::new(false)),
|
||||
};
|
||||
let cloned_agent_state = agent.clone();
|
||||
tokio::spawn(async move {
|
||||
@@ -75,18 +80,23 @@ impl BitwardenDesktopAgent {
|
||||
return;
|
||||
}
|
||||
|
||||
let wrapper = tokio_stream::wrappers::UnixListenerStream::new(listener);
|
||||
let stream = PeercredUnixListenerStream::new(listener);
|
||||
|
||||
let cloned_keystore = cloned_agent_state.keystore.clone();
|
||||
let cloned_cancellation_token = cloned_agent_state.cancellation_token.clone();
|
||||
*cloned_agent_state.is_running.lock().await = true;
|
||||
cloned_agent_state
|
||||
.is_running
|
||||
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
let _ = ssh_agent::serve(
|
||||
wrapper,
|
||||
stream,
|
||||
cloned_agent_state.clone(),
|
||||
cloned_keystore,
|
||||
cloned_cancellation_token,
|
||||
)
|
||||
.await;
|
||||
*cloned_agent_state.is_running.lock().await = false;
|
||||
cloned_agent_state
|
||||
.is_running
|
||||
.store(false, std::sync::atomic::Ordering::Relaxed);
|
||||
println!("[SSH Agent Native Module] SSH Agent server exited");
|
||||
}
|
||||
Err(e) => {
|
||||
|
||||
@@ -3,16 +3,19 @@ pub mod named_pipe_listener_stream;
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, RwLock},
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicU32},
|
||||
Arc, RwLock,
|
||||
},
|
||||
};
|
||||
use tokio::sync::Mutex;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use super::BitwardenDesktopAgent;
|
||||
use super::{BitwardenDesktopAgent, SshAgentUIRequest};
|
||||
|
||||
impl BitwardenDesktopAgent {
|
||||
pub async fn start_server(
|
||||
auth_request_tx: tokio::sync::mpsc::Sender<(u32, (String, bool))>,
|
||||
auth_request_tx: tokio::sync::mpsc::Sender<SshAgentUIRequest>,
|
||||
auth_response_rx: Arc<Mutex<tokio::sync::broadcast::Receiver<(u32, bool)>>>,
|
||||
) -> Result<Self, anyhow::Error> {
|
||||
let agent_state = BitwardenDesktopAgent {
|
||||
@@ -20,9 +23,9 @@ impl BitwardenDesktopAgent {
|
||||
show_ui_request_tx: auth_request_tx,
|
||||
get_ui_response_rx: auth_response_rx,
|
||||
cancellation_token: CancellationToken::new(),
|
||||
request_id: Arc::new(tokio::sync::Mutex::new(0)),
|
||||
needs_unlock: Arc::new(tokio::sync::Mutex::new(true)),
|
||||
is_running: Arc::new(tokio::sync::Mutex::new(true)),
|
||||
request_id: Arc::new(AtomicU32::new(0)),
|
||||
needs_unlock: Arc::new(AtomicBool::new(true)),
|
||||
is_running: Arc::new(AtomicBool::new(true)),
|
||||
};
|
||||
let stream = named_pipe_listener_stream::NamedPipeServerStream::new(
|
||||
agent_state.cancellation_token.clone(),
|
||||
@@ -31,7 +34,9 @@ impl BitwardenDesktopAgent {
|
||||
|
||||
let cloned_agent_state = agent_state.clone();
|
||||
tokio::spawn(async move {
|
||||
*cloned_agent_state.is_running.lock().await = true;
|
||||
cloned_agent_state
|
||||
.is_running
|
||||
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
let _ = ssh_agent::serve(
|
||||
stream,
|
||||
cloned_agent_state.clone(),
|
||||
@@ -39,7 +44,9 @@ impl BitwardenDesktopAgent {
|
||||
cloned_agent_state.cancellation_token.clone(),
|
||||
)
|
||||
.await;
|
||||
*cloned_agent_state.is_running.lock().await = false;
|
||||
cloned_agent_state
|
||||
.is_running
|
||||
.store(false, std::sync::atomic::Ordering::Relaxed);
|
||||
});
|
||||
Ok(agent_state)
|
||||
}
|
||||
|
||||
2
apps/desktop/desktop_native/napi/index.d.ts
vendored
2
apps/desktop/desktop_native/napi/index.d.ts
vendored
@@ -67,7 +67,7 @@ export declare namespace sshagent {
|
||||
status: SshKeyImportStatus
|
||||
sshKey?: SshKey
|
||||
}
|
||||
export function serve(callback: (err: Error | null, arg0: string, arg1: boolean) => any): Promise<SshAgentState>
|
||||
export function serve(callback: (err: Error | null, arg0: string | undefined | null, arg1: boolean, arg2: string) => any): Promise<SshAgentState>
|
||||
export function stop(agentState: SshAgentState): void
|
||||
export function isRunning(agentState: SshAgentState): boolean
|
||||
export function setKeys(agentState: SshAgentState, newKeys: Array<PrivateKey>): void
|
||||
|
||||
@@ -247,30 +247,28 @@ pub mod sshagent {
|
||||
|
||||
#[napi]
|
||||
pub async fn serve(
|
||||
callback: ThreadsafeFunction<(String, bool), CalleeHandled>,
|
||||
callback: ThreadsafeFunction<(Option<String>, bool, String), CalleeHandled>,
|
||||
) -> napi::Result<SshAgentState> {
|
||||
let (auth_request_tx, mut auth_request_rx) =
|
||||
tokio::sync::mpsc::channel::<(u32, (String, bool))>(32);
|
||||
tokio::sync::mpsc::channel::<desktop_core::ssh_agent::SshAgentUIRequest>(32);
|
||||
let (auth_response_tx, auth_response_rx) =
|
||||
tokio::sync::broadcast::channel::<(u32, bool)>(32);
|
||||
let auth_response_tx_arc = Arc::new(Mutex::new(auth_response_tx));
|
||||
tokio::spawn(async move {
|
||||
let _ = auth_response_rx;
|
||||
|
||||
while let Some((request_id, (cipher_uuid, is_list_request))) =
|
||||
auth_request_rx.recv().await
|
||||
{
|
||||
let cloned_request_id = request_id.clone();
|
||||
let cloned_cipher_uuid = cipher_uuid.clone();
|
||||
while let Some(request) = auth_request_rx.recv().await {
|
||||
let cloned_response_tx_arc = auth_response_tx_arc.clone();
|
||||
let cloned_callback = callback.clone();
|
||||
tokio::spawn(async move {
|
||||
let request_id = cloned_request_id;
|
||||
let cipher_uuid = cloned_cipher_uuid;
|
||||
let auth_response_tx_arc = cloned_response_tx_arc;
|
||||
let callback = cloned_callback;
|
||||
let promise_result: Result<Promise<bool>, napi::Error> = callback
|
||||
.call_async(Ok((cipher_uuid, is_list_request)))
|
||||
.call_async(Ok((
|
||||
request.cipher_id,
|
||||
request.is_list,
|
||||
request.process_name,
|
||||
)))
|
||||
.await;
|
||||
match promise_result {
|
||||
Ok(promise_result) => match promise_result.await {
|
||||
@@ -278,7 +276,7 @@ pub mod sshagent {
|
||||
let _ = auth_response_tx_arc
|
||||
.lock()
|
||||
.await
|
||||
.send((request_id, result))
|
||||
.send((request.request_id, result))
|
||||
.expect("should be able to send auth response to agent");
|
||||
}
|
||||
Err(e) => {
|
||||
@@ -286,7 +284,7 @@ pub mod sshagent {
|
||||
let _ = auth_response_tx_arc
|
||||
.lock()
|
||||
.await
|
||||
.send((request_id, false))
|
||||
.send((request.request_id, false))
|
||||
.expect("should be able to send auth response to agent");
|
||||
}
|
||||
},
|
||||
@@ -295,7 +293,7 @@ pub mod sshagent {
|
||||
let _ = auth_response_tx_arc
|
||||
.lock()
|
||||
.await
|
||||
.send((request_id, false))
|
||||
.send((request.request_id, false))
|
||||
.expect("should be able to send auth response to agent");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ pub fn create_key(key: &str, subkey: &str, value: &str) -> Result<()> {
|
||||
let key = convert_key(key)?;
|
||||
|
||||
let subkey = key.create(subkey)?;
|
||||
|
||||
|
||||
const DEFAULT: &str = "";
|
||||
subkey.set_string(DEFAULT, value)?;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ export class MainSshAgentService {
|
||||
init() {
|
||||
// handle sign request passing to UI
|
||||
sshagent
|
||||
.serve(async (err: Error, cipherId: string, isListRequest: boolean) => {
|
||||
.serve(async (err: Error, cipherId: string, isListRequest: boolean, processName: string) => {
|
||||
// clear all old (> SIGN_TIMEOUT) requests
|
||||
this.requestResponses = this.requestResponses.filter(
|
||||
(response) => response.timestamp > new Date(Date.now() - this.SIGN_TIMEOUT),
|
||||
@@ -41,6 +41,7 @@ export class MainSshAgentService {
|
||||
cipherId,
|
||||
isListRequest,
|
||||
requestId: id_for_this_request,
|
||||
processName,
|
||||
});
|
||||
|
||||
const result = await firstValueFrom(
|
||||
|
||||
@@ -122,6 +122,10 @@ export class SshAgentService implements OnDestroy {
|
||||
const cipherId = message.cipherId as string;
|
||||
const isListRequest = message.isListRequest as boolean;
|
||||
const requestId = message.requestId as number;
|
||||
let application = message.processName as string;
|
||||
if (application == "") {
|
||||
application = this.i18nService.t("unknownApplication");
|
||||
}
|
||||
|
||||
if (isListRequest) {
|
||||
const sshCiphers = ciphers.filter(
|
||||
@@ -151,7 +155,7 @@ export class SshAgentService implements OnDestroy {
|
||||
const dialogRef = ApproveSshRequestComponent.open(
|
||||
this.dialogService,
|
||||
cipher.name,
|
||||
this.i18nService.t("unknownApplication"),
|
||||
application,
|
||||
);
|
||||
|
||||
const result = await firstValueFrom(dialogRef.closed);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<div class="tw-mb-3 tw-flex tw-justify-between">
|
||||
<span class="tw-text-lg tw-pr-1 tw-font-bold">{{ "selectAPlan" | i18n }}</span>
|
||||
<!-- Discount Badge -->
|
||||
<div class="tw-items-center tw-gap-2">
|
||||
<div class="tw-flex tw-items-center tw-gap-2">
|
||||
<span
|
||||
class="tw-mr-1"
|
||||
*ngIf="
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
class="tw-cursor-pointer"
|
||||
rel="noreferrer noopener"
|
||||
>
|
||||
{{ "routeToPaymentMethodTrigger" | i18n }}
|
||||
{{ "clickHereToAddPaymentMethod" | i18n }}
|
||||
</a>
|
||||
</bit-banner>
|
||||
<app-header></app-header>
|
||||
|
||||
@@ -54,11 +54,11 @@ export class TrialFlowService {
|
||||
|
||||
getFreeTrialMessage(trialRemainingDays: number): string {
|
||||
if (trialRemainingDays >= 2) {
|
||||
return this.i18nService.t("freeTrialEndPrompt", trialRemainingDays);
|
||||
return this.i18nService.t("freeTrialEndPromptCount", trialRemainingDays);
|
||||
} else if (trialRemainingDays === 1) {
|
||||
return this.i18nService.t("freeTrialEndPromptForOneDayNoOrgName");
|
||||
return this.i18nService.t("freeTrialEndPromptTomorrowNoOrgName");
|
||||
} else {
|
||||
return this.i18nService.t("freeTrialEndingSoonWithoutOrgName");
|
||||
return this.i18nService.t("freeTrialEndingTodayWithoutOrgName");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
AsyncValidatorFn,
|
||||
ValidationErrors,
|
||||
} from "@angular/forms";
|
||||
import { Router } from "@angular/router";
|
||||
import { combineLatest, firstValueFrom, map, Observable, Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
@@ -26,6 +27,8 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
import { FreeFamiliesPolicyService } from "../services/free-families-policy.service";
|
||||
|
||||
interface RequestSponsorshipForm {
|
||||
selectedSponsorshipOrgId: FormControl<string>;
|
||||
sponsorshipEmail: FormControl<string>;
|
||||
@@ -62,6 +65,8 @@ export class SponsoredFamiliesComponent implements OnInit, OnDestroy {
|
||||
private toastService: ToastService,
|
||||
private configService: ConfigService,
|
||||
private policyService: PolicyService,
|
||||
private freeFamiliesPolicyService: FreeFamiliesPolicyService,
|
||||
private router: Router,
|
||||
) {
|
||||
this.sponsorshipForm = this.formBuilder.group<RequestSponsorshipForm>({
|
||||
selectedSponsorshipOrgId: new FormControl("", {
|
||||
@@ -86,6 +91,8 @@ export class SponsoredFamiliesComponent implements OnInit, OnDestroy {
|
||||
);
|
||||
|
||||
if (this.isFreeFamilyFlagEnabled) {
|
||||
await this.preventAccessToFreeFamiliesPage();
|
||||
|
||||
this.availableSponsorshipOrgs$ = combineLatest([
|
||||
this.organizationService.organizations$,
|
||||
this.policyService.getAll$(PolicyType.FreeFamiliesSponsorshipPolicy),
|
||||
@@ -142,6 +149,17 @@ export class SponsoredFamiliesComponent implements OnInit, OnDestroy {
|
||||
this._destroy.complete();
|
||||
}
|
||||
|
||||
private async preventAccessToFreeFamiliesPage() {
|
||||
const showFreeFamiliesPage = await firstValueFrom(
|
||||
this.freeFamiliesPolicyService.showFreeFamilies$,
|
||||
);
|
||||
|
||||
if (!showFreeFamiliesPage) {
|
||||
await this.router.navigate(["/"]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
submit = async () => {
|
||||
this.formPromise = this.apiService.postCreateSponsorship(
|
||||
this.sponsorshipForm.value.selectedSponsorshipOrgId,
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
class="tw-cursor-pointer"
|
||||
rel="noreferrer noopener"
|
||||
>
|
||||
{{ "routeToPaymentMethodTrigger" | i18n }}
|
||||
{{ "clickHereToAddPaymentMethod" | i18n }}
|
||||
</a>
|
||||
</bit-banner>
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
rel="noreferrer noopener"
|
||||
class="tw-cursor-pointer"
|
||||
>
|
||||
{{ "routeToPaymentMethodTrigger" | i18n }}
|
||||
{{ "clickHereToAddPaymentMethod" | i18n }}
|
||||
</a>
|
||||
</bit-banner>
|
||||
|
||||
|
||||
@@ -71,14 +71,14 @@ export class VaultBannersComponent implements OnInit {
|
||||
freeTrialMessage(organization: FreeTrial) {
|
||||
if (organization.remainingDays >= 2) {
|
||||
return this.i18nService.t(
|
||||
"freeTrialEndPromptAboveTwoDays",
|
||||
"freeTrialEndPromptMultipleDays",
|
||||
organization.organizationName,
|
||||
organization.remainingDays.toString(),
|
||||
);
|
||||
} else if (organization.remainingDays === 1) {
|
||||
return this.i18nService.t("freeTrialEndPromptForOneDay", organization.organizationName);
|
||||
return this.i18nService.t("freeTrialEndPromptTomorrow", organization.organizationName);
|
||||
} else {
|
||||
return this.i18nService.t("freeTrialEndPromptForLessThanADay", organization.organizationName);
|
||||
return this.i18nService.t("freeTrialEndPromptToday", organization.organizationName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
class="tw-cursor-pointer"
|
||||
rel="noreferrer noopener"
|
||||
>
|
||||
{{ "routeToPaymentMethodTrigger" | i18n }}
|
||||
{{ "clickHereToAddPaymentMethod" | i18n }}
|
||||
</a>
|
||||
</bit-banner>
|
||||
</ng-container>
|
||||
|
||||
@@ -3903,30 +3903,30 @@
|
||||
"updateBrowserDesc": {
|
||||
"message": "You are using an unsupported web browser. The web vault may not function properly."
|
||||
},
|
||||
"freeTrialEndPrompt": {
|
||||
"message": "Your free trial ends in $COUNT$ days. To maintain your subscription,",
|
||||
"freeTrialEndPromptCount": {
|
||||
"message": "Your free trial ends in $COUNT$ days.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
"example": "You must set up 2FA on your user account before you can join this organization."
|
||||
}
|
||||
}
|
||||
},
|
||||
"freeTrialEndPromptAboveTwoDays": {
|
||||
"message": "$ORGANIZATION$, your free trial ends in $COUNT$ days. To maintain your subscription,",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$2",
|
||||
"example": "organization name"
|
||||
},
|
||||
"organization": {
|
||||
"content": "$1",
|
||||
"example": "remaining days"
|
||||
}
|
||||
}
|
||||
},
|
||||
"freeTrialEndPromptForOneDay": {
|
||||
"message": "$ORGANIZATION$, your free trial ends tomorrow. To maintain your subscription,",
|
||||
"freeTrialEndPromptMultipleDays": {
|
||||
"message": "$ORGANIZATION$, your free trial ends in $COUNT$ days.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$2",
|
||||
"example": "remaining days"
|
||||
},
|
||||
"organization": {
|
||||
"content": "$1",
|
||||
"example": "organization name"
|
||||
}
|
||||
}
|
||||
},
|
||||
"freeTrialEndPromptTomorrow": {
|
||||
"message": "$ORGANIZATION$, your free trial ends tomorrow.",
|
||||
"placeholders": {
|
||||
"organization": {
|
||||
"content": "$1",
|
||||
@@ -3934,11 +3934,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"freeTrialEndPromptForOneDayNoOrgName": {
|
||||
"message": "Your free trial ends tomorrow. To maintain your subscription,"
|
||||
"freeTrialEndPromptTomorrowNoOrgName": {
|
||||
"message": "Your free trial ends tomorrow."
|
||||
},
|
||||
"freeTrialEndPromptForLessThanADay": {
|
||||
"message": "$ORGANIZATION$, your free trial ends today. To maintain your subscription,",
|
||||
"freeTrialEndPromptToday": {
|
||||
"message": "$ORGANIZATION$, your free trial ends today.",
|
||||
"placeholders": {
|
||||
"organization": {
|
||||
"content": "$1",
|
||||
@@ -3946,11 +3946,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"freeTrialEndingSoonWithoutOrgName": {
|
||||
"message": "Your free trial ends today. To maintain your subscription,"
|
||||
"freeTrialEndingTodayWithoutOrgName": {
|
||||
"message": "Your free trial ends today."
|
||||
},
|
||||
"routeToPaymentMethodTrigger": {
|
||||
"message": "add a payment method."
|
||||
"clickHereToAddPaymentMethod": {
|
||||
"message": "Click here to add a payment method."
|
||||
},
|
||||
"joinOrganization": {
|
||||
"message": "Join organization"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
(click)="navigateToPaymentMethod()"
|
||||
rel="noreferrer noopener"
|
||||
>
|
||||
{{ "routeToPaymentMethodTrigger" | i18n }}
|
||||
{{ "clickHereToAddPaymentMethod" | i18n }}
|
||||
</a>
|
||||
</bit-banner>
|
||||
</ng-container>
|
||||
|
||||
22
libs/angular/src/directives/text-drag.directive.ts
Normal file
22
libs/angular/src/directives/text-drag.directive.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Directive, HostListener, Input } from "@angular/core";
|
||||
|
||||
@Directive({
|
||||
selector: "[appTextDrag]",
|
||||
standalone: true,
|
||||
host: {
|
||||
draggable: "true",
|
||||
class: "tw-cursor-move",
|
||||
},
|
||||
})
|
||||
export class TextDragDirective {
|
||||
@Input({
|
||||
alias: "appTextDrag",
|
||||
required: true,
|
||||
})
|
||||
data = "";
|
||||
|
||||
@HostListener("dragstart", ["$event"])
|
||||
onDragStart(event: DragEvent) {
|
||||
event.dataTransfer.setData("text", this.data);
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ import { LaunchClickDirective } from "./directives/launch-click.directive";
|
||||
import { NotPremiumDirective } from "./directives/not-premium.directive";
|
||||
import { StopClickDirective } from "./directives/stop-click.directive";
|
||||
import { StopPropDirective } from "./directives/stop-prop.directive";
|
||||
import { TextDragDirective } from "./directives/text-drag.directive";
|
||||
import { TrueFalseValueDirective } from "./directives/true-false-value.directive";
|
||||
import { CreditCardNumberPipe } from "./pipes/credit-card-number.pipe";
|
||||
import { PluralizePipe } from "./pipes/pluralize.pipe";
|
||||
@@ -81,6 +82,7 @@ import { IconComponent } from "./vault/components/icon.component";
|
||||
IconModule,
|
||||
LinkModule,
|
||||
IconModule,
|
||||
TextDragDirective,
|
||||
],
|
||||
declarations: [
|
||||
A11yInvalidDirective,
|
||||
@@ -150,6 +152,7 @@ import { IconComponent } from "./vault/components/icon.component";
|
||||
NoInvoicesComponent,
|
||||
ManageTaxInformationComponent,
|
||||
TwoFactorIconComponent,
|
||||
TextDragDirective,
|
||||
],
|
||||
providers: [
|
||||
CreditCardNumberPipe,
|
||||
|
||||
@@ -6,6 +6,9 @@ import { CredentialGenerator, EffUsernameGenerationOptions, GeneratedCredential
|
||||
import { Randomizer } from "./abstractions";
|
||||
import { WordsRequest } from "./types";
|
||||
|
||||
/** The number of digits used when generating an Eff username with a number. */
|
||||
const NUMBER_OF_DIGITS = 4;
|
||||
|
||||
/** Generation algorithms that produce randomized usernames */
|
||||
export class UsernameRandomizer implements CredentialGenerator<EffUsernameGenerationOptions> {
|
||||
/** Instantiates the username randomizer
|
||||
@@ -51,7 +54,7 @@ export class UsernameRandomizer implements CredentialGenerator<EffUsernameGenera
|
||||
async generate(_request: GenerationRequest, settings: EffUsernameGenerationOptions) {
|
||||
if (isEffUsernameGenerationOptions(settings)) {
|
||||
const username = await this.randomWords({
|
||||
digits: settings.wordIncludeNumber ? 1 : 0,
|
||||
digits: settings.wordIncludeNumber ? NUMBER_OF_DIGITS : 0,
|
||||
casing: settings.wordCapitalize ? "TitleCase" : "lowercase",
|
||||
});
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
</bit-section-header>
|
||||
<bit-card class="[&_bit-form-field:last-of-type]:tw-mb-0">
|
||||
<bit-form-field disableReadOnlyBorder>
|
||||
<bit-label>{{ "note" | i18n }}</bit-label>
|
||||
<textarea readonly bitInput rows="5" aria-readonly="true">{{ notes }}</textarea>
|
||||
<bit-label [appTextDrag]="notes">{{ "note" | i18n }}</bit-label>
|
||||
<textarea readonly id="notes" bitInput rows="5" aria-readonly="true">{{ notes }}</textarea>
|
||||
<button
|
||||
bitSuffix
|
||||
bitIconButton="bwi-clone"
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
</bit-section-header>
|
||||
<read-only-cipher-card>
|
||||
<bit-form-field *ngIf="card.cardholderName">
|
||||
<bit-label>{{ "cardholderName" | i18n }}</bit-label>
|
||||
<bit-label [appTextDrag]="card.cardholderName">{{ "cardholderName" | i18n }}</bit-label>
|
||||
<input
|
||||
id="cardholderName"
|
||||
readonly
|
||||
bitInput
|
||||
type="text"
|
||||
@@ -15,8 +16,9 @@
|
||||
/>
|
||||
</bit-form-field>
|
||||
<bit-form-field *ngIf="card.number">
|
||||
<bit-label>{{ "number" | i18n }}</bit-label>
|
||||
<bit-label [appTextDrag]="card.number">{{ "number" | i18n }}</bit-label>
|
||||
<input
|
||||
id="cardNumber"
|
||||
readonly
|
||||
bitInput
|
||||
type="password"
|
||||
@@ -45,8 +47,9 @@
|
||||
></button>
|
||||
</bit-form-field>
|
||||
<bit-form-field *ngIf="card.expiration">
|
||||
<bit-label>{{ "expiration" | i18n }}</bit-label>
|
||||
<bit-label [appTextDrag]="card.expiration">{{ "expiration" | i18n }}</bit-label>
|
||||
<input
|
||||
id="expiration"
|
||||
readonly
|
||||
bitInput
|
||||
type="text"
|
||||
@@ -56,8 +59,9 @@
|
||||
/>
|
||||
</bit-form-field>
|
||||
<bit-form-field *ngIf="card.code">
|
||||
<bit-label>{{ "securityCode" | i18n }}</bit-label>
|
||||
<bit-label [appTextDrag]="card.code">{{ "securityCode" | i18n }}</bit-label>
|
||||
<input
|
||||
id="securityCode"
|
||||
readonly
|
||||
bitInput
|
||||
type="password"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
data-testid="custom-field"
|
||||
>
|
||||
<bit-form-field *ngIf="field.type === fieldType.Text" [disableReadOnlyBorder]="last">
|
||||
<bit-label>{{ field.name }}</bit-label>
|
||||
<bit-label [appTextDrag]="field.value">{{ field.name }}</bit-label>
|
||||
<input readonly bitInput type="text" [value]="field.value" aria-readonly="true" />
|
||||
<button
|
||||
bitIconButton="bwi-clone"
|
||||
@@ -24,7 +24,7 @@
|
||||
></button>
|
||||
</bit-form-field>
|
||||
<bit-form-field *ngIf="field.type === fieldType.Hidden" [disableReadOnlyBorder]="last">
|
||||
<bit-label>{{ field.name }}</bit-label>
|
||||
<bit-label [appTextDrag]="field.value">{{ field.name }}</bit-label>
|
||||
<input
|
||||
readonly
|
||||
bitInput
|
||||
@@ -59,7 +59,9 @@
|
||||
aria-readonly="true"
|
||||
disabled
|
||||
/>
|
||||
<bit-label> {{ field.name }} </bit-label>
|
||||
<bit-label [appTextDrag]="field.value">
|
||||
{{ field.name }}
|
||||
</bit-label>
|
||||
</bit-form-control>
|
||||
<bit-form-field *ngIf="field.type === fieldType.Linked" [disableReadOnlyBorder]="last">
|
||||
<bit-label> {{ "cfTypeLinked" | i18n }}: {{ field.name }} </bit-label>
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
[disableMargin]="!cipher.collectionIds?.length && !showOwnership && !cipher.folderId"
|
||||
[disableReadOnlyBorder]="!cipher.collectionIds?.length && !showOwnership && !cipher.folderId"
|
||||
>
|
||||
<bit-label>
|
||||
<bit-label [appTextDrag]="cipher.name">
|
||||
{{ "itemName" | i18n }}
|
||||
</bit-label>
|
||||
<input
|
||||
readonly
|
||||
id="itemName"
|
||||
bitInput
|
||||
type="text"
|
||||
[value]="cipher.name"
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
</bit-section-header>
|
||||
<read-only-cipher-card>
|
||||
<bit-form-field *ngIf="cipher.login.username">
|
||||
<bit-label>
|
||||
<bit-label [appTextDrag]="cipher.login.username">
|
||||
{{ "username" | i18n }}
|
||||
</bit-label>
|
||||
<input
|
||||
id="userName"
|
||||
readonly
|
||||
bitInput
|
||||
type="text"
|
||||
@@ -27,8 +28,9 @@
|
||||
></button>
|
||||
</bit-form-field>
|
||||
<bit-form-field *ngIf="cipher.login.password">
|
||||
<bit-label>{{ "password" | i18n }}</bit-label>
|
||||
<bit-label [appTextDrag]="cipher.login.password">{{ "password" | i18n }}</bit-label>
|
||||
<input
|
||||
id="password"
|
||||
readonly
|
||||
bitInput
|
||||
type="password"
|
||||
@@ -80,8 +82,11 @@
|
||||
></bit-color-password>
|
||||
</div>
|
||||
<bit-form-field *ngIf="cipher.login?.fido2Credentials?.length > 0">
|
||||
<bit-label>{{ "typePasskey" | i18n }} </bit-label>
|
||||
<bit-label [appTextDrag]="fido2CredentialCreationDateValue"
|
||||
>{{ "typePasskey" | i18n }}
|
||||
</bit-label>
|
||||
<input
|
||||
id="fido"
|
||||
readonly
|
||||
bitInput
|
||||
type="text"
|
||||
@@ -91,7 +96,7 @@
|
||||
/>
|
||||
</bit-form-field>
|
||||
<bit-form-field *ngIf="cipher.login.totp">
|
||||
<bit-label
|
||||
<bit-label [appTextDrag]="totpCodeCopyObj?.totpCode"
|
||||
>{{ "verificationCodeTotp" | i18n }}
|
||||
<span
|
||||
*ngIf="!(isPremium$ | async)"
|
||||
@@ -105,6 +110,7 @@
|
||||
</span>
|
||||
</bit-label>
|
||||
<input
|
||||
id="totp"
|
||||
readonly
|
||||
bitInput
|
||||
[type]="!(isPremium$ | async) ? 'password' : 'text'"
|
||||
|
||||
@@ -5,8 +5,14 @@
|
||||
|
||||
<read-only-cipher-card>
|
||||
<bit-form-field *ngIf="cipher.identity.fullName">
|
||||
<bit-label>{{ "name" | i18n }}</bit-label>
|
||||
<input bitInput [value]="cipher.identity.fullName" readonly data-testid="name" />
|
||||
<bit-label [appTextDrag]="cipher.identity.fullName">{{ "name" | i18n }}</bit-label>
|
||||
<input
|
||||
bitInput
|
||||
id="fullName"
|
||||
[value]="cipher.identity.fullName"
|
||||
readonly
|
||||
data-testid="name"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton="bwi-clone"
|
||||
@@ -19,8 +25,14 @@
|
||||
></button>
|
||||
</bit-form-field>
|
||||
<bit-form-field *ngIf="cipher.identity.username">
|
||||
<bit-label>{{ "username" | i18n }}</bit-label>
|
||||
<input bitInput [value]="cipher.identity.username" readonly data-testid="username" />
|
||||
<bit-label [appTextDrag]="cipher.identity.username">{{ "username" | i18n }}</bit-label>
|
||||
<input
|
||||
bitInput
|
||||
id="username"
|
||||
[value]="cipher.identity.username"
|
||||
readonly
|
||||
data-testid="username"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton="bwi-clone"
|
||||
@@ -32,8 +44,14 @@
|
||||
></button>
|
||||
</bit-form-field>
|
||||
<bit-form-field *ngIf="cipher.identity.company">
|
||||
<bit-label>{{ "company" | i18n }}</bit-label>
|
||||
<input bitInput [value]="cipher.identity.company" readonly data-testid="company" />
|
||||
<bit-label [appTextDrag]="cipher.identity.company">{{ "company" | i18n }}</bit-label>
|
||||
<input
|
||||
bitInput
|
||||
id="company"
|
||||
[value]="cipher.identity.company"
|
||||
readonly
|
||||
data-testid="company"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton="bwi-clone"
|
||||
@@ -55,8 +73,15 @@
|
||||
|
||||
<read-only-cipher-card>
|
||||
<bit-form-field *ngIf="cipher.identity.ssn">
|
||||
<bit-label>{{ "ssn" | i18n }}</bit-label>
|
||||
<input bitInput type="password" [value]="cipher.identity.ssn" readonly data-testid="ssn" />
|
||||
<bit-label [appTextDrag]="cipher.identity.ssn">{{ "ssn" | i18n }}</bit-label>
|
||||
<input
|
||||
bitInput
|
||||
id="ssn"
|
||||
type="password"
|
||||
[value]="cipher.identity.ssn"
|
||||
readonly
|
||||
data-testid="ssn"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton
|
||||
@@ -76,8 +101,11 @@
|
||||
></button>
|
||||
</bit-form-field>
|
||||
<bit-form-field *ngIf="cipher.identity.passportNumber">
|
||||
<bit-label>{{ "passportNumber" | i18n }}</bit-label>
|
||||
<bit-label [appTextDrag]="cipher.identity.passportNumber">{{
|
||||
"passportNumber" | i18n
|
||||
}}</bit-label>
|
||||
<input
|
||||
id="passportNumber"
|
||||
bitInput
|
||||
type="password"
|
||||
[value]="cipher.identity.passportNumber"
|
||||
@@ -103,8 +131,16 @@
|
||||
></button>
|
||||
</bit-form-field>
|
||||
<bit-form-field *ngIf="cipher.identity.licenseNumber">
|
||||
<bit-label>{{ "licenseNumber" | i18n }}</bit-label>
|
||||
<input bitInput [value]="cipher.identity.licenseNumber" readonly data-testid="license" />
|
||||
<bit-label [appTextDrag]="cipher.identity.licenseNumber">{{
|
||||
"licenseNumber" | i18n
|
||||
}}</bit-label>
|
||||
<input
|
||||
bitInput
|
||||
id="licenseNumber"
|
||||
[value]="cipher.identity.licenseNumber"
|
||||
readonly
|
||||
data-testid="license"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton="bwi-clone"
|
||||
@@ -126,8 +162,8 @@
|
||||
|
||||
<read-only-cipher-card>
|
||||
<bit-form-field *ngIf="cipher.identity.email">
|
||||
<bit-label>{{ "email" | i18n }}</bit-label>
|
||||
<input bitInput [value]="cipher.identity.email" readonly data-testid="email" />
|
||||
<bit-label [appTextDrag]="cipher.identity.email">{{ "email" | i18n }}</bit-label>
|
||||
<input bitInput id="email" [value]="cipher.identity.email" readonly data-testid="email" />
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton="bwi-clone"
|
||||
@@ -140,8 +176,8 @@
|
||||
></button>
|
||||
</bit-form-field>
|
||||
<bit-form-field *ngIf="cipher.identity.phone">
|
||||
<bit-label>{{ "phone" | i18n }}</bit-label>
|
||||
<input bitInput [value]="cipher.identity.phone" readonly data-testid="phone" />
|
||||
<bit-label [appTextDrag]="cipher.identity.phone">{{ "phone" | i18n }}</bit-label>
|
||||
<input bitInput id="phone" [value]="cipher.identity.phone" readonly data-testid="phone" />
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton="bwi-clone"
|
||||
@@ -154,9 +190,10 @@
|
||||
></button>
|
||||
</bit-form-field>
|
||||
<bit-form-field *ngIf="addressFields">
|
||||
<bit-label>{{ "address" | i18n }}</bit-label>
|
||||
<bit-label [appTextDrag]="addressFields">{{ "address" | i18n }}</bit-label>
|
||||
<textarea
|
||||
bitInput
|
||||
id="address"
|
||||
class="tw-resize-none"
|
||||
[value]="addressFields"
|
||||
[rows]="addressRows"
|
||||
|
||||
556
package-lock.json
generated
556
package-lock.json
generated
@@ -88,15 +88,15 @@
|
||||
"@electron/notarize": "2.5.0",
|
||||
"@electron/rebuild": "3.7.1",
|
||||
"@ngtools/webpack": "17.3.11",
|
||||
"@storybook/addon-a11y": "8.4.5",
|
||||
"@storybook/addon-actions": "8.4.5",
|
||||
"@storybook/addon-a11y": "8.4.7",
|
||||
"@storybook/addon-actions": "8.4.7",
|
||||
"@storybook/addon-designs": "8.0.4",
|
||||
"@storybook/addon-essentials": "8.4.5",
|
||||
"@storybook/addon-interactions": "8.4.5",
|
||||
"@storybook/addon-links": "8.4.5",
|
||||
"@storybook/angular": "8.4.5",
|
||||
"@storybook/manager-api": "8.4.5",
|
||||
"@storybook/theming": "8.4.5",
|
||||
"@storybook/addon-essentials": "8.4.7",
|
||||
"@storybook/addon-interactions": "8.4.7",
|
||||
"@storybook/addon-links": "8.4.7",
|
||||
"@storybook/angular": "8.4.7",
|
||||
"@storybook/manager-api": "8.4.7",
|
||||
"@storybook/theming": "8.4.7",
|
||||
"@types/argon2-browser": "1.18.4",
|
||||
"@types/chrome": "0.0.280",
|
||||
"@types/firefox-webext-browser": "120.0.4",
|
||||
@@ -127,7 +127,7 @@
|
||||
"babel-loader": "9.2.1",
|
||||
"base64-loader": "1.0.0",
|
||||
"browserslist": "4.23.2",
|
||||
"chromatic": "11.19.0",
|
||||
"chromatic": "11.20.0",
|
||||
"concurrently": "9.1.0",
|
||||
"copy-webpack-plugin": "12.0.2",
|
||||
"cross-env": "7.0.3",
|
||||
@@ -166,9 +166,9 @@
|
||||
"rimraf": "6.0.1",
|
||||
"sass": "1.81.0",
|
||||
"sass-loader": "16.0.4",
|
||||
"storybook": "8.4.5",
|
||||
"storybook": "8.4.7",
|
||||
"style-loader": "4.0.0",
|
||||
"tailwindcss": "3.4.15",
|
||||
"tailwindcss": "3.4.16",
|
||||
"ts-jest": "29.2.2",
|
||||
"ts-loader": "9.5.1",
|
||||
"tsconfig-paths-webpack-plugin": "4.1.0",
|
||||
@@ -178,7 +178,7 @@
|
||||
"url": "0.11.4",
|
||||
"util": "0.12.5",
|
||||
"wait-on": "8.0.1",
|
||||
"webpack": "5.96.1",
|
||||
"webpack": "5.97.1",
|
||||
"webpack-cli": "5.1.4",
|
||||
"webpack-dev-server": "5.0.4",
|
||||
"webpack-node-externals": "3.0.0"
|
||||
@@ -8641,13 +8641,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-a11y": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-8.4.5.tgz",
|
||||
"integrity": "sha512-lqIOpWJZNR0Ur+2zUcnFAMvdOe7kYEDeXPv1TM7fwEGyzKPYoM/k5xPA2cJCrYwtydxOqqrmn1jUIw0Qdkhuhg==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-8.4.7.tgz",
|
||||
"integrity": "sha512-GpUvXp6n25U1ZSv+hmDC+05BEqxWdlWjQTb/GaboRXZQeMBlze6zckpVb66spjmmtQAIISo0eZxX1+mGcVR7lA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@storybook/addon-highlight": "8.4.5",
|
||||
"@storybook/addon-highlight": "8.4.7",
|
||||
"axe-core": "^4.2.0"
|
||||
},
|
||||
"funding": {
|
||||
@@ -8655,13 +8655,13 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-actions": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.4.5.tgz",
|
||||
"integrity": "sha512-rbB19uiGJ61XHbKIbS1a9bUS6re5L8rT5NMNeEJhCxXRpFUPrlTXMSoD/Pgcn3ENeEMVZsm8/eCzxAVgAP3Mgg==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.4.7.tgz",
|
||||
"integrity": "sha512-mjtD5JxcPuW74T6h7nqMxWTvDneFtokg88p6kQ5OnC1M259iAXb//yiSZgu/quunMHPCXSiqn4FNOSgASTSbsA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -8676,13 +8676,13 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-backgrounds": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.4.5.tgz",
|
||||
"integrity": "sha512-FeMt4qHCMYDQiLGGDKiRuSPXFup2WXOaZSdL137v1W36wEL/vGkK1A5iQt1qJ8MZzL5WZQuedox8rSybFy7eow==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.4.7.tgz",
|
||||
"integrity": "sha512-I4/aErqtFiazcoWyKafOAm3bLpxTj6eQuH/woSbk1Yx+EzN+Dbrgx1Updy8//bsNtKkcrXETITreqHC+a57DHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -8695,13 +8695,13 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-controls": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.4.5.tgz",
|
||||
"integrity": "sha512-RVTtDDuESLYc1+SJQv2kI7wzBddzAS9uoEe8P75quN6S4pC0GxAB6xirWZ2+WOcba4eHosY+PxMwuBXQfH78Ew==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.4.7.tgz",
|
||||
"integrity": "sha512-377uo5IsJgXLnQLJixa47+11V+7Wn9KcDEw+96aGCBCfLbWNH8S08tJHHnSu+jXg9zoqCAC23MetntVp6LetHA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -8714,7 +8714,7 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-designs": {
|
||||
@@ -8752,16 +8752,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-docs": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.4.5.tgz",
|
||||
"integrity": "sha512-zPELIl7wXormOylVaaSpkUIuuCCxrO+OFPMKZnlENt6zSReyy0dJu4V0tzfV8FCw+V4D6Y4wrLRk/TIG951Ojw==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.4.7.tgz",
|
||||
"integrity": "sha512-NwWaiTDT5puCBSUOVuf6ME7Zsbwz7Y79WF5tMZBx/sLQ60vpmJVQsap6NSjvK1Ravhc21EsIXqemAcBjAWu80w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@mdx-js/react": "^3.0.0",
|
||||
"@storybook/blocks": "8.4.5",
|
||||
"@storybook/csf-plugin": "8.4.5",
|
||||
"@storybook/react-dom-shim": "8.4.5",
|
||||
"@storybook/blocks": "8.4.7",
|
||||
"@storybook/csf-plugin": "8.4.7",
|
||||
"@storybook/react-dom-shim": "8.4.7",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"ts-dedent": "^2.0.0"
|
||||
@@ -8771,25 +8771,25 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-essentials": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.4.5.tgz",
|
||||
"integrity": "sha512-AxetQo/zSPIu3RZqWG2opwAz22Bb+jpf1nWbHp0kEpCrBemcWd8X2gonVmXNOC1PDKNl3jcWyc3lmg/+3mxjYg==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.4.7.tgz",
|
||||
"integrity": "sha512-+BtZHCBrYtQKILtejKxh0CDRGIgTl9PumfBOKRaihYb4FX1IjSAxoV/oo/IfEjlkF5f87vouShWsRa8EUauFDw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@storybook/addon-actions": "8.4.5",
|
||||
"@storybook/addon-backgrounds": "8.4.5",
|
||||
"@storybook/addon-controls": "8.4.5",
|
||||
"@storybook/addon-docs": "8.4.5",
|
||||
"@storybook/addon-highlight": "8.4.5",
|
||||
"@storybook/addon-measure": "8.4.5",
|
||||
"@storybook/addon-outline": "8.4.5",
|
||||
"@storybook/addon-toolbars": "8.4.5",
|
||||
"@storybook/addon-viewport": "8.4.5",
|
||||
"@storybook/addon-actions": "8.4.7",
|
||||
"@storybook/addon-backgrounds": "8.4.7",
|
||||
"@storybook/addon-controls": "8.4.7",
|
||||
"@storybook/addon-docs": "8.4.7",
|
||||
"@storybook/addon-highlight": "8.4.7",
|
||||
"@storybook/addon-measure": "8.4.7",
|
||||
"@storybook/addon-outline": "8.4.7",
|
||||
"@storybook/addon-toolbars": "8.4.7",
|
||||
"@storybook/addon-viewport": "8.4.7",
|
||||
"ts-dedent": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
@@ -8797,13 +8797,13 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-highlight": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.4.5.tgz",
|
||||
"integrity": "sha512-sMA7v+4unaKY+5RDhow6lLncJqNX9ZLUnBIt3vzY1ntUsOYVwykAY1Hq4Ysj0luCBXjJJdJ6223ylrycnb7Ilw==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.4.7.tgz",
|
||||
"integrity": "sha512-whQIDBd3PfVwcUCrRXvCUHWClXe9mQ7XkTPCdPo4B/tZ6Z9c6zD8JUHT76ddyHivixFLowMnA8PxMU6kCMAiNw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -8814,19 +8814,19 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-interactions": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.4.5.tgz",
|
||||
"integrity": "sha512-s6R8XVD8LTp+LQTDbhtDjDLE6S44I7FtMLxPdMNwN9VEJjBk01NONLDuGDpNq5o/0bnybA3rMHk9+3afsgzidQ==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.4.7.tgz",
|
||||
"integrity": "sha512-fnufT3ym8ht3HHUIRVXAH47iOJW/QOb0VSM+j269gDuvyDcY03D1civCu1v+eZLGaXPKJ8vtjr0L8zKQ/4P0JQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@storybook/global": "^5.0.0",
|
||||
"@storybook/instrumenter": "8.4.5",
|
||||
"@storybook/test": "8.4.5",
|
||||
"@storybook/instrumenter": "8.4.7",
|
||||
"@storybook/test": "8.4.7",
|
||||
"polished": "^4.2.2",
|
||||
"ts-dedent": "^2.2.0"
|
||||
},
|
||||
@@ -8835,13 +8835,13 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-links": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.4.5.tgz",
|
||||
"integrity": "sha512-ac3OtplFdrPw/2jtLnteuVllwu2yCe3sgKJS9AbdYMT/65OW47M7oDnzcpRPsDGufrKlDMBJXXEv4SfTtlT+rg==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.4.7.tgz",
|
||||
"integrity": "sha512-L/1h4dMeMKF+MM0DanN24v5p3faNYbbtOApMgg7SlcBT/tgo3+cAjkgmNpYA8XtKnDezm+T2mTDhB8mmIRZpIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -8855,7 +8855,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta",
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react": {
|
||||
@@ -8864,9 +8864,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-measure": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.4.5.tgz",
|
||||
"integrity": "sha512-+sNjew991YaoXQyWWloFybjEGrDO40Jk6w8BgZs2X7oc3D5t/6oFzvyC862U++LGqKFA3quXDeBjEb92CI9cRA==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.4.7.tgz",
|
||||
"integrity": "sha512-QfvqYWDSI5F68mKvafEmZic3SMiK7zZM8VA0kTXx55hF/+vx61Mm0HccApUT96xCXIgmwQwDvn9gS4TkX81Dmw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -8878,13 +8878,13 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-outline": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.4.5.tgz",
|
||||
"integrity": "sha512-XlpN98AUDnWQWNFSFVm+HkRUzm3xIUMjBGTkv6HsL6zt6XoJ+LsQMca+PPtYqlBJA+5CU41xMDaG8HC/p+sd3A==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.4.7.tgz",
|
||||
"integrity": "sha512-6LYRqUZxSodmAIl8icr585Oi8pmzbZ90aloZJIpve+dBAzo7ydYrSQxxoQEVltXbKf3VeVcrs64ouAYqjisMYA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -8896,13 +8896,13 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-toolbars": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.4.5.tgz",
|
||||
"integrity": "sha512-hOq5560ONOU/qrslrwosWzxnC4nrF8HZWD43ciKwtethm8HuptU2M+Jrui1CRsMScEZLopWWVE9o0vJMdKpIFQ==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.4.7.tgz",
|
||||
"integrity": "sha512-OSfdv5UZs+NdGB+nZmbafGUWimiweJ/56gShlw8Neo/4jOJl1R3rnRqqY7MYx8E4GwoX+i3GF5C3iWFNQqlDcw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
@@ -8910,13 +8910,13 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-viewport": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.4.5.tgz",
|
||||
"integrity": "sha512-l7Y41gIbJAsIN/QCg1QJ9sr61FLz1C/imUotcDej41tOHxUTSQOlXpNtVnfhUM1vGQc0yNpP3pVxj8BpXi0cAw==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.4.7.tgz",
|
||||
"integrity": "sha512-hvczh/jjuXXcOogih09a663sRDDSATXwbE866al1DXgbDFraYD/LxX/QDb38W9hdjU9+Qhx8VFIcNWoMQns5HQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -8927,23 +8927,23 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/angular": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/angular/-/angular-8.4.5.tgz",
|
||||
"integrity": "sha512-Ks+l4sgMQpCk8hy6J+f0N+fE8J7nihlnYkT0jrWTKnb7hZUipr+xPi03rnufBkk1a3KOFXD4/FEtFWh3IAhvAw==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/angular/-/angular-8.4.7.tgz",
|
||||
"integrity": "sha512-PYWWEvoe+sT8riprSQVCyGnQbifbuzT9YNYPi22YBxB8ZGVuIVwjshKjSZvC99ULQbMvJ/g2OPCcBA8hhc3aTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@storybook/builder-webpack5": "8.4.5",
|
||||
"@storybook/components": "8.4.5",
|
||||
"@storybook/core-webpack": "8.4.5",
|
||||
"@storybook/builder-webpack5": "8.4.7",
|
||||
"@storybook/components": "8.4.7",
|
||||
"@storybook/core-webpack": "8.4.7",
|
||||
"@storybook/global": "^5.0.0",
|
||||
"@storybook/manager-api": "8.4.5",
|
||||
"@storybook/preview-api": "8.4.5",
|
||||
"@storybook/theming": "8.4.5",
|
||||
"@storybook/manager-api": "8.4.7",
|
||||
"@storybook/preview-api": "8.4.7",
|
||||
"@storybook/theming": "8.4.7",
|
||||
"@types/node": "^22.0.0",
|
||||
"@types/react": "^18.0.37",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
@@ -8978,7 +8978,7 @@
|
||||
"@angular/platform-browser": ">=15.0.0 < 20.0.0",
|
||||
"@angular/platform-browser-dynamic": ">=15.0.0 < 20.0.0",
|
||||
"rxjs": "^6.0.0 || ^7.4.0",
|
||||
"storybook": "^8.4.5",
|
||||
"storybook": "^8.4.7",
|
||||
"typescript": "^4.0.0 || ^5.0.0",
|
||||
"zone.js": ">= 0.11.1 < 1.0.0"
|
||||
},
|
||||
@@ -8989,9 +8989,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/blocks": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.4.5.tgz",
|
||||
"integrity": "sha512-Z+LHauSqm3A4HBR9pUEf9KQhD3/3xYMt0FXgA+GHCAyDa6lFeD1C6r9Y2nlT+9dt8gv9B9oygTZvV6GqFVyRSQ==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.4.7.tgz",
|
||||
"integrity": "sha512-+QH7+JwXXXIyP3fRCxz/7E2VZepAanXJM7G8nbR3wWsqWgrRp4Wra6MvybxAYCxU7aNfJX5c+RW84SNikFpcIA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -9006,7 +9006,7 @@
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta",
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react": {
|
||||
@@ -9018,13 +9018,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/builder-webpack5": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.4.5.tgz",
|
||||
"integrity": "sha512-5TSpirK2LIL4Wultpowlkrv3iAje57HTw92Hy6c4Zn64tAs30123mkdE6MoJcXMBfD4JwX9I2K2Q+ofZXblJPg==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.4.7.tgz",
|
||||
"integrity": "sha512-O8LpsQ+4g2x5kh7rI9+jEUdX8k1a5egBQU1lbudmHchqsV0IKiVqBD9LL5Gj3wpit4vB8coSW4ZWTFBw8FQb4Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@storybook/core-webpack": "8.4.5",
|
||||
"@storybook/core-webpack": "8.4.7",
|
||||
"@types/node": "^22.0.0",
|
||||
"@types/semver": "^7.3.4",
|
||||
"browser-assert": "^1.2.1",
|
||||
@@ -9055,7 +9055,7 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
@@ -9117,9 +9117,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/components": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/components/-/components-8.4.5.tgz",
|
||||
"integrity": "sha512-2PdnKfqNNv3sO7qILgWXiNvmLOi503oN9OMemNCQjTIvdvySc5JpS9/eClwcl/JfmE4qHdSHZr8dLLkBM9S7+Q==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/components/-/components-8.4.7.tgz",
|
||||
"integrity": "sha512-uyJIcoyeMWKAvjrG9tJBUCKxr2WZk+PomgrgrUwejkIfXMO76i6jw9BwLa0NZjYdlthDv30r9FfbYZyeNPmF0g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
@@ -9130,10 +9130,42 @@
|
||||
"storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/core": {
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.4.7.tgz",
|
||||
"integrity": "sha512-7Z8Z0A+1YnhrrSXoKKwFFI4gnsLbWzr8fnDCU6+6HlDukFYh8GHRcZ9zKfqmy6U3hw2h8H5DrHsxWfyaYUUOoA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@storybook/csf": "^0.1.11",
|
||||
"better-opn": "^3.0.2",
|
||||
"browser-assert": "^1.2.1",
|
||||
"esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0",
|
||||
"esbuild-register": "^3.5.0",
|
||||
"jsdoc-type-pratt-parser": "^4.0.0",
|
||||
"process": "^0.11.10",
|
||||
"recast": "^0.23.5",
|
||||
"semver": "^7.6.2",
|
||||
"util": "^0.12.5",
|
||||
"ws": "^8.2.3"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"prettier": "^2 || ^3"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"prettier": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/core-webpack": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.4.5.tgz",
|
||||
"integrity": "sha512-IpK/3fM+l2WjRNplTtP+MtnRf/394GcBwyemZknUCzFFDJWNYAN1+meEZmOaZKzJ3tQyRYiErrJLHzd1+UH6Dw==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.4.7.tgz",
|
||||
"integrity": "sha512-Tj+CjQLpFyBJxhhMms+vbPT3+gTRAiQlrhY3L1IEVwBa3wtRMS0qjozH26d1hK4G6mUIEdwu13L54HMU/w33Sg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -9145,7 +9177,20 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/core/node_modules/semver": {
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/csf": {
|
||||
@@ -9159,9 +9204,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/csf-plugin": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.4.5.tgz",
|
||||
"integrity": "sha512-qd2rQTglOTS+phQmTbNTXNjNyxdGvolaqHqDNMw3Vf6h9o3U+mLkwnDWNVnQ9oqvOoUEAqpBthgwzU9FhkIk+A==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.4.7.tgz",
|
||||
"integrity": "sha512-Fgogplu4HImgC+AYDcdGm1rmL6OR1rVdNX1Be9C/NEXwOCpbbBwi0BxTf/2ZxHRk9fCeaPEcOdP5S8QHfltc1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -9172,7 +9217,7 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/global": {
|
||||
@@ -9197,9 +9242,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/instrumenter": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.4.5.tgz",
|
||||
"integrity": "sha512-8qM35FkueuRpJr0zA6ENvhQICbo+iKL1ln450DwV1kKJtc41KdbA3CuCvtZ/FnoPsFnwdtPjhhICFtRt8LRTSg==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.4.7.tgz",
|
||||
"integrity": "sha512-k6NSD3jaRCCHAFtqXZ7tw8jAzD/yTEWXGya+REgZqq5RCkmJ+9S4Ytp/6OhQMPtPFX23gAuJJzTQVLcCr+gjRg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -9211,13 +9256,13 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/manager-api": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.4.5.tgz",
|
||||
"integrity": "sha512-t39JaMy3UX4StbUH/tIDcaflBDxTcyIq853wQtBMhVL3e1+Dw3MIiiG/5bw79HU4R7kSmPVLXIIbV3FmXkq7KQ==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.4.7.tgz",
|
||||
"integrity": "sha512-ELqemTviCxAsZ5tqUz39sDmQkvhVAvAgiplYy9Uf15kO0SP2+HKsCMzlrm2ue2FfkUNyqbDayCPPCB0Cdn/mpQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
@@ -9229,9 +9274,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/preview-api": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.4.5.tgz",
|
||||
"integrity": "sha512-MKIZ2jQO/3cUdsT57eq8jRgB6inALo9BxrQ88f7mqzltOkMvADvTAY6y8JZqTUoDzWTH/ny/8SGGdtpqlxRuiQ==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.4.7.tgz",
|
||||
"integrity": "sha512-0QVQwHw+OyZGHAJEXo6Knx+6/4er7n2rTDE5RYJ9F2E2Lg42E19pfdLlq2Jhoods2Xrclo3wj6GWR//Ahi39Eg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
@@ -9243,9 +9288,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/react-dom-shim": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.4.5.tgz",
|
||||
"integrity": "sha512-YTWTfPagptEYXJsnxAl3zP97Ev0zebtaEV0WgjGaEeumr+zsfgKKwzzHxgrtumBmDzwkuKlzFwlQB5A8keOIGA==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.4.7.tgz",
|
||||
"integrity": "sha512-6bkG2jvKTmWrmVzCgwpTxwIugd7Lu+2btsLAqhQSzDyIj2/uhMNp8xIMr/NBDtLgq3nomt9gefNa9xxLwk/OMg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
@@ -9255,19 +9300,19 @@
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta",
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/test": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/test/-/test-8.4.5.tgz",
|
||||
"integrity": "sha512-mHsRc6m60nfcEBsjvUkKz+Jnz0or4WH5jmJ1VL2pGKO4VzESCPqAwDnwDqP2YyeSQ0b/MAKUT5kdoLE2RE2eVw==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/test/-/test-8.4.7.tgz",
|
||||
"integrity": "sha512-AhvJsu5zl3uG40itSQVuSy5WByp3UVhS6xAnme4FWRwgSxhvZjATJ3AZkkHWOYjnnk+P2/sbz/XuPli1FVCWoQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@storybook/csf": "^0.1.11",
|
||||
"@storybook/global": "^5.0.0",
|
||||
"@storybook/instrumenter": "8.4.5",
|
||||
"@storybook/instrumenter": "8.4.7",
|
||||
"@testing-library/dom": "10.4.0",
|
||||
"@testing-library/jest-dom": "6.5.0",
|
||||
"@testing-library/user-event": "14.5.2",
|
||||
@@ -9279,13 +9324,13 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^8.4.5"
|
||||
"storybook": "^8.4.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/theming": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.4.5.tgz",
|
||||
"integrity": "sha512-45e/jeG4iuqdZcHg3PbB6dwXQTwlnnEB7r/QcVExyC7ibrkTnjUfvxzyUw4mmU3CXETFGD5EcUobFkgK+/aPxQ==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.4.7.tgz",
|
||||
"integrity": "sha512-99rgLEjf7iwfSEmdqlHkSG3AyLcK0sfExcr0jnc6rLiAkBhzuIsvcHjjUwkR210SOCgXqBPW0ZA6uhnuyppHLw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
@@ -10989,73 +11034,73 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/ast": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz",
|
||||
"integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
|
||||
"integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/helper-numbers": "1.11.6",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6"
|
||||
"@webassemblyjs/helper-numbers": "1.13.2",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.13.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/floating-point-hex-parser": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
|
||||
"integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==",
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
|
||||
"integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-api-error": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
|
||||
"integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==",
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
|
||||
"integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-buffer": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz",
|
||||
"integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
|
||||
"integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-numbers": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
|
||||
"integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
|
||||
"integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/floating-point-hex-parser": "1.11.6",
|
||||
"@webassemblyjs/helper-api-error": "1.11.6",
|
||||
"@webassemblyjs/floating-point-hex-parser": "1.13.2",
|
||||
"@webassemblyjs/helper-api-error": "1.13.2",
|
||||
"@xtuc/long": "4.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-wasm-bytecode": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
|
||||
"integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==",
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
|
||||
"integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-wasm-section": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz",
|
||||
"integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
|
||||
"integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.12.1",
|
||||
"@webassemblyjs/helper-buffer": "1.12.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||
"@webassemblyjs/wasm-gen": "1.12.1"
|
||||
"@webassemblyjs/ast": "1.14.1",
|
||||
"@webassemblyjs/helper-buffer": "1.14.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
|
||||
"@webassemblyjs/wasm-gen": "1.14.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/ieee754": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
|
||||
"integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
|
||||
"integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -11063,9 +11108,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/leb128": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
|
||||
"integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
|
||||
"integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
@@ -11073,79 +11118,79 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/utf8": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
|
||||
"integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==",
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
|
||||
"integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@webassemblyjs/wasm-edit": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz",
|
||||
"integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
|
||||
"integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.12.1",
|
||||
"@webassemblyjs/helper-buffer": "1.12.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||
"@webassemblyjs/helper-wasm-section": "1.12.1",
|
||||
"@webassemblyjs/wasm-gen": "1.12.1",
|
||||
"@webassemblyjs/wasm-opt": "1.12.1",
|
||||
"@webassemblyjs/wasm-parser": "1.12.1",
|
||||
"@webassemblyjs/wast-printer": "1.12.1"
|
||||
"@webassemblyjs/ast": "1.14.1",
|
||||
"@webassemblyjs/helper-buffer": "1.14.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
|
||||
"@webassemblyjs/helper-wasm-section": "1.14.1",
|
||||
"@webassemblyjs/wasm-gen": "1.14.1",
|
||||
"@webassemblyjs/wasm-opt": "1.14.1",
|
||||
"@webassemblyjs/wasm-parser": "1.14.1",
|
||||
"@webassemblyjs/wast-printer": "1.14.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/wasm-gen": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz",
|
||||
"integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
|
||||
"integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.12.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||
"@webassemblyjs/ieee754": "1.11.6",
|
||||
"@webassemblyjs/leb128": "1.11.6",
|
||||
"@webassemblyjs/utf8": "1.11.6"
|
||||
"@webassemblyjs/ast": "1.14.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
|
||||
"@webassemblyjs/ieee754": "1.13.2",
|
||||
"@webassemblyjs/leb128": "1.13.2",
|
||||
"@webassemblyjs/utf8": "1.13.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/wasm-opt": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz",
|
||||
"integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
|
||||
"integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.12.1",
|
||||
"@webassemblyjs/helper-buffer": "1.12.1",
|
||||
"@webassemblyjs/wasm-gen": "1.12.1",
|
||||
"@webassemblyjs/wasm-parser": "1.12.1"
|
||||
"@webassemblyjs/ast": "1.14.1",
|
||||
"@webassemblyjs/helper-buffer": "1.14.1",
|
||||
"@webassemblyjs/wasm-gen": "1.14.1",
|
||||
"@webassemblyjs/wasm-parser": "1.14.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/wasm-parser": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz",
|
||||
"integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
|
||||
"integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.12.1",
|
||||
"@webassemblyjs/helper-api-error": "1.11.6",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||
"@webassemblyjs/ieee754": "1.11.6",
|
||||
"@webassemblyjs/leb128": "1.11.6",
|
||||
"@webassemblyjs/utf8": "1.11.6"
|
||||
"@webassemblyjs/ast": "1.14.1",
|
||||
"@webassemblyjs/helper-api-error": "1.13.2",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
|
||||
"@webassemblyjs/ieee754": "1.13.2",
|
||||
"@webassemblyjs/leb128": "1.13.2",
|
||||
"@webassemblyjs/utf8": "1.13.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/wast-printer": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz",
|
||||
"integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
|
||||
"integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.12.1",
|
||||
"@webassemblyjs/ast": "1.14.1",
|
||||
"@xtuc/long": "4.2.2"
|
||||
}
|
||||
},
|
||||
@@ -13661,9 +13706,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/chromatic": {
|
||||
"version": "11.19.0",
|
||||
"resolved": "https://registry.npmjs.org/chromatic/-/chromatic-11.19.0.tgz",
|
||||
"integrity": "sha512-3JZ1Tt26N2uDok6nXApsvHmTnkrgE0HClq1bmfF5WmCJ61bMN80CObhuFc7kiBCv5QbE7GOe3rpy3MiuZ4h9IA==",
|
||||
"version": "11.20.0",
|
||||
"resolved": "https://registry.npmjs.org/chromatic/-/chromatic-11.20.0.tgz",
|
||||
"integrity": "sha512-Btdli1qoAI01UKmk3Iqe6vKhAhePRXqNI/2uKKy2R16q7SN/5kLTqhd1JI20LFOZSnH3xSJaUXeJ2xZOJB//3A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
@@ -22602,9 +22647,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/lilconfig": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
|
||||
"integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
|
||||
"integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -30143,13 +30188,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/storybook": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/storybook/-/storybook-8.4.5.tgz",
|
||||
"integrity": "sha512-9tfgabXnMibYp3SvoaJXXMD63Pw0SA9Hnf5v6TxysCYZs4DZ/04fAkK+9RW+K4C5JkV83qXMMlrsPj766R47fg==",
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/storybook/-/storybook-8.4.7.tgz",
|
||||
"integrity": "sha512-RP/nMJxiWyFc8EVMH5gp20ID032Wvk+Yr3lmKidoegto5Iy+2dVQnUoElZb2zpbVXNHWakGuAkfI0dY1Hfp/vw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@storybook/core": "8.4.5"
|
||||
"@storybook/core": "8.4.7"
|
||||
},
|
||||
"bin": {
|
||||
"getstorybook": "bin/index.cjs",
|
||||
@@ -30169,51 +30214,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/storybook/node_modules/@storybook/core": {
|
||||
"version": "8.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.4.5.tgz",
|
||||
"integrity": "sha512-aB1sQNX5nRoUAqg5u1py0MuR/VPd6c6PhECa4rW6pmr7kZcfyP4PP6UFpXuN71ypTQlkRE3Vc5PQZ3gLhE9o3g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@storybook/csf": "^0.1.11",
|
||||
"better-opn": "^3.0.2",
|
||||
"browser-assert": "^1.2.1",
|
||||
"esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0",
|
||||
"esbuild-register": "^3.5.0",
|
||||
"jsdoc-type-pratt-parser": "^4.0.0",
|
||||
"process": "^0.11.10",
|
||||
"recast": "^0.23.5",
|
||||
"semver": "^7.6.2",
|
||||
"util": "^0.12.5",
|
||||
"ws": "^8.2.3"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"prettier": "^2 || ^3"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"prettier": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/storybook/node_modules/semver": {
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/stream-combiner": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz",
|
||||
@@ -30643,9 +30643,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tailwindcss": {
|
||||
"version": "3.4.15",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz",
|
||||
"integrity": "sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==",
|
||||
"version": "3.4.16",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.16.tgz",
|
||||
"integrity": "sha512-TI4Cyx7gDiZ6r44ewaJmt0o6BrMCT5aK5e0rmJ/G9Xq3w7CX/5VXl/zIPEJZFUK5VEqwByyhqNPycPlvcK4ZNw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -30658,7 +30658,7 @@
|
||||
"glob-parent": "^6.0.2",
|
||||
"is-glob": "^4.0.3",
|
||||
"jiti": "^1.21.6",
|
||||
"lilconfig": "^2.1.0",
|
||||
"lilconfig": "^3.1.3",
|
||||
"micromatch": "^4.0.8",
|
||||
"normalize-path": "^3.0.0",
|
||||
"object-hash": "^3.0.0",
|
||||
@@ -30693,16 +30693,6 @@
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwindcss/node_modules/lilconfig": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
|
||||
"integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
||||
@@ -33115,17 +33105,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.96.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz",
|
||||
"integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==",
|
||||
"version": "5.97.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz",
|
||||
"integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/eslint-scope": "^3.7.7",
|
||||
"@types/estree": "^1.0.6",
|
||||
"@webassemblyjs/ast": "^1.12.1",
|
||||
"@webassemblyjs/wasm-edit": "^1.12.1",
|
||||
"@webassemblyjs/wasm-parser": "^1.12.1",
|
||||
"@webassemblyjs/ast": "^1.14.1",
|
||||
"@webassemblyjs/wasm-edit": "^1.14.1",
|
||||
"@webassemblyjs/wasm-parser": "^1.14.1",
|
||||
"acorn": "^8.14.0",
|
||||
"browserslist": "^4.24.0",
|
||||
"chrome-trace-event": "^1.0.2",
|
||||
|
||||
24
package.json
24
package.json
@@ -49,15 +49,15 @@
|
||||
"@electron/notarize": "2.5.0",
|
||||
"@electron/rebuild": "3.7.1",
|
||||
"@ngtools/webpack": "17.3.11",
|
||||
"@storybook/addon-a11y": "8.4.5",
|
||||
"@storybook/addon-actions": "8.4.5",
|
||||
"@storybook/addon-a11y": "8.4.7",
|
||||
"@storybook/addon-actions": "8.4.7",
|
||||
"@storybook/addon-designs": "8.0.4",
|
||||
"@storybook/addon-essentials": "8.4.5",
|
||||
"@storybook/addon-interactions": "8.4.5",
|
||||
"@storybook/addon-links": "8.4.5",
|
||||
"@storybook/angular": "8.4.5",
|
||||
"@storybook/manager-api": "8.4.5",
|
||||
"@storybook/theming": "8.4.5",
|
||||
"@storybook/addon-essentials": "8.4.7",
|
||||
"@storybook/addon-interactions": "8.4.7",
|
||||
"@storybook/addon-links": "8.4.7",
|
||||
"@storybook/angular": "8.4.7",
|
||||
"@storybook/manager-api": "8.4.7",
|
||||
"@storybook/theming": "8.4.7",
|
||||
"@types/argon2-browser": "1.18.4",
|
||||
"@types/chrome": "0.0.280",
|
||||
"@types/firefox-webext-browser": "120.0.4",
|
||||
@@ -88,7 +88,7 @@
|
||||
"babel-loader": "9.2.1",
|
||||
"base64-loader": "1.0.0",
|
||||
"browserslist": "4.23.2",
|
||||
"chromatic": "11.19.0",
|
||||
"chromatic": "11.20.0",
|
||||
"concurrently": "9.1.0",
|
||||
"copy-webpack-plugin": "12.0.2",
|
||||
"cross-env": "7.0.3",
|
||||
@@ -127,9 +127,9 @@
|
||||
"rimraf": "6.0.1",
|
||||
"sass": "1.81.0",
|
||||
"sass-loader": "16.0.4",
|
||||
"storybook": "8.4.5",
|
||||
"storybook": "8.4.7",
|
||||
"style-loader": "4.0.0",
|
||||
"tailwindcss": "3.4.15",
|
||||
"tailwindcss": "3.4.16",
|
||||
"ts-jest": "29.2.2",
|
||||
"ts-loader": "9.5.1",
|
||||
"tsconfig-paths-webpack-plugin": "4.1.0",
|
||||
@@ -139,7 +139,7 @@
|
||||
"url": "0.11.4",
|
||||
"util": "0.12.5",
|
||||
"wait-on": "8.0.1",
|
||||
"webpack": "5.96.1",
|
||||
"webpack": "5.97.1",
|
||||
"webpack-cli": "5.1.4",
|
||||
"webpack-dev-server": "5.0.4",
|
||||
"webpack-node-externals": "3.0.0"
|
||||
|
||||
Reference in New Issue
Block a user