Updated deps and misc fixes and updates

- Updated some Rust dependencies
- Fixed an issue with CSP header, this was not configured correctly
- Prevent sending CSP and Frame headers for the MFA connector.html files.
  Else some clients will fail to handle these protocols.
- Add `unsafe-inline` for `script-src` only to the CSP for the Admin Interface
- Updated JavaScript and CSS files for the Admin interface
- Changed the layout for showing overridden settings, better visible now.
- Made the version check cachable to prevent hitting the Github API rate limits
- Hide the `database_url` as if it is a password in the Admin Interface
  Else for MariaDB/MySQL or PostgreSQL this was plain text.
- Fixed an issue that pressing enter on the SMTP Test would save the config.
  resolves #2542
- Prevent user names larger then 50 characters
  resolves #2419
pull/2543/head
BlackDex 3 years ago
parent f95bd3bb04
commit 5d05ec58be
No known key found for this signature in database
GPG Key ID: 58C80A2AA6C765E1

@ -8,7 +8,6 @@ on:
- "migrations/**" - "migrations/**"
- "Cargo.*" - "Cargo.*"
- "build.rs" - "build.rs"
- "diesel.toml"
- "rust-toolchain" - "rust-toolchain"
pull_request: pull_request:
paths: paths:
@ -17,7 +16,6 @@ on:
- "migrations/**" - "migrations/**"
- "Cargo.*" - "Cargo.*"
- "build.rs" - "build.rs"
- "diesel.toml"
- "rust-toolchain" - "rust-toolchain"
jobs: jobs:

@ -1,7 +1,7 @@
--- ---
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.2.0 rev: v4.3.0
hooks: hooks:
- id: check-yaml - id: check-yaml
- id: check-json - id: check-json
@ -26,7 +26,8 @@ repos:
entry: cargo test entry: cargo test
language: system language: system
args: ["--features", "sqlite,mysql,postgresql,enable_mimalloc", "--"] args: ["--features", "sqlite,mysql,postgresql,enable_mimalloc", "--"]
types: [rust] types_or: [file, rust]
files: (Cargo.toml|Cargo.lock)
pass_filenames: false pass_filenames: false
- id: cargo-clippy - id: cargo-clippy
name: cargo clippy name: cargo clippy
@ -34,5 +35,6 @@ repos:
entry: cargo clippy entry: cargo clippy
language: system language: system
args: ["--features", "sqlite,mysql,postgresql,enable_mimalloc", "--", "-D", "warnings"] args: ["--features", "sqlite,mysql,postgresql,enable_mimalloc", "--", "-D", "warnings"]
types: [rust] types_or: [file, rust]
files: (Cargo.toml|Cargo.lock)
pass_filenames: false pass_filenames: false

310
Cargo.lock generated

