diff --git a/.env.template b/.env.template
index 03990820..a12559ad 100644
--- a/.env.template
+++ b/.env.template
@@ -50,10 +50,11 @@
#########################
## Database URL
-## When using SQLite, this is the path to the DB file, and it defaults to
-## %DATA_FOLDER%/db.sqlite3. If DATA_FOLDER is set to an external location, this
-## must be set to a local sqlite3 file path.
-# DATABASE_URL=data/db.sqlite3
+## When using SQLite, this should use the sqlite:// scheme followed by the path
+## to the DB file. It defaults to sqlite://%DATA_FOLDER%/db.sqlite3.
+## Bare paths without the sqlite:// scheme are supported for backwards compatibility,
+## but only if the database file already exists.
+# DATABASE_URL=sqlite://data/db.sqlite3
## When using MySQL, specify an appropriate connection URI.
## Details: https://docs.diesel.rs/2.1.x/diesel/mysql/struct.MysqlConnection.html
# DATABASE_URL=mysql://user:password@host[:port]/database_name
diff --git a/.gitattributes b/.gitattributes
index b33a6211..4d7cadd3 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,3 +1,2 @@
# Ignore vendored scripts in GitHub stats
src/static/scripts/* linguist-vendored
-
diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml
index c9e02cf9..83d00210 100644
--- a/.github/workflows/trivy.yml
+++ b/.github/workflows/trivy.yml
@@ -38,7 +38,7 @@ jobs:
persist-credentials: false
- name: Run Trivy vulnerability scanner
- uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0
+ uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
env:
TRIVY_DB_REPOSITORY: docker.io/aquasec/trivy-db:2,public.ecr.aws/aquasecurity/trivy-db:2,ghcr.io/aquasecurity/trivy-db:2
TRIVY_JAVA_DB_REPOSITORY: docker.io/aquasec/trivy-java-db:1,public.ecr.aws/aquasecurity/trivy-java-db:1,ghcr.io/aquasecurity/trivy-java-db:1
@@ -50,6 +50,6 @@ jobs:
severity: CRITICAL,HIGH
- name: Upload Trivy scan results to GitHub Security tab
- uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
+ uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
with:
sarif_file: 'trivy-results.sarif'
diff --git a/.github/workflows/typos.yml b/.github/workflows/typos.yml
index f68ef29d..eaf77896 100644
--- a/.github/workflows/typos.yml
+++ b/.github/workflows/typos.yml
@@ -23,4 +23,4 @@ jobs:
# When this version is updated, do not forget to update this in `.pre-commit-config.yaml` too
- name: Spell Check Repo
- uses: crate-ci/typos@02ea592e44b3a53c302f697cddca7641cd051c3d # v1.45.0
+ uses: crate-ci/typos@5374cbf686e897b15713110e233094e2874de7ef # v1.46.1
diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml
index 4bd40db3..d5bc7464 100644
--- a/.github/workflows/zizmor.yml
+++ b/.github/workflows/zizmor.yml
@@ -24,7 +24,7 @@ jobs:
persist-credentials: false
- name: Run zizmor
- uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2
+ uses: zizmorcore/zizmor-action@b572f7b1a1c2d41efaab43d504f68d215c3cd727 # v0.5.4
with:
# intentionally not scanning the entire repository,
# since it contains integration tests.
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 0b6ad451..11f0b439 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,58 +1,60 @@
---
repos:
-- repo: https://github.com/pre-commit/pre-commit-hooks
+ - repo: https://github.com/pre-commit/pre-commit-hooks
rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # v6.0.0
hooks:
- - id: check-yaml
- - id: check-json
- - id: check-toml
- - id: mixed-line-ending
- args: ["--fix=no"]
- - id: end-of-file-fixer
- exclude: "(.*js$|.*css$)"
- - id: check-case-conflict
- - id: check-merge-conflict
- - id: detect-private-key
- - id: check-symlinks
- - id: forbid-submodules
-- repo: local
+ - id: check-yaml
+ - id: check-json
+ - id: check-toml
+ - id: mixed-line-ending
+ args: [ "--fix=no" ]
+ - id: end-of-file-fixer
+ exclude: "(.*js$|.*css$)"
+ - id: check-case-conflict
+ - id: check-merge-conflict
+ - id: detect-private-key
+ - id: check-symlinks
+ - id: forbid-submodules
+
+ # When this version is updated, do not forget to update this in `.github/workflows/typos.yaml` too
+ - repo: https://github.com/crate-ci/typos
+ rev: 5374cbf686e897b15713110e233094e2874de7ef # v1.46.1
hooks:
- - id: fmt
- name: fmt
- description: Format files with cargo fmt.
- entry: cargo fmt
- language: system
- always_run: true
- pass_filenames: false
- args: ["--", "--check"]
- - id: cargo-test
- name: cargo test
- description: Test the package for errors.
- entry: cargo test
- language: system
- args: ["--features", "sqlite,mysql,postgresql", "--"]
- types_or: [rust, file]
- files: (Cargo.toml|Cargo.lock|rust-toolchain.toml|rustfmt.toml|.*\.rs$)
- pass_filenames: false
- - id: cargo-clippy
- name: cargo clippy
- description: Lint Rust sources
- entry: cargo clippy
- language: system
- args: ["--features", "sqlite,mysql,postgresql", "--", "-D", "warnings"]
- types_or: [rust, file]
- files: (Cargo.toml|Cargo.lock|rust-toolchain.toml|rustfmt.toml|.*\.rs$)
- pass_filenames: false
- - id: check-docker-templates
- name: check docker templates
- description: Check if the Docker templates are updated
- language: system
- entry: sh
- args:
- - "-c"
- - "cd docker && make"
-# When this version is updated, do not forget to update this in `.github/workflows/typos.yaml` too
-- repo: https://github.com/crate-ci/typos
- rev: 02ea592e44b3a53c302f697cddca7641cd051c3d # v1.45.0
- hooks:
- - id: typos
+ - id: typos
+
+ - repo: local
+ hooks:
+ - id: fmt
+ name: fmt
+ description: Format files with cargo fmt.
+ entry: cargo fmt
+ language: system
+ always_run: true
+ pass_filenames: false
+ args: [ "--", "--check" ]
+ - id: cargo-test
+ name: cargo test
+ description: Test the package for errors.
+ entry: cargo test
+ language: system
+ args: [ "--features", "sqlite,mysql,postgresql", "--" ]
+ types_or: [ rust, file ]
+ files: (Cargo.toml|Cargo.lock|rust-toolchain.toml|rustfmt.toml|.*\.rs$)
+ pass_filenames: false
+ - id: cargo-clippy
+ name: cargo clippy
+ description: Lint Rust sources
+ entry: cargo clippy
+ language: system
+ args: [ "--features", "sqlite,mysql,postgresql", "--", "-D", "warnings" ]
+ types_or: [ rust, file ]
+ files: (Cargo.toml|Cargo.lock|rust-toolchain.toml|rustfmt.toml|.*\.rs$)
+ pass_filenames: false
+ - id: check-docker-templates
+ name: check docker templates
+ description: Check if the Docker templates are updated
+ language: system
+ entry: sh
+ args:
+ - "-c"
+ - "cd docker && make"
diff --git a/.typos.toml b/.typos.toml
index 59f6d7d6..87c0c4a6 100644
--- a/.typos.toml
+++ b/.typos.toml
@@ -23,4 +23,6 @@ extend-ignore-re = [
# https://github.com/bitwarden/server/blob/dff9f1cf538198819911cf2c20f8cda3307701c5/src/Notifications/HubHelpers.cs#L86
# https://github.com/bitwarden/clients/blob/9612a4ac45063e372a6fbe87eb253c7cb3c588fb/libs/common/src/auth/services/anonymous-hub.service.ts#L45
"AuthRequestResponseRecieved",
+ # Ignore Punycode/IDN tests
+ "xn--.+"
]
diff --git a/Cargo.lock b/Cargo.lock
index 3d4d5921..f4d87f9b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -8,17 +8,6 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
-[[package]]
-name = "aes"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
-dependencies = [
- "cfg-if",
- "cipher",
- "cpufeatures 0.2.17",
-]
-
[[package]]
name = "ahash"
version = "0.8.12"
@@ -152,9 +141,9 @@ dependencies = [
[[package]]
name = "async-compression"
-version = "0.4.41"
+version = "0.4.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0f9ee0f6e02ffd7ad5816e9464499fba7b3effd01123b515c41d1697c43dad1"
+checksum = "e79b3f8a79cccc2898f31920fc69f304859b3bd567490f75ebf51ae1c792a9ac"
dependencies = [
"compression-codecs",
"compression-core",
@@ -351,9 +340,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "aws-config"
-version = "1.8.15"
+version = "1.8.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11493b0bad143270fb8ad284a096dd529ba91924c5409adeac856cc1bf047dbc"
+checksum = "50f156acdd2cf55f5aa53ee416c4ac851cf1222694506c0b1f78c85695e9ca9d"
dependencies = [
"aws-credential-types",
"aws-runtime",
@@ -393,9 +382,9 @@ dependencies = [
[[package]]
name = "aws-runtime"
-version = "1.7.2"
+version = "1.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fc0651c57e384202e47153c1260b84a9936e19803d747615edf199dc3b98d17"
+checksum = "5dcd93c82209ac7413532388067dce79be5a8780c1786e5fae3df22e4dee2864"
dependencies = [
"aws-credential-types",
"aws-sigv4",
@@ -418,9 +407,9 @@ dependencies = [
[[package]]
name = "aws-sdk-sso"
-version = "1.97.0"
+version = "1.98.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9aadc669e184501caaa6beafb28c6267fc1baef0810fb58f9b205485ca3f2567"
+checksum = "d69c77aafa20460c68b6b3213c84f6423b6e76dbf89accd3e1789a686ffd9489"
dependencies = [
"aws-credential-types",
"aws-runtime",
@@ -442,9 +431,9 @@ dependencies = [
[[package]]
name = "aws-sdk-ssooidc"
-version = "1.99.0"
+version = "1.100.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1342a7db8f358d3de0aed2007a0b54e875458e39848d54cc1d46700b2bfcb0a8"
+checksum = "1c7e7b09346d5ca22a2a08267555843a6a0127fb20d8964cb6ecfb8fdb190225"
dependencies = [
"aws-credential-types",
"aws-runtime",
@@ -466,9 +455,9 @@ dependencies = [
[[package]]
name = "aws-sdk-sts"
-version = "1.101.0"
+version = "1.103.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab41ad64e4051ecabeea802d6a17845a91e83287e1dd249e6963ea1ba78c428a"
+checksum = "c2249b81a2e73a8027c41c378463a81ec39b8510f184f2caab87de912af0f49b"
dependencies = [
"aws-credential-types",
"aws-runtime",
@@ -491,9 +480,9 @@ dependencies = [
[[package]]
name = "aws-sigv4"
-version = "1.4.2"
+version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0b660013a6683ab23797778e21f1f854744fdf05f68204b4cca4c8c04b5d1f4"
+checksum = "68dc0b907359b120170613b5c09ccc61304eac3998ff6274b97d93ee6490115a"
dependencies = [
"aws-credential-types",
"aws-smithy-http",
@@ -502,11 +491,11 @@ dependencies = [
"bytes",
"form_urlencoded",
"hex",
- "hmac",
+ "hmac 0.13.0",
"http 0.2.12",
"http 1.4.0",
"percent-encoding",
- "sha2",
+ "sha2 0.11.0",
"time",
"tracing",
]
@@ -573,9 +562,9 @@ dependencies = [
[[package]]
name = "aws-smithy-runtime"
-version = "1.10.3"
+version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "028999056d2d2fd58a697232f9eec4a643cf73a71cf327690a7edad1d2af2110"
+checksum = "0504b1ab12debb5959e5165ee5fe97dd387e7aa7ea6a477bfd7635dfe769a4f5"
dependencies = [
"aws-smithy-async",
"aws-smithy-http",
@@ -597,11 +586,12 @@ dependencies = [
[[package]]
name = "aws-smithy-runtime-api"
-version = "1.11.6"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "876ab3c9c29791ba4ba02b780a3049e21ec63dabda09268b175272c3733a79e6"
+checksum = "b71a13df6ada0aafbf21a73bdfcdf9324cfa9df77d96b8446045be3cde61b42e"
dependencies = [
"aws-smithy-async",
+ "aws-smithy-runtime-api-macros",
"aws-smithy-types",
"bytes",
"http 0.2.12",
@@ -612,6 +602,17 @@ dependencies = [
"zeroize",
]
+[[package]]
+name = "aws-smithy-runtime-api-macros"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d7396fd9500589e62e460e987ecb671bad374934e55ec3b5f498cc7a8a8a7b7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "aws-smithy-types"
version = "1.4.7"
@@ -646,9 +647,9 @@ dependencies = [
[[package]]
name = "aws-types"
-version = "1.3.14"
+version = "1.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47c8323699dd9b3c8d5b3c13051ae9cdef58fd179957c882f8374dd8725962d9"
+checksum = "2f4bbcaa9304ea40902d3d5f42a0428d1bd895a2b0f6999436fb279ffddc58ac"
dependencies = [
"aws-credential-types",
"aws-smithy-async",
@@ -658,17 +659,6 @@ dependencies = [
"tracing",
]
-[[package]]
-name = "backon"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef"
-dependencies = [
- "fastrand",
- "gloo-timers",
- "tokio",
-]
-
[[package]]
name = "base16ct"
version = "0.2.0"
@@ -705,9 +695,9 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]]
name = "base64urlsafedata"
-version = "0.5.4"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42f7f6be94fa637132933fd0a68b9140bcb60e3d46164cb68e82a2bb8d102b3a"
+checksum = "b08e33815c87d8cadcddb1e74ac307368a3751fbe40c961538afa21a1899f21c"
dependencies = [
"base64 0.21.7",
"pastey 0.1.1",
@@ -735,9 +725,9 @@ checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72"
[[package]]
name = "bitflags"
-version = "2.11.0"
+version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
+checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
[[package]]
name = "blake2"
@@ -745,7 +735,7 @@ version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
dependencies = [
- "digest",
+ "digest 0.10.7",
]
[[package]]
@@ -758,12 +748,12 @@ dependencies = [
]
[[package]]
-name = "block-padding"
-version = "0.3.3"
+name = "block-buffer"
+version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
+checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be"
dependencies = [
- "generic-array",
+ "hybrid-array",
]
[[package]]
@@ -800,6 +790,15 @@ dependencies = [
"alloc-stdlib",
]
+[[package]]
+name = "bs58"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4"
+dependencies = [
+ "tinyvec",
+]
+
[[package]]
name = "bumpalo"
version = "3.20.2"
@@ -871,20 +870,11 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0"
-[[package]]
-name = "cbc"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
-dependencies = [
- "cipher",
-]
-
[[package]]
name = "cc"
-version = "1.2.60"
+version = "1.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20"
+checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98"
dependencies = [
"find-msvc-tools",
"jobserver",
@@ -898,12 +888,6 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
-[[package]]
-name = "cfg_aliases"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
-
[[package]]
name = "chacha20"
version = "0.10.0"
@@ -912,7 +896,7 @@ checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601"
dependencies = [
"cfg-if",
"cpufeatures 0.3.0",
- "rand_core 0.10.0",
+ "rand_core 0.10.1",
]
[[package]]
@@ -940,14 +924,10 @@ dependencies = [
]
[[package]]
-name = "cipher"
-version = "0.4.4"
+name = "cmov"
+version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
-dependencies = [
- "crypto-common",
- "inout",
-]
+checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746"
[[package]]
name = "codemap"
@@ -955,11 +935,21 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e769b5c8c8283982a987c6e948e540254f1058d5a74b8794914d4ef5fc2a24"
+[[package]]
+name = "combine"
+version = "4.6.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
+dependencies = [
+ "bytes",
+ "memchr",
+]
+
[[package]]
name = "compression-codecs"
-version = "0.4.37"
+version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb7b51a7d9c967fc26773061ba86150f19c50c0d65c887cb1fbe295fd16619b7"
+checksum = "ce2548391e9c1929c21bf6aa2680af86fe4c1b33e6cea9ac1cfeec0bd11218cf"
dependencies = [
"brotli",
"compression-core",
@@ -971,9 +961,9 @@ dependencies = [
[[package]]
name = "compression-core"
-version = "0.4.31"
+version = "0.4.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75984efb6ed102a0d42db99afb6c1948f0380d1d91808d5529916e6c08b49d8d"
+checksum = "cc14f565cf027a105f7a44ccf9e5b424348421a1d8952a8fc9d499d313107789"
[[package]]
name = "concurrent-queue"
@@ -990,6 +980,12 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
+[[package]]
+name = "const-oid"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
+
[[package]]
name = "const-random"
version = "0.1.18"
@@ -1179,6 +1175,24 @@ dependencies = [
"typenum",
]
+[[package]]
+name = "crypto-common"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710"
+dependencies = [
+ "hybrid-array",
+]
+
+[[package]]
+name = "ctutils"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e"
+dependencies = [
+ "cmov",
+]
+
[[package]]
name = "curve25519-dalek"
version = "4.1.3"
@@ -1188,7 +1202,7 @@ dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
"curve25519-dalek-derive",
- "digest",
+ "digest 0.10.7",
"fiat-crypto",
"rustc_version",
"subtle",
@@ -1326,9 +1340,9 @@ dependencies = [
[[package]]
name = "data-encoding"
-version = "2.10.0"
+version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea"
+checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8"
[[package]]
name = "data-url"
@@ -1342,7 +1356,7 @@ version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
dependencies = [
- "const-oid",
+ "const-oid 0.9.6",
"pem-rfc7468",
"zeroize",
]
@@ -1460,9 +1474,9 @@ dependencies = [
[[package]]
name = "diesel"
-version = "2.3.7"
+version = "2.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4ae09a41a4b89f94ec1e053623da8340d996bc32c6517d325a9daad9b239358"
+checksum = "9940fb8467a0a06312218ed384185cb8536aa10d8ec017d0ce7fad2c1bd882d5"
dependencies = [
"bigdecimal",
"bitflags",
@@ -1497,9 +1511,9 @@ dependencies = [
[[package]]
name = "diesel_derives"
-version = "2.3.7"
+version = "2.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47618bf0fac06bb670c036e48404c26a865e6a71af4114dfd97dfe89936e404e"
+checksum = "d1817b7f4279b947fc4cafddec12b0e5f8727141706561ce3ac94a60bddd1cf5"
dependencies = [
"diesel_table_macro_syntax",
"dsl_auto_type",
@@ -1510,9 +1524,9 @@ dependencies = [
[[package]]
name = "diesel_migrations"
-version = "2.3.1"
+version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "745fd255645f0f1135f9ec55c7b00e0882192af9683ab4731e4bba3da82b8f9c"
+checksum = "28d0f4a98124ba6d4ca75da535f65984badec16a003b6e2f94a01e31a79490b8"
dependencies = [
"diesel",
"migrations_internals",
@@ -1534,12 +1548,24 @@ version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
- "block-buffer",
- "const-oid",
- "crypto-common",
+ "block-buffer 0.10.4",
+ "const-oid 0.9.6",
+ "crypto-common 0.1.6",
"subtle",
]
+[[package]]
+name = "digest"
+version = "0.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
+dependencies = [
+ "block-buffer 0.12.0",
+ "const-oid 0.10.2",
+ "crypto-common 0.2.1",
+ "ctutils",
+]
+
[[package]]
name = "displaydoc"
version = "0.2.5"
@@ -1608,7 +1634,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
dependencies = [
"der",
- "digest",
+ "digest 0.10.7",
"elliptic-curve",
"rfc6979",
"signature",
@@ -1634,7 +1660,7 @@ dependencies = [
"curve25519-dalek",
"ed25519",
"serde",
- "sha2",
+ "sha2 0.10.9",
"subtle",
"zeroize",
]
@@ -1653,7 +1679,7 @@ checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
dependencies = [
"base16ct",
"crypto-bigint",
- "digest",
+ "digest 0.10.7",
"ff",
"generic-array",
"group",
@@ -1694,18 +1720,6 @@ dependencies = [
"cfg-if",
]
-[[package]]
-name = "enum-as-inner"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc"
-dependencies = [
- "heck",
- "proc-macro2",
- "quote",
- "syn",
-]
-
[[package]]
name = "equivalent"
version = "1.0.2"
@@ -2022,7 +2036,7 @@ dependencies = [
"cfg-if",
"libc",
"r-efi 6.0.0",
- "rand_core 0.10.0",
+ "rand_core 0.10.1",
"wasip2",
"wasip3",
]
@@ -2062,7 +2076,7 @@ dependencies = [
"parking_lot",
"portable-atomic",
"quanta",
- "rand 0.9.3",
+ "rand 0.9.4",
"smallvec",
"spinning_top",
"web-time",
@@ -2094,9 +2108,9 @@ dependencies = [
[[package]]
name = "h2"
-version = "0.4.13"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54"
+checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733"
dependencies = [
"atomic-waker",
"bytes",
@@ -2177,9 +2191,9 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.17.0"
+version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
+checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "heck"
@@ -2200,46 +2214,70 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
-name = "hickory-proto"
-version = "0.25.2"
+name = "hickory-net"
+version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502"
+checksum = "e2295ed2f9c31e471e1428a8f88a3f0e1f4b27c15049592138d1eebe9c35b183"
dependencies = [
"async-trait",
"cfg-if",
"data-encoding",
- "enum-as-inner",
"futures-channel",
"futures-io",
"futures-util",
+ "hickory-proto",
"idna",
"ipnet",
+ "jni",
+ "rand 0.10.1",
+ "thiserror 2.0.18",
+ "tinyvec",
+ "tokio",
+ "tracing",
+ "url",
+]
+
+[[package]]
+name = "hickory-proto"
+version = "0.26.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bab31817bfb44672a252e97fe81cd0c18d1b2cf892108922f6818820df8c643"
+dependencies = [
+ "data-encoding",
+ "idna",
+ "ipnet",
+ "jni",
"once_cell",
- "rand 0.9.3",
+ "prefix-trie",
+ "rand 0.10.1",
"ring",
"thiserror 2.0.18",
"tinyvec",
- "tokio",
"tracing",
"url",
]
[[package]]
name = "hickory-resolver"
-version = "0.25.2"
+version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a"
+checksum = "f0d58d28879ceecde6607729660c2667a081ccdc082e082675042793960f178c"
dependencies = [
"cfg-if",
"futures-util",
+ "hickory-net",
"hickory-proto",
"ipconfig",
+ "ipnet",
+ "jni",
"moka",
+ "ndk-context",
"once_cell",
"parking_lot",
- "rand 0.9.3",
+ "rand 0.10.1",
"resolv-conf",
"smallvec",
+ "system-configuration",
"thiserror 2.0.18",
"tokio",
"tracing",
@@ -2251,7 +2289,7 @@ version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
dependencies = [
- "hmac",
+ "hmac 0.12.1",
]
[[package]]
@@ -2260,16 +2298,16 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
- "digest",
+ "digest 0.10.7",
]
[[package]]
-name = "home"
-version = "0.5.12"
+name = "hmac"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d"
+checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f"
dependencies = [
- "windows-sys 0.61.2",
+ "digest 0.11.3",
]
[[package]]
@@ -2359,6 +2397,15 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
+[[package]]
+name = "hybrid-array"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da"
+dependencies = [
+ "typenum",
+]
+
[[package]]
name = "hyper"
version = "0.14.32"
@@ -2405,20 +2452,17 @@ dependencies = [
[[package]]
name = "hyper-rustls"
-version = "0.27.7"
+version = "0.27.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58"
+checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f"
dependencies = [
"http 1.4.0",
"hyper 1.9.0",
"hyper-util",
- "rustls 0.23.37",
- "rustls-native-certs",
- "rustls-pki-types",
+ "rustls 0.23.40",
"tokio",
"tokio-rustls 0.26.4",
"tower-service",
- "webpki-roots",
]
[[package]]
@@ -2577,9 +2621,9 @@ dependencies = [
[[package]]
name = "idna_adapter"
-version = "1.2.1"
+version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
+checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714"
dependencies = [
"icu_normalizer",
"icu_properties",
@@ -2603,7 +2647,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
- "hashbrown 0.17.0",
+ "hashbrown 0.17.1",
"serde",
"serde_core",
]
@@ -2614,16 +2658,6 @@ version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb"
-[[package]]
-name = "inout"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
-dependencies = [
- "block-padding",
- "generic-array",
-]
-
[[package]]
name = "ipconfig"
version = "0.3.4"
@@ -2642,14 +2676,7 @@ name = "ipnet"
version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
-
-[[package]]
-name = "iri-string"
-version = "0.7.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20"
dependencies = [
- "memchr",
"serde",
]
@@ -2687,24 +2714,26 @@ checksum = "47f142fe24a9c9944451e8349de0a56af5f3e7226dc46f3ed4d4ecc0b85af75e"
[[package]]
name = "jiff"
-version = "0.2.23"
+version = "0.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359"
+checksum = "f00b5dbd620d61dfdcb6007c9c1f6054ebd75319f163d886a9055cec1155073d"
dependencies = [
"jiff-static",
"jiff-tzdb-platform",
+ "js-sys",
"log",
"portable-atomic",
"portable-atomic-util",
"serde_core",
+ "wasm-bindgen",
"windows-sys 0.61.2",
]
[[package]]
name = "jiff-static"
-version = "0.2.23"
+version = "0.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4"
+checksum = "e000de030ff8022ea1da3f466fbb0f3a809f5e51ed31f6dd931c35181ad8e6d7"
dependencies = [
"proc-macro2",
"quote",
@@ -2726,6 +2755,55 @@ dependencies = [
"jiff-tzdb",
]
+[[package]]
+name = "jni"
+version = "0.22.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498"
+dependencies = [
+ "cfg-if",
+ "combine",
+ "jni-macros",
+ "jni-sys",
+ "log",
+ "simd_cesu8",
+ "thiserror 2.0.18",
+ "walkdir",
+ "windows-link",
+]
+
+[[package]]
+name = "jni-macros"
+version = "0.22.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "rustc_version",
+ "simd_cesu8",
+ "syn",
+]
+
+[[package]]
+name = "jni-sys"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2"
+dependencies = [
+ "jni-sys-macros",
+]
+
+[[package]]
+name = "jni-sys-macros"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
+dependencies = [
+ "quote",
+ "syn",
+]
+
[[package]]
name = "job_scheduler_ng"
version = "2.4.0"
@@ -2749,9 +2827,9 @@ dependencies = [
[[package]]
name = "js-sys"
-version = "0.3.95"
+version = "0.3.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca"
+checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08"
dependencies = [
"cfg-if",
"futures-util",
@@ -2761,40 +2839,26 @@ dependencies = [
[[package]]
name = "jsonwebtoken"
-version = "9.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde"
-dependencies = [
- "base64 0.22.1",
- "js-sys",
- "pem",
- "ring",
- "serde",
- "serde_json",
- "simple_asn1",
-]
-
-[[package]]
-name = "jsonwebtoken"
-version = "10.3.0"
+version = "10.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0529410abe238729a60b108898784df8984c87f6054c9c4fcacc47e4803c1ce1"
+checksum = "eba32bfb4ffdeaca3e34431072faf01745c9b26d25504aa7a6cf5684334fc4fc"
dependencies = [
"base64 0.22.1",
"ed25519-dalek",
"getrandom 0.2.17",
- "hmac",
+ "hmac 0.12.1",
"js-sys",
"p256",
"p384",
"pem",
- "rand 0.8.5",
+ "rand 0.8.6",
"rsa",
"serde",
"serde_json",
- "sha2",
+ "sha2 0.10.9",
"signature",
"simple_asn1",
+ "zeroize",
]
[[package]]
@@ -2832,9 +2896,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "lettre"
-version = "0.11.21"
+version = "0.11.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dabda5859ee7c06b995b9d1165aa52c39110e079ef609db97178d86aeb051fa7"
+checksum = "0da65617f6cb926332d039cb578aad56178da86e128db6a1b09f4c94fa5b3349"
dependencies = [
"async-std",
"async-trait",
@@ -2851,7 +2915,7 @@ dependencies = [
"nom 8.0.0",
"percent-encoding",
"quoted_printable",
- "rustls 0.23.37",
+ "rustls 0.23.40",
"rustls-native-certs",
"serde",
"socket2 0.6.3",
@@ -2863,9 +2927,9 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.184"
+version = "0.2.186"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af"
+checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]]
name = "libm"
@@ -2875,19 +2939,18 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
[[package]]
name = "libmimalloc-sys"
-version = "0.1.44"
+version = "0.1.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "667f4fec20f29dfc6bc7357c582d91796c169ad7e2fce709468aefeb2c099870"
+checksum = "2d1eacfa31c33ec25e873c136ba5669f00f9866d0688bea7be4d3f7e43067df6"
dependencies = [
"cc",
- "libc",
]
[[package]]
name = "libsqlite3-sys"
-version = "0.36.0"
+version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95b4103cffefa72eb8428cb6b47d6627161e51c2739fc5e3b734584157bc642a"
+checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1"
dependencies = [
"cc",
"pkg-config",
@@ -2945,12 +3008,6 @@ dependencies = [
"tracing-subscriber",
]
-[[package]]
-name = "lru-slab"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
-
[[package]]
name = "macros"
version = "0.1.0"
@@ -2975,7 +3032,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
dependencies = [
"cfg-if",
- "digest",
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "mea"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6747f54621d156e1b47eb6b25f39a941b9fc347f98f67d25d8881ff99e8ed832"
+dependencies = [
+ "slab",
]
[[package]]
@@ -3007,9 +3073,9 @@ dependencies = [
[[package]]
name = "mimalloc"
-version = "0.1.48"
+version = "0.1.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1ee66a4b64c74f4ef288bcbb9192ad9c3feaad75193129ac8509af543894fd8"
+checksum = "b3627c4272df786b9260cabaa46aec1d59c93ede723d4c3ef646c503816b0640"
dependencies = [
"libmimalloc-sys",
]
@@ -3097,6 +3163,12 @@ dependencies = [
"vcpkg",
]
+[[package]]
+name = "ndk-context"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b"
+
[[package]]
name = "nom"
version = "7.1.3"
@@ -3152,7 +3224,7 @@ dependencies = [
"num-integer",
"num-iter",
"num-traits",
- "rand 0.8.5",
+ "rand 0.8.6",
"smallvec",
"zeroize",
]
@@ -3248,12 +3320,11 @@ dependencies = [
"chrono",
"getrandom 0.2.17",
"http 1.4.0",
- "rand 0.8.5",
- "reqwest",
+ "rand 0.8.6",
"serde",
"serde_json",
"serde_path_to_error",
- "sha2",
+ "sha2 0.10.9",
"thiserror 1.0.69",
"url",
]
@@ -3279,31 +3350,76 @@ dependencies = [
[[package]]
name = "opendal"
-version = "0.55.0"
+version = "0.56.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97b31d3d8e99a85d83b73ec26647f5607b80578ed9375810b6e44ffa3590a236"
+dependencies = [
+ "opendal-core",
+ "opendal-service-fs",
+ "opendal-service-s3",
+]
+
+[[package]]
+name = "opendal-core"
+version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d075ab8a203a6ab4bc1bce0a4b9fe486a72bf8b939037f4b78d95386384bc80a"
+checksum = "1849dd2687e173e776d3af5fce1ba3ae47b9dd37a09d1c4deba850ef45fe00ca"
dependencies = [
"anyhow",
- "backon",
"base64 0.22.1",
"bytes",
- "crc32c",
"futures",
- "getrandom 0.2.17",
"http 1.4.0",
"http-body 1.0.1",
"jiff",
"log",
"md-5",
+ "mea",
"percent-encoding",
"quick-xml 0.38.4",
- "reqsign",
+ "reqsign-core",
"reqwest",
"serde",
"serde_json",
"tokio",
"url",
"uuid",
+ "web-time",
+]
+
+[[package]]
+name = "opendal-service-fs"
+version = "0.56.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf0be0417abeeb0053376d816b90fceb9ca98f20dfb54ebf1f2a282729f83663"
+dependencies = [
+ "bytes",
+ "log",
+ "opendal-core",
+ "serde",
+ "tokio",
+ "xattr",
+]
+
+[[package]]
+name = "opendal-service-s3"
+version = "0.56.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dadddeb9bb50b0d30927dd914c298c4ddca47e4c1cfa7674d311f0cf9b051c8"
+dependencies = [
+ "base64 0.22.1",
+ "bytes",
+ "crc32c",
+ "http 1.4.0",
+ "log",
+ "md-5",
+ "opendal-core",
+ "quick-xml 0.38.4",
+ "reqsign-aws-v4",
+ "reqsign-core",
+ "reqsign-file-read-tokio",
+ "serde",
+ "url",
]
[[package]]
@@ -3316,14 +3432,14 @@ dependencies = [
"chrono",
"dyn-clone",
"ed25519-dalek",
- "hmac",
+ "hmac 0.12.1",
"http 1.4.0",
"itertools",
"log",
"oauth2",
"p256",
"p384",
- "rand 0.8.5",
+ "rand 0.8.6",
"rsa",
"serde",
"serde-value",
@@ -3331,7 +3447,7 @@ dependencies = [
"serde_path_to_error",
"serde_plain",
"serde_with",
- "sha2",
+ "sha2 0.10.9",
"subtle",
"thiserror 1.0.69",
"url",
@@ -3339,15 +3455,14 @@ dependencies = [
[[package]]
name = "openssl"
-version = "0.10.76"
+version = "0.10.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf"
+checksum = "bf0b434746ee2832f4f0baf10137e1cabb18cbe6912c69e2e33263c45250f542"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
- "once_cell",
"openssl-macros",
"openssl-sys",
]
@@ -3380,9 +3495,9 @@ dependencies = [
[[package]]
name = "openssl-sys"
-version = "0.9.112"
+version = "0.9.115"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb"
+checksum = "158fe5b292746440aa6e7a7e690e55aeb72d41505e2804c23c6973ad0e9c9781"
dependencies = [
"cc",
"libc",
@@ -3425,7 +3540,7 @@ dependencies = [
"ecdsa",
"elliptic-curve",
"primeorder",
- "sha2",
+ "sha2 0.10.9",
]
[[package]]
@@ -3437,7 +3552,7 @@ dependencies = [
"ecdsa",
"elliptic-curve",
"primeorder",
- "sha2",
+ "sha2 0.10.9",
]
[[package]]
@@ -3488,19 +3603,9 @@ checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec"
[[package]]
name = "pastey"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b867cad97c0791bbd3aaa6472142568c6c9e8f71937e98379f584cfb0cf35bec"
-
-[[package]]
-name = "pbkdf2"
-version = "0.12.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
-dependencies = [
- "digest",
- "hmac",
-]
+checksum = "c5a797f0e07bdf071d15742978fc3128ec6c22891c31a3a931513263904c982a"
[[package]]
name = "pear"
@@ -3590,7 +3695,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220"
dependencies = [
"pest",
- "sha2",
+ "sha2 0.10.9",
]
[[package]]
@@ -3619,7 +3724,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
dependencies = [
"phf_shared 0.11.3",
- "rand 0.8.5",
+ "rand 0.8.6",
]
[[package]]
@@ -3693,21 +3798,6 @@ dependencies = [
"spki",
]
-[[package]]
-name = "pkcs5"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6"
-dependencies = [
- "aes",
- "cbc",
- "der",
- "pbkdf2",
- "scrypt",
- "sha2",
- "spki",
-]
-
[[package]]
name = "pkcs8"
version = "0.10.2"
@@ -3715,16 +3805,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
dependencies = [
"der",
- "pkcs5",
- "rand_core 0.6.4",
"spki",
]
[[package]]
name = "pkg-config"
-version = "0.3.32"
+version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
+checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
[[package]]
name = "polling"
@@ -3748,9 +3836,9 @@ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
[[package]]
name = "portable-atomic-util"
-version = "0.2.6"
+version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3"
+checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618"
dependencies = [
"portable-atomic",
]
@@ -3790,6 +3878,17 @@ dependencies = [
"vcpkg",
]
+[[package]]
+name = "prefix-trie"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cf6e3177f0684016a5c209b00882e15f8bdd3f3bb48f0491df10cd102d0c6e7"
+dependencies = [
+ "either",
+ "ipnet",
+ "num-traits",
+]
+
[[package]]
name = "prettyplease"
version = "0.2.37"
@@ -3870,9 +3969,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
[[package]]
name = "quick-xml"
-version = "0.37.5"
+version = "0.38.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
+checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c"
dependencies = [
"memchr",
"serde",
@@ -3880,69 +3979,14 @@ dependencies = [
[[package]]
name = "quick-xml"
-version = "0.38.4"
+version = "0.39.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c"
+checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e"
dependencies = [
"memchr",
"serde",
]
-[[package]]
-name = "quinn"
-version = "0.11.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20"
-dependencies = [
- "bytes",
- "cfg_aliases",
- "pin-project-lite",
- "quinn-proto",
- "quinn-udp",
- "rustc-hash",
- "rustls 0.23.37",
- "socket2 0.6.3",
- "thiserror 2.0.18",
- "tokio",
- "tracing",
- "web-time",
-]
-
-[[package]]
-name = "quinn-proto"
-version = "0.11.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098"
-dependencies = [
- "bytes",
- "getrandom 0.3.4",
- "lru-slab",
- "rand 0.9.3",
- "ring",
- "rustc-hash",
- "rustls 0.23.37",
- "rustls-pki-types",
- "slab",
- "thiserror 2.0.18",
- "tinyvec",
- "tracing",
- "web-time",
-]
-
-[[package]]
-name = "quinn-udp"
-version = "0.5.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd"
-dependencies = [
- "cfg_aliases",
- "libc",
- "once_cell",
- "socket2 0.6.3",
- "tracing",
- "windows-sys 0.60.2",
-]
-
[[package]]
name = "quote"
version = "1.0.45"
@@ -3983,9 +4027,9 @@ dependencies = [
[[package]]
name = "rand"
-version = "0.8.5"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
dependencies = [
"libc",
"rand_chacha 0.3.1",
@@ -3994,9 +4038,9 @@ dependencies = [
[[package]]
name = "rand"
-version = "0.9.3"
+version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ec095654a25171c2124e9e3393a930bddbffdc939556c914957a4c3e0a87166"
+checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.5",
@@ -4010,7 +4054,7 @@ checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
dependencies = [
"chacha20",
"getrandom 0.4.2",
- "rand_core 0.10.0",
+ "rand_core 0.10.1",
]
[[package]]
@@ -4053,9 +4097,9 @@ dependencies = [
[[package]]
name = "rand_core"
-version = "0.10.0"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba"
+checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
[[package]]
name = "raw-cpuid"
@@ -4142,43 +4186,64 @@ dependencies = [
]
[[package]]
-name = "reqsign"
-version = "0.16.5"
+name = "reqsign-aws-v4"
+version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43451dbf3590a7590684c25fb8d12ecdcc90ed3ac123433e500447c7d77ed701"
+checksum = "44eaca382e94505a49f1a4849658d153aebf79d9c1a58e5dd3b10361511e9f43"
dependencies = [
"anyhow",
- "async-trait",
- "base64 0.22.1",
- "chrono",
+ "bytes",
"form_urlencoded",
- "getrandom 0.2.17",
- "hex",
- "hmac",
- "home",
"http 1.4.0",
- "jsonwebtoken 9.3.1",
"log",
- "once_cell",
"percent-encoding",
- "quick-xml 0.37.5",
- "rand 0.8.5",
- "reqwest",
- "rsa",
+ "quick-xml 0.39.4",
+ "reqsign-core",
"rust-ini",
"serde",
"serde_json",
+ "serde_urlencoded",
+ "sha1",
+]
+
+[[package]]
+name = "reqsign-core"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b10302cf0a7d7e7352ba211fc92c3c5bebf1286153e49cc5aa87348078a8e102"
+dependencies = [
+ "anyhow",
+ "base64 0.22.1",
+ "bytes",
+ "form_urlencoded",
+ "futures",
+ "hex",
+ "hmac 0.12.1",
+ "http 1.4.0",
+ "jiff",
+ "log",
+ "percent-encoding",
"sha1",
- "sha2",
+ "sha2 0.10.9",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "reqsign-file-read-tokio"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2d89295b3d17abea31851cc8de55d843d89c52132c864963c38d41920613dc5"
+dependencies = [
+ "anyhow",
+ "reqsign-core",
"tokio",
- "toml 0.8.23",
]
[[package]]
name = "reqwest"
-version = "0.12.28"
+version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147"
+checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0"
dependencies = [
"base64 0.22.1",
"bytes",
@@ -4200,10 +4265,9 @@ dependencies = [
"mime",
"percent-encoding",
"pin-project-lite",
- "quinn",
- "rustls 0.23.37",
- "rustls-native-certs",
+ "rustls 0.23.40",
"rustls-pki-types",
+ "rustls-platform-verifier",
"serde",
"serde_json",
"serde_urlencoded",
@@ -4219,7 +4283,6 @@ dependencies = [
"wasm-bindgen-futures",
"wasm-streams",
"web-sys",
- "webpki-roots",
]
[[package]]
@@ -4234,7 +4297,7 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
dependencies = [
- "hmac",
+ "hmac 0.12.1",
"subtle",
]
@@ -4291,7 +4354,7 @@ dependencies = [
"num_cpus",
"parking_lot",
"pin-project-lite",
- "rand 0.8.5",
+ "rand 0.8.6",
"ref-cast",
"rocket_codegen",
"rocket_http",
@@ -4367,13 +4430,13 @@ dependencies = [
[[package]]
name = "rpassword"
-version = "7.4.0"
+version = "7.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66d4c8b64f049c6721ec8ccec37ddfc3d641c4a7fca57e8f2a89de509c73df39"
+checksum = "5ac5b223d9738ef56e0b98305410be40fa0941bf6036c56f1506751e43552d64"
dependencies = [
"libc",
"rtoolbox",
- "windows-sys 0.59.0",
+ "windows-sys 0.61.2",
]
[[package]]
@@ -4382,15 +4445,14 @@ version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d"
dependencies = [
- "const-oid",
- "digest",
+ "const-oid 0.9.6",
+ "digest 0.10.7",
"num-bigint-dig",
"num-integer",
"num-traits",
"pkcs1",
"pkcs8",
"rand_core 0.6.4",
- "sha2",
"signature",
"spki",
"subtle",
@@ -4409,12 +4471,12 @@ dependencies = [
[[package]]
name = "rtoolbox"
-version = "0.0.3"
+version = "0.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7cc970b249fbe527d6e02e0a227762c9108b2f49d81094fe357ffc6d14d7f6f"
+checksum = "50a0e551c1e27e1731aba276dbeaeac73f53c7cd34d1bda485d02bd1e0f36844"
dependencies = [
"libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -4427,12 +4489,6 @@ dependencies = [
"ordered-multimap",
]
-[[package]]
-name = "rustc-hash"
-version = "2.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
-
[[package]]
name = "rustc_version"
version = "0.4.1"
@@ -4478,15 +4534,15 @@ dependencies = [
[[package]]
name = "rustls"
-version = "0.23.37"
+version = "0.23.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4"
+checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b"
dependencies = [
"log",
"once_cell",
"ring",
"rustls-pki-types",
- "rustls-webpki 0.103.11",
+ "rustls-webpki 0.103.13",
"subtle",
"zeroize",
]
@@ -4514,14 +4570,40 @@ dependencies = [
[[package]]
name = "rustls-pki-types"
-version = "1.14.0"
+version = "1.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd"
+checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9"
dependencies = [
- "web-time",
"zeroize",
]
+[[package]]
+name = "rustls-platform-verifier"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0"
+dependencies = [
+ "core-foundation 0.10.1",
+ "core-foundation-sys",
+ "jni",
+ "log",
+ "once_cell",
+ "rustls 0.23.40",
+ "rustls-native-certs",
+ "rustls-platform-verifier-android",
+ "rustls-webpki 0.103.13",
+ "security-framework",
+ "security-framework-sys",
+ "webpki-root-certs",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "rustls-platform-verifier-android"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
+
[[package]]
name = "rustls-webpki"
version = "0.101.7"
@@ -4534,9 +4616,9 @@ dependencies = [
[[package]]
name = "rustls-webpki"
-version = "0.103.11"
+version = "0.103.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20a6af516fea4b20eccceaf166e8aa666ac996208e8a644ce3ef5aa783bc7cd4"
+checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
dependencies = [
"ring",
"rustls-pki-types",
@@ -4555,15 +4637,6 @@ version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
-[[package]]
-name = "salsa20"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213"
-dependencies = [
- "cipher",
-]
-
[[package]]
name = "same-file"
version = "1.0.6"
@@ -4627,17 +4700,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
-[[package]]
-name = "scrypt"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f"
-dependencies = [
- "pbkdf2",
- "salsa20",
- "sha2",
-]
-
[[package]]
name = "sct"
version = "0.7.1"
@@ -4806,11 +4868,12 @@ dependencies = [
[[package]]
name = "serde_with"
-version = "3.18.0"
+version = "3.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f"
+checksum = "e72c1c2cb7b223fafb600a619537a871c2818583d619401b785e7c0b746ccde2"
dependencies = [
"base64 0.22.1",
+ "bs58",
"chrono",
"hex",
"indexmap 1.9.3",
@@ -4825,9 +4888,9 @@ dependencies = [
[[package]]
name = "serde_with_macros"
-version = "3.18.0"
+version = "3.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65"
+checksum = "b90c488738ecb4fb0262f41f43bc40efc5868d9fb744319ddf5f5317f417bfac"
dependencies = [
"darling 0.23.0",
"proc-macro2",
@@ -4843,7 +4906,7 @@ checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
- "digest",
+ "digest 0.10.7",
]
[[package]]
@@ -4854,7 +4917,18 @@ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
- "digest",
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "sha2"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
+dependencies = [
+ "cfg-if",
+ "cpufeatures 0.3.0",
+ "digest 0.11.3",
]
[[package]]
@@ -4898,7 +4972,7 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
dependencies = [
- "digest",
+ "digest 0.10.7",
"rand_core 0.6.4",
]
@@ -4908,6 +4982,22 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
+[[package]]
+name = "simd_cesu8"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33"
+dependencies = [
+ "rustc_version",
+ "simdutf8",
+]
+
+[[package]]
+name = "simdutf8"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
+
[[package]]
name = "simple_asn1"
version = "0.6.4"
@@ -4922,9 +5012,9 @@ dependencies = [
[[package]]
name = "siphasher"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
+checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
[[package]]
name = "slab"
@@ -4985,9 +5075,9 @@ dependencies = [
[[package]]
name = "sqlite-wasm-rs"
-version = "0.5.2"
+version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f4206ed3a67690b9c29b77d728f6acc3ce78f16bf846d83c94f76400320181b"
+checksum = "1b2c760607300407ddeaee518acf28c795661b7108c75421303dbefb237d3a36"
dependencies = [
"cc",
"js-sys",
@@ -5254,9 +5344,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
-version = "1.51.1"
+version = "1.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c"
+checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe"
dependencies = [
"bytes",
"libc",
@@ -5296,7 +5386,7 @@ version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61"
dependencies = [
- "rustls 0.23.37",
+ "rustls 0.23.40",
"tokio",
]
@@ -5400,7 +5490,7 @@ version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
dependencies = [
- "winnow 1.0.1",
+ "winnow 1.0.3",
]
[[package]]
@@ -5415,10 +5505,10 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8e43134db17199f7f721803383ac5854edd0d3d523cc34dba321d6acfbe76c3"
dependencies = [
- "digest",
- "hmac",
+ "digest 0.10.7",
+ "hmac 0.12.1",
"sha1",
- "sha2",
+ "sha2 0.10.9",
]
[[package]]
@@ -5438,9 +5528,9 @@ dependencies = [
[[package]]
name = "tower-http"
-version = "0.6.8"
+version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
+checksum = "68d6fdd9f81c2819c9a8b0e0cd91660e7746a8e6ea2ba7c6b2b057985f6bcb51"
dependencies = [
"async-compression",
"bitflags",
@@ -5450,13 +5540,13 @@ dependencies = [
"http 1.4.0",
"http-body 1.0.1",
"http-body-util",
- "iri-string",
"pin-project-lite",
"tokio",
"tokio-util",
"tower",
"tower-layer",
"tower-service",
+ "url",
]
[[package]]
@@ -5551,7 +5641,7 @@ dependencies = [
"http 1.4.0",
"httparse",
"log",
- "rand 0.8.5",
+ "rand 0.8.6",
"sha1",
"thiserror 1.0.69",
"url",
@@ -5560,9 +5650,9 @@ dependencies = [
[[package]]
name = "typenum"
-version = "1.19.0"
+version = "1.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
+checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de"
[[package]]
name = "ubyte"
@@ -5646,9 +5736,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "uuid"
-version = "1.23.0"
+version = "1.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9"
+checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76"
dependencies = [
"getrandom 0.4.2",
"js-sys",
@@ -5672,7 +5762,6 @@ checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0"
name = "vaultwarden"
version = "1.0.0"
dependencies = [
- "anyhow",
"argon2",
"aws-config",
"aws-credential-types",
@@ -5702,7 +5791,7 @@ dependencies = [
"html5gum",
"http 1.4.0",
"job_scheduler_ng",
- "jsonwebtoken 10.3.0",
+ "jsonwebtoken",
"lettre",
"libsqlite3-sys",
"log",
@@ -5714,18 +5803,20 @@ dependencies = [
"opendal",
"openidconnect",
"openssl",
- "pastey 0.2.1",
+ "pastey 0.2.2",
"percent-encoding",
"pico-args",
"rand 0.10.1",
"regex",
- "reqsign",
+ "reqsign-aws-v4",
+ "reqsign-core",
"reqwest",
"ring",
"rmpv",
"rocket",
"rocket_ws",
"rpassword",
+ "rustls 0.23.40",
"semver",
"serde",
"serde_json",
@@ -5791,11 +5882,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasip2"
-version = "1.0.2+wasi-0.2.9"
+version = "1.0.3+wasi-0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
+checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
dependencies = [
- "wit-bindgen",
+ "wit-bindgen 0.57.1",
]
[[package]]
@@ -5804,14 +5895,14 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
dependencies = [
- "wit-bindgen",
+ "wit-bindgen 0.51.0",
]
[[package]]
name = "wasm-bindgen"
-version = "0.2.118"
+version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89"
+checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790"
dependencies = [
"cfg-if",
"once_cell",
@@ -5822,9 +5913,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.68"
+version = "0.4.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8"
+checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -5832,9 +5923,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.118"
+version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed"
+checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -5842,9 +5933,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.118"
+version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904"
+checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2"
dependencies = [
"bumpalo",
"proc-macro2",
@@ -5855,9 +5946,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.118"
+version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129"
+checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441"
dependencies = [
"unicode-ident",
]
@@ -5886,9 +5977,9 @@ dependencies = [
[[package]]
name = "wasm-streams"
-version = "0.4.2"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
+checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb"
dependencies = [
"futures-util",
"js-sys",
@@ -5911,9 +6002,9 @@ dependencies = [
[[package]]
name = "web-sys"
-version = "0.3.95"
+version = "0.3.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d"
+checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -5931,9 +6022,9 @@ dependencies = [
[[package]]
name = "webauthn-attestation-ca"
-version = "0.5.4"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fafcf13f7dc1fb292ed4aea22cdd3757c285d7559e9748950ee390249da4da6b"
+checksum = "6475c0bbd1a3f04afaa3e98880408c5be61680c5e6bd3c6f8c250990d5d3e18e"
dependencies = [
"base64urlsafedata",
"openssl",
@@ -5945,9 +6036,9 @@ dependencies = [
[[package]]
name = "webauthn-rs"
-version = "0.5.4"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b24d082d3360258fefb6ffe56123beef7d6868c765c779f97b7a2fcf06727f8"
+checksum = "6c548915e0e92ee946bbf2aecf01ea21bef53d974b0793cc6732ba81a03fc422"
dependencies = [
"base64urlsafedata",
"serde",
@@ -5959,9 +6050,9 @@ dependencies = [
[[package]]
name = "webauthn-rs-core"
-version = "0.5.4"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15784340a24c170ce60567282fb956a0938742dbfbf9eff5df793a686a009b8b"
+checksum = "296d2d501feb715d80b8e186fb88bab1073bca17f460303a1013d17b673bea6a"
dependencies = [
"base64 0.21.7",
"base64urlsafedata",
@@ -5970,7 +6061,7 @@ dependencies = [
"nom 7.1.3",
"openssl",
"openssl-sys",
- "rand 0.9.3",
+ "rand 0.9.4",
"rand_chacha 0.9.0",
"serde",
"serde_cbor_2",
@@ -5986,9 +6077,9 @@ dependencies = [
[[package]]
name = "webauthn-rs-proto"
-version = "0.5.4"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16a1fb2580ce73baa42d3011a24de2ceab0d428de1879ece06e02e8c416e497c"
+checksum = "c37393beac9c1ed1ca6dbb30b1e01783fb316ab3a45d90ecd48c99052dd7ef1e"
dependencies = [
"base64 0.21.7",
"base64urlsafedata",
@@ -5998,10 +6089,10 @@ dependencies = [
]
[[package]]
-name = "webpki-roots"
-version = "1.0.6"
+name = "webpki-root-certs"
+version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed"
+checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c"
dependencies = [
"rustls-pki-types",
]
@@ -6149,15 +6240,6 @@ dependencies = [
"windows-targets 0.52.6",
]
-[[package]]
-name = "windows-sys"
-version = "0.60.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
-dependencies = [
- "windows-targets 0.53.5",
-]
-
[[package]]
name = "windows-sys"
version = "0.61.2"
@@ -6191,30 +6273,13 @@ dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
- "windows_i686_gnullvm 0.52.6",
+ "windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
-[[package]]
-name = "windows-targets"
-version = "0.53.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
-dependencies = [
- "windows-link",
- "windows_aarch64_gnullvm 0.53.1",
- "windows_aarch64_msvc 0.53.1",
- "windows_i686_gnu 0.53.1",
- "windows_i686_gnullvm 0.53.1",
- "windows_i686_msvc 0.53.1",
- "windows_x86_64_gnu 0.53.1",
- "windows_x86_64_gnullvm 0.53.1",
- "windows_x86_64_msvc 0.53.1",
-]
-
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
@@ -6227,12 +6292,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
-
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
@@ -6245,12 +6304,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
-
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
@@ -6263,24 +6316,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
-[[package]]
-name = "windows_i686_gnu"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
-
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
-[[package]]
-name = "windows_i686_gnullvm"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
-
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
@@ -6293,12 +6334,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
-[[package]]
-name = "windows_i686_msvc"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
-
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
@@ -6311,12 +6346,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
-
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
@@ -6329,12 +6358,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
-
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
@@ -6347,12 +6370,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
-
[[package]]
name = "winnow"
version = "0.6.26"
@@ -6373,9 +6390,9 @@ dependencies = [
[[package]]
name = "winnow"
-version = "1.0.1"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5"
+checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1"
[[package]]
name = "wit-bindgen"
@@ -6386,6 +6403,12 @@ dependencies = [
"wit-bindgen-rust-macro",
]
+[[package]]
+name = "wit-bindgen"
+version = "0.57.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
+
[[package]]
name = "wit-bindgen-core"
version = "0.51.0"
@@ -6488,11 +6511,21 @@ dependencies = [
"time",
]
+[[package]]
+name = "xattr"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156"
+dependencies = [
+ "libc",
+ "rustix",
+]
+
[[package]]
name = "xml"
-version = "1.2.1"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8aa498d22c9bbaf482329839bc5620c46be275a19a812e9a22a2b07529a642a"
+checksum = "636f85e5ca6488e96401b61eb7de54f4e44755c988af0f52cf90230c312a1a89"
[[package]]
name = "xmlparser"
@@ -6534,15 +6567,15 @@ dependencies = [
[[package]]
name = "yubico_ng"
-version = "0.14.1"
+version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "929981f5b46b8fb8ee54b144de6b55c3a94fbe26635ee25b0e126e184250867c"
+checksum = "228e2862e3c66f3224102d9a00d9d3646b271a05cc6c4819fea195fa8b5c00e0"
dependencies = [
"base64 0.22.1",
"form_urlencoded",
"futures",
- "hmac",
- "rand 0.9.3",
+ "hmac 0.12.1",
+ "rand 0.9.4",
"reqwest",
"sha1",
"threadpool",
@@ -6570,9 +6603,9 @@ dependencies = [
[[package]]
name = "zerofrom"
-version = "0.1.7"
+version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df"
+checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272"
dependencies = [
"zerofrom-derive",
]
@@ -6594,6 +6627,20 @@ name = "zeroize"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
+dependencies = [
+ "zeroize_derive",
+]
+
+[[package]]
+name = "zeroize_derive"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
[[package]]
name = "zerotrie"
diff --git a/Cargo.toml b/Cargo.toml
index 1ba9ddfd..599af5c8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[workspace.package]
-edition = "2021"
-rust-version = "1.92.0"
+edition = "2024"
+rust-version = "1.93.0"
license = "AGPL-3.0-only"
repository = "https://github.com/dani-garcia/vaultwarden"
publish = false
@@ -24,20 +24,31 @@ publish.workspace = true
[features]
default = [
# "sqlite",
+ # "sqlite_system",
# "mysql",
# "postgresql",
]
# Empty to keep compatibility, prefer to set USE_SYSLOG=true
enable_syslog = []
+# Please enable at least one of these DB backends.
mysql = ["diesel/mysql", "diesel_migrations/mysql"]
postgresql = ["diesel/postgres", "diesel_migrations/postgres"]
-sqlite = ["diesel/sqlite", "diesel_migrations/sqlite", "dep:libsqlite3-sys"]
+sqlite_system = ["diesel/sqlite", "diesel_migrations/sqlite"] # Dynamically link SQLite
+sqlite = ["sqlite_system", "libsqlite3-sys/bundled"] # Statically link SQLite into the binary instead of dynamically.
# Enable to use a vendored and statically linked openssl
vendored_openssl = ["openssl/vendored"]
# Enable MiMalloc memory allocator to replace the default malloc
# This can improve performance for Alpine builds
enable_mimalloc = ["dep:mimalloc"]
-s3 = ["opendal/services-s3", "dep:aws-config", "dep:aws-credential-types", "dep:aws-smithy-runtime-api", "dep:anyhow", "dep:http", "dep:reqsign"]
+s3 = [
+ "opendal/services-s3",
+ "dep:aws-config",
+ "dep:aws-credential-types",
+ "dep:aws-smithy-runtime-api",
+ "dep:http",
+ "dep:reqsign-aws-v4",
+ "dep:reqsign-core",
+]
# OIDC specific features
oidc-accept-rfc3339-timestamps = ["openidconnect/accept-rfc3339-timestamps"]
@@ -57,7 +68,8 @@ macros = { path = "./macros" }
# Logging
log = "0.4.29"
fern = { version = "0.7.1", features = ["syslog-7", "reopen-1"] }
-tracing = { version = "0.1.44", features = ["log"] } # Needed to have lettre and webauthn-rs trace logging to work
+# We need the `log` feature for `tracing` to enable logging for several crates to work, like lettre or webauthn-rs
+tracing = { version = "0.1.44", features = ["log"] }
# A `dotenv` implementation for Rust
dotenvy = { version = "0.15.7", default-features = false }
@@ -68,8 +80,8 @@ num-derive = "0.4.2"
bigdecimal = "0.4.10"
# Web framework
-rocket = { version = "0.5.1", features = ["tls", "json"], default-features = false }
-rocket_ws = { version ="0.1.1" }
+rocket = { version = "0.5.1", default-features = false, features = ["json", "tls"] }
+rocket_ws = { version = "0.1.1" }
# WebSockets libraries
rmpv = "1.3.1" # MessagePack library
@@ -79,34 +91,48 @@ dashmap = "6.1.0"
# Async futures
futures = "0.3.32"
-tokio = { version = "1.51.1", features = ["rt-multi-thread", "fs", "io-util", "parking_lot", "time", "signal", "net"] }
-tokio-util = { version = "0.7.18", features = ["compat"]}
+tokio = { version = "1.52.3", features = [
+ "fs",
+ "io-util",
+ "net",
+ "parking_lot",
+ "rt-multi-thread",
+ "signal",
+ "time",
+] }
+tokio-util = { version = "0.7.18", features = ["compat"] }
# A generic serialization/deserialization framework
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
# A safe, extensible ORM and Query builder
-# Currently pinned diesel to v2.3.3 as newer version break MySQL/MariaDB compatibility
-diesel = { version = "2.3.7", features = ["chrono", "r2d2", "numeric"] }
-diesel_migrations = "2.3.1"
-
-derive_more = { version = "2.1.1", features = ["from", "into", "as_ref", "deref", "display"] }
+diesel = { version = "2.3.9", features = ["chrono", "r2d2", "numeric"] }
+diesel_migrations = "2.3.2"
+
+derive_more = { version = "2.1.1", features = [
+ "as_ref",
+ "deref",
+ "display",
+ "from",
+ "into",
+] }
diesel-derive-newtype = "2.1.2"
-# Bundled/Static SQLite
-libsqlite3-sys = { version = "0.36.0", features = ["bundled"], optional = true }
+# SQLite, statically bundled unless the `sqlite_system` feature is enabled
+libsqlite3-sys = { version = "0.37.0", optional = true }
# Crypto-related libraries
rand = "0.10.1"
ring = "0.17.14"
+rustls = { version = "0.23.40", features = ["ring", "std"], default-features = false }
subtle = "2.6.1"
# UUID generation
-uuid = { version = "1.23.0", features = ["v4"] }
+uuid = { version = "1.23.1", features = ["v4"] }
# Date and time libraries
-chrono = { version = "0.4.44", features = ["clock", "serde"], default-features = false }
+chrono = { version = "0.4.44", default-features = false, features = ["clock", "serde"] }
chrono-tz = "0.10.4"
time = "0.3.47"
@@ -114,29 +140,42 @@ time = "0.3.47"
job_scheduler_ng = "2.4.0"
# Data encoding library Hex/Base32/Base64
-data-encoding = "2.10.0"
+data-encoding = "2.11.0"
# JWT library
-jsonwebtoken = { version = "10.3.0", features = ["use_pem", "rust_crypto"], default-features = false }
+jsonwebtoken = { version = "10.4.0", default-features = false, features = ["rust_crypto", "use_pem"] }
# TOTP library
totp-lite = "2.0.1"
# Yubico Library
-yubico = { package = "yubico_ng", version = "0.14.1", features = ["online-tokio"], default-features = false }
+yubico = { package = "yubico_ng", version = "0.15.0", default-features = false, features = ["online-tokio"] }
# WebAuthn libraries
# danger-allow-state-serialisation is needed to save the state in the db
# danger-credential-internals is needed to support U2F to Webauthn migration
-webauthn-rs = { version = "0.5.4", features = ["danger-allow-state-serialisation", "danger-credential-internals"] }
-webauthn-rs-proto = "0.5.4"
-webauthn-rs-core = "0.5.4"
+webauthn-rs = { version = "0.5.5", features = ["danger-allow-state-serialisation", "danger-credential-internals"] }
+webauthn-rs-proto = "0.5.5"
+webauthn-rs-core = "0.5.5"
# Handling of URL's for WebAuthn and favicons
url = "2.5.8"
# Email libraries
-lettre = { version = "0.11.21", features = ["smtp-transport", "sendmail-transport", "builder", "serde", "hostname", "tracing", "tokio1-rustls", "ring", "rustls-native-certs"], default-features = false }
+lettre = { version = "0.11.22", default-features = false, features = [
+ # Misc
+ "tracing",
+ "serde",
+ "builder",
+ "hostname",
+ # TLS/Security
+ "ring",
+ "rustls-native-certs",
+ "tokio1-rustls",
+ # Transport
+ "smtp-transport",
+ "sendmail-transport",
+] }
percent-encoding = "2.3.2" # URL encoding library used for URL's in the emails
email_address = "0.2.9"
@@ -144,12 +183,33 @@ email_address = "0.2.9"
handlebars = { version = "6.4.0", features = ["dir_source"] }
# HTTP client (Used for favicons, version check, DUO and HIBP API)
-reqwest = { version = "0.12.28", features = ["rustls-tls", "rustls-tls-native-roots", "stream", "json", "deflate", "gzip", "brotli", "zstd", "socks", "cookies", "charset", "http2", "system-proxy"], default-features = false}
-hickory-resolver = "0.25.2"
+reqwest = { version = "0.13.3", default-features = false, features = [
+ # Misc
+ "charset",
+ "cookies",
+ "http2",
+ "json",
+ "form",
+ "rustls-no-provider",
+ "stream",
+ # Compression
+ "brotli",
+ "deflate",
+ "gzip",
+ "zstd",
+ # Proxy
+ "socks",
+ "system-proxy",
+] }
+hickory-resolver = "0.26.1"
# Favicon extraction libraries
html5gum = "0.8.3"
-regex = { version = "1.12.3", features = ["std", "perf", "unicode-perl"], default-features = false }
+regex = { version = "1.12.3", default-features = false, features = [
+ "perf",
+ "std",
+ "unicode-perl",
+] }
data-url = "0.3.2"
bytes = "1.11.1"
svg-hush = "0.9.6"
@@ -162,17 +222,17 @@ cookie = "0.18.1"
cookie_store = "0.22.1"
# Used by U2F, JWT and PostgreSQL
-openssl = "0.10.76"
+openssl = "0.10.79"
# CLI argument parsing
pico-args = "0.5.0"
# Macro ident concatenation
-pastey = "0.2.1"
+pastey = "0.2.2"
governor = "0.10.4"
# OIDC for SSO
-openidconnect = { version = "4.0.1", features = ["reqwest", "rustls-tls"] }
+openidconnect = { version = "4.0.1", default-features = false }
moka = { version = "0.12.15", features = ["future"] }
# Check client versions for specific features.
@@ -180,7 +240,7 @@ semver = "1.0.28"
# Allow overriding the default memory allocator
# Mainly used for the musl builds, since the default musl malloc is very slow
-mimalloc = { version = "0.1.48", features = ["secure"], default-features = false, optional = true }
+mimalloc = { version = "0.1.50", optional = true, default-features = false, features = ["secure"] }
which = "8.0.2"
@@ -188,21 +248,26 @@ which = "8.0.2"
argon2 = "0.5.3"
# Reading a password from the cli for generating the Argon2id ADMIN_TOKEN
-rpassword = "7.4.0"
+rpassword = "7.5.2"
# Loading a dynamic CSS Stylesheet
grass_compiler = { version = "0.13.4", default-features = false }
# File are accessed through Apache OpenDAL
-opendal = { version = "0.55.0", features = ["services-fs"], default-features = false }
+opendal = { version = "0.56.0", default-features = false, features = ["services-fs"] }
# For retrieving AWS credentials, including temporary SSO credentials
-anyhow = { version = "1.0.102", optional = true }
-aws-config = { version = "1.8.15", features = ["behavior-version-latest", "rt-tokio", "credentials-process", "sso"], default-features = false, optional = true }
+aws-config = { version = "1.8.16", optional = true, default-features = false, features = [
+ "behavior-version-latest",
+ "credentials-process",
+ "rt-tokio",
+ "sso",
+] }
aws-credential-types = { version = "1.2.14", optional = true }
-aws-smithy-runtime-api = { version = "1.11.6", optional = true }
+aws-smithy-runtime-api = { version = "1.12.0", optional = true }
http = { version = "1.4.0", optional = true }
-reqsign = { version = "0.16.5", optional = true }
+reqsign-aws-v4 = { version = "3.0.0", optional = true }
+reqsign-core = { version = "3.0.0", optional = true }
# Strip debuginfo from the release builds
# The debug symbols are to provide better panic traces
@@ -262,75 +327,74 @@ unsafe_code = "forbid"
non_ascii_idents = "forbid"
# Deny
-deprecated_in_future = "deny"
+warnings = "deny" # Explicitly deny all warnings since we deny all warnings in the end
+
+# Deny lint groups
deprecated_safe = { level = "deny", priority = -1 }
future_incompatible = { level = "deny", priority = -1 }
keyword_idents = { level = "deny", priority = -1 }
let_underscore = { level = "deny", priority = -1 }
nonstandard_style = { level = "deny", priority = -1 }
-noop_method_call = "deny"
refining_impl_trait = { level = "deny", priority = -1 }
rust_2018_idioms = { level = "deny", priority = -1 }
rust_2021_compatibility = { level = "deny", priority = -1 }
rust_2024_compatibility = { level = "deny", priority = -1 }
+unused = { level = "deny", priority = -1 }
+
+# Deny individual lints
+closure_returning_async_block = "deny"
+deprecated_in_future = "deny"
single_use_lifetimes = "deny"
trivial_casts = "deny"
trivial_numeric_casts = "deny"
-unused = { level = "deny", priority = -1 }
unused_import_braces = "deny"
unused_lifetimes = "deny"
unused_qualifications = "deny"
variant_size_differences = "deny"
-# Allow the following lints since these cause issues with Rust v1.84.0 or newer
-# Building Vaultwarden with Rust v1.85.0 with edition 2024 also works without issues
-edition_2024_expr_fragment_specifier = "allow" # Once changed to Rust 2024 this should be removed and macro's should be validated again
-if_let_rescope = "allow"
-tail_expr_drop_order = "allow"
# https://rust-lang.github.io/rust-clippy/stable/index.html
[workspace.lints.clippy]
-# Warn
+# Warn only so you can still use these during development, but not in the final code
dbg_macro = "warn"
todo = "warn"
# Ignore/Allow
result_large_err = "allow"
-# Deny
+# Warn on these lint group (Some might be warn by default already though)
+# Will be denied during CI!
+complexity = { level = "warn", priority = -1 }
+pedantic = { level = "warn", priority = -1 }
+perf = { level = "warn", priority = -1 }
+style = { level = "warn", priority = -1 }
+suspicious = { level = "warn", priority = -1 }
+
+# Deny individual lints
branches_sharing_code = "deny"
-case_sensitive_file_extension_comparisons = "deny"
-cast_lossless = "deny"
clone_on_ref_ptr = "deny"
equatable_if_let = "deny"
-excessive_precision = "deny"
-filter_map_next = "deny"
float_cmp_const = "deny"
-implicit_clone = "deny"
-inefficient_to_string = "deny"
iter_on_empty_collections = "deny"
iter_on_single_items = "deny"
-linkedlist = "deny"
-macro_use_imports = "deny"
-manual_assert = "deny"
-manual_instant_elapsed = "deny"
-manual_string_new = "deny"
-match_wildcard_for_single_variants = "deny"
mem_forget = "deny"
-needless_borrow = "deny"
needless_collect = "deny"
-needless_continue = "deny"
-needless_lifetimes = "deny"
-option_option = "deny"
redundant_clone = "deny"
-string_add_assign = "deny"
-unnecessary_join = "deny"
unnecessary_self_imports = "deny"
-unnested_or_patterns = "deny"
-unused_async = "deny"
-unused_self = "deny"
useless_let_if_seq = "deny"
verbose_file_reads = "deny"
-zero_sized_map_values = "deny"
+str_to_string = "deny"
+
+# Pedantic Opt-Outs
+inline_always = "allow" # We use this sparsely
+struct_field_names = "allow" # Noisy and some items are Bitwarden controlled
+large_futures = "allow" # Causes a fail in some Rocket macro's, since we experience no issues, allow it
+too_many_lines = "allow" # For now, allow this, good to enable in the future and see if we can refactor
+unnecessary_wraps = "allow" # Too much false positives because of Rocket integrations
+# We do not use these doc items
+doc_link_with_quotes = "allow"
+doc_markdown = "allow"
+missing_errors_doc = "allow"
+missing_panics_doc = "allow"
[lints]
workspace = true
diff --git a/README.md b/README.md
index c84a9c40..0b24ba69 100644
--- a/README.md
+++ b/README.md
@@ -59,8 +59,9 @@ A nearly complete implementation of the Bitwarden Client API is provided, includ
## Usage
> [!IMPORTANT]
-> The web-vault requires the use a secure context for the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API).
-> That means it will only work via `http://localhost:8000` (using the port from the example below) or if you [enable HTTPS](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-HTTPS).
+> The web-vault requires the use of HTTPS and a secure context for the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API).
+> That means it will only work if you [enable HTTPS](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-HTTPS).
+> We also suggest to use a [reverse proxy](https://github.com/dani-garcia/vaultwarden/wiki/Proxy-examples).
The recommended way to install and use Vaultwarden is via our container images which are published to [ghcr.io](https://github.com/dani-garcia/vaultwarden/pkgs/container/vaultwarden), [docker.io](https://hub.docker.com/r/vaultwarden/server) and [quay.io](https://quay.io/repository/vaultwarden/server).
See [which container image to use](https://github.com/dani-garcia/vaultwarden/wiki/Which-container-image-to-use) for an explanation of the provided tags.
diff --git a/build.rs b/build.rs
index 4a831737..32fcf845 100644
--- a/build.rs
+++ b/build.rs
@@ -1,22 +1,21 @@
-use std::env;
-use std::process::Command;
+use std::{env, io::Error, process::Command};
fn main() {
- // This allow using #[cfg(sqlite)] instead of #[cfg(feature = "sqlite")], which helps when trying to add them through macros
- #[cfg(feature = "sqlite")]
+ // These allow using e.g. #[cfg(mysql)] instead of #[cfg(feature = "mysql")], which helps when trying to add them through macros
+ #[cfg(feature = "sqlite_system")] // The `sqlite` feature implies this one.
println!("cargo:rustc-cfg=sqlite");
#[cfg(feature = "mysql")]
println!("cargo:rustc-cfg=mysql");
#[cfg(feature = "postgresql")]
println!("cargo:rustc-cfg=postgresql");
- #[cfg(feature = "s3")]
- println!("cargo:rustc-cfg=s3");
-
- #[cfg(not(any(feature = "sqlite", feature = "mysql", feature = "postgresql")))]
+ #[cfg(not(any(feature = "sqlite_system", feature = "mysql", feature = "postgresql")))]
compile_error!(
"You need to enable one DB backend. To build with previous defaults do: cargo build --features sqlite"
);
+ #[cfg(feature = "s3")]
+ println!("cargo:rustc-cfg=s3");
+
// Use check-cfg to let cargo know which cfg's we define,
// and avoid warnings when they are used in the code.
println!("cargo::rustc-check-cfg=cfg(sqlite)");
@@ -42,13 +41,12 @@ fn main() {
}
}
-fn run(args: &[&str]) -> Result {
+fn run(args: &[&str]) -> Result {
let out = Command::new(args[0]).args(&args[1..]).output()?;
if !out.status.success() {
- use std::io::Error;
return Err(Error::other("Command not successful"));
}
- Ok(String::from_utf8(out.stdout).unwrap().trim().to_string())
+ Ok(String::from_utf8(out.stdout).unwrap().trim().to_owned())
}
/// This method reads info from Git, namely tags, branch, and revision
@@ -58,7 +56,7 @@ fn run(args: &[&str]) -> Result {
/// - `env!("GIT_BRANCH")`
/// - `env!("GIT_REV")`
/// - `env!("VW_VERSION")`
-fn version_from_git_info() -> Result {
+fn version_from_git_info() -> Result {
// The exact tag for the current commit, can be empty when
// the current commit doesn't have an associated tag
let exact_tag = run(&["git", "describe", "--abbrev=0", "--tags", "--exact-match"]).ok();
diff --git a/diesel.toml b/diesel.toml
index 5a78b550..71215dbf 100644
--- a/diesel.toml
+++ b/diesel.toml
@@ -2,4 +2,4 @@
# see diesel.rs/guides/configuring-diesel-cli
[print_schema]
-file = "src/db/schema.rs"
\ No newline at end of file
+file = "src/db/schema.rs"
diff --git a/docker/DockerSettings.yaml b/docker/DockerSettings.yaml
index c679b0da..9d4a563a 100644
--- a/docker/DockerSettings.yaml
+++ b/docker/DockerSettings.yaml
@@ -1,11 +1,11 @@
---
-vault_version: "v2026.2.0"
-vault_image_digest: "sha256:37c8661fa59dcdfbd3baa8366b6e950ef292b15adfeff1f57812b075c1fd3447"
+vault_version: "v2026.4.1"
+vault_image_digest: "sha256:ca2a4251c4e63c9ad428262b4dd452789a1b9f6fce71da351e93dceed0d2edbe"
# Cross Compile Docker Helper Scripts v1.9.0
# We use the linux/amd64 platform shell scripts since there is no difference between the different platform scripts
# https://github.com/tonistiigi/xx | https://hub.docker.com/r/tonistiigi/xx/tags
xx_image_digest: "sha256:c64defb9ed5a91eacb37f96ccc3d4cd72521c4bd18d5442905b95e2226b0e707"
-rust_version: 1.94.1 # Rust version to be used
+rust_version: 1.95.0 # Rust version to be used
debian_version: trixie # Debian release name to be used
alpine_version: "3.23" # Alpine version to be used
# For which platforms/architectures will we try to build images
diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine
index ddcc9efe..88492d94 100644
--- a/docker/Dockerfile.alpine
+++ b/docker/Dockerfile.alpine
@@ -19,23 +19,23 @@
# - From https://hub.docker.com/r/vaultwarden/web-vault/tags,
# click the tag name to view the digest of the image it currently points to.
# - From the command line:
-# $ docker pull docker.io/vaultwarden/web-vault:v2026.2.0
-# $ docker image inspect --format "{{.RepoDigests}}" docker.io/vaultwarden/web-vault:v2026.2.0
-# [docker.io/vaultwarden/web-vault@sha256:37c8661fa59dcdfbd3baa8366b6e950ef292b15adfeff1f57812b075c1fd3447]
+# $ docker pull docker.io/vaultwarden/web-vault:v2026.4.1
+# $ docker image inspect --format "{{.RepoDigests}}" docker.io/vaultwarden/web-vault:v2026.4.1
+# [docker.io/vaultwarden/web-vault@sha256:ca2a4251c4e63c9ad428262b4dd452789a1b9f6fce71da351e93dceed0d2edbe]
#
# - Conversely, to get the tag name from the digest:
-# $ docker image inspect --format "{{.RepoTags}}" docker.io/vaultwarden/web-vault@sha256:37c8661fa59dcdfbd3baa8366b6e950ef292b15adfeff1f57812b075c1fd3447
-# [docker.io/vaultwarden/web-vault:v2026.2.0]
+# $ docker image inspect --format "{{.RepoTags}}" docker.io/vaultwarden/web-vault@sha256:ca2a4251c4e63c9ad428262b4dd452789a1b9f6fce71da351e93dceed0d2edbe
+# [docker.io/vaultwarden/web-vault:v2026.4.1]
#
-FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:37c8661fa59dcdfbd3baa8366b6e950ef292b15adfeff1f57812b075c1fd3447 AS vault
+FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:ca2a4251c4e63c9ad428262b4dd452789a1b9f6fce71da351e93dceed0d2edbe AS vault
########################## ALPINE BUILD IMAGES ##########################
## NOTE: The Alpine Base Images do not support other platforms then linux/amd64 and linux/arm64
## And for Alpine we define all build images here, they will only be loaded when actually used
-FROM --platform=$BUILDPLATFORM ghcr.io/blackdex/rust-musl:x86_64-musl-stable-1.94.1 AS build_amd64
-FROM --platform=$BUILDPLATFORM ghcr.io/blackdex/rust-musl:aarch64-musl-stable-1.94.1 AS build_arm64
-FROM --platform=$BUILDPLATFORM ghcr.io/blackdex/rust-musl:armv7-musleabihf-stable-1.94.1 AS build_armv7
-FROM --platform=$BUILDPLATFORM ghcr.io/blackdex/rust-musl:arm-musleabi-stable-1.94.1 AS build_armv6
+FROM --platform=$BUILDPLATFORM ghcr.io/blackdex/rust-musl:x86_64-musl-stable-1.95.0 AS build_amd64
+FROM --platform=$BUILDPLATFORM ghcr.io/blackdex/rust-musl:aarch64-musl-stable-1.95.0 AS build_arm64
+FROM --platform=$BUILDPLATFORM ghcr.io/blackdex/rust-musl:armv7-musleabihf-stable-1.95.0 AS build_armv7
+FROM --platform=$BUILDPLATFORM ghcr.io/blackdex/rust-musl:arm-musleabi-stable-1.95.0 AS build_armv6
########################## BUILD IMAGE ##########################
# hadolint ignore=DL3006
@@ -57,7 +57,6 @@ ENV DEBIAN_FRONTEND=noninteractive \
# Debian Trixie uses libpq v17
PQ_LIB_DIR="/usr/local/musl/pq17/lib"
-
# Create CARGO_HOME folder and don't download rust docs
RUN mkdir -pv "${CARGO_HOME}" && \
rustup set profile minimal
diff --git a/docker/Dockerfile.debian b/docker/Dockerfile.debian
index 18dd3d6c..04f93361 100644
--- a/docker/Dockerfile.debian
+++ b/docker/Dockerfile.debian
@@ -19,15 +19,15 @@
# - From https://hub.docker.com/r/vaultwarden/web-vault/tags,
# click the tag name to view the digest of the image it currently points to.
# - From the command line:
-# $ docker pull docker.io/vaultwarden/web-vault:v2026.2.0
-# $ docker image inspect --format "{{.RepoDigests}}" docker.io/vaultwarden/web-vault:v2026.2.0
-# [docker.io/vaultwarden/web-vault@sha256:37c8661fa59dcdfbd3baa8366b6e950ef292b15adfeff1f57812b075c1fd3447]
+# $ docker pull docker.io/vaultwarden/web-vault:v2026.4.1
+# $ docker image inspect --format "{{.RepoDigests}}" docker.io/vaultwarden/web-vault:v2026.4.1
+# [docker.io/vaultwarden/web-vault@sha256:ca2a4251c4e63c9ad428262b4dd452789a1b9f6fce71da351e93dceed0d2edbe]
#
# - Conversely, to get the tag name from the digest:
-# $ docker image inspect --format "{{.RepoTags}}" docker.io/vaultwarden/web-vault@sha256:37c8661fa59dcdfbd3baa8366b6e950ef292b15adfeff1f57812b075c1fd3447
-# [docker.io/vaultwarden/web-vault:v2026.2.0]
+# $ docker image inspect --format "{{.RepoTags}}" docker.io/vaultwarden/web-vault@sha256:ca2a4251c4e63c9ad428262b4dd452789a1b9f6fce71da351e93dceed0d2edbe
+# [docker.io/vaultwarden/web-vault:v2026.4.1]
#
-FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:37c8661fa59dcdfbd3baa8366b6e950ef292b15adfeff1f57812b075c1fd3447 AS vault
+FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:ca2a4251c4e63c9ad428262b4dd452789a1b9f6fce71da351e93dceed0d2edbe AS vault
########################## Cross Compile Docker Helper Scripts ##########################
## We use the linux/amd64 no matter which Build Platform, since these are all bash scripts
@@ -36,7 +36,7 @@ FROM --platform=linux/amd64 docker.io/tonistiigi/xx@sha256:c64defb9ed5a91eacb37f
########################## BUILD IMAGE ##########################
# hadolint ignore=DL3006
-FROM --platform=$BUILDPLATFORM docker.io/library/rust:1.94.1-slim-trixie AS build
+FROM --platform=$BUILDPLATFORM docker.io/library/rust:1.95.0-slim-trixie AS build
COPY --from=xx / /
ARG TARGETARCH
ARG TARGETVARIANT
@@ -51,7 +51,7 @@ ENV DEBIAN_FRONTEND=noninteractive \
TERM=xterm-256color \
CARGO_HOME="/root/.cargo" \
USER="root"
-# Install clang to get `xx-cargo` working
+# Install clang && xx-c-essentials to get `xx-cargo` working
# Install pkg-config to allow amd64 builds to find all libraries
# Install git so build.rs can determine the correct version
# Install the libc cross packages based upon the debian-arch
@@ -59,19 +59,16 @@ RUN apt-get update && \
apt-get install -y \
--no-install-recommends \
clang \
- pkg-config \
- git \
- "libc6-$(xx-info debian-arch)-cross" \
- "libc6-dev-$(xx-info debian-arch)-cross" \
- "linux-libc-dev-$(xx-info debian-arch)-cross" && \
+ git && \
xx-apt-get install -y \
--no-install-recommends \
- gcc \
libpq-dev \
libpq5 \
libssl-dev \
libmariadb-dev \
- zlib1g-dev && \
+ pkg-config \
+ zlib1g-dev \
+ xx-c-essentials && \
# Run xx-cargo early, since it sometimes seems to break when run at a later stage
echo "export CARGO_TARGET=$(xx-cargo --print-target-triple)" >> /env-cargo
@@ -83,29 +80,6 @@ RUN mkdir -pv "${CARGO_HOME}" && \
RUN USER=root cargo new --bin /app
WORKDIR /app
-# Environment variables for Cargo on Debian based builds
-ARG TARGET_PKG_CONFIG_PATH
-
-RUN source /env-cargo && \
- if xx-info is-cross ; then \
- # We can't use xx-cargo since that uses clang, which doesn't work for our libraries.
- # Because of this we generate the needed environment variables here which we can load in the needed steps.
- echo "export CC_$(echo "${CARGO_TARGET}" | tr '[:upper:]' '[:lower:]' | tr - _)=/usr/bin/$(xx-info)-gcc" >> /env-cargo && \
- echo "export CARGO_TARGET_$(echo "${CARGO_TARGET}" | tr '[:lower:]' '[:upper:]' | tr - _)_LINKER=/usr/bin/$(xx-info)-gcc" >> /env-cargo && \
- echo "export CROSS_COMPILE=1" >> /env-cargo && \
- echo "export PKG_CONFIG_ALLOW_CROSS=1" >> /env-cargo && \
- # For some architectures `xx-info` returns a triple which doesn't matches the path on disk
- # In those cases you can override this by setting the `TARGET_PKG_CONFIG_PATH` build-arg
- if [[ -n "${TARGET_PKG_CONFIG_PATH}" ]]; then \
- echo "export TARGET_PKG_CONFIG_PATH=${TARGET_PKG_CONFIG_PATH}" >> /env-cargo ; \
- else \
- echo "export PKG_CONFIG_PATH=/usr/lib/$(xx-info)/pkgconfig" >> /env-cargo ; \
- fi && \
- echo "# End of env-cargo" >> /env-cargo ; \
- fi && \
- # Output the current contents of the file
- cat /env-cargo
-
RUN source /env-cargo && \
rustup target add "${CARGO_TARGET}"
@@ -122,7 +96,9 @@ ARG DB=sqlite,mysql,postgresql
# dummy project, except the target folder
# This folder contains the compiled dependencies
RUN source /env-cargo && \
- cargo build --features ${DB} --profile "${CARGO_PROFILE}" --target="${CARGO_TARGET}" && \
+ # Workaround for xx related build issues
+ # https://github.com/tonistiigi/xx/pull/108#issuecomment-3700635977
+ PKG_CONFIG="$(command -v "$(xx-info)-pkg-config")" xx-cargo build --features ${DB} --profile "${CARGO_PROFILE}" && \
find . -not -path "./target*" -delete
# Copies the complete project
@@ -137,7 +113,9 @@ RUN source /env-cargo && \
# Also do this for build.rs to ensure the version is rechecked
touch build.rs src/main.rs && \
# Create a symlink to the binary target folder to easy copy the binary in the final stage
- cargo build --features ${DB} --profile "${CARGO_PROFILE}" --target="${CARGO_TARGET}" && \
+ # Workaround for xx related build issues
+ # https://github.com/tonistiigi/xx/pull/108#issuecomment-3700635977
+ PKG_CONFIG="$(command -v "$(xx-info)-pkg-config")" xx-cargo build --features ${DB} --profile "${CARGO_PROFILE}" && \
if [[ "${CARGO_PROFILE}" == "dev" ]] ; then \
ln -vfsr "/app/target/${CARGO_TARGET}/debug" /app/target/final ; \
else \
diff --git a/docker/Dockerfile.j2 b/docker/Dockerfile.j2
index f745780e..f7a056ff 100644
--- a/docker/Dockerfile.j2
+++ b/docker/Dockerfile.j2
@@ -27,6 +27,11 @@
# $ docker image inspect --format "{{ '{{' }}.RepoTags}}" docker.io/vaultwarden/web-vault@{{ vault_image_digest }}
# [docker.io/vaultwarden/web-vault:{{ vault_version | replace('+', '_') }}]
#
+{% macro xx_cargo_config() -%}
+# Workaround for xx related build issues
+ # https://github.com/tonistiigi/xx/pull/108#issuecomment-3700635977
+ PKG_CONFIG="$(command -v "$(xx-info)-pkg-config")" xx-cargo build --features ${DB} --profile "${CARGO_PROFILE}"
+{%- endmacro %}
FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@{{ vault_image_digest }} AS vault
{% if base == "debian" %}
@@ -66,10 +71,10 @@ ENV DEBIAN_FRONTEND=noninteractive \
# Use PostgreSQL v17 during Alpine/MUSL builds instead of the default v16
# Debian Trixie uses libpq v17
PQ_LIB_DIR="/usr/local/musl/pq17/lib"
-{% endif %}
+{%- endif %}
{% if base == "debian" %}
-# Install clang to get `xx-cargo` working
+# Install clang && xx-c-essentials to get `xx-cargo` working
# Install pkg-config to allow amd64 builds to find all libraries
# Install git so build.rs can determine the correct version
# Install the libc cross packages based upon the debian-arch
@@ -77,19 +82,16 @@ RUN apt-get update && \
apt-get install -y \
--no-install-recommends \
clang \
- pkg-config \
- git \
- "libc6-$(xx-info debian-arch)-cross" \
- "libc6-dev-$(xx-info debian-arch)-cross" \
- "linux-libc-dev-$(xx-info debian-arch)-cross" && \
+ git && \
xx-apt-get install -y \
--no-install-recommends \
- gcc \
libpq-dev \
libpq5 \
libssl-dev \
libmariadb-dev \
- zlib1g-dev && \
+ pkg-config \
+ zlib1g-dev \
+ xx-c-essentials && \
# Run xx-cargo early, since it sometimes seems to break when run at a later stage
echo "export CARGO_TARGET=$(xx-cargo --print-target-triple)" >> /env-cargo
{% endif %}
@@ -102,31 +104,7 @@ RUN mkdir -pv "${CARGO_HOME}" && \
RUN USER=root cargo new --bin /app
WORKDIR /app
-{% if base == "debian" %}
-# Environment variables for Cargo on Debian based builds
-ARG TARGET_PKG_CONFIG_PATH
-
-RUN source /env-cargo && \
- if xx-info is-cross ; then \
- # We can't use xx-cargo since that uses clang, which doesn't work for our libraries.
- # Because of this we generate the needed environment variables here which we can load in the needed steps.
- echo "export CC_$(echo "${CARGO_TARGET}" | tr '[:upper:]' '[:lower:]' | tr - _)=/usr/bin/$(xx-info)-gcc" >> /env-cargo && \
- echo "export CARGO_TARGET_$(echo "${CARGO_TARGET}" | tr '[:lower:]' '[:upper:]' | tr - _)_LINKER=/usr/bin/$(xx-info)-gcc" >> /env-cargo && \
- echo "export CROSS_COMPILE=1" >> /env-cargo && \
- echo "export PKG_CONFIG_ALLOW_CROSS=1" >> /env-cargo && \
- # For some architectures `xx-info` returns a triple which doesn't matches the path on disk
- # In those cases you can override this by setting the `TARGET_PKG_CONFIG_PATH` build-arg
- if [[ -n "${TARGET_PKG_CONFIG_PATH}" ]]; then \
- echo "export TARGET_PKG_CONFIG_PATH=${TARGET_PKG_CONFIG_PATH}" >> /env-cargo ; \
- else \
- echo "export PKG_CONFIG_PATH=/usr/lib/$(xx-info)/pkgconfig" >> /env-cargo ; \
- fi && \
- echo "# End of env-cargo" >> /env-cargo ; \
- fi && \
- # Output the current contents of the file
- cat /env-cargo
-
-{% elif base == "alpine" %}
+{% if base == "alpine" %}
# Environment variables for Cargo on Alpine based builds
RUN echo "export CARGO_TARGET=${RUST_MUSL_CROSS_TARGET}" >> /env-cargo && \
# Output the current contents of the file
@@ -154,7 +132,11 @@ ARG DB=sqlite,mysql,postgresql,enable_mimalloc
# dummy project, except the target folder
# This folder contains the compiled dependencies
RUN source /env-cargo && \
+{% if base == "debian" %}
+ {{ xx_cargo_config() }} && \
+{% elif base == "alpine" %}
cargo build --features ${DB} --profile "${CARGO_PROFILE}" --target="${CARGO_TARGET}" && \
+{% endif %}
find . -not -path "./target*" -delete
# Copies the complete project
@@ -169,7 +151,11 @@ RUN source /env-cargo && \
# Also do this for build.rs to ensure the version is rechecked
touch build.rs src/main.rs && \
# Create a symlink to the binary target folder to easy copy the binary in the final stage
+{% if base == "debian" %}
+ {{ xx_cargo_config() }} && \
+{% elif base == "alpine" %}
cargo build --features ${DB} --profile "${CARGO_PROFILE}" --target="${CARGO_TARGET}" && \
+{% endif %}
if [[ "${CARGO_PROFILE}" == "dev" ]] ; then \
ln -vfsr "/app/target/${CARGO_TARGET}/debug" /app/target/final ; \
else \
diff --git a/macros/src/lib.rs b/macros/src/lib.rs
index 2d923ce1..73b23a22 100644
--- a/macros/src/lib.rs
+++ b/macros/src/lib.rs
@@ -1,14 +1,15 @@
use proc_macro::TokenStream;
use quote::quote;
+use syn::{DeriveInput, parse_macro_input};
#[proc_macro_derive(UuidFromParam)]
pub fn derive_uuid_from_param(input: TokenStream) -> TokenStream {
- let ast = syn::parse(input).unwrap();
+ let ast = parse_macro_input!(input as DeriveInput);
impl_derive_uuid_macro(&ast)
}
-fn impl_derive_uuid_macro(ast: &syn::DeriveInput) -> TokenStream {
+fn impl_derive_uuid_macro(ast: &DeriveInput) -> TokenStream {
let name = &ast.ident;
let gen_derive = quote! {
#[automatically_derived]
@@ -30,12 +31,12 @@ fn impl_derive_uuid_macro(ast: &syn::DeriveInput) -> TokenStream {
#[proc_macro_derive(IdFromParam)]
pub fn derive_id_from_param(input: TokenStream) -> TokenStream {
- let ast = syn::parse(input).unwrap();
+ let ast = parse_macro_input!(input as DeriveInput);
impl_derive_safestring_macro(&ast)
}
-fn impl_derive_safestring_macro(ast: &syn::DeriveInput) -> TokenStream {
+fn impl_derive_safestring_macro(ast: &DeriveInput) -> TokenStream {
let name = &ast.ident;
let gen_derive = quote! {
#[automatically_derived]
diff --git a/migrations/mysql/2026-03-09-005927_add_archives/down.sql b/migrations/mysql/2026-03-09-005927_add_archives/down.sql
new file mode 100644
index 00000000..a3ef20c3
--- /dev/null
+++ b/migrations/mysql/2026-03-09-005927_add_archives/down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS archives;
diff --git a/migrations/mysql/2026-03-09-005927_add_archives/up.sql b/migrations/mysql/2026-03-09-005927_add_archives/up.sql
new file mode 100644
index 00000000..6d7a7024
--- /dev/null
+++ b/migrations/mysql/2026-03-09-005927_add_archives/up.sql
@@ -0,0 +1,10 @@
+DROP TABLE IF EXISTS archives;
+
+CREATE TABLE archives (
+ user_uuid CHAR(36) NOT NULL,
+ cipher_uuid CHAR(36) NOT NULL,
+ archived_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (user_uuid, cipher_uuid),
+ FOREIGN KEY (user_uuid) REFERENCES users (uuid) ON DELETE CASCADE,
+ FOREIGN KEY (cipher_uuid) REFERENCES ciphers (uuid) ON DELETE CASCADE
+);
diff --git a/migrations/mysql/2026-04-25-120000_sso_auth_binding/down.sql b/migrations/mysql/2026-04-25-120000_sso_auth_binding/down.sql
new file mode 100644
index 00000000..17e3d8c7
--- /dev/null
+++ b/migrations/mysql/2026-04-25-120000_sso_auth_binding/down.sql
@@ -0,0 +1 @@
+ALTER TABLE sso_auth DROP COLUMN binding_hash;
diff --git a/migrations/mysql/2026-04-25-120000_sso_auth_binding/up.sql b/migrations/mysql/2026-04-25-120000_sso_auth_binding/up.sql
new file mode 100644
index 00000000..53ee8063
--- /dev/null
+++ b/migrations/mysql/2026-04-25-120000_sso_auth_binding/up.sql
@@ -0,0 +1 @@
+ALTER TABLE sso_auth ADD COLUMN binding_hash TEXT;
diff --git a/migrations/mysql/2026-05-05-120000_sso_auth_error/down.sql b/migrations/mysql/2026-05-05-120000_sso_auth_error/down.sql
new file mode 100644
index 00000000..98a6d836
--- /dev/null
+++ b/migrations/mysql/2026-05-05-120000_sso_auth_error/down.sql
@@ -0,0 +1 @@
+ALTER TABLE sso_auth DROP COLUMN code_response_error;
diff --git a/migrations/mysql/2026-05-05-120000_sso_auth_error/up.sql b/migrations/mysql/2026-05-05-120000_sso_auth_error/up.sql
new file mode 100644
index 00000000..6042a7d4
--- /dev/null
+++ b/migrations/mysql/2026-05-05-120000_sso_auth_error/up.sql
@@ -0,0 +1 @@
+ALTER TABLE sso_auth ADD COLUMN code_response_error TEXT;
diff --git a/migrations/postgresql/2026-03-09-005927_add_archives/down.sql b/migrations/postgresql/2026-03-09-005927_add_archives/down.sql
new file mode 100644
index 00000000..a3ef20c3
--- /dev/null
+++ b/migrations/postgresql/2026-03-09-005927_add_archives/down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS archives;
diff --git a/migrations/postgresql/2026-03-09-005927_add_archives/up.sql b/migrations/postgresql/2026-03-09-005927_add_archives/up.sql
new file mode 100644
index 00000000..c56d01a0
--- /dev/null
+++ b/migrations/postgresql/2026-03-09-005927_add_archives/up.sql
@@ -0,0 +1,8 @@
+DROP TABLE IF EXISTS archives;
+
+CREATE TABLE archives (
+ user_uuid CHAR(36) NOT NULL REFERENCES users (uuid) ON DELETE CASCADE,
+ cipher_uuid CHAR(36) NOT NULL REFERENCES ciphers (uuid) ON DELETE CASCADE,
+ archived_at TIMESTAMP NOT NULL DEFAULT now(),
+ PRIMARY KEY (user_uuid, cipher_uuid)
+);
diff --git a/migrations/postgresql/2026-04-25-120000_sso_auth_binding/down.sql b/migrations/postgresql/2026-04-25-120000_sso_auth_binding/down.sql
new file mode 100644
index 00000000..17e3d8c7
--- /dev/null
+++ b/migrations/postgresql/2026-04-25-120000_sso_auth_binding/down.sql
@@ -0,0 +1 @@
+ALTER TABLE sso_auth DROP COLUMN binding_hash;
diff --git a/migrations/postgresql/2026-04-25-120000_sso_auth_binding/up.sql b/migrations/postgresql/2026-04-25-120000_sso_auth_binding/up.sql
new file mode 100644
index 00000000..53ee8063
--- /dev/null
+++ b/migrations/postgresql/2026-04-25-120000_sso_auth_binding/up.sql
@@ -0,0 +1 @@
+ALTER TABLE sso_auth ADD COLUMN binding_hash TEXT;
diff --git a/migrations/postgresql/2026-05-05-120000_sso_auth_error/down.sql b/migrations/postgresql/2026-05-05-120000_sso_auth_error/down.sql
new file mode 100644
index 00000000..fae11ae3
--- /dev/null
+++ b/migrations/postgresql/2026-05-05-120000_sso_auth_error/down.sql
@@ -0,0 +1 @@
+ALTER TABLE sso_auth DROP COLUMN IF EXISTS code_response_error;
diff --git a/migrations/postgresql/2026-05-05-120000_sso_auth_error/up.sql b/migrations/postgresql/2026-05-05-120000_sso_auth_error/up.sql
new file mode 100644
index 00000000..d4524898
--- /dev/null
+++ b/migrations/postgresql/2026-05-05-120000_sso_auth_error/up.sql
@@ -0,0 +1 @@
+ALTER TABLE sso_auth ADD COLUMN IF NOT EXISTS code_response_error TEXT;
diff --git a/migrations/sqlite/2026-03-09-005927_add_archives/down.sql b/migrations/sqlite/2026-03-09-005927_add_archives/down.sql
new file mode 100644
index 00000000..a3ef20c3
--- /dev/null
+++ b/migrations/sqlite/2026-03-09-005927_add_archives/down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS archives;
diff --git a/migrations/sqlite/2026-03-09-005927_add_archives/up.sql b/migrations/sqlite/2026-03-09-005927_add_archives/up.sql
new file mode 100644
index 00000000..d624f57b
--- /dev/null
+++ b/migrations/sqlite/2026-03-09-005927_add_archives/up.sql
@@ -0,0 +1,8 @@
+DROP TABLE IF EXISTS archives;
+
+CREATE TABLE archives (
+ user_uuid CHAR(36) NOT NULL REFERENCES users (uuid) ON DELETE CASCADE,
+ cipher_uuid CHAR(36) NOT NULL REFERENCES ciphers (uuid) ON DELETE CASCADE,
+ archived_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (user_uuid, cipher_uuid)
+);
diff --git a/migrations/sqlite/2026-04-25-120000_sso_auth_binding/down.sql b/migrations/sqlite/2026-04-25-120000_sso_auth_binding/down.sql
new file mode 100644
index 00000000..17e3d8c7
--- /dev/null
+++ b/migrations/sqlite/2026-04-25-120000_sso_auth_binding/down.sql
@@ -0,0 +1 @@
+ALTER TABLE sso_auth DROP COLUMN binding_hash;
diff --git a/migrations/sqlite/2026-04-25-120000_sso_auth_binding/up.sql b/migrations/sqlite/2026-04-25-120000_sso_auth_binding/up.sql
new file mode 100644
index 00000000..53ee8063
--- /dev/null
+++ b/migrations/sqlite/2026-04-25-120000_sso_auth_binding/up.sql
@@ -0,0 +1 @@
+ALTER TABLE sso_auth ADD COLUMN binding_hash TEXT;
diff --git a/migrations/sqlite/2026-05-05-120000_sso_auth_error/down.sql b/migrations/sqlite/2026-05-05-120000_sso_auth_error/down.sql
new file mode 100644
index 00000000..98a6d836
--- /dev/null
+++ b/migrations/sqlite/2026-05-05-120000_sso_auth_error/down.sql
@@ -0,0 +1 @@
+ALTER TABLE sso_auth DROP COLUMN code_response_error;
diff --git a/migrations/sqlite/2026-05-05-120000_sso_auth_error/up.sql b/migrations/sqlite/2026-05-05-120000_sso_auth_error/up.sql
new file mode 100644
index 00000000..6042a7d4
--- /dev/null
+++ b/migrations/sqlite/2026-05-05-120000_sso_auth_error/up.sql
@@ -0,0 +1 @@
+ALTER TABLE sso_auth ADD COLUMN code_response_error TEXT;
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index 151be09f..775ded5a 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,4 +1,4 @@
[toolchain]
-channel = "1.94.1"
+channel = "1.95.0"
components = [ "rustfmt", "clippy" ]
profile = "minimal"
diff --git a/rustfmt.toml b/rustfmt.toml
index 1d5e440f..a00d27e0 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -1,4 +1,4 @@
-edition = "2021"
+edition = "2024"
max_width = 120
newline_style = "Unix"
use_small_heuristics = "Off"
diff --git a/src/api/admin.rs b/src/api/admin.rs
index 1546676f..cb31a353 100644
--- a/src/api/admin.rs
+++ b/src/api/admin.rs
@@ -2,39 +2,40 @@ use std::{env, sync::LazyLock};
use reqwest::Method;
use rocket::{
+ Catcher, Route,
form::Form,
http::{Cookie, CookieJar, MediaType, SameSite, Status},
request::{FromRequest, Outcome, Request},
- response::{content::RawHtml as Html, Redirect},
+ response::{Redirect, content::RawHtml as Html},
serde::json::Json,
- Catcher, Route,
};
use serde::de::DeserializeOwned;
use serde_json::Value;
use crate::{
+ CONFIG, VERSION,
api::{
+ ApiResult, EmptyResult, JsonResult, Notify,
core::{log_event, two_factor},
- unregister_push_device, ApiResult, EmptyResult, JsonResult, Notify,
+ unregister_push_device,
},
- auth::{decode_admin, encode_jwt, generate_admin_claims, ClientIp, Secure},
+ auth::{ClientIp, Secure, decode_admin, encode_jwt, generate_admin_claims},
config::ConfigBuilder,
db::{
- backup_sqlite, get_sql_server_version,
+ ACTIVE_DB_TYPE, DbConn, DbConnType, backup_sqlite, get_sql_server_version,
models::{
Attachment, Cipher, Collection, Device, Event, EventType, Group, Invitation, Membership, MembershipId,
MembershipType, OrgPolicy, Organization, OrganizationId, SsoUser, TwoFactor, User, UserId,
},
- DbConn, DbConnType, ACTIVE_DB_TYPE,
},
error::{Error, MapResult},
http_client::make_http_request,
mail,
+ sso::FAKE_SSO_IDENTIFIER,
util::{
- container_base_image, format_naive_datetime_local, get_active_web_release, get_display_size,
- is_running_in_container, parse_experimental_client_feature_flags, FeatureFlagFilter, NumberOrString,
+ FeatureFlagFilter, NumberOrString, container_base_image, format_naive_datetime_local, get_active_web_release,
+ get_display_size, is_running_in_container, parse_experimental_client_feature_flags,
},
- CONFIG, VERSION,
};
pub fn routes() -> Vec {
@@ -92,8 +93,7 @@ static DB_TYPE: LazyLock<&str> = LazyLock::new(|| match ACTIVE_DB_TYPE.get() {
});
#[cfg(sqlite)]
-static CAN_BACKUP: LazyLock =
- LazyLock::new(|| ACTIVE_DB_TYPE.get().map(|t| *t == DbConnType::Sqlite).unwrap_or(false));
+static CAN_BACKUP: LazyLock = LazyLock::new(|| ACTIVE_DB_TYPE.get().is_some_and(|t| *t == DbConnType::Sqlite));
#[cfg(not(sqlite))]
static CAN_BACKUP: LazyLock = LazyLock::new(|| false);
@@ -199,13 +199,7 @@ fn post_admin_login(
}
// If the token is invalid, redirect to login page
- if !_validate_token(&data.token) {
- error!("Invalid admin token. IP: {}", ip.ip);
- Err(AdminResponse::Unauthorized(render_admin_login(
- Some("Invalid admin token, please try again."),
- redirect.as_deref(),
- )))
- } else {
+ if validate_token(&data.token) {
// If the token received is valid, generate JWT and save it as a cookie
let claims = generate_admin_claims();
let jwt = encode_jwt(&claims);
@@ -223,10 +217,16 @@ fn post_admin_login(
} else {
Err(AdminResponse::Ok(render_admin_page()))
}
+ } else {
+ error!("Invalid admin token. IP: {}", ip.ip);
+ Err(AdminResponse::Unauthorized(render_admin_login(
+ Some("Invalid admin token, please try again."),
+ redirect.as_deref(),
+ )))
}
}
-fn _validate_token(token: &str) -> bool {
+fn validate_token(token: &str) -> bool {
match CONFIG.admin_token().as_ref() {
None => false,
Some(t) if t.starts_with("$argon2") => {
@@ -306,17 +306,14 @@ async fn get_user_or_404(user_id: &UserId, conn: &DbConn) -> ApiResult {
#[post("/invite", format = "application/json", data = "")]
async fn invite_user(data: Json, _token: AdminToken, conn: DbConn) -> JsonResult {
- let data: InviteData = data.into_inner();
- if User::find_by_mail(&data.email, &conn).await.is_some() {
- err_code!("User already exists", Status::Conflict.code)
- }
-
- let mut user = User::new(&data.email, None);
-
- async fn _generate_invite(user: &User, conn: &DbConn) -> EmptyResult {
+ async fn generate_invite(user: &User, conn: &DbConn) -> EmptyResult {
if CONFIG.mail_enabled() {
- let org_id: OrganizationId = FAKE_ADMIN_UUID.to_string().into();
- let member_id: MembershipId = FAKE_ADMIN_UUID.to_string().into();
+ let org_id: OrganizationId = if CONFIG.sso_enabled() {
+ FAKE_SSO_IDENTIFIER.into()
+ } else {
+ FAKE_ADMIN_UUID.into()
+ };
+ let member_id: MembershipId = FAKE_ADMIN_UUID.to_owned().into();
mail::send_invite(user, org_id, member_id, &CONFIG.invitation_org_name(), None).await
} else {
let invitation = Invitation::new(&user.email);
@@ -324,7 +321,14 @@ async fn invite_user(data: Json, _token: AdminToken, conn: DbConn) -
}
}
- _generate_invite(&user, &conn).await.map_err(|e| e.with_code(Status::InternalServerError.code))?;
+ let data: InviteData = data.into_inner();
+ if User::find_by_mail(&data.email, &conn).await.is_some() {
+ err_code!("User already exists", Status::Conflict.code)
+ }
+
+ let mut user = User::new(&data.email, None);
+
+ generate_invite(&user, &conn).await.map_err(|e| e.with_code(Status::InternalServerError.code))?;
user.save(&conn).await.map_err(|e| e.with_code(Status::InternalServerError.code))?;
Ok(Json(user.to_json(&conn).await))
@@ -381,7 +385,7 @@ async fn users_overview(_token: AdminToken, conn: DbConn) -> ApiResult json!("Never"),
};
- usr["sso_identifier"] = json!(sso_u.map(|u| u.identifier.to_string()).unwrap_or(String::new()));
+ usr["sso_identifier"] = json!(sso_u.map_or(String::new(), |u| u.identifier.to_string()));
users_json.push(usr);
}
@@ -464,10 +468,10 @@ async fn deauth_user(user_id: UserId, _token: AdminToken, conn: DbConn, nt: Noti
if CONFIG.push_enabled() {
for device in Device::find_push_devices_by_user(&user.uuid, &conn).await {
- match unregister_push_device(&device.push_uuid).await {
+ match unregister_push_device(device.push_uuid.as_ref()).await {
Ok(r) => r,
Err(e) => error!("Unable to unregister devices from Bitwarden server: {e}"),
- };
+ }
}
}
@@ -518,8 +522,12 @@ async fn resend_user_invite(user_id: UserId, _token: AdminToken, conn: DbConn) -
}
if CONFIG.mail_enabled() {
- let org_id: OrganizationId = FAKE_ADMIN_UUID.to_string().into();
- let member_id: MembershipId = FAKE_ADMIN_UUID.to_string().into();
+ let org_id: OrganizationId = if CONFIG.sso_enabled() {
+ FAKE_SSO_IDENTIFIER.into()
+ } else {
+ FAKE_ADMIN_UUID.into()
+ };
+ let member_id: MembershipId = FAKE_ADMIN_UUID.to_owned().into();
mail::send_invite(&user, org_id, member_id, &CONFIG.invitation_org_name(), None).await
} else {
Ok(())
@@ -545,9 +553,10 @@ async fn update_membership_type(data: Json, token: AdminToke
err!("The specified user isn't member of the organization")
};
- let new_type = match MembershipType::from_str(&data.user_type.into_string()) {
- Some(new_type) => new_type as i32,
- None => err!("Invalid type"),
+ let new_type = if let Some(new_type) = MembershipType::from_str(&data.user_type.into_string()) {
+ new_type as i32
+ } else {
+ err!("Invalid type")
};
if member_to_edit.atype == MembershipType::Owner && new_type != MembershipType::Owner {
@@ -647,42 +656,40 @@ async fn get_release_info(has_http_access: bool) -> (String, String, String) {
.await
{
Ok(r) => r.tag_name,
- _ => "-".to_string(),
+ _ => "-".to_owned(),
},
match get_json_api::("https://api.github.com/repos/dani-garcia/vaultwarden/commits/main").await {
Ok(mut c) => {
c.sha.truncate(8);
c.sha
}
- _ => "-".to_string(),
+ _ => "-".to_owned(),
},
// Do not fetch the web-vault version when running within a container
// The web-vault version is embedded within the container it self, and should not be updated manually
match get_json_api::("https://api.github.com/repos/dani-garcia/bw_web_builds/releases/latest")
.await
{
- Ok(r) => r.tag_name.trim_start_matches('v').to_string(),
- _ => "-".to_string(),
+ Ok(r) => r.tag_name.trim_start_matches('v').to_owned(),
+ _ => "-".to_owned(),
},
)
} else {
- ("-".to_string(), "-".to_string(), "-".to_string())
+ ("-".to_owned(), "-".to_owned(), "-".to_owned())
}
}
async fn get_ntp_time(has_http_access: bool) -> String {
- if has_http_access {
- if let Ok(cf_trace) = get_text_api("https://cloudflare.com/cdn-cgi/trace").await {
- for line in cf_trace.lines() {
- if let Some((key, value)) = line.split_once('=') {
- if key == "ts" {
- let ts = value.split_once('.').map_or(value, |(s, _)| s);
- if let Ok(dt) = chrono::DateTime::parse_from_str(ts, "%s") {
- return dt.format("%Y-%m-%d %H:%M:%S UTC").to_string();
- }
- break;
- }
+ if has_http_access && let Ok(cf_trace) = get_text_api("https://cloudflare.com/cdn-cgi/trace").await {
+ for line in cf_trace.lines() {
+ if let Some((key, value)) = line.split_once('=')
+ && key == "ts"
+ {
+ let ts = value.split_once('.').map_or(value, |(s, _)| s);
+ if let Ok(dt) = chrono::DateTime::parse_from_str(ts, "%s") {
+ return dt.format("%Y-%m-%d %H:%M:%S UTC").to_string();
}
+ break;
}
}
}
@@ -725,7 +732,7 @@ async fn diagnostics(_token: AdminToken, ip_header: IpHeader, conn: DbConn) -> A
// Check if we are able to resolve DNS entries
let dns_resolved = match ("github.com", 0).to_socket_addrs().map(|mut i| i.next()) {
Ok(Some(a)) => a.ip().to_string(),
- _ => "Unable to resolve domain name.".to_string(),
+ _ => "Unable to resolve domain name.".to_owned(),
};
let (latest_vw_release, latest_vw_commit, latest_web_release) = get_release_info(has_http_access).await;
@@ -736,7 +743,7 @@ async fn diagnostics(_token: AdminToken, ip_header: IpHeader, conn: DbConn) -> A
let invalid_feature_flags: Vec = parse_experimental_client_feature_flags(
&CONFIG.experimental_client_feature_flags(),
- FeatureFlagFilter::InvalidOnly,
+ &FeatureFlagFilter::InvalidOnly,
)
.into_keys()
.collect();
@@ -825,33 +832,30 @@ impl<'r> FromRequest<'r> for AdminToken {
type Error = &'static str;
async fn from_request(request: &'r Request<'_>) -> Outcome {
- let ip = match ClientIp::from_request(request).await {
- Outcome::Success(ip) => ip,
- _ => err_handler!("Error getting Client IP"),
+ let Outcome::Success(ip) = ClientIp::from_request(request).await else {
+ err_handler!("Error getting Client IP")
};
if !CONFIG.disable_admin_token() {
let cookies = request.cookies();
- let access_token = match cookies.get(COOKIE_NAME) {
- Some(cookie) => cookie.value(),
- None => {
- let requested_page =
- request.segments::(0..).unwrap_or_default().display().to_string();
- // When the requested page is empty, it is `/admin`, in that case, Forward, so it will render the login page
- // Else, return a 401 failure, which will be caught
- if requested_page.is_empty() {
- return Outcome::Forward(Status::Unauthorized);
- } else {
- return Outcome::Error((Status::Unauthorized, "Unauthorized"));
- }
+ let access_token = if let Some(cookie) = cookies.get(COOKIE_NAME) {
+ cookie.value()
+ } else {
+ let requested_page =
+ request.segments::(0..).unwrap_or_default().display().to_string();
+ // When the requested page is empty, it is `/admin`, in that case, Forward, so it will render the login page
+ // Else, return a 401 failure, which will be caught
+ if requested_page.is_empty() {
+ return Outcome::Forward(Status::Unauthorized);
}
+ return Outcome::Error((Status::Unauthorized, "Unauthorized"));
};
if decode_admin(access_token).is_err() {
// Remove admin cookie
cookies.remove(Cookie::build(COOKIE_NAME).path(admin_path()));
- error!("Invalid or expired admin JWT. IP: {}.", &ip.ip);
+ error!("Invalid or expired admin JWT. IP: {}.", ip.ip);
return Outcome::Error((Status::Unauthorized, "Session expired"));
}
}
diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs
index 8841c184..954b35bd 100644
--- a/src/api/core/accounts.rs
+++ b/src/api/core/accounts.rs
@@ -1,34 +1,37 @@
use std::collections::HashSet;
-use crate::db::DbPool;
use chrono::Utc;
-use rocket::serde::json::Json;
+use rocket::{
+ http::Status,
+ request::{FromRequest, Outcome, Request},
+ serde::json::Json,
+};
use serde_json::Value;
use crate::{
+ CONFIG,
api::{
+ AnonymousNotify, ApiResult, EmptyResult, JsonResult, Notify, PasswordOrOtpData, UpdateType,
core::{accept_org_invite, log_user_event, two_factor::email},
- master_password_policy, register_push_device, unregister_push_device, AnonymousNotify, ApiResult, EmptyResult,
- JsonResult, Notify, PasswordOrOtpData, UpdateType,
+ master_password_policy, register_push_device, unregister_push_device,
},
- auth::{decode_delete, decode_invite, decode_verify_email, ClientHeaders, Headers},
+ auth::{ClientHeaders, Headers, decode_delete, decode_invite, decode_verify_email},
crypto,
db::{
+ DbConn, DbPool,
models::{
- AuthRequest, AuthRequestId, Cipher, CipherId, Device, DeviceId, DeviceType, EmergencyAccess,
- EmergencyAccessId, EventType, Folder, FolderId, Invitation, Membership, MembershipId, OrgPolicy,
- OrgPolicyType, Organization, OrganizationId, Send, SendId, User, UserId, UserKdfType,
+ AuthRequest, AuthRequestId, Cipher, CipherId, Device, DeviceId, DeviceType, DeviceWithAuthRequest,
+ EmergencyAccess, EmergencyAccessId, EventType, Folder, FolderId, Invitation, Membership, MembershipId,
+ OrgPolicy, OrgPolicyType, Organization, OrganizationId, Send, SendId, User, UserId, UserKdfType,
},
- DbConn,
},
mail,
- util::{deser_opt_nonempty_str, format_date, NumberOrString},
- CONFIG,
+ util::{NumberOrString, deser_opt_nonempty_str, format_date},
};
-use rocket::{
- http::Status,
- request::{FromRequest, Outcome, Request},
+use super::{
+ ciphers::{CipherData, update_cipher_from_data},
+ sends::{SendData, update_send_from_data},
};
pub fn routes() -> Vec {
@@ -54,9 +57,9 @@ pub fn routes() -> Vec {
delete_account,
revision_date,
password_hint,
- prelogin,
+ post_prelogin,
verify_password,
- api_key,
+ post_api_key,
rotate_api_key,
get_known_device,
get_all_devices,
@@ -137,17 +140,17 @@ struct KeysData {
}
/// Trims whitespace from password hints, and converts blank password hints to `None`.
-fn clean_password_hint(password_hint: &Option) -> Option {
+fn clean_password_hint(password_hint: Option<&String>) -> Option {
match password_hint {
None => None,
Some(h) => match h.trim() {
"" => None,
- ht => Some(ht.to_string()),
+ ht => Some(ht.to_owned()),
},
}
}
-fn enforce_password_hint_setting(password_hint: &Option) -> EmptyResult {
+fn enforce_password_hint_setting(password_hint: Option<&String>) -> EmptyResult {
if password_hint.is_some() && !CONFIG.password_hints_allowed() {
err!("Password hints have been disabled by the administrator. Remove the hint and try again.");
}
@@ -166,7 +169,7 @@ async fn is_email_2fa_required(member_id: Option, conn: &DbConn) -
false
}
-pub async fn _register(data: Json, email_verification: bool, conn: DbConn) -> JsonResult {
+pub async fn register(data: Json, email_verification: bool, conn: DbConn) -> JsonResult {
let mut data: RegisterData = data.into_inner();
let email = data.email.to_lowercase();
@@ -237,16 +240,16 @@ pub async fn _register(data: Json, email_verification: bool, conn:
// Check if the length of the username exceeds 50 characters (Same is Upstream Bitwarden)
// This also prevents issues with very long usernames causing to large JWT's. See #2419
- if let Some(ref name) = data.name {
- if name.len() > 50 {
- err!("The field Name must be a string with a maximum length of 50.");
- }
+ if let Some(ref name) = data.name
+ && name.len() > 50
+ {
+ err!("The field Name must be a string with a maximum length of 50.");
}
// Check against the password hint setting here so if it fails, the user
// can retry without losing their invitation below.
- let password_hint = clean_password_hint(&data.master_password_hint);
- enforce_password_hint_setting(&password_hint)?;
+ let password_hint = clean_password_hint(data.master_password_hint.as_ref());
+ enforce_password_hint_setting(password_hint.as_ref())?;
let mut user = match User::find_by_mail(&email, &conn).await {
Some(user) => {
@@ -353,8 +356,8 @@ async fn post_set_password(data: Json, headers: Headers, conn:
// Check against the password hint setting here so if it fails,
// the user can retry without losing their invitation below.
- let password_hint = clean_password_hint(&data.master_password_hint);
- enforce_password_hint_setting(&password_hint)?;
+ let password_hint = clean_password_hint(data.master_password_hint.as_ref());
+ enforce_password_hint_setting(password_hint.as_ref())?;
set_kdf_data(&mut user, &data.kdf)?;
@@ -373,18 +376,19 @@ async fn post_set_password(data: Json, headers: Headers, conn:
user.public_key = Some(keys.public_key);
}
- if let Some(identifier) = data.org_identifier {
- if identifier != crate::sso::FAKE_IDENTIFIER && identifier != crate::api::admin::FAKE_ADMIN_UUID {
- let Some(org) = Organization::find_by_uuid(&identifier.into(), &conn).await else {
- err!("Failed to retrieve the associated organization")
- };
+ if let Some(identifier) = data.org_identifier
+ && identifier != crate::sso::FAKE_SSO_IDENTIFIER
+ && identifier != crate::api::admin::FAKE_ADMIN_UUID
+ {
+ let Some(org) = Organization::find_by_uuid(&identifier.into(), &conn).await else {
+ err!("Failed to retrieve the associated organization")
+ };
- let Some(membership) = Membership::find_by_user_and_org(&user.uuid, &org.uuid, &conn).await else {
- err!("Failed to retrieve the invitation")
- };
+ let Some(membership) = Membership::find_by_user_and_org(&user.uuid, &org.uuid, &conn).await else {
+ err!("Failed to retrieve the invitation")
+ };
- accept_org_invite(&user, membership, None, &conn).await?;
- }
+ accept_org_invite(&user, membership, None, &conn).await?;
}
if CONFIG.mail_enabled() {
@@ -451,10 +455,10 @@ async fn put_avatar(data: Json, headers: Headers, conn: DbConn) -> J
// It looks like it only supports the 6 hex color format.
// If you try to add the short value it will not show that color.
// Check and force 7 chars, including the #.
- if let Some(color) = &data.avatar_color {
- if color.len() != 7 {
- err!("The field AvatarColor must be a HTML/Hex color code with a length of 7 characters")
- }
+ if let Some(color) = &data.avatar_color
+ && color.len() != 7
+ {
+ err!("The field AvatarColor must be a HTML/Hex color code with a length of 7 characters")
}
let mut user = headers.user;
@@ -515,8 +519,8 @@ async fn post_password(data: Json, headers: Headers, conn: DbCon
err!("Invalid password")
}
- user.password_hint = clean_password_hint(&data.master_password_hint);
- enforce_password_hint_setting(&user.password_hint)?;
+ user.password_hint = clean_password_hint(data.master_password_hint.as_ref());
+ enforce_password_hint_setting(user.password_hint.as_ref())?;
log_user_event(EventType::UserChangedPassword as i32, &user.uuid, headers.device.atype, &headers.ip.ip, &conn)
.await;
@@ -668,9 +672,6 @@ struct UpdateResetPasswordData {
reset_password_key: String,
}
-use super::ciphers::CipherData;
-use super::sends::{update_send_from_data, SendData};
-
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct KeyData {
@@ -840,7 +841,7 @@ async fn post_rotatekey(data: Json, headers: Headers, conn: DbConn, nt:
};
saved_folder.name = folder_data.name;
- saved_folder.save(&conn).await?
+ saved_folder.save(&conn).await?;
}
}
@@ -853,7 +854,7 @@ async fn post_rotatekey(data: Json, headers: Headers, conn: DbConn, nt:
};
saved_emergency_access.key_encrypted = Some(emergency_access_data.key_encrypted);
- saved_emergency_access.save(&conn).await?
+ saved_emergency_access.save(&conn).await?;
}
// Update reset password data
@@ -865,7 +866,7 @@ async fn post_rotatekey(data: Json, headers: Headers, conn: DbConn, nt:
};
membership.reset_password_key = Some(reset_password_data.reset_password_key);
- membership.save(&conn).await?
+ membership.save(&conn).await?;
}
// Update send data
@@ -878,8 +879,6 @@ async fn post_rotatekey(data: Json, headers: Headers, conn: DbConn, nt:
}
// Update cipher data
- use super::ciphers::update_cipher_from_data;
-
for cipher_data in data.account_data.ciphers {
if cipher_data.organization_id.is_none() {
let Some(saved_cipher) = existing_ciphers.iter_mut().find(|c| &c.uuid == cipher_data.id.as_ref().unwrap())
@@ -890,7 +889,7 @@ async fn post_rotatekey(data: Json, headers: Headers, conn: DbConn, nt:
// Prevent triggering cipher updates via WebSockets by settings UpdateType::None
// The user sessions are invalidated because all the ciphers were re-encrypted and thus triggering an update could cause issues.
// We force the users to logout after the user has been saved to try and prevent these issues.
- update_cipher_from_data(saved_cipher, cipher_data, &headers, None, &conn, &nt, UpdateType::None).await?
+ update_cipher_from_data(saved_cipher, cipher_data, &headers, None, &conn, &nt, UpdateType::None).await?;
}
}
@@ -1020,24 +1019,22 @@ async fn post_email(data: Json, headers: Headers, conn: DbConn,
err!("Email already in use");
}
- match user.email_new {
- Some(ref val) => {
- if val != &data.new_email {
- err!("Email change mismatch");
- }
+ if let Some(ref val) = user.email_new {
+ if val != &data.new_email {
+ err!("Email change mismatch");
}
- None => err!("No email change pending"),
+ } else {
+ err!("No email change pending")
}
if CONFIG.mail_enabled() {
// Only check the token if we sent out an email...
- match user.email_new_token {
- Some(ref val) => {
- if *val != data.token.into_string() {
- err!("Token mismatch");
- }
+ if let Some(ref val) = user.email_new_token {
+ if *val != data.token.into_string() {
+ err!("Token mismatch");
}
- None => err!("No email change pending"),
+ } else {
+ err!("No email change pending")
}
user.verified_at = Some(Utc::now().naive_utc());
} else {
@@ -1114,10 +1111,10 @@ async fn post_delete_recover(data: Json, conn: DbConn) -> Emp
let data: DeleteRecoverData = data.into_inner();
if CONFIG.mail_enabled() {
- if let Some(user) = User::find_by_mail(&data.email, &conn).await {
- if let Err(e) = mail::send_delete_account(&user.email, &user.uuid).await {
- error!("Error sending delete account email: {e:#?}");
- }
+ if let Some(user) = User::find_by_mail(&data.email, &conn).await
+ && let Err(e) = mail::send_delete_account(&user.email, &user.uuid).await
+ {
+ error!("Error sending delete account email: {e:#?}");
}
Ok(())
} else {
@@ -1169,6 +1166,7 @@ async fn delete_account(data: Json, headers: Headers, conn: D
user.delete(&conn).await
}
+#[expect(clippy::needless_pass_by_value, reason = "Not beneficial for Headers")]
#[get("/accounts/revision-date")]
fn revision_date(headers: Headers) -> JsonResult {
let revision_date = headers.user.updated_at.and_utc().timestamp_millis();
@@ -1183,12 +1181,12 @@ struct PasswordHintData {
#[post("/accounts/password-hint", data = "")]
async fn password_hint(data: Json, conn: DbConn) -> EmptyResult {
+ const NO_HINT: &str = "Sorry, you have no password hint...";
+
if !CONFIG.password_hints_allowed() || (!CONFIG.mail_enabled() && !CONFIG.show_password_hint()) {
err!("This server is not configured to provide password hints.");
}
- const NO_HINT: &str = "Sorry, you have no password hint...";
-
let data: PasswordHintData = data.into_inner();
let email = &data.email;
@@ -1199,9 +1197,9 @@ async fn password_hint(data: Json, conn: DbConn) -> EmptyResul
// There is still a timing side channel here in that the code
// paths that send mail take noticeably longer than ones that
// don't. Add a randomized sleep to mitigate this somewhat.
- use rand::{rngs::SmallRng, RngExt};
+ use rand::{RngExt, rngs::SmallRng};
let mut rng: SmallRng = rand::make_rng();
- let sleep_ms = rng.random_range(900..=1100) as u64;
+ let sleep_ms: u64 = rng.random_range(900..=1100);
tokio::time::sleep(tokio::time::Duration::from_millis(sleep_ms)).await;
Ok(())
} else {
@@ -1229,11 +1227,11 @@ pub struct PreloginData {
}
#[post("/accounts/prelogin", data = "")]
-async fn prelogin(data: Json, conn: DbConn) -> Json {
- _prelogin(data, conn).await
+async fn post_prelogin(data: Json, conn: DbConn) -> Json {
+ prelogin(data, conn).await
}
-pub async fn _prelogin(data: Json, conn: DbConn) -> Json {
+pub async fn prelogin(data: Json, conn: DbConn) -> Json {
let data: PreloginData = data.into_inner();
let (kdf_type, kdf_iter, kdf_mem, kdf_para) = match User::find_by_mail(&data.email, &conn).await {
@@ -1283,9 +1281,7 @@ async fn verify_password(data: Json, headers: Headers
Ok(Json(master_password_policy(&user, &conn).await))
}
-async fn _api_key(data: Json, rotate: bool, headers: Headers, conn: DbConn) -> JsonResult {
- use crate::util::format_date;
-
+async fn update_api_key(data: Json, rotate: bool, headers: Headers, conn: DbConn) -> JsonResult {
let data: PasswordOrOtpData = data.into_inner();
let mut user = headers.user;
@@ -1304,13 +1300,13 @@ async fn _api_key(data: Json, rotate: bool, headers: Headers,
}
#[post("/accounts/api-key", data = "")]
-async fn api_key(data: Json, headers: Headers, conn: DbConn) -> JsonResult {
- _api_key(data, false, headers, conn).await
+async fn post_api_key(data: Json, headers: Headers, conn: DbConn) -> JsonResult {
+ update_api_key(data, false, headers, conn).await
}
#[post("/accounts/rotate-api-key", data = "")]
async fn rotate_api_key(data: Json, headers: Headers, conn: DbConn) -> JsonResult {
- _api_key(data, true, headers, conn).await
+ update_api_key(data, true, headers, conn).await
}
#[get("/devices/knowndevice")]
@@ -1353,7 +1349,7 @@ impl<'r> FromRequest<'r> for KnownDevice {
};
let uuid = if let Some(uuid) = req.headers().get_one("X-Device-Identifier") {
- uuid.to_string().into()
+ uuid.to_owned().into()
} else {
return Outcome::Error((Status::BadRequest, "X-Device-Identifier value is required"));
};
@@ -1368,7 +1364,7 @@ impl<'r> FromRequest<'r> for KnownDevice {
#[get("/devices")]
async fn get_all_devices(headers: Headers, conn: DbConn) -> JsonResult {
let devices = Device::find_with_auth_request_by_user(&headers.user.uuid, &conn).await;
- let devices = devices.iter().map(|device| device.to_json()).collect::>();
+ let devices = devices.iter().map(DeviceWithAuthRequest::to_json).collect::>();
Ok(Json(json!({
"data": devices,
@@ -1438,7 +1434,7 @@ async fn put_clear_device_token(device_id: DeviceId, conn: DbConn) -> EmptyResul
if let Some(device) = Device::find_by_uuid(&device_id, &conn).await {
Device::clear_push_token_by_uuid(&device_id, &conn).await?;
- unregister_push_device(&device.push_uuid).await?;
+ unregister_push_device(device.push_uuid.as_ref()).await?;
}
Ok(())
@@ -1708,6 +1704,6 @@ pub async fn purge_auth_requests(pool: DbPool) {
if let Ok(conn) = pool.get().await {
AuthRequest::purge_expired_auth_requests(&conn).await;
} else {
- error!("Failed to get DB connection while purging auth requests")
+ error!("Failed to get DB connection while purging auth requests");
}
}
diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs
index 6d4e1f41..6b9994cf 100644
--- a/src/api/core/ciphers.rs
+++ b/src/api/core/ciphers.rs
@@ -2,30 +2,30 @@ use std::collections::{HashMap, HashSet};
use chrono::{NaiveDateTime, Utc};
use num_traits::ToPrimitive;
-use rocket::fs::TempFile;
-use rocket::serde::json::Json;
use rocket::{
- form::{Form, FromForm},
Route,
+ form::{Form, FromForm},
+ fs::TempFile,
+ serde::json::Json,
};
use serde_json::Value;
-use crate::auth::ClientVersion;
-use crate::util::{deser_opt_nonempty_str, save_temp_file, NumberOrString};
use crate::{
- api::{self, core::log_event, EmptyResult, JsonResult, Notify, PasswordOrOtpData, UpdateType},
+ CONFIG,
+ api::{self, EmptyResult, JsonResult, Notify, PasswordOrOtpData, UpdateType, core::log_event},
+ auth::ClientVersion,
auth::{Headers, OrgIdGuard, OwnerHeaders},
config::PathType,
crypto,
db::{
+ DbConn, DbPool,
models::{
- Attachment, AttachmentId, Cipher, CipherId, Collection, CollectionCipher, CollectionGroup, CollectionId,
- CollectionUser, EventType, Favorite, Folder, FolderCipher, FolderId, Group, Membership, MembershipType,
- OrgPolicy, OrgPolicyType, OrganizationId, RepromptType, Send, UserId,
+ Archive, Attachment, AttachmentId, Cipher, CipherId, Collection, CollectionCipher, CollectionGroup,
+ CollectionId, CollectionUser, EventType, Favorite, Folder, FolderCipher, FolderId, Group, Membership,
+ MembershipType, OrgPolicy, OrgPolicyType, OrganizationId, RepromptType, Send, UserId,
},
- DbConn, DbPool,
},
- CONFIG,
+ util::{NumberOrString, deser_opt_nonempty_str, save_temp_file},
};
use super::folders::FolderData;
@@ -96,6 +96,10 @@ pub fn routes() -> Vec {
post_collections_update,
post_collections_admin,
put_collections_admin,
+ archive_cipher_put,
+ archive_cipher_selected,
+ unarchive_cipher_put,
+ unarchive_cipher_selected,
]
}
@@ -104,7 +108,7 @@ pub async fn purge_trashed_ciphers(pool: DbPool) {
if let Ok(conn) = pool.get().await {
Cipher::purge_trash(&conn).await;
} else {
- error!("Failed to get DB connection while purging trashed ciphers")
+ error!("Failed to get DB connection while purging trashed ciphers");
}
}
@@ -160,7 +164,7 @@ async fn sync(data: SyncData, headers: Headers, client_version: Option,
+ archived_date: Option,
}
#[derive(Debug, Deserialize)]
@@ -396,20 +401,34 @@ pub async fn update_cipher_from_data(
nt: &Notify<'_>,
ut: UpdateType,
) -> EmptyResult {
+ // Cleanup cipher data, like removing the 'Response' key.
+ // This key is somewhere generated during Javascript so no way for us this fix this.
+ // Also, upstream only retrieves keys they actually want to store, and thus skip the 'Response' key.
+ // We do not mind which data is in it, the keep our model more flexible when there are upstream changes.
+ // But, we at least know we do not need to store and return this specific key.
+ fn clean_cipher_data(mut json_data: Value) -> Value {
+ if json_data.is_array() {
+ json_data.as_array_mut().unwrap().iter_mut().for_each(|ref mut f| {
+ f.as_object_mut().unwrap().remove("response");
+ });
+ }
+ json_data
+ }
+
enforce_personal_ownership_policy(Some(&data), headers, conn).await?;
// Check that the client isn't updating an existing cipher with stale data.
// And only perform this check when not importing ciphers, else the date/time check will fail.
- if ut != UpdateType::None {
- if let Some(dt) = data.last_known_revision_date {
- match NaiveDateTime::parse_from_str(&dt, "%+") {
- // ISO 8601 format
- Err(err) => warn!("Error parsing LastKnownRevisionDate '{dt}': {err}"),
- Ok(dt) if cipher.updated_at.signed_duration_since(dt).num_seconds() > 1 => {
- err!("The client copy of this cipher is out of date. Resync the client and try again.")
- }
- Ok(_) => (),
+ if ut != UpdateType::None
+ && let Some(dt) = data.last_known_revision_date
+ {
+ match NaiveDateTime::parse_from_str(&dt, "%+") {
+ // ISO 8601 format
+ Err(err) => warn!("Error parsing LastKnownRevisionDate '{dt}': {err}"),
+ Ok(dt) if cipher.updated_at.signed_duration_since(dt).num_seconds() > 1 => {
+ err!("The client copy of this cipher is out of date. Resync the client and try again.")
}
+ Ok(_) => (),
}
}
@@ -451,25 +470,22 @@ pub async fn update_cipher_from_data(
cipher.user_uuid = Some(headers.user.uuid.clone());
}
- if let Some(ref folder_id) = data.folder_id {
- if Folder::find_by_uuid_and_user(folder_id, &headers.user.uuid, conn).await.is_none() {
- err!("Invalid folder", "Folder does not exist or belongs to another user");
- }
+ if let Some(ref folder_id) = data.folder_id
+ && Folder::find_by_uuid_and_user(folder_id, &headers.user.uuid, conn).await.is_none()
+ {
+ err!("Invalid folder", "Folder does not exist or belongs to another user");
}
// Modify attachments name and keys when rotating
if let Some(attachments) = data.attachments2 {
for (id, attachment) in attachments {
- let mut saved_att = match Attachment::find_by_id(&id, conn).await {
- Some(att) => att,
- None => {
- // Warn and continue here.
- // A missing attachment means it was removed via an other client.
- // Also the Desktop Client supports removing attachments and save an update afterwards.
- // Bitwarden it self ignores these mismatches server side.
- warn!("Attachment {id} doesn't exist");
- continue;
- }
+ let Some(mut saved_att) = Attachment::find_by_id(&id, conn).await else {
+ // Warn and continue here.
+ // A missing attachment means it was removed via an other client.
+ // Also the Desktop Client supports removing attachments and save an update afterwards.
+ // Bitwarden it self ignores these mismatches server side.
+ warn!("Attachment {id} doesn't exist");
+ continue;
};
if saved_att.cipher_uuid != cipher.uuid {
@@ -486,20 +502,6 @@ pub async fn update_cipher_from_data(
}
}
- // Cleanup cipher data, like removing the 'Response' key.
- // This key is somewhere generated during Javascript so no way for us this fix this.
- // Also, upstream only retrieves keys they actually want to store, and thus skip the 'Response' key.
- // We do not mind which data is in it, the keep our model more flexible when there are upstream changes.
- // But, we at least know we do not need to store and return this specific key.
- fn _clean_cipher_data(mut json_data: Value) -> Value {
- if json_data.is_array() {
- json_data.as_array_mut().unwrap().iter_mut().for_each(|ref mut f| {
- f.as_object_mut().unwrap().remove("response");
- });
- };
- json_data
- }
-
let type_data_opt = match data.r#type {
1 => data.login,
2 => data.secure_note,
@@ -509,23 +511,22 @@ pub async fn update_cipher_from_data(
_ => err!("Invalid type"),
};
- let type_data = match type_data_opt {
- Some(mut data) => {
- // Remove the 'Response' key from the base object.
- data.as_object_mut().unwrap().remove("response");
- // Remove the 'Response' key from every Uri.
- if data["uris"].is_array() {
- data["uris"] = _clean_cipher_data(data["uris"].clone());
- }
- data
+ let type_data = if let Some(mut data) = type_data_opt {
+ // Remove the 'Response' key from the base object.
+ data.as_object_mut().unwrap().remove("response");
+ // Remove the 'Response' key from every Uri.
+ if data["uris"].is_array() {
+ data["uris"] = clean_cipher_data(data["uris"].clone());
}
- None => err!("Data missing"),
+ data
+ } else {
+ err!("Data missing")
};
cipher.key = data.key;
cipher.name = data.name;
cipher.notes = data.notes;
- cipher.fields = data.fields.map(|f| _clean_cipher_data(f).to_string());
+ cipher.fields = data.fields.map(|f| clean_cipher_data(f).to_string());
cipher.data = type_data.to_string();
cipher.password_history = data.password_history.map(|f| f.to_string());
cipher.reprompt = data.reprompt.filter(|r| *r == RepromptType::None as i32 || *r == RepromptType::Password as i32);
@@ -534,6 +535,13 @@ pub async fn update_cipher_from_data(
cipher.move_to_folder(data.folder_id, &headers.user.uuid, conn).await?;
cipher.set_favorite(data.favorite, &headers.user.uuid, conn).await?;
+ if let Some(dt_str) = data.archived_date {
+ match NaiveDateTime::parse_from_str(&dt_str, "%+") {
+ Ok(dt) => cipher.set_archived_at(dt, &headers.user.uuid, conn).await?,
+ Err(err) => warn!("Error parsing ArchivedDate '{dt_str}': {err}"),
+ }
+ }
+
if ut != UpdateType::None {
// Only log events for organizational ciphers
if let Some(org_id) = &cipher.organization_uuid {
@@ -600,7 +608,7 @@ async fn post_ciphers_import(data: Json, headers: Headers, conn: DbC
let existing_folders: HashSet