@ -178,12 +178,6 @@ dependencies = [
"rustc-demangle", "rustc-demangle",
] ]
[[package]]
name = "base-x"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc19a4937b4fbd3fe3379793130e42060d10627a360f2127802b10b87e7baf74"
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.13.0" version = "0.13.0"
@ -279,9 +273,9 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
[[package]] [[package]]
name = "cached" name = "cached"
version = "0.34.0" version = "0.34.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aadf76ddea74bab35ebeb8f1eb115b9bc04eaee42d8acc0d5f477dee6b176c9a" checksum = "12f5cd208ba696f870238022d81ca1d80ed9d696fd62341c747f2d8f6ecdd9fe"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"async_once", "async_once",
@ -370,23 +364,6 @@ dependencies = [
"generic-array 0.14.5", "generic-array 0.14.5",
] ]
[[package]]
name = "const_fn"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935"
[[package]]
name = "cookie"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5f1c7727e460397e56abc4bddc1d49e07a1ad78fc98eb2e1c8f032a58a2f80d"
dependencies = [
"percent-encoding 2.1.0",
"time 0.2.27",
"version_check",
]
[[package]] [[package]]
name = "cookie" name = "cookie"
version = "0.16.0" version = "0.16.0"
@ -405,29 +382,13 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "cookie_store"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3f7034c0932dc36f5bd8ec37368d971346809435824f277cb3b8299fc56167c"
dependencies = [
"cookie 0.15.1",
"idna 0.2.3",
"log",
"publicsuffix",
"serde",
"serde_json",
"time 0.2.27",
"url 2.2.2",
]
[[package]] [[package]]
name = "cookie_store" name = "cookie_store"
version = "0.16.1" version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e4b6aa369f41f5faa04bb80c9b1f4216ea81646ed6124d76ba5c49a7aafd9cd" checksum = "2e4b6aa369f41f5faa04bb80c9b1f4216ea81646ed6124d76ba5c49a7aafd9cd"
dependencies = [ dependencies = [
"cookie 0.16.0", "cookie",
"idna 0.2.3", "idna 0.2.3",
"log", "log",
"publicsuffix", "publicsuffix",
@ -694,12 +655,6 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "discard"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
[[package]] [[package]]
name = "dotenvy" name = "dotenvy"
version = "0.15.1" version = "0.15.1"
@ -717,9 +672,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]] [[package]]
name = "email-encoding" name = "email-encoding"
version = "0.1.1" version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b91dddc343e7eaa27f9764e5bffe57370d957017fdd75244f5045e829a8441" checksum = "827e1fb86d24d558ab0454ca3fa084f8a6144ade1e3e6982f697c586bf96b41b"
dependencies = [ dependencies = [
"base64", "base64",
"memchr", "memchr",
@ -742,9 +697,9 @@ dependencies = [
[[package]] [[package]]
name = "enum-as-inner" name = "enum-as-inner"
version = "0.3.4" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4" checksum = "21cdad81446a7f7dc43f6a77409efeb9733d2fa65553efef6018ef257c959b73"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
@ -970,13 +925,13 @@ dependencies = [
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.6" version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"wasi 0.10.2+wasi-snapshot-preview1", "wasi 0.11.0+wasi-snapshot-preview1",
] ]
[[package]] [[package]]
@ -1033,7 +988,7 @@ dependencies = [
"indexmap", "indexmap",
"slab", "slab",
"tokio", "tokio",
"tokio-util 0.7.2", "tokio-util 0.7.3",
"tracing", "tracing",
] ]
@ -1045,9 +1000,9 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
[[package]] [[package]]
name = "handlebars" name = "handlebars"
version = "4.3.0" version = "4.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d113a9853e5accd30f43003560b5563ffbb007e3f325e8b103fa0d0029c6e6df" checksum = "b66d0c1b6e3abfd1e72818798925e16e02ed77e1b47f6c25a95a23b377ee4299"
dependencies = [ dependencies = [
"log", "log",
"pest", "pest",
@ -1125,9 +1080,9 @@ dependencies = [
[[package]] [[package]]
name = "http" name = "http"
version = "0.2.7" version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb" checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
dependencies = [ dependencies = [
"bytes", "bytes",
"fnv", "fnv",
@ -1174,7 +1129,7 @@ dependencies = [
"httpdate", "httpdate",
"itoa", "itoa",
"pin-project-lite", "pin-project-lite",
"socket2 0.4.4", "socket2",
"tokio", "tokio",
"tower-service", "tower-service",
"tracing", "tracing",
@ -1250,14 +1205,14 @@ dependencies = [
[[package]] [[package]]
name = "ipconfig" name = "ipconfig"
version = "0.2.2" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" checksum = "723519edce41262b05d4143ceb95050e4c614f483e78e9fd9e39a8275a84ad98"
dependencies = [ dependencies = [
"socket2 0.3.19", "socket2",
"widestring", "widestring",
"winapi", "winapi",
"winreg 0.6.2", "winreg 0.7.0",
] ]
[[package]] [[package]]
@ -1337,7 +1292,7 @@ dependencies = [
"once_cell", "once_cell",
"quoted_printable", "quoted_printable",
"serde", "serde",
"socket2 0.4.4", "socket2",
"tracing", "tracing",
] ]
@ -2194,15 +2149,15 @@ dependencies = [
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.11.10" version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92"
dependencies = [ dependencies = [
"async-compression", "async-compression",
"base64", "base64",
"bytes", "bytes",
"cookie 0.15.1", "cookie",
"cookie_store 0.15.1", "cookie_store",
"encoding_rs", "encoding_rs",
"futures-core", "futures-core",
"futures-util", "futures-util",
@ -2226,7 +2181,8 @@ dependencies = [
"tokio", "tokio",
"tokio-native-tls", "tokio-native-tls",
"tokio-socks", "tokio-socks",
"tokio-util 0.6.10", "tokio-util 0.7.3",
"tower-service",
"trust-dns-resolver", "trust-dns-resolver",
"url 2.2.2", "url 2.2.2",
"wasm-bindgen", "wasm-bindgen",
@ -2314,7 +2270,7 @@ dependencies = [
"time 0.3.9", "time 0.3.9",
"tokio", "tokio",
"tokio-stream", "tokio-stream",
"tokio-util 0.7.2", "tokio-util 0.7.3",
"ubyte", "ubyte",
"version_check", "version_check",
"yansi", "yansi",
@ -2342,7 +2298,7 @@ version = "0.5.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ded65d127954de3c12471630bf4b81a2792f065984461e65b91d0fdaafc17a2" checksum = "2ded65d127954de3c12471630bf4b81a2792f065984461e65b91d0fdaafc17a2"
dependencies = [ dependencies = [
"cookie 0.16.0", "cookie",
"either", "either",
"futures", "futures",
"http", "http",
@ -2372,15 +2328,6 @@ version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.20.6" version = "0.20.6"
@ -2487,21 +2434,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.137" version = "1.0.137"
@ -2578,15 +2510,6 @@ dependencies = [
"digest 0.10.3", "digest 0.10.3",
] ]
[[package]]
name = "sha1"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770"
dependencies = [
"sha1_smol",
]
[[package]] [[package]]
name = "sha1" name = "sha1"
version = "0.10.1" version = "0.10.1"
@ -2598,12 +2521,6 @@ dependencies = [
"digest 0.10.3", "digest 0.10.3",
] ]
[[package]]
name = "sha1_smol"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
[[package]] [[package]]
name = "sha2" name = "sha2"
version = "0.10.2" version = "0.10.2"
@ -2663,17 +2580,6 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
[[package]]
name = "socket2"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
dependencies = [
"cfg-if",
"libc",
"winapi",
]
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.4.4" version = "0.4.4"
@ -2705,15 +2611,6 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "standback"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff"
dependencies = [
"version_check",
]
[[package]] [[package]]
name = "state" name = "state"
version = "0.5.3" version = "0.5.3"
@ -2723,55 +2620,6 @@ dependencies = [
"loom", "loom",
] ]
[[package]]
name = "stdweb"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
dependencies = [
"discard",
"rustc_version",
"stdweb-derive",
"stdweb-internal-macros",
"stdweb-internal-runtime",
"wasm-bindgen",
]
[[package]]
name = "stdweb-derive"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
dependencies = [
"proc-macro2",
"quote",
"serde",
"serde_derive",
"syn",
]
[[package]]
name = "stdweb-internal-macros"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
dependencies = [
"base-x",
"proc-macro2",
"quote",
"serde",
"serde_derive",
"serde_json",
"sha1 0.6.1",
"syn",
]
[[package]]
name = "stdweb-internal-runtime"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.10.0" version = "0.10.0"
@ -2870,21 +2718,6 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "time"
version = "0.2.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242"
dependencies = [
"const_fn",
"libc",
"standback",
"stdweb",
"time-macros 0.1.1",
"version_check",
"winapi",
]
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.9" version = "0.3.9"
@ -2894,17 +2727,7 @@ dependencies = [
"itoa", "itoa",
"libc", "libc",
"num_threads", "num_threads",
"time-macros 0.2.4", "time-macros",
]
[[package]]
name = "time-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1"
dependencies = [
"proc-macro-hack",
"time-macros-impl",
] ]
[[package]] [[package]]
@ -2913,19 +2736,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
[[package]]
name = "time-macros-impl"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f"
dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"standback",
"syn",
]
[[package]] [[package]]
name = "tinyvec" name = "tinyvec"
version = "1.6.0" version = "1.6.0"
@ -2943,9 +2753,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.19.0" version = "1.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f392c8f16bda3456c0b00c6de39cb100449b98de55ac41c6cdd2bfcf53a1245" checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439"
dependencies = [ dependencies = [
"bytes", "bytes",
"libc", "libc",
@ -2956,16 +2766,16 @@ dependencies = [
"parking_lot 0.12.1", "parking_lot 0.12.1",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"socket2 0.4.4", "socket2",
"tokio-macros", "tokio-macros",
"winapi", "winapi",
] ]
[[package]] [[package]]
name = "tokio-macros" name = "tokio-macros"
version = "1.7.0" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -3007,9 +2817,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-stream" name = "tokio-stream"
version = "0.1.8" version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"pin-project-lite", "pin-project-lite",
@ -3044,9 +2854,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.2" version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-core", "futures-core",
@ -3085,9 +2895,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
[[package]] [[package]]
name = "tracing" name = "tracing"
version = "0.1.34" version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"log", "log",
@ -3109,11 +2919,11 @@ dependencies = [
[[package]] [[package]]
name = "tracing-core" name = "tracing-core"
version = "0.1.26" version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" checksum = "7709595b8878a4965ce5e87ebf880a7d39c9afc6837721b21a5a816a8117d921"
dependencies = [ dependencies = [
"lazy_static", "once_cell",
"valuable", "valuable",
] ]
@ -3148,9 +2958,9 @@ dependencies = [
[[package]] [[package]]
name = "trust-dns-proto" name = "trust-dns-proto"
version = "0.20.4" version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca94d4e9feb6a181c690c4040d7a24ef34018d8313ac5044a61d21222ae24e31" checksum = "9c31f240f59877c3d4bb3b3ea0ec5a6a0cff07323580ff8c7a605cd7d08b255d"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"cfg-if", "cfg-if",
@ -3173,9 +2983,9 @@ dependencies = [
[[package]] [[package]]
name = "trust-dns-resolver" name = "trust-dns-resolver"
version = "0.20.4" version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecae383baad9995efaa34ce8e57d12c3f305e545887472a492b838f4b5cfb77a" checksum = "e4ba72c2ea84515690c9fcef4c6c660bb9df3036ed1051686de84605b74fd558"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"futures-util", "futures-util",
@ -3183,7 +2993,7 @@ dependencies = [
"lazy_static", "lazy_static",
"log", "log",
"lru-cache", "lru-cache",
"parking_lot 0.11.2", "parking_lot 0.12.1",
"resolv-conf", "resolv-conf",
"smallvec", "smallvec",
"thiserror", "thiserror",
@ -3255,9 +3065,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.0" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
[[package]] [[package]]
name = "unicode-normalization" name = "unicode-normalization"
@ -3322,9 +3132,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.1.1" version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6d5d669b51467dcf7b2f1a796ce0f955f05f01cafda6c19d6e95f730df29238" checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f"
dependencies = [ dependencies = [
"getrandom", "getrandom",
] ]
@ -3344,8 +3154,8 @@ dependencies = [
"cached", "cached",
"chrono", "chrono",
"chrono-tz", "chrono-tz",
"cookie 0.16.0", "cookie",
"cookie_store 0.16.1", "cookie_store",
"ctrlc", "ctrlc",
"dashmap", "dashmap",
"data-encoding", "data-encoding",
@ -3543,9 +3353,9 @@ dependencies = [
[[package]] [[package]]
name = "widestring" name = "widestring"
version = "0.4.3" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983"
[[package]] [[package]]
name = "winapi" name = "winapi"
@ -3623,9 +3433,9 @@ checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
[[package]] [[package]]
name = "winreg" name = "winreg"
version = "0.6.2" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
dependencies = [ dependencies = [
"winapi", "winapi",
] ]
@ -3657,6 +3467,6 @@ dependencies = [
"hmac", "hmac",
"rand", "rand",
"reqwest", "reqwest",
"sha1 0.10.1", "sha1",
"threadpool", "threadpool",
] ]

@ -37,7 +37,7 @@ syslog = "6.0.1" # Needs to be v4 until fern is updated
# Logging # Logging
log = "0.4.17" log = "0.4.17"
fern = { version = "0.6.1", features = ["syslog-6"] } fern = { version = "0.6.1", features = ["syslog-6"] }
tracing = { version = "0.1.34", features = ["log"] } # Needed to have lettre and webauthn-rs trace logging to work tracing = { version = "0.1.35", features = ["log"] } # Needed to have lettre and webauthn-rs trace logging to work
backtrace = "0.3.65" # Logging panics to logfile instead stderr only backtrace = "0.3.65" # Logging panics to logfile instead stderr only
@ -61,7 +61,7 @@ dashmap = "5.3.4" # Concurrent hashmap implementation
# Async futures # Async futures
futures = "0.3.21" futures = "0.3.21"
tokio = { version = "1.19.0", features = ["rt-multi-thread", "fs", "io-util", "parking_lot", "time"] } tokio = { version = "1.19.2", features = ["rt-multi-thread", "fs", "io-util", "parking_lot", "time"] }
# A generic serialization/deserialization framework # A generic serialization/deserialization framework
serde = { version = "1.0.137", features = ["derive"] } serde = { version = "1.0.137", features = ["derive"] }
@ -79,7 +79,7 @@ rand = { version = "0.8.5", features = ["small_rng"] }
ring = "0.16.20" ring = "0.16.20"
# UUID generation # UUID generation
uuid = { version = "1.1.1", features = ["v4"] } uuid = { version = "1.1.2", features = ["v4"] }
# Date and time libraries # Date and time libraries
chrono = { version = "0.4.19", features = ["clock", "serde"], default-features = false } chrono = { version = "0.4.19", features = ["clock", "serde"], default-features = false }
@ -112,17 +112,17 @@ lettre = { version = "0.10.0-rc.7", features = ["smtp-transport", "builder", "se
percent-encoding = "2.1.0" # URL encoding library used for URL's in the emails percent-encoding = "2.1.0" # URL encoding library used for URL's in the emails
# Template library # Template library
handlebars = { version = "4.3.0", features = ["dir_source"] } handlebars = { version = "4.3.1", features = ["dir_source"] }
# HTTP client # HTTP client
reqwest = { version = "0.11.10", features = ["stream", "json", "gzip", "brotli", "socks", "cookies", "trust-dns"] } reqwest = { version = "0.11.11", features = ["stream", "json", "gzip", "brotli", "socks", "cookies", "trust-dns"] }
# For favicon extraction from main website # For favicon extraction from main website
html5gum = "0.4.0" html5gum = "0.4.0"
regex = { version = "1.5.6", features = ["std", "perf", "unicode-perl"], default-features = false } regex = { version = "1.5.6", features = ["std", "perf", "unicode-perl"], default-features = false }
data-url = "0.1.1" data-url = "0.1.1"
bytes = "1.1.0" bytes = "1.1.0"
cached = "0.34.0" cached = "0.34.1"
# Used for custom short lived cookie jar during favicon extraction # Used for custom short lived cookie jar during favicon extraction
cookie = "0.16.0" cookie = "0.16.0"

@ -491,41 +491,14 @@ async fn has_http_access() -> bool {
} }
} }
#[get("/diagnostics")] use cached::proc_macro::cached;
async fn diagnostics(_token: AdminToken, ip_header: IpHeader, conn: DbConn) -> ApiResult<Html<String>> { /// Cache this function to prevent API call rate limit. Github only allows 60 requests per hour, and we use 3 here already.
use crate::util::read_file_string; /// It will cache this function for 300 seconds (5 minutes) which should prevent the exhaustion of the rate limit.
use chrono::prelude::*; #[cached(time = 300, sync_writes = true)]
use std::net::ToSocketAddrs; async fn get_release_info(has_http_access: bool, running_within_docker: bool) -> (String, String, String) {
// Get current running versions
let web_vault_version: WebVaultVersion =
match read_file_string(&format!("{}/{}", CONFIG.web_vault_folder(), "vw-version.json")) {
Ok(s) => serde_json::from_str(&s)?,
_ => match read_file_string(&format!("{}/{}", CONFIG.web_vault_folder(), "version.json")) {
Ok(s) => serde_json::from_str(&s)?,
_ => WebVaultVersion {
version: String::from("Version file missing"),
},
},
};
// Execute some environment checks
let running_within_docker = is_running_in_docker();
let has_http_access = has_http_access().await;
let uses_proxy = env::var_os("HTTP_PROXY").is_some()
|| env::var_os("http_proxy").is_some()
|| env::var_os("HTTPS_PROXY").is_some()
|| env::var_os("https_proxy").is_some();
// 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(),
_ => "Could not resolve domain name.".to_string(),
};
// If the HTTP Check failed, do not even attempt to check for new versions since we were not able to connect with github.com anyway. // If the HTTP Check failed, do not even attempt to check for new versions since we were not able to connect with github.com anyway.
// TODO: Maybe we need to cache this using a LazyStatic or something. Github only allows 60 requests per hour, and we use 3 here already. if has_http_access {
let (latest_release, latest_commit, latest_web_build) = if has_http_access { info!("Running get_release_info!!");
( (
match get_github_api::<GitRelease>("https://api.github.com/repos/dani-garcia/vaultwarden/releases/latest") match get_github_api::<GitRelease>("https://api.github.com/repos/dani-garcia/vaultwarden/releases/latest")
.await .await
@ -558,8 +531,44 @@ async fn diagnostics(_token: AdminToken, ip_header: IpHeader, conn: DbConn) -> A
) )
} else { } else {
("-".to_string(), "-".to_string(), "-".to_string()) ("-".to_string(), "-".to_string(), "-".to_string())
}
}
#[get("/diagnostics")]
async fn diagnostics(_token: AdminToken, ip_header: IpHeader, conn: DbConn) -> ApiResult<Html<String>> {
use crate::util::read_file_string;
use chrono::prelude::*;
use std::net::ToSocketAddrs;
// Get current running versions
let web_vault_version: WebVaultVersion =
match read_file_string(&format!("{}/{}", CONFIG.web_vault_folder(), "vw-version.json")) {
Ok(s) => serde_json::from_str(&s)?,
_ => match read_file_string(&format!("{}/{}", CONFIG.web_vault_folder(), "version.json")) {
Ok(s) => serde_json::from_str(&s)?,
_ => WebVaultVersion {
version: String::from("Version file missing"),
},
},
};
// Execute some environment checks
let running_within_docker = is_running_in_docker();
let has_http_access = has_http_access().await;
let uses_proxy = env::var_os("HTTP_PROXY").is_some()
|| env::var_os("http_proxy").is_some()
|| env::var_os("HTTPS_PROXY").is_some()
|| env::var_os("https_proxy").is_some();
// 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(),
_ => "Could not resolve domain name.".to_string(),
}; };
let (latest_release, latest_commit, latest_web_build) =
get_release_info(has_http_access, running_within_docker).await;
let ip_header_name = match &ip_header.0 { let ip_header_name = match &ip_header.0 {
Some(h) => h, Some(h) => h,
_ => "", _ => "",

@ -67,6 +67,14 @@ async fn register(data: JsonUpcase<RegisterData>, conn: DbConn) -> EmptyResult {
let data: RegisterData = data.into_inner().data; let data: RegisterData = data.into_inner().data;
let email = data.Email.to_lowercase(); let email = data.Email.to_lowercase();
// 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.");
}
}
let mut user = match User::find_by_mail(&email, &conn).await { let mut user = match User::find_by_mail(&email, &conn).await {
Some(user) => { Some(user) => {
if !user.password_hash.is_empty() { if !user.password_hash.is_empty() {
@ -176,6 +184,12 @@ async fn put_profile(data: JsonUpcase<ProfileData>, headers: Headers, conn: DbCo
async fn post_profile(data: JsonUpcase<ProfileData>, headers: Headers, conn: DbConn) -> JsonResult { async fn post_profile(data: JsonUpcase<ProfileData>, headers: Headers, conn: DbConn) -> JsonResult {
let data: ProfileData = data.into_inner().data; let data: ProfileData = data.into_inner().data;
// 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 data.Name.len() > 50 {
err!("The field Name must be a string with a maximum length of 50.");
}
let mut user = headers.user; let mut user = headers.user;
user.name = data.Name; user.name = data.Name;

@ -1058,12 +1058,11 @@ fn js_escape_helper<'reg, 'rc>(
_rc: &mut RenderContext<'reg, 'rc>, _rc: &mut RenderContext<'reg, 'rc>,
out: &mut dyn Output, out: &mut dyn Output,
) -> HelperResult { ) -> HelperResult {
let param = h.param(0).ok_or_else(|| RenderError::new("Param not found for helper \"js_escape\""))?; let param = h.param(0).ok_or_else(|| RenderError::new("Param not found for helper \"jsesc\""))?;
let no_quote = h.param(1).is_some(); let no_quote = h.param(1).is_some();
let value = let value = param.value().as_str().ok_or_else(|| RenderError::new("Param for helper \"jsesc\" is not a String"))?;
param.value().as_str().ok_or_else(|| RenderError::new("Param for helper \"js_escape\" is not a String"))?;
let mut escaped_value = value.replace('\\', "").replace('\'', "\\x22").replace('\"', "\\x27"); let mut escaped_value = value.replace('\\', "").replace('\'', "\\x22").replace('\"', "\\x27");
if !no_quote { if !no_quote {

@ -21,7 +21,7 @@ db_object! {
} }
} }
#[derive(Copy, Clone, PartialEq, num_derive::FromPrimitive)] #[derive(Copy, Clone, Eq, PartialEq, num_derive::FromPrimitive)]
pub enum OrgPolicyType { pub enum OrgPolicyType {
TwoFactorAuthentication = 0, TwoFactorAuthentication = 0,
MasterPassword = 1, MasterPassword = 1,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -4,13 +4,175 @@
* *
* To rebuild or modify this file with the latest versions of the included * To rebuild or modify this file with the latest versions of the included
* software please visit: * software please visit:
* https://datatables.net/download/#bs5/dt-1.11.5 * https://datatables.net/download/#bs5/dt-1.12.1
* *
* Included libraries: * Included libraries:
* DataTables 1.11.5 * DataTables 1.12.1
*/ */
@charset "UTF-8"; @charset "UTF-8";
table.dataTable td.dt-control {
text-align: center;
cursor: pointer;
}
table.dataTable td.dt-control:before {
height: 1em;
width: 1em;
margin-top: -9px;
display: inline-block;
color: white;
border: 0.15em solid white;
border-radius: 1em;
box-shadow: 0 0 0.2em #444;
box-sizing: content-box;
text-align: center;
text-indent: 0 !important;
font-family: "Courier New", Courier, monospace;
line-height: 1em;
content: "+";
background-color: #31b131;
}
table.dataTable tr.dt-hasChild td.dt-control:before {
content: "-";
background-color: #d33333;
}
table.dataTable thead > tr > th.sorting, table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting_asc_disabled, table.dataTable thead > tr > th.sorting_desc_disabled,
table.dataTable thead > tr > td.sorting,
table.dataTable thead > tr > td.sorting_asc,
table.dataTable thead > tr > td.sorting_desc,
table.dataTable thead > tr > td.sorting_asc_disabled,
table.dataTable thead > tr > td.sorting_desc_disabled {
cursor: pointer;
position: relative;
padding-right: 26px;
}
table.dataTable thead > tr > th.sorting:before, table.dataTable thead > tr > th.sorting:after, table.dataTable thead > tr > th.sorting_asc:before, table.dataTable thead > tr > th.sorting_asc:after, table.dataTable thead > tr > th.sorting_desc:before, table.dataTable thead > tr > th.sorting_desc:after, table.dataTable thead > tr > th.sorting_asc_disabled:before, table.dataTable thead > tr > th.sorting_asc_disabled:after, table.dataTable thead > tr > th.sorting_desc_disabled:before, table.dataTable thead > tr > th.sorting_desc_disabled:after,
table.dataTable thead > tr > td.sorting:before,
table.dataTable thead > tr > td.sorting:after,
table.dataTable thead > tr > td.sorting_asc:before,
table.dataTable thead > tr > td.sorting_asc:after,
table.dataTable thead > tr > td.sorting_desc:before,
table.dataTable thead > tr > td.sorting_desc:after,
table.dataTable thead > tr > td.sorting_asc_disabled:before,
table.dataTable thead > tr > td.sorting_asc_disabled:after,
table.dataTable thead > tr > td.sorting_desc_disabled:before,
table.dataTable thead > tr > td.sorting_desc_disabled:after {
position: absolute;
display: block;
opacity: 0.125;
right: 10px;
line-height: 9px;
font-size: 0.9em;
}
table.dataTable thead > tr > th.sorting:before, table.dataTable thead > tr > th.sorting_asc:before, table.dataTable thead > tr > th.sorting_desc:before, table.dataTable thead > tr > th.sorting_asc_disabled:before, table.dataTable thead > tr > th.sorting_desc_disabled:before,
table.dataTable thead > tr > td.sorting:before,
table.dataTable thead > tr > td.sorting_asc:before,
table.dataTable thead > tr > td.sorting_desc:before,
table.dataTable thead > tr > td.sorting_asc_disabled:before,
table.dataTable thead > tr > td.sorting_desc_disabled:before {
bottom: 50%;
content: "▴";
}
table.dataTable thead > tr > th.sorting:after, table.dataTable thead > tr > th.sorting_asc:after, table.dataTable thead > tr > th.sorting_desc:after, table.dataTable thead > tr > th.sorting_asc_disabled:after, table.dataTable thead > tr > th.sorting_desc_disabled:after,
table.dataTable thead > tr > td.sorting:after,
table.dataTable thead > tr > td.sorting_asc:after,
table.dataTable thead > tr > td.sorting_desc:after,
table.dataTable thead > tr > td.sorting_asc_disabled:after,
table.dataTable thead > tr > td.sorting_desc_disabled:after {
top: 50%;
content: "▾";
}
table.dataTable thead > tr > th.sorting_asc:before, table.dataTable thead > tr > th.sorting_desc:after,
table.dataTable thead > tr > td.sorting_asc:before,
table.dataTable thead > tr > td.sorting_desc:after {
opacity: 0.6;
}
table.dataTable thead > tr > th.sorting_desc_disabled:after, table.dataTable thead > tr > th.sorting_asc_disabled:before,
table.dataTable thead > tr > td.sorting_desc_disabled:after,
table.dataTable thead > tr > td.sorting_asc_disabled:before {
display: none;
}
table.dataTable thead > tr > th:active,
table.dataTable thead > tr > td:active {
outline: none;
}
div.dataTables_scrollBody table.dataTable thead > tr > th:before, div.dataTables_scrollBody table.dataTable thead > tr > th:after,
div.dataTables_scrollBody table.dataTable thead > tr > td:before,
div.dataTables_scrollBody table.dataTable thead > tr > td:after {
display: none;
}
div.dataTables_processing {
position: absolute;
top: 50%;
left: 50%;
width: 200px;
margin-left: -100px;
margin-top: -26px;
text-align: center;
padding: 2px;
}
div.dataTables_processing > div:last-child {
position: relative;
width: 80px;
height: 15px;
margin: 1em auto;
}
div.dataTables_processing > div:last-child > div {
position: absolute;
top: 0;
width: 13px;
height: 13px;
border-radius: 50%;
background: rgba(13, 110, 253, 0.9);
animation-timing-function: cubic-bezier(0, 1, 1, 0);
}
div.dataTables_processing > div:last-child > div:nth-child(1) {
left: 8px;
animation: datatables-loader-1 0.6s infinite;
}
div.dataTables_processing > div:last-child > div:nth-child(2) {
left: 8px;
animation: datatables-loader-2 0.6s infinite;
}
div.dataTables_processing > div:last-child > div:nth-child(3) {
left: 32px;
animation: datatables-loader-2 0.6s infinite;
}
div.dataTables_processing > div:last-child > div:nth-child(4) {
left: 56px;
animation: datatables-loader-3 0.6s infinite;
}
@keyframes datatables-loader-1 {
0% {
transform: scale(0);
}
100% {
transform: scale(1);
}
}
@keyframes datatables-loader-3 {
0% {
transform: scale(1);
}
100% {
transform: scale(0);
}
}
@keyframes datatables-loader-2 {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(24px, 0);
}
}
table.dataTable.nowrap th, table.dataTable.nowrap td {
white-space: nowrap;
}
table.dataTable th.dt-left, table.dataTable th.dt-left,
table.dataTable td.dt-left { table.dataTable td.dt-left {
text-align: left; text-align: left;
@ -32,6 +194,12 @@ table.dataTable th.dt-nowrap,
table.dataTable td.dt-nowrap { table.dataTable td.dt-nowrap {
white-space: nowrap; white-space: nowrap;
} }
table.dataTable thead th,
table.dataTable thead td,
table.dataTable tfoot th,
table.dataTable tfoot td {
text-align: left;
}
table.dataTable thead th.dt-head-left, table.dataTable thead th.dt-head-left,
table.dataTable thead td.dt-head-left, table.dataTable thead td.dt-head-left,
table.dataTable tfoot th.dt-head-left, table.dataTable tfoot th.dt-head-left,
@ -82,31 +250,6 @@ table.dataTable tbody th.dt-body-nowrap,
table.dataTable tbody td.dt-body-nowrap { table.dataTable tbody td.dt-body-nowrap {
white-space: nowrap; white-space: nowrap;
} }
table.dataTable td.dt-control {
text-align: center;
cursor: pointer;
}
table.dataTable td.dt-control:before {
height: 1em;
width: 1em;
margin-top: -9px;
display: inline-block;
color: white;
border: 0.15em solid white;
border-radius: 1em;
box-shadow: 0 0 0.2em #444;
box-sizing: content-box;
text-align: center;
text-indent: 0 !important;
font-family: "Courier New", Courier, monospace;
line-height: 1em;
content: "+";
background-color: #31b131;
}
table.dataTable tr.dt-hasChild td.dt-control:before {
content: "-";
background-color: #d33333;
}
/*! Bootstrap 5 integration for DataTables /*! Bootstrap 5 integration for DataTables
* *
@ -134,6 +277,28 @@ table.dataTable.nowrap th,
table.dataTable.nowrap td { table.dataTable.nowrap td {
white-space: nowrap; white-space: nowrap;
} }
table.dataTable.table-striped > tbody > tr:nth-of-type(2n+1) > * {
box-shadow: none;
}
table.dataTable > tbody > tr {
background-color: transparent;
}
table.dataTable > tbody > tr.selected > * {
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.9);
color: white;
}
table.dataTable.table-striped > tbody > tr.odd > * {
box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.05);
}
table.dataTable.table-striped > tbody > tr.odd.selected > * {
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.95);
}
table.dataTable.table-hover > tbody > tr:hover > * {
box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.075);
}
table.dataTable.table-hover > tbody > tr.selected:hover > * {
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.975);
}
div.dataTables_wrapper div.dataTables_length label { div.dataTables_wrapper div.dataTables_length label {
font-weight: normal; font-weight: normal;
@ -170,71 +335,6 @@ div.dataTables_wrapper div.dataTables_paginate ul.pagination {
white-space: nowrap; white-space: nowrap;
justify-content: flex-end; justify-content: flex-end;
} }
div.dataTables_wrapper div.dataTables_processing {
position: absolute;
top: 50%;
left: 50%;
width: 200px;
margin-left: -100px;
margin-top: -26px;
text-align: center;
padding: 1em 0;
}
table.dataTable > thead > tr > th:active,
table.dataTable > thead > tr > td:active {
outline: none;
}
table.dataTable > thead > tr > th:not(.sorting_disabled),
table.dataTable > thead > tr > td:not(.sorting_disabled) {
padding-right: 30px;
}
table.dataTable > thead .sorting,
table.dataTable > thead .sorting_asc,
table.dataTable > thead .sorting_desc,
table.dataTable > thead .sorting_asc_disabled,
table.dataTable > thead .sorting_desc_disabled {
cursor: pointer;
position: relative;
}
table.dataTable > thead .sorting:before, table.dataTable > thead .sorting:after,
table.dataTable > thead .sorting_asc:before,
table.dataTable > thead .sorting_asc:after,
table.dataTable > thead .sorting_desc:before,
table.dataTable > thead .sorting_desc:after,
table.dataTable > thead .sorting_asc_disabled:before,
table.dataTable > thead .sorting_asc_disabled:after,
table.dataTable > thead .sorting_desc_disabled:before,
table.dataTable > thead .sorting_desc_disabled:after {
position: absolute;
bottom: 0.5em;
display: block;
opacity: 0.3;
}
table.dataTable > thead .sorting:before,
table.dataTable > thead .sorting_asc:before,
table.dataTable > thead .sorting_desc:before,
table.dataTable > thead .sorting_asc_disabled:before,
table.dataTable > thead .sorting_desc_disabled:before {
right: 1em;
content: "↑";
}
table.dataTable > thead .sorting:after,
table.dataTable > thead .sorting_asc:after,
table.dataTable > thead .sorting_desc:after,
table.dataTable > thead .sorting_asc_disabled:after,
table.dataTable > thead .sorting_desc_disabled:after {
right: 0.5em;
content: "↓";
}
table.dataTable > thead .sorting_asc:before,
table.dataTable > thead .sorting_desc:after {
opacity: 1;
}
table.dataTable > thead .sorting_asc_disabled:before,
table.dataTable > thead .sorting_desc_disabled:after {
opacity: 0;
}
div.dataTables_scrollHead table.dataTable { div.dataTables_scrollHead table.dataTable {
margin-bottom: 0 !important; margin-bottom: 0 !important;
@ -280,17 +380,6 @@ div.dataTables_wrapper div.dataTables_paginate {
table.dataTable.table-sm > thead > tr > th:not(.sorting_disabled) { table.dataTable.table-sm > thead > tr > th:not(.sorting_disabled) {
padding-right: 20px; padding-right: 20px;
} }
table.dataTable.table-sm .sorting:before,
table.dataTable.table-sm .sorting_asc:before,
table.dataTable.table-sm .sorting_desc:before {
top: 5px;
right: 0.85em;
}
table.dataTable.table-sm .sorting:after,
table.dataTable.table-sm .sorting_asc:after,
table.dataTable.table-sm .sorting_desc:after {
top: 5px;
}
table.table-bordered.dataTable { table.table-bordered.dataTable {
border-right-width: 0; border-right-width: 0;
@ -332,11 +421,4 @@ div.table-responsive > div.dataTables_wrapper > div.row > div[class^=col-]:last-
padding-right: 0; padding-right: 0;
} }
table.dataTable.table-striped > tbody > tr:nth-of-type(2n+1) {
--bs-table-accent-bg: transparent;
}
table.dataTable.table-striped > tbody > tr.odd {
--bs-table-accent-bg: var(--bs-table-striped-bg);
}

@ -4,24 +4,23 @@
* *
* To rebuild or modify this file with the latest versions of the included * To rebuild or modify this file with the latest versions of the included
* software please visit: * software please visit:
* https://datatables.net/download/#bs5/dt-1.11.5 * https://datatables.net/download/#bs5/dt-1.12.1
* *
* Included libraries: * Included libraries:
* DataTables 1.11.5 * DataTables 1.12.1
*/ */
/*! DataTables 1.11.5 /*! DataTables 1.12.1
* ©2008-2021 SpryMedia Ltd - datatables.net/license * ©2008-2022 SpryMedia Ltd - datatables.net/license
*/ */
/** /**
* @summary DataTables * @summary DataTables
* @description Paginate, search and order HTML tables * @description Paginate, search and order HTML tables
* @version 1.11.5 * @version 1.12.1
* @file jquery.dataTables.js
* @author SpryMedia Ltd * @author SpryMedia Ltd
* @contact www.datatables.net * @contact www.datatables.net
* @copyright Copyright 2008-2021 SpryMedia Ltd. * @copyright SpryMedia Ltd.
* *
* This source file is free software, available under the following license: * This source file is free software, available under the following license:
* MIT license - http://datatables.net/license * MIT license - http://datatables.net/license
@ -1077,7 +1076,7 @@
success: function ( json ) { success: function ( json ) {
_fnCamelToHungarian( defaults.oLanguage, json ); _fnCamelToHungarian( defaults.oLanguage, json );
_fnLanguageCompat( json ); _fnLanguageCompat( json );
$.extend( true, oLanguage, json ); $.extend( true, oLanguage, json, oSettings.oInit.oLanguage );
_fnCallbackFire( oSettings, null, 'i18n', [oSettings]); _fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
_fnInitialise( oSettings ); _fnInitialise( oSettings );
@ -2310,9 +2309,17 @@
th.addClass( oOptions.sClass ); th.addClass( oOptions.sClass );
} }
var origClass = oCol.sClass;
$.extend( oCol, oOptions ); $.extend( oCol, oOptions );
_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" ); _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
// Merge class from previously defined classes with this one, rather than just
// overwriting it in the extend above
if (origClass !== oCol.sClass) {
oCol.sClass = origClass + ' ' + oCol.sClass;
}
/* iDataSort to be applied (backwards compatibility), but aDataSort will take /* iDataSort to be applied (backwards compatibility), but aDataSort will take
* priority if defined * priority if defined
*/ */
@ -2585,9 +2592,11 @@
def = aoColDefs[i]; def = aoColDefs[i];
/* Each definition can target multiple columns, as it is an array */ /* Each definition can target multiple columns, as it is an array */
var aTargets = def.targets !== undefined ? var aTargets = def.target !== undefined
def.targets : ? def.target
def.aTargets; : def.targets !== undefined
? def.targets
: def.aTargets;
if ( ! Array.isArray( aTargets ) ) if ( ! Array.isArray( aTargets ) )
{ {
@ -5089,6 +5098,7 @@
'class': settings.oClasses.sProcessing 'class': settings.oClasses.sProcessing
} ) } )
.html( settings.oLanguage.sProcessing ) .html( settings.oLanguage.sProcessing )
.append('<div><div></div><div></div><div></div><div></div></div>')
.insertBefore( settings.nTable )[0]; .insertBefore( settings.nTable )[0];
} }
@ -5338,6 +5348,7 @@
footerCopy = footer.clone().prependTo( table ); footerCopy = footer.clone().prependTo( table );
footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
footerSrcEls = footerCopy.find('tr'); footerSrcEls = footerCopy.find('tr');
footerCopy.find('[id]').removeAttr('id');
} }
// Clone the current header and footer elements and then place it into the inner table // Clone the current header and footer elements and then place it into the inner table
@ -5345,6 +5356,7 @@
headerTrgEls = header.find('tr'); // original header is in its own table headerTrgEls = header.find('tr'); // original header is in its own table
headerSrcEls = headerCopy.find('tr'); headerSrcEls = headerCopy.find('tr');
headerCopy.find('th, td').removeAttr('tabindex'); headerCopy.find('th, td').removeAttr('tabindex');
headerCopy.find('[id]').removeAttr('id');
/* /*
@ -6471,6 +6483,17 @@
// Store the saved state so it might be accessed at any time // Store the saved state so it might be accessed at any time
settings.oLoadedState = $.extend( true, {}, s ); settings.oLoadedState = $.extend( true, {}, s );
// Page Length
if ( s.length !== undefined ) {
// If already initialised just set the value directly so that the select element is also updated
if (api) {
api.page.len(s.length)
}
else {
settings._iDisplayLength = s.length;
}
}
// Restore key features - todo - for 1.11 this needs to be done by // Restore key features - todo - for 1.11 this needs to be done by
// subscribed events // subscribed events
if ( s.start !== undefined ) { if ( s.start !== undefined ) {
@ -6479,13 +6502,9 @@
settings.iInitDisplayStart = s.start; settings.iInitDisplayStart = s.start;
} }
else { else {
_fnPageChange(settings, s.start/s.length); _fnPageChange(settings, s.start/settings._iDisplayLength);
} }
} }
if ( s.length !== undefined ) {
settings._iDisplayLength = s.length;
}
// Order // Order
if ( s.order !== undefined ) { if ( s.order !== undefined ) {
@ -7218,8 +7237,10 @@
pluck: function ( prop ) pluck: function ( prop )
{ {
let fn = DataTable.util.get(prop);
return this.map( function ( el ) { return this.map( function ( el ) {
return el[ prop ]; return fn(el);
} ); } );
}, },
@ -8448,7 +8469,7 @@
var api = new _Api( settings ); var api = new _Api( settings );
var namespace = '.dt.DT_details'; var namespace = '.dt.DT_details';
var drawEvent = 'draw'+namespace; var drawEvent = 'draw'+namespace;
var colvisEvent = 'column-visibility'+namespace; var colvisEvent = 'column-sizing'+namespace;
var destroyEvent = 'destroy'+namespace; var destroyEvent = 'destroy'+namespace;
var data = settings.aoData; var data = settings.aoData;
@ -9500,7 +9521,6 @@
remove = remove || false; remove = remove || false;
return this.iterator( 'table', function ( settings ) { return this.iterator( 'table', function ( settings ) {
var orig = settings.nTableWrapper.parentNode;
var classes = settings.oClasses; var classes = settings.oClasses;
var table = settings.nTable; var table = settings.nTable;
var tbody = settings.nTBody; var tbody = settings.nTBody;
@ -9555,6 +9575,8 @@
jqTbody.children().detach(); jqTbody.children().detach();
jqTbody.append( rows ); jqTbody.append( rows );
var orig = settings.nTableWrapper.parentNode;
// Remove the DataTables generated nodes, events and classes // Remove the DataTables generated nodes, events and classes
var removedMethod = remove ? 'remove' : 'detach'; var removedMethod = remove ? 'remove' : 'detach';
jqTable[ removedMethod ](); jqTable[ removedMethod ]();
@ -9648,7 +9670,7 @@
* @type string * @type string
* @default Version number * @default Version number
*/ */
DataTable.version = "1.11.5"; DataTable.version = "1.12.1";
/** /**
* Private data store, containing all of the settings objects that are * Private data store, containing all of the settings objects that are
@ -11853,7 +11875,6 @@
* Text which is displayed when the table is processing a user action * Text which is displayed when the table is processing a user action
* (usually a sort command or similar). * (usually a sort command or similar).
* @type string * @type string
* @default Processing...
* *
* @dtopt Language * @dtopt Language
* @name DataTable.defaults.language.processing * @name DataTable.defaults.language.processing
@ -11867,7 +11888,7 @@
* } ); * } );
* } ); * } );
*/ */
"sProcessing": "Processing...", "sProcessing": "",
/** /**
@ -14073,7 +14094,7 @@
* *
* @type string * @type string
*/ */
build:"bs5/dt-1.11.5", build:"bs5/dt-1.12.1",
/** /**
@ -15119,6 +15140,213 @@
d; d;
}; };
// Common logic for moment, luxon or a date action
function __mld( dt, momentFn, luxonFn, dateFn, arg1 ) {
if (window.moment) {
return dt[momentFn]( arg1 );
}
else if (window.luxon) {
return dt[luxonFn]( arg1 );
}
return dateFn ? dt[dateFn]( arg1 ) : dt;
}
var __mlWarning = false;
function __mldObj (d, format, locale) {
var dt;
if (window.moment) {
dt = window.moment.utc( d, format, locale, true );
if (! dt.isValid()) {
return null;
}
}
else if (window.luxon) {
dt = format
? window.luxon.DateTime.fromFormat( d, format )
: window.luxon.DateTime.fromISO( d );
if (! dt.isValid) {
return null;
}
dt.setLocale(locale);
}
else if (! format) {
// No format given, must be ISO
dt = new Date(d);
}
else {
if (! __mlWarning) {
alert('DataTables warning: Formatted date without Moment.js or Luxon - https://datatables.net/tn/17');
}
__mlWarning = true;
}
return dt;
}
// Wrapper for date, datetime and time which all operate the same way with the exception of
// the output string for auto locale support
function __mlHelper (localeString) {
return function ( from, to, locale, def ) {
// Luxon and Moment support
// Argument shifting
if ( arguments.length === 0 ) {
locale = 'en';
to = null; // means toLocaleString
from = null; // means iso8601
}
else if ( arguments.length === 1 ) {
locale = 'en';
to = from;
from = null;
}
else if ( arguments.length === 2 ) {
locale = to;
to = from;
from = null;
}
var typeName = 'datetime-' + to;
// Add type detection and sorting specific to this date format - we need to be able to identify
// date type columns as such, rather than as numbers in extensions. Hence the need for this.
if (! DataTable.ext.type.order[typeName]) {
// The renderer will give the value to type detect as the type!
DataTable.ext.type.detect.unshift(function (d) {
return d === typeName ? typeName : false;
});
// The renderer gives us Moment, Luxon or Date obects for the sorting, all of which have a
// `valueOf` which gives milliseconds epoch
DataTable.ext.type.order[typeName + '-asc'] = function (a, b) {
var x = a.valueOf();
var y = b.valueOf();
return x === y
? 0
: x < y
? -1
: 1;
}
DataTable.ext.type.order[typeName + '-desc'] = function (a, b) {
var x = a.valueOf();
var y = b.valueOf();
return x === y
? 0
: x > y
? -1
: 1;
}
}
return function ( d, type ) {
// Allow for a default value
if (d === null || d === undefined) {
if (def === '--now') {
// We treat everything as UTC further down, so no changes are
// made, as such need to get the local date / time as if it were
// UTC
var local = new Date();
d = new Date( Date.UTC(
local.getFullYear(), local.getMonth(), local.getDate(),
local.getHours(), local.getMinutes(), local.getSeconds()
) );
}
else {
d = '';
}
}
if (type === 'type') {
// Typing uses the type name for fast matching
return typeName;
}
if (d === '') {
return type !== 'sort'
? ''
: __mldObj('0000-01-01 00:00:00', null, locale);
}
// Shortcut. If `from` and `to` are the same, we are using the renderer to
// format for ordering, not display - its already in the display format.
if ( to !== null && from === to && type !== 'sort' && type !== 'type' && ! (d instanceof Date) ) {
return d;
}
var dt = __mldObj(d, from, locale);
if (dt === null) {
return d;
}
if (type === 'sort') {
return dt;
}
var formatted = to === null
? __mld(dt, 'toDate', 'toJSDate', '')[localeString]()
: __mld(dt, 'format', 'toFormat', 'toISOString', to);
// XSS protection
return type === 'display' ?
__htmlEscapeEntities( formatted ) :
formatted;
};
}
}
// Based on locale, determine standard number formatting
// Fallback for legacy browsers is US English
var __thousands = ',';
var __decimal = '.';
if (Intl) {
try {
var num = new Intl.NumberFormat().formatToParts(100000.1);
for (var i=0 ; i<num.length ; i++) {
if (num[i].type === 'group') {
__thousands = num[i].value;
}
else if (num[i].type === 'decimal') {
__decimal = num[i].value;
}
}
}
catch (e) {
// noop
}
}
// Formatted date time detection - use by declaring the formats you are going to use
DataTable.datetime = function ( format, locale ) {
var typeName = 'datetime-detect-' + format;
if (! locale) {
locale = 'en';
}
if (! DataTable.ext.type.order[typeName]) {
DataTable.ext.type.detect.unshift(function (d) {
var dt = __mldObj(d, format, locale);
return d === '' || dt ? typeName : false;
});
DataTable.ext.type.order[typeName + '-pre'] = function (d) {
return __mldObj(d, format, locale) || 0;
}
}
}
/** /**
* Helpers for `columns.render`. * Helpers for `columns.render`.
* *
@ -15146,13 +15374,29 @@
* @namespace * @namespace
*/ */
DataTable.render = { DataTable.render = {
date: __mlHelper('toLocaleDateString'),
datetime: __mlHelper('toLocaleString'),
time: __mlHelper('toLocaleTimeString'),
number: function ( thousands, decimal, precision, prefix, postfix ) { number: function ( thousands, decimal, precision, prefix, postfix ) {
// Auto locale detection
if (thousands === null || thousands === undefined) {
thousands = __thousands;
}
if (decimal === null || decimal === undefined) {
decimal = __decimal;
}
return { return {
display: function ( d ) { display: function ( d ) {
if ( typeof d !== 'number' && typeof d !== 'string' ) { if ( typeof d !== 'number' && typeof d !== 'string' ) {
return d; return d;
} }
if (d === '' || d === null) {
return d;
}
var negative = d < 0 ? '-' : ''; var negative = d < 0 ? '-' : '';
var flo = parseFloat( d ); var flo = parseFloat( d );

@ -20,8 +20,15 @@
width: auto; width: auto;
margin: -5px 0 0 0; margin: -5px 0 0 0;
} }
/* Special alert-row class to use Bootstrap v5.2+ variable colors */
.alert-row {
--bs-alert-border: 1px solid var(--bs-alert-border-color);
color: var(--bs-alert-color);
background-color: var(--bs-alert-bg);
border: var(--bs-alert-border);
}
</style> </style>
<script src="{{urlpath}}/vw_static/identicon.js"></script> <script defer="defer" src="{{urlpath}}/vw_static/identicon.js"></script>
<script> <script>
'use strict'; 'use strict';
@ -135,6 +142,6 @@
} }
})(); })();
</script> </script>
<script src="{{urlpath}}/vw_static/bootstrap-native.js"></script> <script defer="defer" src="{{urlpath}}/vw_static/bootstrap-native.js"></script>
</body> </body>
</html> </html>

@ -5,7 +5,7 @@
<div class="small text-white mb-3"> <div class="small text-white mb-3">
<span class="font-weight-bolder">NOTE:</span> The settings here override the environment variables. Once saved, it's recommended to stop setting them to avoid confusion.<br> <span class="font-weight-bolder">NOTE:</span> The settings here override the environment variables. Once saved, it's recommended to stop setting them to avoid confusion.<br>
This does not apply to the read-only section, which can only be set via environment variables.<br> This does not apply to the read-only section, which can only be set via environment variables.<br>
Settings which are overridden are shown with <span class="is-overridden-true">double underscores</span>. Settings which are overridden are shown with <span class="is-overridden-true alert-row px-1">a yellow colored background</span>.
</div> </div>
<form class="form needs-validation" id="config-form" onsubmit="saveConfig(); return false;" novalidate> <form class="form needs-validation" id="config-form" onsubmit="saveConfig(); return false;" novalidate>
@ -16,7 +16,7 @@
<div id="g_{{group}}" class="card-body collapse"> <div id="g_{{group}}" class="card-body collapse">
{{#each elements}} {{#each elements}}
{{#if editable}} {{#if editable}}
<div class="row my-2 align-items-center is-overridden-{{overridden}}" title="[{{name}}] {{doc.description}}"> <div class="row my-2 align-items-center is-overridden-{{overridden}} alert-row" title="[{{name}}] {{doc.description}}">
{{#case type "text" "number" "password"}} {{#case type "text" "number" "password"}}
<label for="input_{{name}}" class="col-sm-3 col-form-label">{{doc.name}}</label> <label for="input_{{name}}" class="col-sm-3 col-form-label">{{doc.name}}</label>
<div class="col-sm-8"> <div class="col-sm-8">
@ -71,16 +71,25 @@
{{#each config}} {{#each config}}
{{#each elements}} {{#each elements}}
{{#unless editable}} {{#unless editable}}
<div class="row my-2 align-items-center" title="[{{name}}] {{doc.description}}"> <div class="row my-2 align-items-center alert-row" title="[{{name}}] {{doc.description}}">
{{#case type "text" "number" "password"}} {{#case type "text" "number" "password"}}
<label for="input_{{name}}" class="col-sm-3 col-form-label">{{doc.name}}</label> <label for="input_{{name}}" class="col-sm-3 col-form-label">{{doc.name}}</label>
<div class="col-sm-8"> <div class="col-sm-8">
<div class="input-group"> <div class="input-group">
<input readonly class="form-control" id="input_{{name}}" type="{{type}}" {{!--
value="{{value}}" {{#if default}} placeholder="Default: {{default}}" {{/if}}> Also set the database_url input as password here.
If we would set it to password in config.rs it will not be character masked for the support string.
And sometimes this is more useful for providing support than just 3 asterisk.
--}}
{{#if (eq name "database_url")}}
<input readonly class="form-control" id="input_{{name}}" type="password" value="{{value}}" {{#if default}} placeholder="Default: {{default}}" {{/if}}>
<button class="btn btn-outline-secondary" type="button" onclick="toggleVis('input_{{name}}');">Show/hide</button>
{{else}}
<input readonly class="form-control" id="input_{{name}}" type="{{type}}" value="{{value}}" {{#if default}} placeholder="Default: {{default}}" {{/if}}>
{{#case type "password"}} {{#case type "password"}}
<button class="btn btn-outline-secondary" type="button" onclick="toggleVis('input_{{name}}');">Show/hide</button> <button class="btn btn-outline-secondary" type="button" onclick="toggleVis('input_{{name}}');">Show/hide</button>
{{/case}} {{/case}}
{{/if}}
</div> </div>
</div> </div>
{{/case}} {{/case}}
@ -134,7 +143,9 @@
} }
.is-overridden-true { .is-overridden-true {
text-decoration: underline double; --bs-alert-color: #664d03;
--bs-alert-bg: #fff3cd;
--bs-alert-border-color: #ffecb5;
} }
</style> </style>
@ -238,19 +249,45 @@
return Array.from(form).some(el => 'origValue' in el.dataset && ( el.dataset.origValue !== el.value)); return Array.from(form).some(el => 'origValue' in el.dataset && ( el.dataset.origValue !== el.value));
} }
// Trigger Form Change Detection // This function will prevent submitting a from when someone presses enter.
function preventFormSubmitOnEnter(form) {
form.onkeypress = function(e) {
let key = e.charCode || e.keyCode || 0;
if (key == 13) {
e.preventDefault();
}
}
}
// Initialize Form Change Detection
const config_form = document.getElementById('config-form'); const config_form = document.getElementById('config-form');
initChangeDetection(config_form); initChangeDetection(config_form);
// Prevent enter to submitting the form and save the config.
// Users need to really click on save, this also to prevent accidental submits.
preventFormSubmitOnEnter(config_form);
// This function will hook into the smtp-test-email input field and will call the smtpTest() function when enter is pressed.
function submitTestEmailOnEnter() {
const smtp_test_email_input = document.getElementById('smtp-test-email');
smtp_test_email_input.onkeypress = function(e) {
let key = e.charCode || e.keyCode || 0;
if (key == 13) {
e.preventDefault();
smtpTest();
}
}
}
submitTestEmailOnEnter();
// Colorize some settings which are high risk // Colorize some settings which are high risk
function colorRiskSettings() {
const risk_items = document.getElementsByClassName('col-form-label'); const risk_items = document.getElementsByClassName('col-form-label');
function colorRiskSettings(risk_el) { Array.from(risk_items).forEach((el) => {
Array.from(risk_el).forEach((el) => {
if (el.innerText.toLowerCase().includes('risks') ) { if (el.innerText.toLowerCase().includes('risks') ) {
el.parentElement.className += ' alert-danger' el.parentElement.className += ' alert-danger'
} }
}); });
} }
colorRiskSettings(risk_items); colorRiskSettings();
</script> </script>

@ -29,21 +29,48 @@ impl Fairing for AppHeaders {
} }
} }
async fn on_response<'r>(&self, _req: &'r Request<'_>, res: &mut Response<'r>) { async fn on_response<'r>(&self, req: &'r Request<'_>, res: &mut Response<'r>) {
res.set_raw_header("Permissions-Policy", "accelerometer=(), ambient-light-sensor=(), autoplay=(), camera=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), sync-xhr=(self \"https://haveibeenpwned.com\" \"https://2fa.directory\"), usb=(), vr=()"); res.set_raw_header("Permissions-Policy", "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()");
res.set_raw_header("Referrer-Policy", "same-origin"); res.set_raw_header("Referrer-Policy", "same-origin");
res.set_raw_header("X-Frame-Options", "SAMEORIGIN");
res.set_raw_header("X-Content-Type-Options", "nosniff"); res.set_raw_header("X-Content-Type-Options", "nosniff");
// Obsolete in modern browsers, unsafe (XS-Leak), and largely replaced by CSP // Obsolete in modern browsers, unsafe (XS-Leak), and largely replaced by CSP
res.set_raw_header("X-XSS-Protection", "0"); res.set_raw_header("X-XSS-Protection", "0");
let req_uri_path = req.uri().path();
// Check if we are requesting an admin page, if so, allow unsafe-inline for scripts.
// TODO: In the future maybe we need to see if we can generate a sha256 hash or have no scripts inline at all.
let admin_path = format!("{}/admin", CONFIG.domain_path());
let mut script_src = "";
if req_uri_path.starts_with(admin_path.as_str()) {
script_src = " 'unsafe-inline'";
}
// Do not send the Content-Security-Policy (CSP) Header and X-Frame-Options for the *-connector.html files.
// This can cause issues when some MFA requests needs to open a popup or page within the clients like WebAuthn, or Duo.
// This is the same behaviour as upstream Bitwarden.
if !req_uri_path.ends_with("connector.html") {
let csp = format!( let csp = format!(
// Chrome Web Store: https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb // Chrome Web Store: https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb
// Edge Add-ons: https://microsoftedge.microsoft.com/addons/detail/bitwarden-free-password/jbkfoedolllekgbhcbcoahefnbanhhlh?hl=en-US // Edge Add-ons: https://microsoftedge.microsoft.com/addons/detail/bitwarden-free-password/jbkfoedolllekgbhcbcoahefnbanhhlh?hl=en-US
// Firefox Browser Add-ons: https://addons.mozilla.org/en-US/firefox/addon/bitwarden-password-manager/ // Firefox Browser Add-ons: https://addons.mozilla.org/en-US/firefox/addon/bitwarden-password-manager/
"frame-ancestors 'self' chrome-extension://nngceckbapebfimnlniiiahkandclblb chrome-extension://jbkfoedolllekgbhcbcoahefnbanhhlh moz-extension://* {};", "default-src 'self'; \
script-src 'self'{script_src}; \
style-src 'self' 'unsafe-inline'; \
img-src 'self' data: https://haveibeenpwned.com/ https://www.gravatar.com; \
child-src 'self' https://*.duosecurity.com https://*.duofederal.com; \
frame-src 'self' https://*.duosecurity.com https://*.duofederal.com; \
connect-src 'self' https://api.pwnedpasswords.com/range/ https://2fa.directory/api/ https://app.simplelogin.io/api/ https://app.anonaddy.com/api/; \
object-src 'self' blob:; \
frame-ancestors 'self' chrome-extension://nngceckbapebfimnlniiiahkandclblb chrome-extension://jbkfoedolllekgbhcbcoahefnbanhhlh moz-extension://* {};",
CONFIG.allowed_iframe_ancestors() CONFIG.allowed_iframe_ancestors()
); );
res.set_raw_header("Content-Security-Policy", csp); res.set_raw_header("Content-Security-Policy", csp);
res.set_raw_header("X-Frame-Options", "SAMEORIGIN");
} else {
// It looks like this header get's set somewhere else also, make sure this is not sent for these files, it will cause MFA issues.
res.remove_header("X-Frame-Options");
}
// Disable cache unless otherwise specified // Disable cache unless otherwise specified
if !res.headers().contains("cache-control") { if !res.headers().contains("cache-control") {

Loading…
Cancel
Save